Merge branch 'develop'
This commit is contained in:
41
README.md
41
README.md
@@ -1,5 +1,11 @@
|
||||
<div align="center">
|
||||
|
||||

|
||||
|
||||
# VRCT (VRChat Chatbox Translator & Transcription)
|
||||
|
||||
<div align="left">
|
||||
|
||||
## Overview
|
||||
VRChatのChatBoxにOSC経由でメッセージを送信するツール
|
||||
翻訳エンジンを使用してメッセージとその翻訳部分を同時に送信することができる
|
||||
@@ -15,31 +21,17 @@ VRChatのChatBoxにOSC経由でメッセージを送信するツール
|
||||
- translators(https://github.com/misyaguziya/translators)
|
||||
- custom_speech_recognition(https://github.com/misyaguziya/custom_speech_recognition)
|
||||
|
||||
deepl-translate/translators/custom_speech_recognitionについては追加実装をしています。`pip install`でinstallした場合、動かないので注意
|
||||
**deepl-translate/translators/custom_speech_recognitionについては追加実装をしています**
|
||||
**`pip install`でinstallした場合、動かないので注意**
|
||||
|
||||
## install
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
```bash
|
||||
git clone https://github.com/misyaguziya/translators.git
|
||||
cd translators
|
||||
python ./setup.py install
|
||||
cd ../
|
||||
git clone https://github.com/misyaguziya/deepl-translate.git
|
||||
cd deepl-translate
|
||||
python ./setup.py install
|
||||
cd ../
|
||||
git clone https://github.com/misyaguziya/custom_speech_recognition.git
|
||||
cd custom_speech_recognition
|
||||
python ./setup.py install
|
||||
cd ../
|
||||
./install.bat
|
||||
```
|
||||
|
||||
## Usage
|
||||
```bash
|
||||
ptyhon VRCT.py
|
||||
python VRCT.py
|
||||
```
|
||||
|
||||
## Features
|
||||
@@ -75,26 +67,26 @@ ptyhon VRCT.py
|
||||
- Appearance Theme: ウィンドウテーマを選択
|
||||
- UI Scaling: UIサイズを調整
|
||||
- Font Family: 表示フォントを選択
|
||||
- **(New!) UI Language: UIの表示言語を選択**
|
||||
- UI Language: UIの表示言語を選択
|
||||
- Translation tab
|
||||
- Select Translator: 翻訳エンジンの変更
|
||||
- Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択
|
||||
- Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択
|
||||
- Transcription tab
|
||||
- **(New!) Input Mic Host: マイクのホストAPIを選択**
|
||||
- Input Mic Host: マイクのホストAPIを選択
|
||||
- Input Mic Device: マイクを選択
|
||||
- Input Mic Voice Language: 入力する音声の言語
|
||||
- Input Mic Energy Threshold: 音声取得のしきい値
|
||||
- **(New!) Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化**
|
||||
- Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
- Input Mic Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
- Input Mic Phase Timeout: 文字起こしする音声時間の上限
|
||||
- Input Mic Record Timeout: 音声の区切りの無音時間
|
||||
- Input Mic Max Phrases: 保留する単語の上限
|
||||
- **(New!) Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)**
|
||||
- Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
- Input Speaker Device: スピーカーを選択
|
||||
- Input Speaker Voice Language: 受信する音声の言語
|
||||
- Input Speaker Energy Threshold: 音声取得のしきい値
|
||||
- **(New!) Check threshold point: (New!)Input Speaker Energy Thresholdのしきい値を視覚化**
|
||||
- Check threshold point: Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
- Input Speaker Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
- Input Speaker Record Timeout: 音声の区切りの無音時間
|
||||
- Input Speaker Phase Timeout: 文字起こしする音声時間の上限
|
||||
@@ -108,7 +100,8 @@ ptyhon VRCT.py
|
||||
- [translation]が翻訳されたメッセージに置換される
|
||||
- 初期フォーマット:`[message]([translation])`
|
||||
- Others tab
|
||||
- **(New!) Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする**
|
||||
- Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
- **(New!) Notification XSOverlay: XSOverlayの通知機能を有効(VR only)**
|
||||
|
||||
## Author
|
||||
みしゃ(misyaguzi)
|
||||
|
||||
18
README.txt
18
README.txt
@@ -42,26 +42,26 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ
|
||||
Appearance Theme: ウィンドウテーマを選択
|
||||
UI Scaling: UIサイズを調整
|
||||
Font Family: 表示フォントを選択
|
||||
(New!) UI Language: UIの表示言語を選択
|
||||
UI Language: UIの表示言語を選択
|
||||
Translationタブ
|
||||
Select Translator: 翻訳エンジンの変更
|
||||
Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択
|
||||
Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択
|
||||
Transcriptionタブ
|
||||
(New!) Input Mic Host: マイクのホストAPIを選択
|
||||
Input Mic Host: マイクのホストAPIを選択
|
||||
Input Mic Device: マイクを選択
|
||||
Input Mic Voice Language: 入力する音声の言語
|
||||
Input Mic Energy Threshold: 音声取得のしきい値
|
||||
(New!) Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
Input Mic Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
Input Mic Record Timeout: 音声の区切りの無音時間
|
||||
Input Mic Phase Timeout: 文字起こしする音声時間の上限
|
||||
Input Mic Max Phrases: 保留する単語の上限
|
||||
(New!) Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
Input Speaker Device: スピーカーを選択
|
||||
Input Speaker Voice Language: 受信する音声の言語
|
||||
Input Speaker Energy Threshold: 音声取得のしきい値
|
||||
(New!) Check threshold point: (New!)Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
Check threshold point: Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
Input Speaker Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
Input Speaker Record Timeout: 音声の区切りの無音時間
|
||||
Input Speaker Phase Timeout: 文字起こしする音声時間の上限
|
||||
@@ -75,7 +75,8 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ
|
||||
[translation]が翻訳されたメッセージに置換される
|
||||
初期フォーマット:"[message]([translation])"
|
||||
Othersタブ
|
||||
(New!) Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
(New!) Notification XSOverlay: XSOverlayの通知機能を有効(VR only)
|
||||
|
||||
設定の初期化
|
||||
config.jsonを削除
|
||||
@@ -121,6 +122,11 @@ https://twitter.com/misya_ai
|
||||
- 半角入力時に一部の文字が書き込めないバグを修正
|
||||
[2023-07-22: v1.3.1]
|
||||
- UIの表示言語選択に韓国語を追加
|
||||
[2023-07-30: v1.3.2]
|
||||
- 試験的にXSOverlayへの通知機能を追加
|
||||
- checkbox ONの状態でもConfigを開けるように変更
|
||||
- 文字起こし言語の表示を修正
|
||||
- いくつかのバグを修正
|
||||
|
||||
# 注意事項
|
||||
再配布とかはやめてね
|
||||
269
VRCT.py
269
VRCT.py
@@ -1,3 +1,4 @@
|
||||
from time import sleep
|
||||
from os import path as os_path
|
||||
from json import load as json_load
|
||||
from json import dump as json_dump
|
||||
@@ -10,7 +11,7 @@ from flashtext import KeywordProcessor
|
||||
|
||||
from threading import Thread
|
||||
from utils import save_json, print_textbox, thread_fnc, get_localized_text, widget_main_window_label_setter
|
||||
from osc_tools import send_typing, send_message
|
||||
from osc_tools import send_typing, send_message, send_test_action, receive_osc_parameters
|
||||
from window_config import ToplevelWindowConfig
|
||||
from window_information import ToplevelWindowInformation
|
||||
from languages import transcription_lang, translators, translation_lang, selectable_languages
|
||||
@@ -18,6 +19,7 @@ from audio_utils import get_input_device_list, get_output_device_list, get_defau
|
||||
from audio_recorder import SelectedMicRecorder, SelectedSpeakerRecorder
|
||||
from audio_transcriber import AudioTranscriber
|
||||
from translation import Translator
|
||||
from notification import notification_xsoverlay_for_vrct
|
||||
|
||||
class App(CTk):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -32,8 +34,8 @@ class App(CTk):
|
||||
|
||||
## main window
|
||||
self.ENABLE_TRANSLATION = False
|
||||
self.ENABLE_TRANSCRIPTION_SEND = False
|
||||
self.ENABLE_TRANSCRIPTION_RECEIVE = False
|
||||
# self.ENABLE_TRANSCRIPTION_SEND = False
|
||||
# self.ENABLE_TRANSCRIPTION_RECEIVE = False
|
||||
self.ENABLE_FOREGROUND = False
|
||||
## UI
|
||||
self.TRANSPARENCY = 100
|
||||
@@ -43,10 +45,10 @@ class App(CTk):
|
||||
self.UI_LANGUAGE = "en"
|
||||
## Translation
|
||||
self.CHOICE_TRANSLATOR = translators[0]
|
||||
self.INPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR].keys())[0]
|
||||
self.INPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR].keys())[1]
|
||||
self.OUTPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR].keys())[1]
|
||||
self.OUTPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR].keys())[0]
|
||||
self.INPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[0]
|
||||
self.INPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[1]
|
||||
self.OUTPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[1]
|
||||
self.OUTPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[0]
|
||||
## Transcription Send
|
||||
self.CHOICE_MIC_HOST = get_default_input_device()["host"]["name"]
|
||||
self.CHOICE_MIC_DEVICE = get_default_input_device()["device"]["name"]
|
||||
@@ -65,6 +67,7 @@ class App(CTk):
|
||||
self.INPUT_SPEAKER_RECORD_TIMEOUT = 3
|
||||
self.INPUT_SPEAKER_PHRASE_TIMEOUT = 3
|
||||
self.INPUT_SPEAKER_MAX_PHRASES = 10
|
||||
|
||||
## Parameter
|
||||
self.OSC_IP_ADDRESS = "127.0.0.1"
|
||||
self.OSC_PORT = 9000
|
||||
@@ -77,6 +80,8 @@ class App(CTk):
|
||||
self.MESSAGE_FORMAT = "[message]([translation])"
|
||||
# Others
|
||||
self.ENABLE_AUTO_CLEAR_CHATBOX = False
|
||||
self.ENABLE_OSC = False
|
||||
self.ENABLE_NOTICE_XSOVERLAY =False
|
||||
|
||||
# load config
|
||||
if os_path.isfile(self.PATH_CONFIG) is not False:
|
||||
@@ -123,16 +128,16 @@ class App(CTk):
|
||||
if config["CHOICE_TRANSLATOR"] in list(self.translator.translator_status.keys()):
|
||||
self.CHOICE_TRANSLATOR = config["CHOICE_TRANSLATOR"]
|
||||
if "INPUT_SOURCE_LANG" in config.keys():
|
||||
if config["INPUT_SOURCE_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR].keys()):
|
||||
if config["INPUT_SOURCE_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys()):
|
||||
self.INPUT_SOURCE_LANG = config["INPUT_SOURCE_LANG"]
|
||||
if "INPUT_TARGET_LANG" in config.keys():
|
||||
if config["INPUT_SOURCE_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR].keys()):
|
||||
if config["INPUT_TARGET_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys()):
|
||||
self.INPUT_TARGET_LANG = config["INPUT_TARGET_LANG"]
|
||||
if "OUTPUT_SOURCE_LANG" in config.keys():
|
||||
if config["INPUT_SOURCE_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR].keys()):
|
||||
if config["OUTPUT_SOURCE_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys()):
|
||||
self.OUTPUT_SOURCE_LANG = config["OUTPUT_SOURCE_LANG"]
|
||||
if "OUTPUT_TARGET_LANG" in config.keys():
|
||||
if config["INPUT_SOURCE_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR].keys()):
|
||||
if config["OUTPUT_TARGET_LANG"] in list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys()):
|
||||
self.OUTPUT_TARGET_LANG = config["OUTPUT_TARGET_LANG"]
|
||||
|
||||
# Transcription
|
||||
@@ -209,6 +214,9 @@ class App(CTk):
|
||||
if "ENABLE_AUTO_CLEAR_CHATBOX" in config.keys():
|
||||
if type(config["ENABLE_AUTO_CLEAR_CHATBOX"]) is bool:
|
||||
self.ENABLE_AUTO_CLEAR_CHATBOX = config["ENABLE_AUTO_CLEAR_CHATBOX"]
|
||||
if "ENABLE_NOTICE_XSOVERLAY" in config.keys():
|
||||
if type(config["ENABLE_NOTICE_XSOVERLAY"]) is bool:
|
||||
self.ENABLE_NOTICE_XSOVERLAY = config["ENABLE_NOTICE_XSOVERLAY"]
|
||||
|
||||
with open(self.PATH_CONFIG, 'w') as fp:
|
||||
config = {
|
||||
@@ -247,6 +255,7 @@ class App(CTk):
|
||||
"AUTH_KEYS": self.AUTH_KEYS,
|
||||
"MESSAGE_FORMAT": self.MESSAGE_FORMAT,
|
||||
"ENABLE_AUTO_CLEAR_CHATBOX": self.ENABLE_AUTO_CLEAR_CHATBOX,
|
||||
"ENABLE_NOTICE_XSOVERLAY": self.ENABLE_NOTICE_XSOVERLAY,
|
||||
}
|
||||
json_dump(config, fp, indent=4)
|
||||
|
||||
@@ -316,19 +325,18 @@ class App(CTk):
|
||||
# add button information
|
||||
self.button_information = CTkButton(
|
||||
self.sidebar_frame,
|
||||
text="",
|
||||
width=25,
|
||||
text=None,
|
||||
width=36,
|
||||
command=self.button_information_callback,
|
||||
image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "info-icon-white.png")))
|
||||
)
|
||||
self.button_information.grid(row=5, column=0, padx=(10, 5), pady=(5, 5), sticky="wse")
|
||||
self.information_window = None
|
||||
|
||||
# add button config
|
||||
self.button_config = CTkButton(
|
||||
self.sidebar_frame,
|
||||
text="",
|
||||
width=25,
|
||||
text=None,
|
||||
width=36,
|
||||
command=self.button_config_callback,
|
||||
image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "config-icon-white.png")))
|
||||
)
|
||||
@@ -402,36 +410,49 @@ class App(CTk):
|
||||
self.protocol("WM_DELETE_WINDOW", self.delete_window)
|
||||
|
||||
self.config_window = ToplevelWindowConfig(self)
|
||||
self.information_window = ToplevelWindowInformation(self)
|
||||
|
||||
# start receive osc
|
||||
th_receive_osc_parameters = Thread(target=receive_osc_parameters, args=(self.check_osc_receive,))
|
||||
th_receive_osc_parameters.daemon = True
|
||||
th_receive_osc_parameters.start()
|
||||
|
||||
# check osc started
|
||||
send_test_action()
|
||||
|
||||
def button_config_callback(self):
|
||||
self.foreground_stop()
|
||||
self.transcription_stop()
|
||||
self.checkbox_translation.configure(state="disabled")
|
||||
self.checkbox_transcription_send.configure(state="disabled")
|
||||
self.checkbox_transcription_receive.configure(state="disabled")
|
||||
self.checkbox_foreground.configure(state="disabled")
|
||||
self.tabview_logs.configure(state="disabled")
|
||||
self.textbox_message_log.configure(state="disabled")
|
||||
self.textbox_message_send_log.configure(state="disabled")
|
||||
self.textbox_message_receive_log.configure(state="disabled")
|
||||
self.textbox_message_system_log.configure(state="disabled")
|
||||
self.entry_message_box.configure(state="disabled")
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
|
||||
self.button_information.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
self.config_window.deiconify()
|
||||
self.config_window.focus_set()
|
||||
self.config_window.focus()
|
||||
self.config_window.grab_set()
|
||||
|
||||
def button_information_callback(self):
|
||||
if self.information_window is None or not self.information_window.winfo_exists():
|
||||
self.information_window = ToplevelWindowInformation(self)
|
||||
self.information_window.deiconify()
|
||||
self.information_window.focus_set()
|
||||
self.information_window.focus()
|
||||
|
||||
def checkbox_translation_callback(self):
|
||||
self.ENABLE_TRANSLATION = self.checkbox_translation.get()
|
||||
if self.ENABLE_TRANSLATION:
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
if self.ENABLE_TRANSLATION is True:
|
||||
print_textbox(self.textbox_message_log, "Start translation", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start translation", "INFO")
|
||||
else:
|
||||
if ((self.checkbox_translation.get() is False) and
|
||||
(self.checkbox_transcription_send.get() is False) and
|
||||
(self.checkbox_transcription_receive.get() is False)):
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
print_textbox(self.textbox_message_log, "Stop translation", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop translation", "INFO")
|
||||
save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION)
|
||||
|
||||
def transcription_send_start(self):
|
||||
self.mic_audio_queue = Queue()
|
||||
@@ -477,8 +498,12 @@ class App(CTk):
|
||||
voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result)
|
||||
|
||||
if self.checkbox_transcription_send.get() is True:
|
||||
# send OSC message
|
||||
send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT)
|
||||
if self.ENABLE_OSC is True:
|
||||
# send OSC message
|
||||
send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT)
|
||||
else:
|
||||
print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR")
|
||||
print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR")
|
||||
# update textbox message log
|
||||
print_textbox(self.textbox_message_log, f"{voice_message}", "SEND")
|
||||
print_textbox(self.textbox_message_send_log, f"{voice_message}", "SEND")
|
||||
@@ -490,6 +515,7 @@ class App(CTk):
|
||||
print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO")
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_send_stop(self):
|
||||
if isinstance(self.mic_print_transcript, thread_fnc):
|
||||
@@ -500,20 +526,25 @@ class App(CTk):
|
||||
|
||||
print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO")
|
||||
if ((self.checkbox_translation.get() is False) and
|
||||
(self.checkbox_transcription_send.get() is False) and
|
||||
(self.checkbox_transcription_receive.get() is False)):
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_send_stop_for_config(self):
|
||||
if isinstance(self.mic_print_transcript, thread_fnc):
|
||||
self.mic_print_transcript.stop()
|
||||
if self.mic_audio_recorder.stop != None:
|
||||
self.mic_audio_recorder.stop()
|
||||
self.mic_audio_recorder.stop = None
|
||||
|
||||
print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO")
|
||||
|
||||
def checkbox_transcription_send_callback(self):
|
||||
self.checkbox_transcription_send.configure(state="disabled")
|
||||
self.checkbox_transcription_receive.configure(state="disabled")
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
self.update()
|
||||
self.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get()
|
||||
if self.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
if self.checkbox_transcription_send.get() is True:
|
||||
th_transcription_send_start = Thread(target=self.transcription_send_start)
|
||||
th_transcription_send_start.daemon = True
|
||||
th_transcription_send_start.start()
|
||||
@@ -521,60 +552,62 @@ class App(CTk):
|
||||
th_transcription_send_stop = Thread(target=self.transcription_send_stop)
|
||||
th_transcription_send_stop.daemon = True
|
||||
th_transcription_send_stop.start()
|
||||
save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_SEND", self.ENABLE_TRANSCRIPTION_SEND)
|
||||
|
||||
def transcription_receive_start(self):
|
||||
self.spk_audio_queue = Queue()
|
||||
spk_device = [device for device in get_output_device_list() if device["name"] == self.CHOICE_SPEAKER_DEVICE][0]
|
||||
self.spk_audio_recorder = SelectedSpeakerRecorder(
|
||||
spk_device,
|
||||
self.INPUT_SPEAKER_ENERGY_THRESHOLD,
|
||||
self.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
self.INPUT_SPEAKER_RECORD_TIMEOUT,
|
||||
)
|
||||
self.spk_audio_recorder.record_into_queue(self.spk_audio_queue)
|
||||
self.spk_transcriber = AudioTranscriber(
|
||||
speaker=True,
|
||||
source=self.spk_audio_recorder.source,
|
||||
language=transcription_lang[self.INPUT_SPEAKER_VOICE_LANGUAGE],
|
||||
phrase_timeout=self.INPUT_SPEAKER_PHRASE_TIMEOUT,
|
||||
max_phrases=self.INPUT_SPEAKER_MAX_PHRASES,
|
||||
)
|
||||
self.spk_audio_queue = Queue()
|
||||
spk_device = [device for device in get_output_device_list() if device["name"] == self.CHOICE_SPEAKER_DEVICE][0]
|
||||
self.spk_audio_recorder = SelectedSpeakerRecorder(
|
||||
spk_device,
|
||||
self.INPUT_SPEAKER_ENERGY_THRESHOLD,
|
||||
self.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
self.INPUT_SPEAKER_RECORD_TIMEOUT,
|
||||
)
|
||||
self.spk_audio_recorder.record_into_queue(self.spk_audio_queue)
|
||||
self.spk_transcriber = AudioTranscriber(
|
||||
speaker=True,
|
||||
source=self.spk_audio_recorder.source,
|
||||
language=transcription_lang[self.INPUT_SPEAKER_VOICE_LANGUAGE],
|
||||
phrase_timeout=self.INPUT_SPEAKER_PHRASE_TIMEOUT,
|
||||
max_phrases=self.INPUT_SPEAKER_MAX_PHRASES,
|
||||
)
|
||||
|
||||
def spk_transcript_to_textbox():
|
||||
self.spk_transcriber.transcribe_audio_queue(self.spk_audio_queue)
|
||||
message = self.spk_transcriber.get_transcript()
|
||||
if len(message) > 0:
|
||||
# translate
|
||||
if self.checkbox_translation.get() is False:
|
||||
voice_message = f"{message}"
|
||||
elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False:
|
||||
print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
voice_message = f"{message}"
|
||||
else:
|
||||
result = self.translator.translate(
|
||||
translator_name=self.CHOICE_TRANSLATOR,
|
||||
source_language=self.OUTPUT_SOURCE_LANG,
|
||||
target_language=self.OUTPUT_TARGET_LANG,
|
||||
message=message
|
||||
)
|
||||
voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result)
|
||||
# send OSC message
|
||||
# send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT)
|
||||
def spk_transcript_to_textbox():
|
||||
self.spk_transcriber.transcribe_audio_queue(self.spk_audio_queue)
|
||||
message = self.spk_transcriber.get_transcript()
|
||||
if len(message) > 0:
|
||||
# translate
|
||||
if self.checkbox_translation.get() is False:
|
||||
voice_message = f"{message}"
|
||||
elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False:
|
||||
print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
voice_message = f"{message}"
|
||||
else:
|
||||
result = self.translator.translate(
|
||||
translator_name=self.CHOICE_TRANSLATOR,
|
||||
source_language=self.OUTPUT_SOURCE_LANG,
|
||||
target_language=self.OUTPUT_TARGET_LANG,
|
||||
message=message
|
||||
)
|
||||
voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result)
|
||||
# send OSC message
|
||||
# send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT)
|
||||
|
||||
if self.checkbox_transcription_receive.get() is True:
|
||||
# update textbox message receive log
|
||||
print_textbox(self.textbox_message_log, f"{voice_message}", "RECEIVE")
|
||||
print_textbox(self.textbox_message_receive_log, f"{voice_message}", "RECEIVE")
|
||||
if self.checkbox_transcription_receive.get() is True:
|
||||
# update textbox message receive log
|
||||
print_textbox(self.textbox_message_log, f"{voice_message}", "RECEIVE")
|
||||
print_textbox(self.textbox_message_receive_log, f"{voice_message}", "RECEIVE")
|
||||
if self.ENABLE_NOTICE_XSOVERLAY is True:
|
||||
notification_xsoverlay_for_vrct(content=f"{voice_message}")
|
||||
|
||||
self.spk_print_transcript = thread_fnc(spk_transcript_to_textbox)
|
||||
self.spk_print_transcript.daemon = True
|
||||
self.spk_print_transcript.start()
|
||||
print_textbox(self.textbox_message_log, "Start speaker2log", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO")
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.spk_print_transcript = thread_fnc(spk_transcript_to_textbox)
|
||||
self.spk_print_transcript.daemon = True
|
||||
self.spk_print_transcript.start()
|
||||
print_textbox(self.textbox_message_log, "Start speaker2log", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO")
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_receive_stop(self):
|
||||
if isinstance(self.spk_print_transcript, thread_fnc):
|
||||
@@ -585,20 +618,25 @@ class App(CTk):
|
||||
|
||||
print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO")
|
||||
if ((self.checkbox_translation.get() is False) and
|
||||
(self.checkbox_transcription_send.get() is False) and
|
||||
(self.checkbox_transcription_receive.get() is False)):
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_receive_stop_for_config(self):
|
||||
if isinstance(self.spk_print_transcript, thread_fnc):
|
||||
self.spk_print_transcript.stop()
|
||||
if self.spk_audio_recorder.stop != None:
|
||||
self.spk_audio_recorder.stop()
|
||||
self.spk_audio_recorder.stop = None
|
||||
|
||||
print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO")
|
||||
|
||||
def checkbox_transcription_receive_callback(self):
|
||||
self.checkbox_transcription_send.configure(state="disabled")
|
||||
self.checkbox_transcription_receive.configure(state="disabled")
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
self.update()
|
||||
self.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get()
|
||||
if self.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
if self.checkbox_transcription_receive.get() is True:
|
||||
th_transcription_receive_start = Thread(target=self.transcription_receive_start)
|
||||
th_transcription_receive_start.daemon = True
|
||||
th_transcription_receive_start.start()
|
||||
@@ -607,7 +645,26 @@ class App(CTk):
|
||||
th_transcription_receive_stop.daemon = True
|
||||
th_transcription_receive_stop.start()
|
||||
|
||||
save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_RECEIVE", self.ENABLE_TRANSCRIPTION_RECEIVE)
|
||||
def transcription_start(self):
|
||||
if self.checkbox_transcription_send.get() is True:
|
||||
th_transcription_send_start = Thread(target=self.transcription_send_start)
|
||||
th_transcription_send_start.daemon = True
|
||||
th_transcription_send_start.start()
|
||||
sleep(2)
|
||||
if self.checkbox_transcription_receive.get() is True:
|
||||
th_transcription_receive_start = Thread(target=self.transcription_receive_start)
|
||||
th_transcription_receive_start.daemon = True
|
||||
th_transcription_receive_start.start()
|
||||
|
||||
def transcription_stop(self):
|
||||
if self.checkbox_transcription_send.get() is True:
|
||||
th_transcription_send_stop = Thread(target=self.transcription_send_stop_for_config)
|
||||
th_transcription_send_stop.daemon = True
|
||||
th_transcription_send_stop.start()
|
||||
if self.checkbox_transcription_receive.get() is True:
|
||||
th_transcription_receive_stop = Thread(target=self.transcription_receive_stop_for_config)
|
||||
th_transcription_receive_stop.daemon = True
|
||||
th_transcription_receive_stop.start()
|
||||
|
||||
def checkbox_foreground_callback(self):
|
||||
self.ENABLE_FOREGROUND = self.checkbox_foreground.get()
|
||||
@@ -619,7 +676,20 @@ class App(CTk):
|
||||
self.attributes("-topmost", False)
|
||||
print_textbox(self.textbox_message_log, "Stop foreground", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO")
|
||||
save_json(self.PATH_CONFIG, "ENABLE_FOREGROUND", self.ENABLE_FOREGROUND)
|
||||
|
||||
def foreground_start(self):
|
||||
self.ENABLE_FOREGROUND = self.checkbox_foreground.get()
|
||||
if self.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", True)
|
||||
print_textbox(self.textbox_message_log, "Start foreground", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start foreground", "INFO")
|
||||
|
||||
def foreground_stop(self):
|
||||
if self.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", False)
|
||||
print_textbox(self.textbox_message_log, "Stop foreground", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO")
|
||||
self.ENABLE_FOREGROUND = False
|
||||
|
||||
def entry_message_box_press_key_enter(self, event):
|
||||
# send OSC typing
|
||||
@@ -647,14 +717,18 @@ class App(CTk):
|
||||
chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result)
|
||||
|
||||
# send OSC message
|
||||
send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT)
|
||||
if self.ENABLE_OSC is True:
|
||||
send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT)
|
||||
else:
|
||||
print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR")
|
||||
print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR")
|
||||
|
||||
# update textbox message log
|
||||
print_textbox(self.textbox_message_log, f"{chat_message}", "SEND")
|
||||
print_textbox(self.textbox_message_send_log, f"{chat_message}", "SEND")
|
||||
|
||||
# delete message in entry message box
|
||||
if self.ENABLE_AUTO_CLEAR_CHATBOX == True:
|
||||
if self.ENABLE_AUTO_CLEAR_CHATBOX is True:
|
||||
self.entry_message_box.delete(0, customtkinter.END)
|
||||
|
||||
BREAK_KEYSYM_LIST = [
|
||||
@@ -747,6 +821,11 @@ class App(CTk):
|
||||
|
||||
widget_main_window_label_setter(self, language_yaml_data)
|
||||
|
||||
def check_osc_receive(self, address, osc_arguments):
|
||||
if self.ENABLE_OSC is False:
|
||||
self.ENABLE_OSC = True
|
||||
# print(address, osc_arguments)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
app = App()
|
||||
|
||||
BIN
docs/vrct_logo.png
Normal file
BIN
docs/vrct_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
img/xsoverlay.png
Normal file
BIN
img/xsoverlay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
4
install.bat
Normal file
4
install.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
pip install -r requirements.txt
|
||||
pip install git+https://github.com/misyaguziya/translators
|
||||
pip install git+https://github.com/misyaguziya/deepl-translate
|
||||
pip install git+https://github.com/misyaguziya/custom_speech_recognition
|
||||
244
languages.py
244
languages.py
@@ -1,100 +1,101 @@
|
||||
transcription_lang = {
|
||||
"Japanese Japan":"ja-JP",
|
||||
"English United States":"en-US",
|
||||
"English United Kingdom":"en-GB",
|
||||
"Afrikaans South Africa":"af-ZA",
|
||||
"Arabic Algeria":"ar-DZ",
|
||||
"Arabic Bahrain":"ar-BH",
|
||||
"Arabic Egypt":"ar-EG",
|
||||
"Arabic Israel":"ar-IL",
|
||||
"Arabic Iraq":"ar-IQ",
|
||||
"Arabic Jordan":"ar-JO",
|
||||
"Arabic Kuwait":"ar-KW",
|
||||
"Arabic Lebanon":"ar-LB",
|
||||
"Arabic Morocco":"ar-MA",
|
||||
"Arabic Oman":"ar-OM",
|
||||
"Arabic Palestinian Territory":"ar-PS",
|
||||
"Arabic Qatar":"ar-QA",
|
||||
"Arabic Saudi Arabia":"ar-SA",
|
||||
"Arabic Tunisia":"ar-TN",
|
||||
"Arabic UAE":"ar-AE",
|
||||
"Euskara Spain":"eu-ES",
|
||||
"Bulgarian Bulgaria":"bg-BG",
|
||||
"Catalan Spain":"ca-ES",
|
||||
"Mongolian China (Simp.)":"cmn-Hans-CN",
|
||||
"Mongolian Hong Kong SAR (Trad.)":"cmn-Hans-HK",
|
||||
"Mongolian Taiwan (Trad.)":"cmn-Hant-TW",
|
||||
"Cantonese Hong Kong":"yue-Hant-HK",
|
||||
"Hrvatska Croatia":"hr_HR",
|
||||
"Czech Republic":"cs-CZ",
|
||||
"Danish Denmark":"da-DK",
|
||||
"English Australia":"en-AU",
|
||||
"English Canada":"en-CA",
|
||||
"English India":"en-IN",
|
||||
"English Ireland":"en-IE",
|
||||
"English New Zealand":"en-NZ",
|
||||
"English Philippines":"en-PH",
|
||||
"English South Africa":"en-ZA",
|
||||
"Persian Iran":"fa-IR",
|
||||
"French France":"fr-FR",
|
||||
"Filipino Philippines":"fil-PH",
|
||||
"Galician Spain":"gl-ES",
|
||||
"German Germany":"de-DE",
|
||||
"Greek Greece":"el-GR",
|
||||
"Finnish Finland":"fi-FI",
|
||||
"Hebrew Israel":"he-IL",
|
||||
"Hindi India":"hi-IN",
|
||||
"Hungarian Hungary":"hu-HU",
|
||||
"Indonesian Indonesia":"id-ID",
|
||||
"Icelandic Iceland":"is-IS",
|
||||
"Italian Italy":"it-IT",
|
||||
"Italian Switzerland":"it-CH",
|
||||
"Korean Korea":"ko-KR",
|
||||
"Lithuanian Lithuania":"lt-LT",
|
||||
"Malay Malaysia":"ms-MY",
|
||||
"Nederlands Netherlands":"nl-NL",
|
||||
"Bokmål Norway":"nb-NO",
|
||||
"Polski Poland":"pl-PL",
|
||||
"Português Brazil":"pt-BR",
|
||||
"Português Portugal":"pt-PT",
|
||||
"limba română Romania":"ro-RO",
|
||||
"Russian Russia":"ru-RU",
|
||||
"Serbian Serbia":"sr-RS",
|
||||
"Slovak Slovakia":"sk-SK",
|
||||
"Slovenian Slovenia":"sl-SI",
|
||||
"Spanish Argentina":"es-AR",
|
||||
"Spanish Bolivia":"es-BO",
|
||||
"Spanish Chile":"es-CL",
|
||||
"Spanish Colombia":"es-CO",
|
||||
"Spanish Costa Rica":"es-CR",
|
||||
"Spanish Dominican Republic":"es-DO",
|
||||
"Spanish Ecuador":"es-EC",
|
||||
"Spanish El Salvador":"es-SV",
|
||||
"Spanish Guatemala":"es-GT",
|
||||
"Spanish Honduras":"es-HN",
|
||||
"Spanish México":"es-MX",
|
||||
"Spanish Nicaragua":"es-NI",
|
||||
"Spanish Panamá":"es-PA",
|
||||
"Spanish Paraguay":"es-PY",
|
||||
"Spanish Perú":"es-PE",
|
||||
"Spanish Puerto Rico":"es-PR",
|
||||
"Spanish Spain":"es-ES",
|
||||
"Spanish Uruguay":"es-UY",
|
||||
"Spanish United States":"es-US",
|
||||
"Spanish Venezuela":"es-VE",
|
||||
"Swedish Sweden":"sv-SE",
|
||||
"Thai Thailand":"th-TH",
|
||||
"Turkish Turkey":"tr-TR",
|
||||
"Ukrainian Ukraine":"uk-UA",
|
||||
"Vietnamese Viet Nam":"vi-VN",
|
||||
"Zulu South Africa":"zu-ZA"
|
||||
"Japanese (Japan)":"ja-JP",
|
||||
"English (United States)":"en-US",
|
||||
"English (United Kingdom)":"en-GB",
|
||||
"Afrikaans (South Africa)":"af-ZA",
|
||||
"Arabic (Algeria)":"ar-DZ",
|
||||
"Arabic (Bahrain)":"ar-BH",
|
||||
"Arabic (Egypt)":"ar-EG",
|
||||
"Arabic (Israel)":"ar-IL",
|
||||
"Arabic (Iraq)":"ar-IQ",
|
||||
"Arabic (Jordan)":"ar-JO",
|
||||
"Arabic (Kuwait)":"ar-KW",
|
||||
"Arabic (Lebanon)":"ar-LB",
|
||||
"Arabic (Morocco)":"ar-MA",
|
||||
"Arabic (Oman)":"ar-OM",
|
||||
"Arabic (State of Palestine)":"ar-PS",
|
||||
"Arabic (Qatar)":"ar-QA",
|
||||
"Arabic (Saudi Arabia)":"ar-SA",
|
||||
"Arabic (Tunisia)":"ar-TN",
|
||||
"Arabic (United Arab Emirates)":"ar-AE",
|
||||
"Basque (Spain)":"eu-ES",
|
||||
"Bulgarian (Bulgaria)":"bg-BG",
|
||||
"Catalan (Spain)":"ca-ES",
|
||||
"Chinese, Mandarin (Simplified, China)":"cmn-Hans-CN",
|
||||
"Chinese, Mandarin (Simplified, Hong Kong)":"cmn-Hans-HK",
|
||||
"Chinese, Mandarin (Traditional, Taiwan)":"cmn-Hant-TW",
|
||||
"Chinese, Cantonese (Traditional Hong Kong)":"yue-Hant-HK",
|
||||
"Croatian (Croatia)":"hr-HR",
|
||||
"Czech (Czech Republic)":"cs-CZ",
|
||||
"Danish (Denmark)":"da-DK",
|
||||
"English (Australia)":"en-AU",
|
||||
"English (Canada)":"en-CA",
|
||||
"English (India)":"en-IN",
|
||||
"English (Ireland)":"en-IE",
|
||||
"English (New Zealand)":"en-NZ",
|
||||
"English (Philippines)":"en-PH",
|
||||
"English (South Africa)":"en-ZA",
|
||||
"Persian (Iran)":"fa-IR",
|
||||
"French (France)":"fr-FR",
|
||||
"Filipino (Philippines)":"fil-PH",
|
||||
"Galician (Spain)":"gl-ES",
|
||||
"German (Germany)":"de-DE",
|
||||
"Greek (Greece)":"el-GR",
|
||||
"Finnish (Finland)":"fi-FI",
|
||||
"Hebrew (Israel)":"he-IL",
|
||||
"Hindi (India)":"hi-IN",
|
||||
"Hungarian (Hungary)":"hu-HU",
|
||||
"Indonesian (Indonesia)":"id-ID",
|
||||
"Icelandic (Iceland)":"is-IS",
|
||||
"Italian (Italy)":"it-IT",
|
||||
"Italian (Switzerland)":"it-CH",
|
||||
"Korean (South Korea)":"ko-KR",
|
||||
"Lithuanian (Lithuania)":"lt-LT",
|
||||
"Malay (Malaysia)":"ms-MY",
|
||||
"Dutch (Netherlands)":"nl-NL",
|
||||
"Norwegian Bokmål (Norway)":"nb-NO",
|
||||
"Polish (Poland)":"pl-PL",
|
||||
"Portuguese (Brazil)":"pt-BR",
|
||||
"Portuguese (Portugal)":"pt-PT",
|
||||
"Romanian (Romania)":"ro-RO",
|
||||
"Russian (Russia)":"ru-RU",
|
||||
"Serbian (Serbia)":"sr-RS",
|
||||
"Slovak (Slovakia)":"sk-SK",
|
||||
"Slovenian (Slovenia)":"sl-SI",
|
||||
"Spanish (Argentina)":"es-AR",
|
||||
"Spanish (Bolivia)":"es-BO",
|
||||
"Spanish (Chile)":"es-CL",
|
||||
"Spanish (Colombia)":"es-CO",
|
||||
"Spanish (Costa Rica)":"es-CR",
|
||||
"Spanish (Dominican Republic)":"es-DO",
|
||||
"Spanish (Ecuador)":"es-EC",
|
||||
"Spanish (El Salvador)":"es-SV",
|
||||
"Spanish (Guatemala)":"es-GT",
|
||||
"Spanish (Honduras)":"es-HN",
|
||||
"Spanish (Mexico)":"es-MX",
|
||||
"Spanish (Nicaragua)":"es-NI",
|
||||
"Spanish (Panama)":"es-PA",
|
||||
"Spanish (Paraguay)":"es-PY",
|
||||
"Spanish (Peru)":"es-PE",
|
||||
"Spanish (Puerto Rico)":"es-PR",
|
||||
"Spanish (Spain)":"es-ES",
|
||||
"Spanish (Uruguay)":"es-UY",
|
||||
"Spanish (United States)":"es-US",
|
||||
"Spanish (Venezuela)":"es-VE",
|
||||
"Swedish (Sweden)":"sv-SE",
|
||||
"Thai (Thailand)":"th-TH",
|
||||
"Turkish (Turkey)":"tr-TR",
|
||||
"Ukrainian (Ukraine)":"uk-UA",
|
||||
"Vietnamese (Vietnam)":"vi-VN",
|
||||
"Zulu (South Africa)":"zu-ZA"
|
||||
}
|
||||
|
||||
translators = ["DeepL(web)", "DeepL(auth)", "Google(web)", "Bing(web)"]
|
||||
translation_lang = {}
|
||||
translation_lang["DeepL(web)"] = {
|
||||
dict_deepl_web_languages = {
|
||||
"Japanese":"JA",
|
||||
"English":"EN",
|
||||
"Korean":"KO",
|
||||
"Bulgarian":"BG",
|
||||
"Chinese":"ZH",
|
||||
"Czech":"CS",
|
||||
@@ -116,9 +117,49 @@ translation_lang["DeepL(web)"] = {
|
||||
"Slovak":"SK",
|
||||
"Slovenian":"SL",
|
||||
"Spanish":"ES",
|
||||
"Swedish":"SV"
|
||||
"Swedish":"SV",
|
||||
"Indonesian":"ID",
|
||||
"Ukrainian":"UK",
|
||||
"Turkish":"TR",
|
||||
"Norwegian":"NB",
|
||||
}
|
||||
translation_lang["DeepL(auth)"] = {
|
||||
translation_lang["DeepL(web)"] = {
|
||||
"source":dict_deepl_web_languages,
|
||||
"target":dict_deepl_web_languages,
|
||||
}
|
||||
|
||||
dict_deepl_auth_source_languages = {
|
||||
"Japanese":"ja",
|
||||
"English":"en",
|
||||
"Bulgarian":"bg",
|
||||
"Czech":"cs",
|
||||
"Danish":"da",
|
||||
"German":"de",
|
||||
"Greek":"el",
|
||||
"Spanish":"es",
|
||||
"Estonian":"et",
|
||||
"Finnish":"fi",
|
||||
"French":"fr",
|
||||
"Hungarian":"hu",
|
||||
"Indonesian":"id",
|
||||
"Italian":"it",
|
||||
"Korean":"ko",
|
||||
"Lithuanian":"lt",
|
||||
"Latvian":"lv",
|
||||
"Norwegian":"nb",
|
||||
"Dutch":"nl",
|
||||
"Polish":"pl",
|
||||
"Portuguese":"pt",
|
||||
"Romanian":"ro",
|
||||
"Russian":"ru",
|
||||
"Slovak":"sk",
|
||||
"Slovenian":"sl",
|
||||
"Swedish":"sv",
|
||||
"Turkish":"tr",
|
||||
"Ukrainian":"uk",
|
||||
"Chinese":"zh"
|
||||
}
|
||||
dict_deepl_auth_target_languages = {
|
||||
"Japanese":"ja",
|
||||
"English American":"en-US",
|
||||
"English British":"en-GB",
|
||||
@@ -141,7 +182,6 @@ translation_lang["DeepL(auth)"] = {
|
||||
"Norwegian":"nb",
|
||||
"Dutch":"nl",
|
||||
"Polish":"pl",
|
||||
"Portuguese":"pt",
|
||||
"Portuguese Brazilian":"pt-BR",
|
||||
"Portuguese European":"pt-PT",
|
||||
"Romanian":"ro",
|
||||
@@ -153,7 +193,12 @@ translation_lang["DeepL(auth)"] = {
|
||||
"Ukrainian":"uk",
|
||||
"Chinese":"zh"
|
||||
}
|
||||
translation_lang["Google(web)"] = {
|
||||
translation_lang["DeepL(auth)"] = {
|
||||
"source": dict_deepl_auth_source_languages,
|
||||
"target": dict_deepl_auth_target_languages,
|
||||
}
|
||||
|
||||
dict_google_web_languages = {
|
||||
"Japanese":"ja",
|
||||
"English":"en",
|
||||
"Chinese":"zh",
|
||||
@@ -217,7 +262,12 @@ translation_lang["Google(web)"] = {
|
||||
"Basque":"eu",
|
||||
"Irish":"ga"
|
||||
}
|
||||
translation_lang["Bing(web)"] = {
|
||||
translation_lang["Google(web)"] = {
|
||||
"source":dict_google_web_languages,
|
||||
"target":dict_google_web_languages,
|
||||
}
|
||||
|
||||
dict_bing_web_languages = {
|
||||
"Japanese":"ja",
|
||||
"English":"en",
|
||||
"Chinese":"zh",
|
||||
@@ -279,6 +329,10 @@ translation_lang["Bing(web)"] = {
|
||||
"Punjabi":"pa",
|
||||
"Irish":"ga"
|
||||
}
|
||||
translation_lang["Bing(web)"] = {
|
||||
"source":dict_bing_web_languages,
|
||||
"target":dict_bing_web_languages,
|
||||
}
|
||||
|
||||
selectable_languages = {
|
||||
"en": "English",
|
||||
|
||||
@@ -60,6 +60,7 @@ en:
|
||||
|
||||
# tab Others
|
||||
label_checkbox_auto_clear_chatbox: "Auto clear chat box"
|
||||
label_checkbox_notice_xsoverlay: "Notification XSOverlay"
|
||||
|
||||
|
||||
ja:
|
||||
@@ -125,6 +126,7 @@ ja:
|
||||
|
||||
# tab Others
|
||||
label_checkbox_auto_clear_chatbox: "送信後はチャットボックスを空にする"
|
||||
label_checkbox_notice_xsoverlay: "XSOverlayの通知機能を有効"
|
||||
|
||||
|
||||
ko:
|
||||
|
||||
72
notification.py
Normal file
72
notification.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# ###########################################################################################################################
|
||||
# DOCUMENT:https://xiexe.github.io/XSOverlayDocumentation/#/NotificationsAPI
|
||||
# SOURCE:https://zenn.dev/eeharumt/scraps/95f49a62dd809a
|
||||
# messageType: int = 0 # 1: ポップアップ通知, 2: メディアプレーヤー情報
|
||||
# index: int = 0 # メディアプレーヤーでのみ使用され、手首のアイコンを変更する
|
||||
# timeout: float = 0.5 # 通知インジケータが表示され続ける時間[秒]
|
||||
# height: float = 175 # 通知インジケータの高さ
|
||||
# opacity: float = 1 # 通知インジケータの透明度。0.0-1.0の範囲で低いほど透明に
|
||||
# volume: float = 0.7 # 通知音の大きさ
|
||||
# audioPath: str = "" # 通知音ファイルのパス。規定音として"default", "error", "warning"を指定可能。空文字列で通知音なしにできる。
|
||||
# title: str = "" # 通知タイトル、リッチテキストフォーマットをサポート。
|
||||
# content: str = "" # 通知内容、リッチテキストフォーマットをサポート。省略することで小サイズ通知となる。
|
||||
# useBase64Icon: bool = False # TrueにすることでBase64の画像を表示する
|
||||
# icon: str = "" # Base64画像イメージまたは画像ファイルパス。規定アイコンとして"default", "error", or "warning"を指定可能
|
||||
# sourceApp: str = "" # 通知したアプリ名(デバック用)
|
||||
# ##########################################################################################################################
|
||||
|
||||
import socket
|
||||
import json
|
||||
import base64
|
||||
|
||||
def notification_xsoverlay(
|
||||
endpoint:tuple=("127.0.0.1", 42069), messageType:int=1, index:int=0, timeout:float=2,
|
||||
height:float=120.0, opacity:float=1.0, volume:float=0.0, audioPath:str="",
|
||||
title:str="", content:str="", useBase64Icon:bool=False, icon:str="default", sourceApp:str=""
|
||||
) -> int:
|
||||
|
||||
if icon in ["default", "error", "warning"]:
|
||||
icon_data = icon
|
||||
elif useBase64Icon:
|
||||
try:
|
||||
with open(icon, "rb") as f:
|
||||
icon_data_bytes = f.read()
|
||||
icon_data = base64.b64encode(icon_data_bytes).decode("utf-8")
|
||||
except:
|
||||
icon_data = "default"
|
||||
else:
|
||||
icon_data = icon
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
data_msg = {
|
||||
"messageType": messageType,
|
||||
"index": index,
|
||||
"timeout":timeout,
|
||||
"height": height,
|
||||
"opacity": opacity,
|
||||
"volume": volume,
|
||||
"audioPath": audioPath,
|
||||
"title": title,
|
||||
"content": content,
|
||||
"useBase64Icon": useBase64Icon,
|
||||
"icon": icon_data,
|
||||
"sourceApp": sourceApp,
|
||||
}
|
||||
msg_str = json.dumps(data_msg)
|
||||
response = sock.sendto(msg_str.encode("utf-8"), endpoint)
|
||||
sock.close()
|
||||
return response
|
||||
|
||||
def notification_xsoverlay_for_vrct(content:str="") -> int:
|
||||
response = notification_xsoverlay(
|
||||
title="VRCT",
|
||||
content=content,
|
||||
useBase64Icon=True,
|
||||
icon="./img/xsoverlay.png",
|
||||
sourceApp="VRCT"
|
||||
)
|
||||
return response
|
||||
|
||||
if __name__ == "__main__":
|
||||
notification_xsoverlay_for_vrct(content="notification test")
|
||||
18
osc_tools.py
18
osc_tools.py
@@ -1,5 +1,9 @@
|
||||
from time import sleep
|
||||
from typing import List
|
||||
from pythonosc import osc_message_builder
|
||||
from pythonosc import udp_client
|
||||
from pythonosc import dispatcher
|
||||
from pythonosc import osc_server
|
||||
|
||||
# send OSC message typing
|
||||
def send_typing(flag=False, ip_address="127.0.0.1", port=9000):
|
||||
@@ -18,4 +22,16 @@ def send_message(message=None, ip_address="127.0.0.1", port=9000):
|
||||
msg.add_arg(True)
|
||||
b_msg = msg.build()
|
||||
client = udp_client.SimpleUDPClient(ip_address, port)
|
||||
client.send(b_msg)
|
||||
client.send(b_msg)
|
||||
|
||||
def send_test_action(ip_address="127.0.0.1", port=9000):
|
||||
client = udp_client.SimpleUDPClient(ip_address, port)
|
||||
client.send_message("/input/Vertical", 1)
|
||||
sleep(0.01)
|
||||
client.send_message("/input/Vertical", False)
|
||||
|
||||
def receive_osc_parameters(target, filter="/*", ip_address="127.0.0.1", port=9001):
|
||||
_dispatcher = dispatcher.Dispatcher()
|
||||
_dispatcher.map(filter, target)
|
||||
server = osc_server.ThreadingOSCUDPServer((ip_address, port), _dispatcher)
|
||||
server.serve_forever()
|
||||
@@ -35,8 +35,8 @@ class Translator():
|
||||
def translate(self, translator_name, source_language, target_language, message):
|
||||
result = ""
|
||||
try:
|
||||
source_language=translation_lang[translator_name][source_language]
|
||||
target_language=translation_lang[translator_name][target_language]
|
||||
source_language=translation_lang[translator_name]["source"][source_language]
|
||||
target_language=translation_lang[translator_name]["target"][target_language]
|
||||
if translator_name == "DeepL(web)":
|
||||
result = deepl_web_Translator(
|
||||
source_language=source_language,
|
||||
|
||||
6
utils.py
6
utils.py
@@ -100,15 +100,15 @@ def widget_config_window_label_setter(self, language_yaml_data):
|
||||
"label_input_speaker_phrase_timeout",
|
||||
"label_input_speaker_max_phrases",
|
||||
|
||||
|
||||
# tab Parameter
|
||||
"label_ip_address",
|
||||
"label_port",
|
||||
"label_authkey",
|
||||
"label_message_format",
|
||||
|
||||
|
||||
# tab Others
|
||||
"label_checkbox_auto_clear_chatbox"
|
||||
"label_checkbox_auto_clear_chatbox",
|
||||
"label_checkbox_notice_xsoverlay",
|
||||
]
|
||||
for name in widget_names:
|
||||
widget = getattr(self, name)
|
||||
|
||||
@@ -212,33 +212,33 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
print_textbox(self.parent.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
else:
|
||||
self.optionmenu_translation_input_source_language.configure(
|
||||
values=list(translation_lang[choice].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice].keys())[0]))
|
||||
values=list(translation_lang[choice]["source"].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice]["source"].keys())[0]))
|
||||
self.optionmenu_translation_input_target_language.configure(
|
||||
values=list(translation_lang[choice].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice].keys())[1]))
|
||||
values=list(translation_lang[choice]["target"].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice]["target"].keys())[1]))
|
||||
self.optionmenu_translation_output_source_language.configure(
|
||||
values=list(translation_lang[choice].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice].keys())[1]))
|
||||
values=list(translation_lang[choice]["source"].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice]["source"].keys())[1]))
|
||||
self.optionmenu_translation_output_target_language.configure(
|
||||
values=list(translation_lang[choice].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice].keys())[0]))
|
||||
values=list(translation_lang[choice]["target"].keys()),
|
||||
variable=StringVar(value=list(translation_lang[choice]["target"].keys())[0]))
|
||||
|
||||
if SCROLLABLE_DROPDOWN:
|
||||
self.scrollableDropdown_translation_input_source_language.configure(
|
||||
values=list(translation_lang[choice].keys()))
|
||||
values=list(translation_lang[choice]["source"].keys()))
|
||||
self.scrollableDropdown_translation_input_target_language.configure(
|
||||
values=list(translation_lang[choice].keys()))
|
||||
values=list(translation_lang[choice]["target"].keys()))
|
||||
self.scrollableDropdown_translation_output_source_language.configure(
|
||||
values=list(translation_lang[choice].keys()))
|
||||
values=list(translation_lang[choice]["source"].keys()))
|
||||
self.scrollableDropdown_translation_output_target_language.configure(
|
||||
values=list(translation_lang[choice].keys()))
|
||||
values=list(translation_lang[choice]["target"].keys()))
|
||||
|
||||
self.parent.CHOICE_TRANSLATOR = choice
|
||||
self.parent.INPUT_SOURCE_LANG = list(translation_lang[choice].keys())[0]
|
||||
self.parent.INPUT_TARGET_LANG = list(translation_lang[choice].keys())[1]
|
||||
self.parent.OUTPUT_SOURCE_LANG = list(translation_lang[choice].keys())[1]
|
||||
self.parent.OUTPUT_TARGET_LANG = list(translation_lang[choice].keys())[0]
|
||||
self.parent.INPUT_SOURCE_LANG = list(translation_lang[choice]["source"].keys())[0]
|
||||
self.parent.INPUT_TARGET_LANG = list(translation_lang[choice]["target"].keys())[1]
|
||||
self.parent.OUTPUT_SOURCE_LANG = list(translation_lang[choice]["source"].keys())[1]
|
||||
self.parent.OUTPUT_TARGET_LANG = list(translation_lang[choice]["target"].keys())[0]
|
||||
save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR)
|
||||
save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG)
|
||||
save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG)
|
||||
@@ -492,17 +492,32 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
self.parent.ENABLE_AUTO_CLEAR_CHATBOX = value
|
||||
save_json(self.parent.PATH_CONFIG, "ENABLE_AUTO_CLEAR_CHATBOX", self.parent.ENABLE_AUTO_CLEAR_CHATBOX)
|
||||
|
||||
def checkbox_notice_xsoverlay_callback(self):
|
||||
value = self.checkbox_notice_xsoverlay.get()
|
||||
self.parent.ENABLE_NOTICE_XSOVERLAY = value
|
||||
save_json(self.parent.PATH_CONFIG, "ENABLE_NOTICE_XSOVERLAY", self.parent.ENABLE_NOTICE_XSOVERLAY)
|
||||
|
||||
def delete_window(self):
|
||||
self.checkbox_input_mic_threshold_check.deselect()
|
||||
self.checkbox_input_speaker_threshold_check.deselect()
|
||||
self.checkbox_input_mic_threshold_check_callback()
|
||||
self.checkbox_input_speaker_threshold_check_callback()
|
||||
|
||||
self.parent.transcription_start()
|
||||
self.parent.foreground_start()
|
||||
self.parent.checkbox_translation.configure(state="normal")
|
||||
self.parent.checkbox_transcription_send.configure(state="normal")
|
||||
self.parent.checkbox_transcription_receive.configure(state="normal")
|
||||
self.parent.checkbox_foreground.configure(state="normal")
|
||||
self.parent.tabview_logs.configure(state="normal")
|
||||
self.parent.textbox_message_log.configure(state="normal")
|
||||
self.parent.textbox_message_send_log.configure(state="normal")
|
||||
self.parent.textbox_message_receive_log.configure(state="normal")
|
||||
self.parent.textbox_message_system_log.configure(state="normal")
|
||||
self.parent.entry_message_box.configure(state="normal")
|
||||
self.parent.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
self.parent.config_window.withdraw()
|
||||
self.parent.button_information.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
self.withdraw()
|
||||
self.grab_release()
|
||||
|
||||
def entry_message_format_callback(self, event):
|
||||
value = self.entry_message_format.get()
|
||||
@@ -752,7 +767,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
self.optionmenu_translation_input_source_language = CTkOptionMenu(
|
||||
self.tabview_config.tab(config_tab_title_translation),
|
||||
command=self.optionmenu_translation_input_source_language_callback,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["source"].keys()),
|
||||
variable=StringVar(value=self.parent.INPUT_SOURCE_LANG),
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
dropdown_font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
@@ -763,7 +778,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
if SCROLLABLE_DROPDOWN:
|
||||
self.scrollableDropdown_translation_input_source_language = CTkScrollableDropdown(
|
||||
self.optionmenu_translation_input_source_language,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["source"].keys()),
|
||||
justify="left",
|
||||
button_color="transparent",
|
||||
command=self.optionmenu_translation_input_source_language_callback,
|
||||
@@ -787,7 +802,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
self.optionmenu_translation_input_target_language = CTkOptionMenu(
|
||||
self.tabview_config.tab(config_tab_title_translation),
|
||||
command=self.optionmenu_translation_input_target_language_callback,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["target"].keys()),
|
||||
variable=StringVar(value=self.parent.INPUT_TARGET_LANG),
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
dropdown_font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
@@ -798,7 +813,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
if SCROLLABLE_DROPDOWN:
|
||||
self.scrollableDropdown_translation_input_target_language = CTkScrollableDropdown(
|
||||
self.optionmenu_translation_input_target_language,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["target"].keys()),
|
||||
justify="left",
|
||||
button_color="transparent",
|
||||
command=self.optionmenu_translation_input_target_language_callback,
|
||||
@@ -823,7 +838,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
self.optionmenu_translation_output_source_language = CTkOptionMenu(
|
||||
self.tabview_config.tab(config_tab_title_translation),
|
||||
command=self.optionmenu_translation_output_source_language_callback,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["source"].keys()),
|
||||
variable=StringVar(value=self.parent.OUTPUT_SOURCE_LANG),
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
dropdown_font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
@@ -834,7 +849,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
if SCROLLABLE_DROPDOWN:
|
||||
self.scrollableDropdown_translation_output_source_language = CTkScrollableDropdown(
|
||||
self.optionmenu_translation_output_source_language,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["source"].keys()),
|
||||
justify="left",
|
||||
button_color="transparent",
|
||||
command=self.optionmenu_translation_output_source_language_callback,
|
||||
@@ -858,7 +873,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
self.optionmenu_translation_output_target_language = CTkOptionMenu(
|
||||
self.tabview_config.tab(config_tab_title_translation),
|
||||
command=self.optionmenu_translation_output_target_language_callback,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["target"].keys()),
|
||||
variable=StringVar(value=self.parent.OUTPUT_TARGET_LANG),
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
dropdown_font=CTkFont(family=self.parent.FONT_FAMILY),
|
||||
@@ -869,7 +884,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
if SCROLLABLE_DROPDOWN:
|
||||
self.scrollableDropdown_translation_output_target_language = CTkScrollableDropdown(
|
||||
self.optionmenu_translation_output_target_language,
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR].keys()),
|
||||
values=list(translation_lang[self.parent.CHOICE_TRANSLATOR]["target"].keys()),
|
||||
justify="left",
|
||||
button_color="transparent",
|
||||
command=self.optionmenu_translation_output_target_language_callback,
|
||||
@@ -1381,7 +1396,7 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
|
||||
# tab Others
|
||||
## checkbox auto clear chat box
|
||||
row += 1
|
||||
row = 0
|
||||
self.label_checkbox_auto_clear_chatbox = CTkLabel(
|
||||
self.tabview_config.tab(config_tab_title_others),
|
||||
text=init_lang_text,
|
||||
@@ -1403,4 +1418,26 @@ class ToplevelWindowConfig(CTkToplevel):
|
||||
else:
|
||||
self.checkbox_auto_clear_chatbox.deselect()
|
||||
|
||||
# checkbox notice xsoverlay
|
||||
row += 1
|
||||
self.label_checkbox_notice_xsoverlay = CTkLabel(
|
||||
self.tabview_config.tab(config_tab_title_others),
|
||||
text=init_lang_text,
|
||||
fg_color="transparent",
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY)
|
||||
)
|
||||
self.label_checkbox_notice_xsoverlay.grid(row=row, column=0, columnspan=1, padx=padx, pady=pady, sticky="nsw")
|
||||
self.checkbox_notice_xsoverlay = CTkCheckBox(
|
||||
self.tabview_config.tab(config_tab_title_others),
|
||||
text="",
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=self.checkbox_notice_xsoverlay_callback,
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY)
|
||||
)
|
||||
self.checkbox_notice_xsoverlay.grid(row=row, column=1, columnspan=1, padx=padx, pady=pady, sticky="nsew")
|
||||
if self.parent.ENABLE_NOTICE_XSOVERLAY is True:
|
||||
self.checkbox_notice_xsoverlay.select()
|
||||
else:
|
||||
self.checkbox_notice_xsoverlay.deselect()
|
||||
widget_config_window_label_setter(self, language_yaml_data)
|
||||
@@ -4,6 +4,7 @@ from customtkinter import CTkToplevel, CTkTextbox, CTkFont
|
||||
class ToplevelWindowInformation(CTkToplevel):
|
||||
def __init__(self, parent, *args, **kwargs):
|
||||
super().__init__(parent, *args, **kwargs)
|
||||
self.withdraw()
|
||||
self.parent = parent
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
@@ -18,7 +19,7 @@ class ToplevelWindowInformation(CTkToplevel):
|
||||
font=CTkFont(family=self.parent.FONT_FAMILY)
|
||||
)
|
||||
self.textbox_information.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="nsew")
|
||||
textbox_information_message = """VRCT(v1.3.1)
|
||||
textbox_information_message = """VRCT(v1.3.2)
|
||||
|
||||
# 概要
|
||||
VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツールになります。
|
||||
@@ -61,26 +62,26 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ
|
||||
Appearance Theme: ウィンドウテーマを選択
|
||||
UI Scaling: UIサイズを調整
|
||||
Font Family: 表示フォントを選択
|
||||
(New!) UI Language: UIの表示言語を選択
|
||||
UI Language: UIの表示言語を選択
|
||||
Translationタブ
|
||||
Select Translator: 翻訳エンジンの変更
|
||||
Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択
|
||||
Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択
|
||||
Transcriptionタブ
|
||||
(New!) Input Mic Host: マイクのホストAPIを選択
|
||||
Input Mic Host: マイクのホストAPIを選択
|
||||
Input Mic Device: マイクを選択
|
||||
Input Mic Voice Language: 入力する音声の言語
|
||||
Input Mic Energy Threshold: 音声取得のしきい値
|
||||
(New!) Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
Input Mic Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
Input Mic Record Timeout: 音声の区切りの無音時間
|
||||
Input Mic Phase Timeout: 文字起こしする音声時間の上限
|
||||
Input Mic Max Phrases: 保留する単語の上限
|
||||
(New!) Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
Input Speaker Device: スピーカーを選択
|
||||
Input Speaker Voice Language: 受信する音声の言語
|
||||
Input Speaker Energy Threshold: 音声取得のしきい値
|
||||
(New!) Check threshold point: (New!)Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
Check threshold point: Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
Input Speaker Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
Input Speaker Record Timeout: 音声の区切りの無音時間
|
||||
Input Speaker Phase Timeout: 文字起こしする音声時間の上限
|
||||
@@ -94,7 +95,8 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ
|
||||
[translation]が翻訳されたメッセージに置換される
|
||||
初期フォーマット:"[message]([translation])"
|
||||
Othersタブ
|
||||
(New!) Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
(New!) Notification XSOverlay: XSOverlayの通知機能を有効(VR only)
|
||||
|
||||
設定の初期化
|
||||
config.jsonを削除
|
||||
@@ -140,10 +142,19 @@ https://twitter.com/misya_ai
|
||||
- 半角入力時に一部の文字が書き込めないバグを修正
|
||||
[2023-07-22: v1.3.1]
|
||||
- UIの表示言語選択に韓国語を追加
|
||||
[2023-07-30: v1.3.2]
|
||||
- 試験的にXSOverlayへの通知機能を追加
|
||||
- checkbox ONの状態でもConfigを開けるように変更
|
||||
- 文字起こし言語の表示を修正
|
||||
- いくつかのバグを修正
|
||||
|
||||
# 注意事項
|
||||
再配布とかはやめてね
|
||||
"""
|
||||
|
||||
self.textbox_information.insert("end", textbox_information_message)
|
||||
self.textbox_information.configure(state='disabled')
|
||||
self.textbox_information.configure(state='disabled')
|
||||
self.protocol("WM_DELETE_WINDOW", self.delete_window)
|
||||
|
||||
def delete_window(self):
|
||||
self.withdraw()
|
||||
Reference in New Issue
Block a user