Merge branch 'develop'
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,7 +6,7 @@ VRCT.spec
|
||||
*.pyc
|
||||
logs/
|
||||
.venv/
|
||||
weight/
|
||||
weights/
|
||||
.vscode
|
||||
error.log
|
||||
*.exe
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
pyinstaller --windowed --clean --noconfirm --icon="./img/vrct_logo_mark_black.ico" --add-data "./img;img/" --add-data "./locales;locales/" --add-data "./batch;batch/" --name VRCT --add-data ".venv\Lib\site-packages\customtkinter;customtkinter/" --exclude-module pandas --exclude-module matplotlib --exclude-module PyQt5 main.py
|
||||
pyinstaller --windowed --clean --noconfirm --icon="./img/vrct_logo_mark_black.ico" --add-data "./img;img/" --add-data "./locales;locales/" --add-data "./batch;batch/" --name VRCT --add-data ".venv\Lib\site-packages\customtkinter;customtkinter/" --add-data ".venv\Lib\site-packages\zeroconf;zeroconf/" --exclude-module pandas --exclude-module matplotlib --exclude-module PyQt5 main.py
|
||||
"C:\Program Files (x86)\NSIS\makensis.exe" installer/installer.nsi
|
||||
142
config.py
142
config.py
@@ -39,12 +39,8 @@ class Config:
|
||||
return self._VERSION
|
||||
|
||||
@property
|
||||
def ENABLE_SPEAKER2CHATBOX(self):
|
||||
return self._ENABLE_SPEAKER2CHATBOX
|
||||
|
||||
@property
|
||||
def ENABLE_SPEAKER2CHATBOX(self):
|
||||
return self._ENABLE_SPEAKER2CHATBOX
|
||||
def ENABLE_SPEAKER2CHATBOX_PASS_CONFIRMATION(self):
|
||||
return self._ENABLE_SPEAKER2CHATBOX_PASS_CONFIRMATION
|
||||
|
||||
@property
|
||||
def PATH_LOCAL(self):
|
||||
@@ -70,6 +66,10 @@ class Config:
|
||||
def DOCUMENTS_URL(self):
|
||||
return self._DOCUMENTS_URL
|
||||
|
||||
@property
|
||||
def DEEPL_AUTH_KEY_PAGE_URL(self):
|
||||
return self._DEEPL_AUTH_KEY_PAGE_URL
|
||||
|
||||
@property
|
||||
def TRANSPARENCY_RANGE(self):
|
||||
return self._TRANSPARENCY_RANGE
|
||||
@@ -98,6 +98,10 @@ class Config:
|
||||
def SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT(self):
|
||||
return self._SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT
|
||||
|
||||
@property
|
||||
def SELECTABLE_WHISPER_WEIGHT_TYPE_DICT(self):
|
||||
return self._SELECTABLE_WHISPER_WEIGHT_TYPE_DICT
|
||||
|
||||
@property
|
||||
def MAX_MIC_ENERGY_THRESHOLD(self):
|
||||
return self._MAX_MIC_ENERGY_THRESHOLD
|
||||
@@ -107,6 +111,15 @@ class Config:
|
||||
return self._MAX_SPEAKER_ENERGY_THRESHOLD
|
||||
|
||||
# Read Write
|
||||
@property
|
||||
def ENABLE_SPEAKER2CHATBOX(self):
|
||||
return self._ENABLE_SPEAKER2CHATBOX
|
||||
|
||||
@ENABLE_SPEAKER2CHATBOX.setter
|
||||
def ENABLE_SPEAKER2CHATBOX(self, value):
|
||||
if isinstance(value, bool):
|
||||
self._ENABLE_SPEAKER2CHATBOX = value
|
||||
|
||||
@property
|
||||
def ENABLE_TRANSLATION(self):
|
||||
return self._ENABLE_TRANSLATION
|
||||
@@ -197,6 +210,24 @@ class Config:
|
||||
if value in list(translation_lang.keys()):
|
||||
self._CHOICE_OUTPUT_TRANSLATOR = value
|
||||
|
||||
@property
|
||||
def SENT_MESSAGES_LOG(self):
|
||||
return self._SENT_MESSAGES_LOG
|
||||
|
||||
@SENT_MESSAGES_LOG.setter
|
||||
def SENT_MESSAGES_LOG(self, value):
|
||||
if isinstance(value, list):
|
||||
self._SENT_MESSAGES_LOG = value
|
||||
|
||||
@property
|
||||
def CURRENT_SENT_MESSAGES_LOG_INDEX(self):
|
||||
return self._CURRENT_SENT_MESSAGES_LOG_INDEX
|
||||
|
||||
@CURRENT_SENT_MESSAGES_LOG_INDEX.setter
|
||||
def CURRENT_SENT_MESSAGES_LOG_INDEX(self, value):
|
||||
if isinstance(value, int):
|
||||
self._CURRENT_SENT_MESSAGES_LOG_INDEX = value
|
||||
|
||||
@property
|
||||
def IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION(self):
|
||||
return self._IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION
|
||||
@@ -206,6 +237,15 @@ class Config:
|
||||
if isinstance(value, bool):
|
||||
self._IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION = value
|
||||
|
||||
@property
|
||||
def IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER(self):
|
||||
return self._IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER
|
||||
|
||||
@IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER.setter
|
||||
def IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER(self, value):
|
||||
if isinstance(value, bool):
|
||||
self._IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = value
|
||||
|
||||
# Save Json Data
|
||||
## Main Window
|
||||
@property
|
||||
@@ -263,6 +303,17 @@ class Config:
|
||||
self._SELECTED_TAB_TARGET_LANGUAGES = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('SELECTED_TRANSCRIPTION_ENGINE')
|
||||
def SELECTED_TRANSCRIPTION_ENGINE(self):
|
||||
return self._SELECTED_TRANSCRIPTION_ENGINE
|
||||
|
||||
@SELECTED_TRANSCRIPTION_ENGINE.setter
|
||||
def SELECTED_TRANSCRIPTION_ENGINE(self, value):
|
||||
if isinstance(value, str):
|
||||
self._SELECTED_TRANSCRIPTION_ENGINE = value
|
||||
# saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE')
|
||||
def IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE(self):
|
||||
@@ -569,15 +620,37 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('WEIGHT_TYPE')
|
||||
def WEIGHT_TYPE(self):
|
||||
return self._WEIGHT_TYPE
|
||||
@json_serializable('USE_WHISPER_FEATURE')
|
||||
def USE_WHISPER_FEATURE(self):
|
||||
return self._USE_WHISPER_FEATURE
|
||||
|
||||
@WEIGHT_TYPE.setter
|
||||
def WEIGHT_TYPE(self, value):
|
||||
@USE_WHISPER_FEATURE.setter
|
||||
def USE_WHISPER_FEATURE(self, value):
|
||||
if isinstance(value, bool):
|
||||
self._USE_WHISPER_FEATURE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('CTRANSLATE2_WEIGHT_TYPE')
|
||||
def CTRANSLATE2_WEIGHT_TYPE(self):
|
||||
return self._CTRANSLATE2_WEIGHT_TYPE
|
||||
|
||||
@CTRANSLATE2_WEIGHT_TYPE.setter
|
||||
def CTRANSLATE2_WEIGHT_TYPE(self, value):
|
||||
# if isinstance(value, str) and value in self.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT:
|
||||
if isinstance(value, str):
|
||||
self._WEIGHT_TYPE = value
|
||||
self._CTRANSLATE2_WEIGHT_TYPE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('WHISPER_WEIGHT_TYPE')
|
||||
def WHISPER_WEIGHT_TYPE(self):
|
||||
return self._WHISPER_WEIGHT_TYPE
|
||||
|
||||
@WHISPER_WEIGHT_TYPE.setter
|
||||
def WHISPER_WEIGHT_TYPE(self, value):
|
||||
if isinstance(value, str):
|
||||
self._WHISPER_WEIGHT_TYPE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@@ -687,9 +760,18 @@ class Config:
|
||||
self._RECEIVED_MESSAGE_FORMAT_WITH_T = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
|
||||
|
||||
# Speaker2Chatbox------------------
|
||||
@property
|
||||
@json_serializable('ENABLE_SPEAKER2CHATBOX_PASS')
|
||||
def ENABLE_SPEAKER2CHATBOX_PASS(self):
|
||||
return self._ENABLE_SPEAKER2CHATBOX_PASS
|
||||
|
||||
@ENABLE_SPEAKER2CHATBOX_PASS.setter
|
||||
def ENABLE_SPEAKER2CHATBOX_PASS(self, value):
|
||||
if isinstance(value, str):
|
||||
self._ENABLE_SPEAKER2CHATBOX_PASS = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('ENABLE_SEND_RECEIVED_MESSAGE_TO_VRC')
|
||||
def ENABLE_SEND_RECEIVED_MESSAGE_TO_VRC(self):
|
||||
@@ -731,8 +813,9 @@ class Config:
|
||||
|
||||
def init_config(self):
|
||||
# Read Only
|
||||
self._VERSION = "2.1.1"
|
||||
self._VERSION = "2.2.0"
|
||||
self._ENABLE_SPEAKER2CHATBOX = False # Speaker2Chatbox
|
||||
self._ENABLE_SPEAKER2CHATBOX_PASS_CONFIRMATION = "123456789"
|
||||
self._PATH_LOCAL = os_path.dirname(sys.argv[0])
|
||||
self._PATH_CONFIG = os_path.join(self._PATH_LOCAL, "config.json")
|
||||
self._PATH_LOGS = os_path.join(self._PATH_LOCAL, "logs")
|
||||
@@ -740,6 +823,7 @@ class Config:
|
||||
self._GITHUB_URL = "https://api.github.com/repos/misyaguziya/VRCT/releases/latest"
|
||||
self._BOOTH_URL = "https://misyaguziya.booth.pm/"
|
||||
self._DOCUMENTS_URL = "https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246"
|
||||
self._DEEPL_AUTH_KEY_PAGE_URL = "https://www.deepl.com/ja/account/summary"
|
||||
self._TRANSPARENCY_RANGE = (50, 100)
|
||||
self._APPEARANCE_THEME_LIST = ["Light", "Dark", "System"]
|
||||
self._UI_SCALING_LIST = generatePercentageStringsList(start=40, end=200, step=10)
|
||||
@@ -756,6 +840,18 @@ class Config:
|
||||
"Small": "Small",
|
||||
"Large": "Large",
|
||||
}
|
||||
|
||||
self._SELECTABLE_WHISPER_WEIGHT_TYPE_DICT = {
|
||||
# {Save json str}: {i18n_placeholder} pairs
|
||||
"tiny": "tiny",
|
||||
"base": "base",
|
||||
"small": "small",
|
||||
"medium": "medium",
|
||||
"large-v1": "large-v1",
|
||||
"large-v2": "large-v2",
|
||||
"large-v3": "large-v3",
|
||||
}
|
||||
|
||||
self._MAX_MIC_ENERGY_THRESHOLD = 2000
|
||||
self._MAX_SPEAKER_ENERGY_THRESHOLD = 4000
|
||||
|
||||
@@ -770,7 +866,10 @@ class Config:
|
||||
self._SOURCE_COUNTRY = "Japan"
|
||||
self._TARGET_LANGUAGE = "English"
|
||||
self._TARGET_COUNTRY = "United States"
|
||||
self._SENT_MESSAGES_LOG = []
|
||||
self._CURRENT_SENT_MESSAGES_LOG_INDEX = 0
|
||||
self._IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION = False
|
||||
self._IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = False
|
||||
|
||||
# Save Json Data
|
||||
## Main Window
|
||||
@@ -795,6 +894,7 @@ class Config:
|
||||
"2":"English\n(United States)",
|
||||
"3":"English\n(United States)",
|
||||
}
|
||||
self._SELECTED_TRANSCRIPTION_ENGINE = "Google"
|
||||
self._IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = False
|
||||
|
||||
## Config Window
|
||||
@@ -810,7 +910,7 @@ class Config:
|
||||
"x_pos": "0",
|
||||
"y_pos": "0",
|
||||
"width": "870",
|
||||
"height": "640",
|
||||
"height": "654",
|
||||
}
|
||||
self._CHOICE_MIC_HOST = getDefaultInputDevice()["host"]["name"]
|
||||
self._CHOICE_MIC_DEVICE = getDefaultInputDevice()["device"]["name"]
|
||||
@@ -831,7 +931,9 @@ class Config:
|
||||
"DeepL_API": None,
|
||||
}
|
||||
self._USE_TRANSLATION_FEATURE = True
|
||||
self._WEIGHT_TYPE = "Small"
|
||||
self._CTRANSLATE2_WEIGHT_TYPE = "Small"
|
||||
self._USE_WHISPER_FEATURE = False
|
||||
self._WHISPER_WEIGHT_TYPE = "base"
|
||||
self._SEND_MESSAGE_FORMAT = "[message]"
|
||||
self._SEND_MESSAGE_FORMAT_WITH_T = "[message]([translation])"
|
||||
self._RECEIVED_MESSAGE_FORMAT = "[message]"
|
||||
@@ -842,6 +944,7 @@ class Config:
|
||||
self._ENABLE_NOTICE_XSOVERLAY = False
|
||||
self._ENABLE_SEND_MESSAGE_TO_VRC = True
|
||||
self._ENABLE_SEND_RECEIVED_MESSAGE_TO_VRC = False # Speaker2Chatbox
|
||||
self._ENABLE_SPEAKER2CHATBOX_PASS = "000000000"
|
||||
self._ENABLE_LOGGER = False
|
||||
self._IS_CONFIG_WINDOW_COMPACT_MODE = False
|
||||
|
||||
@@ -855,6 +958,11 @@ class Config:
|
||||
if key == "MESSAGE_FORMAT":
|
||||
old_message_format = config[key]
|
||||
setattr(self, key, config[key])
|
||||
|
||||
if key == "ENABLE_SPEAKER2CHATBOX_PASS":
|
||||
if self.ENABLE_SPEAKER2CHATBOX_PASS_CONFIRMATION == config[key]:
|
||||
self.ENABLE_SPEAKER2CHATBOX = True
|
||||
|
||||
if old_message_format is not None:
|
||||
setattr(self, "SEND_MESSAGE_FORMAT_WITH_T", old_message_format)
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ def changeToCTranslate2Process():
|
||||
# func transcription send message
|
||||
def sendMicMessage(message):
|
||||
if len(message) > 0:
|
||||
addSentMessageLog(message)
|
||||
translation = ""
|
||||
if model.checkKeywords(message):
|
||||
view.printToTextbox_DetectedByWordFilter(detected_message=message)
|
||||
@@ -200,6 +201,7 @@ def stopThreadingTranscriptionReceiveMessageOnOpenConfigWindow():
|
||||
# func message box
|
||||
def sendChatMessage(message):
|
||||
if len(message) > 0:
|
||||
addSentMessageLog(message)
|
||||
translation = ""
|
||||
if config.ENABLE_TRANSLATION is False:
|
||||
pass
|
||||
@@ -249,6 +251,29 @@ def messageBoxFocusOut(e):
|
||||
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
|
||||
model.oscStopSendTyping()
|
||||
|
||||
def addSentMessageLog(sent_message):
|
||||
config.SENT_MESSAGES_LOG.append(sent_message)
|
||||
config.CURRENT_SENT_MESSAGES_LOG_INDEX = len(config.SENT_MESSAGES_LOG)
|
||||
|
||||
def updateMessageBox(index_offset):
|
||||
if len(config.SENT_MESSAGES_LOG) == 0:
|
||||
return
|
||||
try:
|
||||
new_index = config.CURRENT_SENT_MESSAGES_LOG_INDEX + index_offset
|
||||
target_message_text = config.SENT_MESSAGES_LOG[new_index]
|
||||
view.replaceMessageBox(target_message_text)
|
||||
config.CURRENT_SENT_MESSAGES_LOG_INDEX = new_index
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
def messageBoxUpKeyPress():
|
||||
if config.CURRENT_SENT_MESSAGES_LOG_INDEX > 0:
|
||||
updateMessageBox(-1)
|
||||
|
||||
def messageBoxDownKeyPress():
|
||||
if config.CURRENT_SENT_MESSAGES_LOG_INDEX < len(config.SENT_MESSAGES_LOG) - 1:
|
||||
updateMessageBox(1)
|
||||
|
||||
def updateTranslationEngineAndEngineList():
|
||||
engine = config.CHOICE_INPUT_TRANSLATOR
|
||||
engines = model.findTranslationEngines(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
@@ -352,8 +377,10 @@ def callbackSelectedTranslationEngine(selected_translation_engine):
|
||||
def callbackToggleTranslation(is_turned_on):
|
||||
config.ENABLE_TRANSLATION = is_turned_on
|
||||
if config.ENABLE_TRANSLATION is True:
|
||||
model.changeTranslatorCTranslate2Model()
|
||||
view.printToTextbox_enableTranslation()
|
||||
else:
|
||||
model.clearTranslatorCTranslate2Model()
|
||||
view.printToTextbox_disableTranslation()
|
||||
|
||||
def callbackToggleTranscriptionSend(is_turned_on):
|
||||
@@ -505,8 +532,8 @@ def callbackSetUseTranslationFeature(value):
|
||||
|
||||
def callbackSetCtranslate2WeightType(value):
|
||||
print("callbackSetCtranslate2WeightType", value)
|
||||
config.WEIGHT_TYPE = str(value)
|
||||
view.updateSelectedCtranslate2WeightType(config.WEIGHT_TYPE)
|
||||
config.CTRANSLATE2_WEIGHT_TYPE = str(value)
|
||||
view.updateSelectedCtranslate2WeightType(config.CTRANSLATE2_WEIGHT_TYPE)
|
||||
view.setWidgetsStatus_changeWeightType_Pending()
|
||||
if model.checkCTranslatorCTranslate2ModelWeight():
|
||||
config.IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION = False
|
||||
@@ -767,6 +794,35 @@ def callbackSetSpeakerMaxPhrases(value):
|
||||
except Exception:
|
||||
view.showErrorMessage_SpeakerMaxPhrases()
|
||||
|
||||
# Transcription (Internal AI Model)
|
||||
def callbackSetUserWhisperFeature(value):
|
||||
print("callbackSetUserWhisperFeature", value)
|
||||
config.USE_WHISPER_FEATURE = value
|
||||
if config.USE_WHISPER_FEATURE is True:
|
||||
view.openWhisperWeightTypeWidget()
|
||||
if model.checkTranscriptionWhisperModelWeight() is True:
|
||||
config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = False
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Whisper"
|
||||
else:
|
||||
config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = True
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Google"
|
||||
else:
|
||||
view.closeWhisperWeightTypeWidget()
|
||||
config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = False
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Google"
|
||||
view.showRestartButtonIfRequired()
|
||||
|
||||
def callbackSetWhisperWeightType(value):
|
||||
print("callbackSetWhisperWeightType", value)
|
||||
config.WHISPER_WEIGHT_TYPE = str(value)
|
||||
view.updateSelectedWhisperWeightType(config.WHISPER_WEIGHT_TYPE)
|
||||
if model.checkTranscriptionWhisperModelWeight() is True:
|
||||
config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = False
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Whisper"
|
||||
else:
|
||||
config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER = True
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Google"
|
||||
view.showRestartButtonIfRequired()
|
||||
|
||||
# Others Tab
|
||||
def callbackSetEnableAutoClearMessageBox(value):
|
||||
@@ -898,13 +954,18 @@ def createMainWindow(splash):
|
||||
# set Translation Engine
|
||||
updateTranslationEngineAndEngineList()
|
||||
|
||||
# set Transcription Engine
|
||||
if config.USE_WHISPER_FEATURE is True:
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Whisper"
|
||||
else:
|
||||
config.SELECTED_TRANSCRIPTION_ENGINE = "Google"
|
||||
|
||||
# set word filter
|
||||
model.addKeywords()
|
||||
|
||||
# check Software Updated
|
||||
if config.ENABLE_SPEAKER2CHATBOX is False:
|
||||
if model.checkSoftwareUpdated() is True:
|
||||
view.showUpdateAvailableButton()
|
||||
if model.checkSoftwareUpdated() is True:
|
||||
view.showUpdateAvailableButton()
|
||||
|
||||
# init logger
|
||||
if config.ENABLE_LOGGER is True:
|
||||
@@ -949,6 +1010,8 @@ def createMainWindow(splash):
|
||||
"message_box_bind_Any_KeyPress": messageBoxPressKeyAny,
|
||||
"message_box_bind_FocusIn": messageBoxFocusIn,
|
||||
"message_box_bind_FocusOut": messageBoxFocusOut,
|
||||
"message_box_bind_Up_KeyPress": messageBoxUpKeyPress,
|
||||
"message_box_bind_Down_KeyPress": messageBoxDownKeyPress,
|
||||
},
|
||||
|
||||
config_window_registers={
|
||||
@@ -993,6 +1056,10 @@ def createMainWindow(splash):
|
||||
"callback_set_speaker_phrase_timeout": callbackSetSpeakerPhraseTimeout,
|
||||
"callback_set_speaker_max_phrases": callbackSetSpeakerMaxPhrases,
|
||||
|
||||
# Transcription Tab (Internal AI Model)
|
||||
"callback_set_use_whisper_feature": callbackSetUserWhisperFeature,
|
||||
"callback_set_whisper_weight_type": callbackSetWhisperWeightType,
|
||||
|
||||
# Others Tab
|
||||
"callback_set_enable_auto_clear_chatbox": callbackSetEnableAutoClearMessageBox,
|
||||
"callback_set_send_only_translated_messages": callbackSetEnableSendOnlyTranslatedMessages,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
BIN
img/link_icon_black.png
Normal file
BIN
img/link_icon_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 B |
BIN
img/link_icon_white.png
Normal file
BIN
img/link_icon_white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 373 B |
@@ -1,4 +1,2 @@
|
||||
python.exe -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install git+https://github.com/misyaguziya/translators
|
||||
pip install git+https://github.com/misyaguziya/custom_speech_recognition
|
||||
pip install -r requirements.txt
|
||||
@@ -79,9 +79,10 @@ config_window:
|
||||
transcription: Transcription
|
||||
transcription_mic: Mic
|
||||
transcription_speaker: Speaker
|
||||
transcription_internal_model: Transcription Model
|
||||
others: Others
|
||||
others_send_message_formats: Message Formats (Send)
|
||||
others_received_message_formats: Message Formats (Received)
|
||||
others_received_message_formats: Message Formats (XSOverlay & Speaker2Chatbox)
|
||||
others_speaker2chatbox: Speaker2Chatbox
|
||||
advanced_settings: Advanced Settings
|
||||
|
||||
@@ -128,6 +129,7 @@ config_window:
|
||||
deepl_auth_key:
|
||||
label: DeepL Auth Key
|
||||
desc: Please select %{translator} on the main screen with DeepL_API when using. ※Some languages may not be supported.
|
||||
open_auth_key_webpage: Open DeepL Account Webpage
|
||||
|
||||
mic_host:
|
||||
label: Mic Host/Driver
|
||||
@@ -187,6 +189,15 @@ config_window:
|
||||
desc: It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs.
|
||||
error_message: You can set a number equal to or greater than 0.
|
||||
|
||||
use_whisper_feature:
|
||||
label: Use Whisper Model As Transcription
|
||||
desc: In some languages, the accuracy of speech recognition may improve. During speech recognition usage, CPU usage increases, so please consider your PC specs before using this feature.
|
||||
|
||||
whisper_weight_type:
|
||||
label: Select Whisper Model
|
||||
desc: "Generally, models with larger capacity tend to have higher accuracy, but this also results in longer transcription times and increased CPU usage. Please refer to the documentation for explanations of each model.\n※Larger models, especially those exceeding medium size, can be challenging to run even depending on the CPU's performance."
|
||||
model_template: "%{model_name} model (%{capacity})"
|
||||
recommended_model_template: "%{model_name} model (%{capacity}) (Recommended)"
|
||||
|
||||
auto_clear_the_message_box:
|
||||
label: Auto Clear The Message Box
|
||||
@@ -217,25 +228,26 @@ config_window:
|
||||
label: Message Format
|
||||
desc: "You can change the decoration of the message you want to send.\n[message] will be replaced with the message."
|
||||
example_text: This is an example sentence. Fonts, line breaks, etc. may differ from the actual display.
|
||||
error_message: "The characters '[message]' cannot be used."
|
||||
error_message: "Cannot use the term '[message]'."
|
||||
|
||||
send_message_format_with_t:
|
||||
label: Message Format (With translation)
|
||||
label: Message Format (with Translation)
|
||||
desc: "You can change the decoration of the message you want to send.\n[message] will be replaced with the message, and [translation] will be replaced with the translated message."
|
||||
example_text: This is an example sentence. Fonts, line breaks, etc. may differ from the actual display.
|
||||
error_message: "The characters '[message]' and '[translation]' cannot be used."
|
||||
error_message: "Cannot use the terms '[message]' and '[translation]'."
|
||||
|
||||
received_message_format:
|
||||
label: Message Format
|
||||
desc: "You can change the decoration of the received message you want to send.\n[message] will be replaced with the message.\nIt will be used in Notification XSOverlay too."
|
||||
example_text: This is an example sentence. Fonts, line breaks, etc. may differ from the actual display.
|
||||
error_message: "The characters '[message]' cannot be used."
|
||||
label: Format of Received Messages
|
||||
desc: "Used for XSOverlay notification receiving feature.\n[message] will be replaced with the message. \n※It will be used in Speaker2Chatbox too."
|
||||
example_text: This is an example sentence. Actual display may vary, including font and line breaks.
|
||||
error_message: "Cannot use the term '[message]'."
|
||||
|
||||
received_message_format_with_t:
|
||||
label: Message Format (With translation)
|
||||
desc: It will be used in Notification XSOverlay too.
|
||||
example_text: This is an example sentence. Fonts, line breaks, etc. may differ from the actual display.
|
||||
error_message: "The characters '[message]' and '[translation]' cannot be used."
|
||||
label: Format of Received Messages (with Translation)
|
||||
desc: "Used for XSOverlay notification receiving feature.\n[message] will be replaced with the message, and [translation] will be replaced with the translated message.\n※It will be used in Speaker2Chatbox too."
|
||||
example_text: This is an example sentence. Actual display may vary, including font and line breaks.
|
||||
error_message: "Cannot use the terms '[message]' and '[translation]'."
|
||||
|
||||
|
||||
# Note: Speaker2Chatbox localization is fine only in English. Do not translate it into other languages.
|
||||
# Speaker2Chatbox
|
||||
|
||||
@@ -79,7 +79,10 @@ config_window:
|
||||
transcription: 音声認識
|
||||
transcription_mic: マイク
|
||||
transcription_speaker: スピーカー
|
||||
transcription_internal_model: 音声認識モデル
|
||||
others: その他
|
||||
others_send_message_formats: メッセージフォーマット (送信)
|
||||
others_received_message_formats: メッセージフォーマット (XSOverlay & Speaker2Chatbox)
|
||||
advanced_settings: 高度な設定
|
||||
|
||||
|
||||
@@ -125,6 +128,7 @@ config_window:
|
||||
deepl_auth_key:
|
||||
label: DeepL 認証キー
|
||||
desc: "使用の際は、メイン画面にある %{translator} をDeepL_APIに変更してください。\n※対応していない言語もあります。"
|
||||
open_auth_key_webpage: DeepLアカウントページを開く
|
||||
|
||||
mic_host:
|
||||
label: マイク(ホスト/ドライバー)
|
||||
@@ -184,6 +188,16 @@ config_window:
|
||||
desc: 文字起こしされた単語数の下限値で、この数値を超えた場合のみ結果をログに表示します。
|
||||
error_message: 0以上の数値を設定できます。
|
||||
|
||||
use_whisper_feature:
|
||||
label: 音声認識にWhisperモデルを使用する
|
||||
desc: 一部の言語では、音声認識の精度が向上するかもしれません。音声認識使用中、CPUの使用率が上がるので、お使いのPCスペックと相談してこの機能を使用してください。
|
||||
|
||||
whisper_weight_type:
|
||||
label: Whisperモデルのタイプ
|
||||
desc: "基本的に、容量が多いモデルほど精度は高いですが、文字起こしまでの時間が伸び、CPU使用率も増加します。各モデルの説明はドキュメントをご覧ください。\n※特にmediumより容量の大きいモデルは、CPUの性能によっては使用すらも困難です。"
|
||||
model_template: "%{model_name} モデル (%{capacity})"
|
||||
recommended_model_template: "%{model_name} モデル (%{capacity}) (推奨)"
|
||||
|
||||
|
||||
auto_clear_the_message_box:
|
||||
label: 送信後はチャットボックスを空にする
|
||||
@@ -223,14 +237,14 @@ config_window:
|
||||
error_message: "[message]と[translation]という文字は使えません。"
|
||||
|
||||
received_message_format:
|
||||
label: 送信するメッセージのフォーマット
|
||||
desc: "VRChatで相手に実際に見えるフォーマットを変更できます。\n[message]がメッセージに置換されます。\n※XSOverlayでの通知受け取り機能にも使われます。"
|
||||
label: 受信するメッセージのフォーマット
|
||||
desc: "XSOverlay通知受け取り機能で使用されます。\n[message]がメッセージに置換されます。\n※Speaker2Chatboxでの送信機能にも使われます。"
|
||||
example_text: これは例文です。フォントや改行箇所など、実際の表示とは異なる場合があります。
|
||||
error_message: "[message]という文字は使えません。"
|
||||
|
||||
received_message_format_with_t:
|
||||
label: 送信するメッセージのフォーマット(翻訳付き)
|
||||
desc: "VRChatで相手に実際に見えるフォーマットを変更できます。\n[message]がメッセージに置換され、[translation]が翻訳されたメッセージに置換されます。\n※XSOverlayでの通知受け取り機能にも使われます。"
|
||||
label: 受信するメッセージのフォーマット(翻訳付き)
|
||||
desc: "XSOverlay通知受け取り機能で使用されます。\n[message]がメッセージに置換され、[translation]が翻訳されたメッセージに置換されます。\n※Speaker2Chatboxでの送信機能にも使われます。"
|
||||
example_text: これは例文です。フォントや改行箇所など、実際の表示とは異なる場合があります。
|
||||
error_message: "[message]と[translation]という文字は使えません。"
|
||||
|
||||
|
||||
13
main.py
13
main.py
@@ -8,11 +8,20 @@ if __name__ == "__main__":
|
||||
splash.showSplash()
|
||||
|
||||
from config import config
|
||||
from models.translation.utils import downloadCTranslate2Weight
|
||||
# version 2.2.0からweightフォルダをweightsに変更する
|
||||
from utils import renameWeightFolder
|
||||
renameWeightFolder(config.PATH_LOCAL)
|
||||
|
||||
from models.translation.translation_utils import downloadCTranslate2Weight
|
||||
if config.USE_TRANSLATION_FEATURE is True:
|
||||
downloadCTranslate2Weight(config.PATH_LOCAL, config.WEIGHT_TYPE, splash.updateDownloadProgress)
|
||||
downloadCTranslate2Weight(config.PATH_LOCAL, config.CTRANSLATE2_WEIGHT_TYPE, splash.updateDownloadProgress)
|
||||
|
||||
from models.transcription.transcription_whisper import downloadWhisperWeight
|
||||
if config.USE_WHISPER_FEATURE is True:
|
||||
downloadWhisperWeight(config.PATH_LOCAL, config.WHISPER_WEIGHT_TYPE, splash.updateDownloadProgress)
|
||||
|
||||
splash.toProgress(0)
|
||||
|
||||
import controller
|
||||
controller.createMainWindow(splash)
|
||||
splash.destroySplash()
|
||||
|
||||
108
model.py
108
model.py
@@ -1,3 +1,4 @@
|
||||
import gc
|
||||
import tempfile
|
||||
from zipfile import ZipFile
|
||||
from subprocess import Popen
|
||||
@@ -17,13 +18,14 @@ from flashtext import KeywordProcessor
|
||||
from models.translation.translation_translator import Translator
|
||||
from models.transcription.transcription_utils import getInputDevices, getDefaultOutputDevice
|
||||
from models.osc.osc_tools import sendTyping, sendMessage, sendTestAction, receiveOscParameters
|
||||
from models.transcription.transcription_recorder import SelectedMicRecorder, SelectedSpeakerRecorder
|
||||
from models.transcription.transcription_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder
|
||||
from models.transcription.transcription_recorder import SelectedMicEnergyAndAudioRecorder, SelectedSpeakerEnergyAndAudioRecorder
|
||||
from models.transcription.transcription_recorder import SelectedMicEnergyRecorder, SelectedSpeakerEnergyRecorder
|
||||
from models.transcription.transcription_transcriber import AudioTranscriber
|
||||
from models.xsoverlay.notification import xsoverlayForVRCT
|
||||
from models.translation.translation_languages import translation_lang
|
||||
from models.transcription.transcription_languages import transcription_lang
|
||||
from models.translation.utils import checkCTranslate2Weight
|
||||
from models.translation.translation_utils import checkCTranslate2Weight
|
||||
from models.transcription.transcription_whisper import checkWhisperWeight
|
||||
from config import config
|
||||
|
||||
class threadFnc(Thread):
|
||||
@@ -64,15 +66,19 @@ class Model:
|
||||
self.speaker_energy_recorder = None
|
||||
self.speaker_energy_plot_progressbar = None
|
||||
self.translator = Translator()
|
||||
if config.USE_TRANSLATION_FEATURE is True:
|
||||
self.translator.changeCTranslate2Model(config.PATH_LOCAL, config.WEIGHT_TYPE)
|
||||
self.keyword_processor = KeywordProcessor()
|
||||
|
||||
def checkCTranslatorCTranslate2ModelWeight(self):
|
||||
return checkCTranslate2Weight(config.PATH_LOCAL, config.WEIGHT_TYPE)
|
||||
return checkCTranslate2Weight(config.PATH_LOCAL, config.CTRANSLATE2_WEIGHT_TYPE)
|
||||
|
||||
def changeTranslatorCTranslate2Model(self):
|
||||
self.translator.changeCTranslate2Model(config.PATH_LOCAL, config.WEIGHT_TYPE)
|
||||
self.translator.changeCTranslate2Model(config.PATH_LOCAL, config.CTRANSLATE2_WEIGHT_TYPE)
|
||||
|
||||
def clearTranslatorCTranslate2Model(self):
|
||||
self.translator.clearCTranslate2Model()
|
||||
|
||||
def checkTranscriptionWhisperModelWeight(self):
|
||||
return checkWhisperWeight(config.PATH_LOCAL, config.WHISPER_WEIGHT_TYPE)
|
||||
|
||||
def resetKeywordProcessor(self):
|
||||
del self.keyword_processor
|
||||
@@ -317,44 +323,72 @@ class Model:
|
||||
return
|
||||
|
||||
mic_audio_queue = Queue()
|
||||
# mic_energy_queue = Queue()
|
||||
device = [device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0]
|
||||
record_timeout = config.INPUT_MIC_RECORD_TIMEOUT
|
||||
phase_timeout = config.INPUT_MIC_PHRASE_TIMEOUT
|
||||
if record_timeout > phase_timeout:
|
||||
record_timeout = phase_timeout
|
||||
|
||||
self.mic_audio_recorder = SelectedMicRecorder(
|
||||
self.mic_audio_recorder = SelectedMicEnergyAndAudioRecorder(
|
||||
device=device,
|
||||
energy_threshold=config.INPUT_MIC_ENERGY_THRESHOLD,
|
||||
dynamic_energy_threshold=config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD,
|
||||
record_timeout=record_timeout,
|
||||
)
|
||||
self.mic_audio_recorder.recordIntoQueue(mic_audio_queue)
|
||||
mic_transcriber = AudioTranscriber(
|
||||
# self.mic_audio_recorder.recordIntoQueue(mic_audio_queue, mic_energy_queue)
|
||||
self.mic_audio_recorder.recordIntoQueue(mic_audio_queue, None)
|
||||
self.mic_transcriber = AudioTranscriber(
|
||||
speaker=False,
|
||||
source=self.mic_audio_recorder.source,
|
||||
phrase_timeout=phase_timeout,
|
||||
max_phrases=config.INPUT_MIC_MAX_PHRASES,
|
||||
transcription_engine=config.SELECTED_TRANSCRIPTION_ENGINE,
|
||||
root=config.PATH_LOCAL,
|
||||
whisper_weight_type=config.WHISPER_WEIGHT_TYPE,
|
||||
)
|
||||
def sendMicTranscript():
|
||||
mic_transcriber.transcribeAudioQueue(mic_audio_queue, config.SOURCE_LANGUAGE, config.SOURCE_COUNTRY)
|
||||
message = mic_transcriber.getTranscript()
|
||||
self.mic_transcriber.transcribeAudioQueue(mic_audio_queue, config.SOURCE_LANGUAGE, config.SOURCE_COUNTRY)
|
||||
message = self.mic_transcriber.getTranscript()
|
||||
try:
|
||||
fnc(message)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.mic_print_transcript = threadFnc(sendMicTranscript)
|
||||
def endMicTranscript():
|
||||
mic_audio_queue.queue.clear()
|
||||
# mic_energy_queue.queue.clear()
|
||||
del self.mic_transcriber
|
||||
gc.collect()
|
||||
|
||||
# def sendMicEnergy():
|
||||
# if mic_energy_queue.empty() is False:
|
||||
# energy = mic_energy_queue.get()
|
||||
# # print("mic energy:", energy)
|
||||
# try:
|
||||
# fnc(energy)
|
||||
# except Exception:
|
||||
# pass
|
||||
# sleep(0.01)
|
||||
|
||||
self.mic_print_transcript = threadFnc(sendMicTranscript, end_fnc=endMicTranscript)
|
||||
self.mic_print_transcript.daemon = True
|
||||
self.mic_print_transcript.start()
|
||||
|
||||
# self.mic_get_energy = threadFnc(sendMicEnergy)
|
||||
# self.mic_get_energy.daemon = True
|
||||
# self.mic_get_energy.start()
|
||||
|
||||
def stopMicTranscript(self):
|
||||
if isinstance(self.mic_print_transcript, threadFnc):
|
||||
self.mic_print_transcript.stop()
|
||||
self.mic_print_transcript = None
|
||||
if isinstance(self.mic_audio_recorder, SelectedMicRecorder):
|
||||
if isinstance(self.mic_audio_recorder, SelectedMicEnergyAndAudioRecorder):
|
||||
self.mic_audio_recorder.stop()
|
||||
self.mic_audio_recorder = None
|
||||
# if isinstance(self.mic_get_energy, threadFnc):
|
||||
# self.mic_get_energy.stop()
|
||||
# self.mic_get_energy = None
|
||||
|
||||
def startCheckMicEnergy(self, fnc, end_fnc, error_fnc=None):
|
||||
if config.CHOICE_MIC_HOST == "NoHost" or config.CHOICE_MIC_DEVICE == "NoDevice":
|
||||
@@ -399,43 +433,71 @@ class Model:
|
||||
return
|
||||
|
||||
speaker_audio_queue = Queue()
|
||||
# speaker_energy_queue = Queue()
|
||||
record_timeout = config.INPUT_SPEAKER_RECORD_TIMEOUT
|
||||
phase_timeout = config.INPUT_SPEAKER_PHRASE_TIMEOUT
|
||||
if record_timeout > phase_timeout:
|
||||
record_timeout = phase_timeout
|
||||
|
||||
self.speaker_audio_recorder = SelectedSpeakerRecorder(
|
||||
self.speaker_audio_recorder = SelectedSpeakerEnergyAndAudioRecorder(
|
||||
device=speaker_device,
|
||||
energy_threshold=config.INPUT_SPEAKER_ENERGY_THRESHOLD,
|
||||
dynamic_energy_threshold=config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
record_timeout=record_timeout,
|
||||
)
|
||||
self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue)
|
||||
speaker_transcriber = AudioTranscriber(
|
||||
# self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue, speaker_energy_queue)
|
||||
self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue ,None)
|
||||
self.speaker_transcriber = AudioTranscriber(
|
||||
speaker=True,
|
||||
source=self.speaker_audio_recorder.source,
|
||||
phrase_timeout=phase_timeout,
|
||||
max_phrases=config.INPUT_SPEAKER_MAX_PHRASES,
|
||||
transcription_engine=config.SELECTED_TRANSCRIPTION_ENGINE,
|
||||
root=config.PATH_LOCAL,
|
||||
whisper_weight_type=config.WHISPER_WEIGHT_TYPE,
|
||||
)
|
||||
def sendSpeakerTranscript():
|
||||
speaker_transcriber.transcribeAudioQueue(speaker_audio_queue, config.TARGET_LANGUAGE, config.TARGET_COUNTRY)
|
||||
message = speaker_transcriber.getTranscript()
|
||||
self.speaker_transcriber.transcribeAudioQueue(speaker_audio_queue, config.TARGET_LANGUAGE, config.TARGET_COUNTRY)
|
||||
message = self.speaker_transcriber.getTranscript()
|
||||
try:
|
||||
fnc(message)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.speaker_print_transcript = threadFnc(sendSpeakerTranscript)
|
||||
def endSpeakerTranscript():
|
||||
speaker_audio_queue.queue.clear()
|
||||
# speaker_energy_queue.queue.clear()
|
||||
del self.speaker_transcriber
|
||||
gc.collect()
|
||||
|
||||
# def sendSpeakerEnergy():
|
||||
# if speaker_energy_queue.empty() is False:
|
||||
# energy = speaker_energy_queue.get()
|
||||
# # print("speaker energy:", energy)
|
||||
# try:
|
||||
# fnc(energy)
|
||||
# except Exception:
|
||||
# pass
|
||||
# sleep(0.01)
|
||||
|
||||
self.speaker_print_transcript = threadFnc(sendSpeakerTranscript, end_fnc=endSpeakerTranscript)
|
||||
self.speaker_print_transcript.daemon = True
|
||||
self.speaker_print_transcript.start()
|
||||
|
||||
# self.speaker_get_energy = threadFnc(sendSpeakerEnergy)
|
||||
# self.speaker_get_energy.daemon = True
|
||||
# self.speaker_get_energy.start()
|
||||
|
||||
def stopSpeakerTranscript(self):
|
||||
if isinstance(self.speaker_print_transcript, threadFnc):
|
||||
self.speaker_print_transcript.stop()
|
||||
self.speaker_print_transcript = None
|
||||
if isinstance(self.speaker_audio_recorder, SelectedSpeakerRecorder):
|
||||
if isinstance(self.speaker_audio_recorder, SelectedSpeakerEnergyAndAudioRecorder):
|
||||
self.speaker_audio_recorder.stop()
|
||||
self.speaker_audio_recorder = None
|
||||
# if isinstance(self.speaker_get_energy, threadFnc):
|
||||
# self.speaker_get_energy.stop()
|
||||
# self.speaker_get_energy = None
|
||||
|
||||
def startCheckSpeakerEnergy(self, fnc, end_fnc, error_fnc=None):
|
||||
speaker_device = getDefaultOutputDevice()
|
||||
@@ -456,7 +518,7 @@ class Model:
|
||||
sleep(0.01)
|
||||
|
||||
speaker_energy_queue = Queue()
|
||||
self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device)
|
||||
self.speaker_energy_recorder = SelectedSpeakerEnergyRecorder(speaker_device)
|
||||
self.speaker_energy_recorder.recordIntoQueue(speaker_energy_queue)
|
||||
self.speaker_energy_plot_progressbar = threadFnc(sendSpeakerEnergy, end_fnc=end_fnc)
|
||||
self.speaker_energy_plot_progressbar.daemon = True
|
||||
@@ -466,7 +528,7 @@ class Model:
|
||||
if isinstance(self.speaker_energy_plot_progressbar, threadFnc):
|
||||
self.speaker_energy_plot_progressbar.stop()
|
||||
self.speaker_energy_plot_progressbar = None
|
||||
if isinstance(self.speaker_energy_recorder, SelectedSpeakeEnergyRecorder):
|
||||
if isinstance(self.speaker_energy_recorder, SelectedSpeakerEnergyRecorder):
|
||||
self.speaker_energy_recorder.stop()
|
||||
self.speaker_energy_recorder = None
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from time import sleep
|
||||
import threading
|
||||
from pythonosc import osc_message_builder
|
||||
from pythonosc import udp_client
|
||||
from pythonosc import dispatcher
|
||||
from pythonosc import osc_server
|
||||
from tinyoscquery.queryservice import OSCQueryService
|
||||
from tinyoscquery.utility import get_open_udp_port, get_open_tcp_port
|
||||
|
||||
# send OSC message typing
|
||||
def sendTyping(flag=False, ip_address="127.0.0.1", port=9000):
|
||||
@@ -45,12 +48,40 @@ def sendChangeVoice(ip_address="127.0.0.1", port=9000):
|
||||
sendInputVoice(flag=0, ip_address=ip_address, port=port)
|
||||
sleep(0.05)
|
||||
|
||||
def receiveOscParameters(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)
|
||||
return server
|
||||
|
||||
def receiveOscParameters(dict_filter_and_target, ip_address="127.0.0.1", title="VRCT"):
|
||||
osc_port = get_open_udp_port()
|
||||
http_port = get_open_tcp_port()
|
||||
osc_dispatcher = dispatcher.Dispatcher()
|
||||
for filter, target in dict_filter_and_target.items():
|
||||
osc_dispatcher.map(filter, target)
|
||||
|
||||
osc_udp_server = osc_server.ThreadingOSCUDPServer((ip_address, osc_port), osc_dispatcher)
|
||||
threading.Thread(target=osc_udp_server.serve_forever, daemon = True).start()
|
||||
|
||||
osc_client = OSCQueryService(title, http_port, osc_port)
|
||||
for filter, target in dict_filter_and_target.items():
|
||||
osc_client.advertise_endpoint(filter)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sendChangeVoice()
|
||||
sendChangeVoice()
|
||||
osc_parameter_prefix = "/avatar/parameters/"
|
||||
osc_avatar_change_path = "/avatar/change"
|
||||
param_MuteSelf = "MuteSelf"
|
||||
param_Voice = "Voice"
|
||||
|
||||
def print_handler_all(address, *args):
|
||||
print(f"all {address}: {args}")
|
||||
|
||||
def print_handler_muteself(address, *args):
|
||||
print(f"muteself {address}: {args}")
|
||||
|
||||
def print_handler_voice(address, *args):
|
||||
print(f"voice {address}: {args}")
|
||||
|
||||
dict_filter_and_target = {
|
||||
# osc_parameter_prefix + "*": print_handler_all,
|
||||
osc_parameter_prefix + param_MuteSelf: print_handler_muteself,
|
||||
osc_parameter_prefix + param_Voice: print_handler_voice,
|
||||
}
|
||||
|
||||
receiveOscParameters(dict_filter_and_target)
|
||||
@@ -1,177 +1,438 @@
|
||||
transcription_lang = {
|
||||
"Afrikaans":{
|
||||
"South Africa":"af-ZA",
|
||||
"South Africa":{
|
||||
"Google": "af-ZA",
|
||||
"Whisper": "af",
|
||||
},
|
||||
},
|
||||
"Arabic":{
|
||||
"Algeria":"ar-DZ",
|
||||
"Bahrain":"ar-BH",
|
||||
"Egypt":"ar-EG",
|
||||
"Israel":"ar-IL",
|
||||
"Iraq":"ar-IQ",
|
||||
"Jordan":"ar-JO",
|
||||
"Kuwait":"ar-KW",
|
||||
"Lebanon":"ar-LB",
|
||||
"Morocco":"ar-MA",
|
||||
"Oman":"ar-OM",
|
||||
"State of Palestine":"ar-PS",
|
||||
"Qatar":"ar-QA",
|
||||
"Saudi Arabia":"ar-SA",
|
||||
"Tunisia":"ar-TN",
|
||||
"United Arab Emirates":"ar-AE",
|
||||
"Algeria":{
|
||||
"Google": "ar-DZ",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Bahrain":{
|
||||
"Google": "ar-BH",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Egypt":{
|
||||
"Google": "ar-EG",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Israel":{
|
||||
"Google": "ar-IL",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Iraq":{
|
||||
"Google": "ar-IQ",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Jordan":{
|
||||
"Google": "ar-JO",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Kuwait":{
|
||||
"Google": "ar-KW",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Lebanon":{
|
||||
"Google": "ar-LB",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Morocco":{
|
||||
"Google": "ar-MA",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Oman":{
|
||||
"Google": "ar-OM",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"State of Palestine":{
|
||||
"Google": "ar-PS",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Qatar":{
|
||||
"Google": "ar-QA",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Saudi Arabia":{
|
||||
"Google": "ar-SA",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"Tunisia":{
|
||||
"Google": "ar-TN",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
"United Arab Emirates":{
|
||||
"Google": "ar-AE",
|
||||
"Whisper": "ar",
|
||||
},
|
||||
},
|
||||
"Basque":{
|
||||
"Spain":"eu-ES",
|
||||
"Spain":{
|
||||
"Google": "eu-ES",
|
||||
"Whisper": "eu",
|
||||
},
|
||||
},
|
||||
"Bulgarian":{
|
||||
"Bulgaria":"bg-BG",
|
||||
"Bulgaria":{
|
||||
"Google": "bg-BG",
|
||||
"Whisper": "bg",
|
||||
},
|
||||
},
|
||||
"Catalan":{
|
||||
"Spain":"ca-ES",
|
||||
"Spain":{
|
||||
"Google": "ca-ES",
|
||||
"Whisper": "ca",
|
||||
},
|
||||
},
|
||||
"Chinese":{
|
||||
"Mandarin (Simplified, China)":"cmn-Hans-CN",
|
||||
"Mandarin (Simplified, Hong Kong)":"cmn-Hans-HK",
|
||||
"Mandarin (Traditional, Taiwan)":"cmn-Hant-TW",
|
||||
"Cantonese (Traditional Hong Kong)":"yue-Hant-HK",
|
||||
"Mandarin (Simplified, China)":{
|
||||
"Google": "cmn-Hans-CN",
|
||||
"Whisper": "zh",
|
||||
},
|
||||
"Mandarin (Simplified, Hong Kong)":{
|
||||
"Google": "cmn-Hans-HK",
|
||||
"Whisper": "zh",
|
||||
},
|
||||
"Mandarin (Traditional, Taiwan)":{
|
||||
"Google": "cmn-Hant-TW",
|
||||
"Whisper": "zh",
|
||||
},
|
||||
"Cantonese (Traditional Hong Kong)":{
|
||||
"Google": "yue-Hant-HK",
|
||||
"Whisper": "yue",
|
||||
},
|
||||
},
|
||||
"Croatian":{
|
||||
"Croatia":"hr-HR",
|
||||
"Croatia":{
|
||||
"Google": "hr-HR",
|
||||
"Whisper": "hr",
|
||||
},
|
||||
},
|
||||
"Czech":{
|
||||
"Czech Republic":"cs-CZ",
|
||||
"Czech Republic":{
|
||||
"Google": "cs-CZ",
|
||||
"Whisper": "cs",
|
||||
},
|
||||
},
|
||||
"Danish":{
|
||||
"Denmark":"da-DK",
|
||||
"Denmark":{
|
||||
"Google": "da-DK",
|
||||
"Whisper": "da",
|
||||
},
|
||||
},
|
||||
"Dutch":{
|
||||
"Netherlands":"nl-NL",
|
||||
"Netherlands":{
|
||||
"Google": "nl-NL",
|
||||
"Whisper": "nl",
|
||||
},
|
||||
},
|
||||
"English": {
|
||||
"United States":"en-US",
|
||||
"United Kingdom":"en-GB",
|
||||
"Australia":"en-AU",
|
||||
"Canada":"en-CA",
|
||||
"India":"en-IN",
|
||||
"Ireland":"en-IE",
|
||||
"New Zealand":"en-NZ",
|
||||
"Philippines":"en-PH",
|
||||
"South Africa":"en-ZA",
|
||||
"United States":{
|
||||
"Google": "en-US",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"United Kingdom":{
|
||||
"Google": "en-GB",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"Australia":{
|
||||
"Google": "en-AU",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"Canada":{
|
||||
"Google": "en-CA",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"India":{
|
||||
"Google": "en-IN",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"Ireland":{
|
||||
"Google": "en-IE",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"New Zealand":{
|
||||
"Google": "en-NZ",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"Philippines":{
|
||||
"Google": "en-PH",
|
||||
"Whisper": "en",
|
||||
},
|
||||
"South Africa":{
|
||||
"Google": "en-ZA",
|
||||
"Whisper": "en",
|
||||
},
|
||||
},
|
||||
"Filipino":{
|
||||
"Philippines":"fil-PH",
|
||||
"Philippines":{
|
||||
"Google": "fil-PH",
|
||||
"Whisper": "tl",
|
||||
},
|
||||
},
|
||||
"Finnish":{
|
||||
"Finland":"fi-FI",
|
||||
"Finland":{
|
||||
"Google": "fi-FI",
|
||||
"Whisper": "fi",
|
||||
},
|
||||
},
|
||||
"French":{
|
||||
"France":"fr-FR",
|
||||
"France":{
|
||||
"Google": "fr-FR",
|
||||
"Whisper": "fr",
|
||||
},
|
||||
},
|
||||
"Galician":{
|
||||
"Spain":"gl-ES",
|
||||
"Spain":{
|
||||
"Google": "gl-ES",
|
||||
"Whisper": "gl",
|
||||
},
|
||||
},
|
||||
"German":{
|
||||
"Germany":"de-DE",
|
||||
"Germany":{
|
||||
"Google": "de-DE",
|
||||
"Whisper": "de",
|
||||
},
|
||||
},
|
||||
"Greek":{
|
||||
"Greece":"el-GR",
|
||||
"Greece":{
|
||||
"Google": "el-GR",
|
||||
"Whisper": "el",
|
||||
},
|
||||
},
|
||||
"Hebrew":{
|
||||
"Israel":"he-IL",
|
||||
"Israel":{
|
||||
"Google": "he-IL",
|
||||
"Whisper": "he",
|
||||
},
|
||||
},
|
||||
"Hindi": {
|
||||
"India":"hi-IN",
|
||||
"India":{
|
||||
"Google": "hi-IN",
|
||||
"Whisper": "hi",
|
||||
},
|
||||
},
|
||||
"Hungarian":{
|
||||
"Hungary":"hu-HU",
|
||||
"Hungary":{
|
||||
"Google": "hu-HU",
|
||||
"Whisper": "hu",
|
||||
},
|
||||
},
|
||||
"Indonesian":{
|
||||
"Indonesia":"id-ID",
|
||||
"Indonesia":{
|
||||
"Google": "id-ID",
|
||||
"Whisper": "id",
|
||||
},
|
||||
},
|
||||
"Icelandic":{
|
||||
"Iceland":"is-IS",
|
||||
"Iceland":{
|
||||
"Google": "is-IS",
|
||||
"Whisper": "is",
|
||||
},
|
||||
},
|
||||
"Italian":{
|
||||
"Italy":"it-IT",
|
||||
"Switzerland":"it-CH",
|
||||
"Italy":{
|
||||
"Google": "it-IT",
|
||||
"Whisper": "it",
|
||||
},
|
||||
"Switzerland":{
|
||||
"Google": "it-CH",
|
||||
"Whisper": "it",
|
||||
},
|
||||
},
|
||||
"Japanese":{
|
||||
"Japan":"ja-JP",
|
||||
"Japan":{
|
||||
"Google": "ja-JP",
|
||||
"Whisper": "ja",
|
||||
},
|
||||
},
|
||||
"Korean":{
|
||||
"South Korea":"ko-KR",
|
||||
"South Korea":{
|
||||
"Google": "ko-KR",
|
||||
"Whisper": "ko",
|
||||
},
|
||||
},
|
||||
"Lithuanian":{
|
||||
"Lithuania":"lt-LT",
|
||||
"Lithuania":{
|
||||
"Google": "lt-LT",
|
||||
"Whisper": "lt",
|
||||
},
|
||||
},
|
||||
"Malay":{
|
||||
"Malaysia":"ms-MY",
|
||||
"Malaysia":{
|
||||
"Google": "ms-MY",
|
||||
"Whisper": "ms",
|
||||
},
|
||||
},
|
||||
"Norwegian":{
|
||||
"Norway":"nb-NO",
|
||||
"Norway":{
|
||||
"Google": "nb-NO",
|
||||
"Whisper": "no",
|
||||
},
|
||||
},
|
||||
"Persian":{
|
||||
"Iran":"fa-IR",
|
||||
"Iran":{
|
||||
"Google": "fa-IR",
|
||||
"Whisper": "fa",
|
||||
},
|
||||
},
|
||||
"Polish":{
|
||||
"Poland":"pl-PL",
|
||||
"Poland":{
|
||||
"Google": "pl-PL",
|
||||
"Whisper": "pl",
|
||||
},
|
||||
},
|
||||
"Portuguese":{
|
||||
"Brazil":"pt-BR",
|
||||
"Portugal":"pt-PT",
|
||||
"Brazil":{
|
||||
"Google": "pt-BR",
|
||||
"Whisper": "pt",
|
||||
},
|
||||
"Portugal":{
|
||||
"Google": "pt-PT",
|
||||
"Whisper": "pt",
|
||||
},
|
||||
},
|
||||
"Romanian":{
|
||||
"Romania":"ro-RO",
|
||||
"Romania":{
|
||||
"Google": "ro-RO",
|
||||
"Whisper": "ro",
|
||||
},
|
||||
},
|
||||
"Russian":{
|
||||
"Russia":"ru-RU",
|
||||
"Russia":{
|
||||
"Google": "ru-RU",
|
||||
"Whisper": "ru",
|
||||
},
|
||||
},
|
||||
"Serbian":{
|
||||
"Serbia":"sr-RS",
|
||||
"Serbia":{
|
||||
"Google": "sr-RS",
|
||||
"Whisper": "sr",
|
||||
},
|
||||
},
|
||||
"Slovak":{
|
||||
"Slovakia":"sk-SK",
|
||||
"Slovakia":{
|
||||
"Google": "sk-SK",
|
||||
"Whisper": "sk",
|
||||
},
|
||||
},
|
||||
"Slovenian":{
|
||||
"Slovenia":"sl-SI",
|
||||
"Slovenia":{
|
||||
"Google": "sl-SI",
|
||||
"Whisper": "sl",
|
||||
},
|
||||
},
|
||||
"Spanish":{
|
||||
"Argentina":"es-AR",
|
||||
"Bolivia":"es-BO",
|
||||
"Chile":"es-CL",
|
||||
"Colombia":"es-CO",
|
||||
"Costa Rica":"es-CR",
|
||||
"Dominican Republic":"es-DO",
|
||||
"Ecuador":"es-EC",
|
||||
"El Salvador":"es-SV",
|
||||
"Guatemala":"es-GT",
|
||||
"Honduras":"es-HN",
|
||||
"Mexico":"es-MX",
|
||||
"Nicaragua":"es-NI",
|
||||
"Panama":"es-PA",
|
||||
"Paraguay":"es-PY",
|
||||
"Peru":"es-PE",
|
||||
"Puerto Rico":"es-PR",
|
||||
"Spain":"es-ES",
|
||||
"Uruguay":"es-UY",
|
||||
"United States":"es-US",
|
||||
"Venezuela":"es-VE",
|
||||
"Argentina":{
|
||||
"Google": "es-AR",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Bolivia":{
|
||||
"Google": "es-BO",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Chile":{
|
||||
"Google": "es-CL",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Colombia":{
|
||||
"Google": "es-CO",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Costa Rica":{
|
||||
"Google": "es-CR",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Dominican Republic":{
|
||||
"Google": "es-DO",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Ecuador":{
|
||||
"Google": "es-EC",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"El Salvador":{
|
||||
"Google": "es-SV",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Guatemala":{
|
||||
"Google": "es-GT",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Honduras":{
|
||||
"Google": "es-HN",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Mexico":{
|
||||
"Google": "es-MX",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Nicaragua":{
|
||||
"Google": "es-NI",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Panama":{
|
||||
"Google": "es-PA",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Paraguay":{
|
||||
"Google": "es-PY",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Peru":{
|
||||
"Google": "es-PE",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Puerto Rico":{
|
||||
"Google": "es-PR",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Spain":{
|
||||
"Google": "es-ES",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Uruguay":{
|
||||
"Google": "es-UY",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"United States":{
|
||||
"Google": "es-US",
|
||||
"Whisper": "es",
|
||||
},
|
||||
"Venezuela":{
|
||||
"Google": "es-VE",
|
||||
"Whisper": "es",
|
||||
},
|
||||
},
|
||||
"Swedish":{
|
||||
"Sweden":"sv-SE",
|
||||
"Sweden":{
|
||||
"Google": "sv-SE",
|
||||
"Whisper": "sv",
|
||||
},
|
||||
},
|
||||
"Thai":{
|
||||
"Thailand":"th-TH",
|
||||
"Thailand":{
|
||||
"Google": "th-TH",
|
||||
"Whisper": "th",
|
||||
},
|
||||
},
|
||||
"Turkish":{
|
||||
"Turkey":"tr-TR",
|
||||
"Turkey":{
|
||||
"Google": "tr-TR",
|
||||
"Whisper": "tr",
|
||||
},
|
||||
},
|
||||
"Ukrainian":{
|
||||
"Ukraine":"uk-UA",
|
||||
"Ukraine":{
|
||||
"Google": "uk-UA",
|
||||
"Whisper": "uk",
|
||||
},
|
||||
},
|
||||
"Vietnamese":{
|
||||
"Vietnam":"vi-VN",
|
||||
},
|
||||
"Zulu":{
|
||||
"South Africa":"zu-ZA"
|
||||
"Vietnam":{
|
||||
"Google": "vi-VN",
|
||||
"Whisper": "vi",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
from speech_recognition import Recognizer, Microphone
|
||||
from pyaudiowpatch import get_sample_size, paInt16
|
||||
from datetime import datetime
|
||||
from queue import Queue
|
||||
|
||||
class BaseRecorder:
|
||||
def __init__(self, source, energy_threshold, dynamic_energy_threshold, record_timeout):
|
||||
@@ -78,7 +79,7 @@ class SelectedMicEnergyRecorder(BaseEnergyRecorder):
|
||||
super().__init__(source=source)
|
||||
# self.adjustForNoise()
|
||||
|
||||
class SelectedSpeakeEnergyRecorder(BaseEnergyRecorder):
|
||||
class SelectedSpeakerEnergyRecorder(BaseEnergyRecorder):
|
||||
def __init__(self, device):
|
||||
|
||||
source = Microphone(speaker=True,
|
||||
@@ -87,4 +88,54 @@ class SelectedSpeakeEnergyRecorder(BaseEnergyRecorder):
|
||||
channels=device["maxInputChannels"]
|
||||
)
|
||||
super().__init__(source=source)
|
||||
# self.adjustForNoise()
|
||||
|
||||
class BaseEnergyAndAudioRecorder:
|
||||
def __init__(self, source, energy_threshold, dynamic_energy_threshold, record_timeout):
|
||||
self.recorder = Recognizer()
|
||||
self.recorder.energy_threshold = energy_threshold
|
||||
self.recorder.dynamic_energy_threshold = dynamic_energy_threshold
|
||||
self.record_timeout = record_timeout
|
||||
self.stop = None
|
||||
|
||||
if source is None:
|
||||
raise ValueError("audio source can't be None")
|
||||
|
||||
self.source = source
|
||||
|
||||
def adjustForNoise(self):
|
||||
with self.source:
|
||||
self.recorder.adjust_for_ambient_noise(self.source)
|
||||
|
||||
def recordIntoQueue(self, audio_queue, energy_queue):
|
||||
def audioRecordCallback(_, audio):
|
||||
audio_queue.put((audio.get_raw_data(), datetime.now()))
|
||||
|
||||
def energyRecordCallback(energy):
|
||||
energy_queue.put(energy)
|
||||
|
||||
if isinstance(energy_queue, Queue):
|
||||
self.stop = self.recorder.listen_energy_and_audio_in_background(self.source, audioRecordCallback, phrase_time_limit=self.record_timeout, callback_energy=energyRecordCallback)
|
||||
else:
|
||||
self.stop = self.recorder.listen_energy_and_audio_in_background(self.source, audioRecordCallback, phrase_time_limit=self.record_timeout)
|
||||
|
||||
class SelectedMicEnergyAndAudioRecorder(BaseEnergyAndAudioRecorder):
|
||||
def __init__(self, device, energy_threshold, dynamic_energy_threshold, record_timeout):
|
||||
source=Microphone(
|
||||
device_index=device['index'],
|
||||
sample_rate=int(device["defaultSampleRate"]),
|
||||
)
|
||||
super().__init__(source=source, energy_threshold=energy_threshold, dynamic_energy_threshold=dynamic_energy_threshold, record_timeout=record_timeout)
|
||||
# self.adjustForNoise()
|
||||
|
||||
class SelectedSpeakerEnergyAndAudioRecorder(BaseEnergyAndAudioRecorder):
|
||||
def __init__(self, device, energy_threshold, dynamic_energy_threshold, record_timeout):
|
||||
|
||||
source = Microphone(speaker=True,
|
||||
device_index= device["index"],
|
||||
sample_rate=int(device["defaultSampleRate"]),
|
||||
chunk_size=get_sample_size(paInt16),
|
||||
channels=device["maxInputChannels"]
|
||||
)
|
||||
super().__init__(source=source, energy_threshold=energy_threshold, dynamic_energy_threshold=dynamic_energy_threshold, record_timeout=record_timeout)
|
||||
# self.adjustForNoise()
|
||||
@@ -5,18 +5,24 @@ from speech_recognition import Recognizer, AudioData, AudioFile
|
||||
from datetime import timedelta
|
||||
from pyaudiowpatch import get_sample_size, paInt16
|
||||
from .transcription_languages import transcription_lang
|
||||
from .transcription_whisper import getWhisperModel, checkWhisperWeight
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
|
||||
PHRASE_TIMEOUT = 3
|
||||
MAX_PHRASES = 10
|
||||
|
||||
class AudioTranscriber:
|
||||
def __init__(self, speaker, source, phrase_timeout, max_phrases):
|
||||
def __init__(self, speaker, source, phrase_timeout, max_phrases, transcription_engine, root=None, whisper_weight_type=None):
|
||||
self.speaker = speaker
|
||||
self.phrase_timeout = phrase_timeout
|
||||
self.max_phrases = max_phrases
|
||||
self.transcript_data = []
|
||||
self.transcript_changed_event = Event()
|
||||
self.audio_recognizer = Recognizer()
|
||||
self.transcription_engine = "Google"
|
||||
self.whisper_model = None
|
||||
self.audio_sources = {
|
||||
"sample_rate": source.SAMPLE_RATE,
|
||||
"sample_width": source.SAMPLE_WIDTH,
|
||||
@@ -27,22 +33,45 @@ class AudioTranscriber:
|
||||
"process_data_func": self.processSpeakerData if speaker else self.processSpeakerData
|
||||
}
|
||||
|
||||
if transcription_engine == "Whisper" and checkWhisperWeight(root, whisper_weight_type) is True:
|
||||
self.whisper_model = getWhisperModel(root, whisper_weight_type)
|
||||
self.transcription_engine = "Whisper"
|
||||
|
||||
def transcribeAudioQueue(self, audio_queue, language, country):
|
||||
# while True:
|
||||
audio, time_spoken = audio_queue.get()
|
||||
self.updateLastSampleAndPhraseStatus(audio, time_spoken)
|
||||
|
||||
text = ''
|
||||
try:
|
||||
# fd, path = tempfile.mkstemp(suffix=".wav")
|
||||
# os.close(fd)
|
||||
audio_data = self.audio_sources["process_data_func"]()
|
||||
text = self.audio_recognizer.recognize_google(audio_data, language=transcription_lang[language][country])
|
||||
match self.transcription_engine:
|
||||
case "Google":
|
||||
text = self.audio_recognizer.recognize_google(audio_data, language=transcription_lang[language][country][self.transcription_engine])
|
||||
case "Whisper":
|
||||
audio_data = np.frombuffer(audio_data.get_raw_data(convert_rate=16000, convert_width=2), np.int16).flatten().astype(np.float32) / 32768.0
|
||||
if isinstance(audio_data, torch.Tensor):
|
||||
audio_data = audio_data.detach().numpy()
|
||||
segments, _ = self.whisper_model.transcribe(
|
||||
audio_data,
|
||||
beam_size=5,
|
||||
temperature=0.0,
|
||||
log_prob_threshold=-0.8,
|
||||
no_speech_threshold=0.6,
|
||||
language=transcription_lang[language][country][self.transcription_engine],
|
||||
word_timestamps=False,
|
||||
without_timestamps=True,
|
||||
task="transcribe",
|
||||
vad_filter=False,
|
||||
)
|
||||
for s in segments:
|
||||
if s.avg_logprob < -0.8 or s.no_speech_prob > 0.6:
|
||||
continue
|
||||
text += s.text
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
# os.unlink(path)
|
||||
|
||||
if text != '':
|
||||
self.updateTranscript(text)
|
||||
|
||||
98
models/transcription/transcription_whisper.py
Normal file
98
models/transcription/transcription_whisper.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from os import path as os_path, makedirs as os_makedirs
|
||||
from requests import get as requests_get
|
||||
from typing import Callable
|
||||
import huggingface_hub
|
||||
from faster_whisper import WhisperModel
|
||||
import logging
|
||||
logger = logging.getLogger('faster_whisper')
|
||||
logger.setLevel(logging.CRITICAL)
|
||||
|
||||
_MODELS = {
|
||||
"tiny": "Systran/faster-whisper-tiny",
|
||||
"base": "Systran/faster-whisper-base",
|
||||
"small": "Systran/faster-whisper-small",
|
||||
"medium": "Systran/faster-whisper-medium",
|
||||
"large-v1": "Systran/faster-whisper-large-v1",
|
||||
"large-v2": "Systran/faster-whisper-large-v2",
|
||||
"large-v3": "Systran/faster-whisper-large-v3",
|
||||
}
|
||||
|
||||
_FILENAMES = [
|
||||
"config.json",
|
||||
"preprocessor_config.json",
|
||||
"model.bin",
|
||||
"tokenizer.json",
|
||||
"vocabulary.txt",
|
||||
"vocabulary.json",
|
||||
]
|
||||
|
||||
def downloadFile(url, path, func=None):
|
||||
try:
|
||||
res = requests_get(url, stream=True)
|
||||
res.raise_for_status()
|
||||
file_size = int(res.headers.get('content-length', 0))
|
||||
total_chunk = 0
|
||||
with open(os_path.join(path), 'wb') as file:
|
||||
for chunk in res.iter_content(chunk_size=1024*5):
|
||||
file.write(chunk)
|
||||
if isinstance(func, Callable):
|
||||
total_chunk += len(chunk)
|
||||
func(total_chunk/file_size)
|
||||
|
||||
except Exception as e:
|
||||
print("error:downloadFile()", e)
|
||||
|
||||
def checkWhisperWeight(root, weight_type):
|
||||
path = os_path.join(root, "weights", "whisper", weight_type)
|
||||
result = False
|
||||
try:
|
||||
WhisperModel(
|
||||
path,
|
||||
device="cpu",
|
||||
device_index=0,
|
||||
compute_type="int8",
|
||||
cpu_threads=4,
|
||||
num_workers=1,
|
||||
local_files_only=True,
|
||||
)
|
||||
result = True
|
||||
except Exception:
|
||||
pass
|
||||
return result
|
||||
|
||||
def downloadWhisperWeight(root, weight_type, callbackFunc):
|
||||
path = os_path.join(root, "weights", "whisper", weight_type)
|
||||
os_makedirs(path, exist_ok=True)
|
||||
if checkWhisperWeight(root, weight_type) is True:
|
||||
return
|
||||
|
||||
for filename in _FILENAMES:
|
||||
print("Downloading", filename, "...")
|
||||
file_path = os_path.join(path, filename)
|
||||
url = huggingface_hub.hf_hub_url(_MODELS[weight_type], filename)
|
||||
downloadFile(url, file_path, func=callbackFunc)
|
||||
|
||||
def getWhisperModel(root, weight_type):
|
||||
path = os_path.join(root, "weights", "whisper", weight_type)
|
||||
return WhisperModel(
|
||||
path,
|
||||
device="cpu",
|
||||
device_index=0,
|
||||
compute_type="int8",
|
||||
cpu_threads=4,
|
||||
num_workers=1,
|
||||
local_files_only=True,
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
def callback(value):
|
||||
print(value)
|
||||
pass
|
||||
|
||||
downloadWhisperWeight("./", "tiny", callback)
|
||||
downloadWhisperWeight("./", "base", callback)
|
||||
downloadWhisperWeight("./", "small", callback)
|
||||
downloadWhisperWeight("./", "medium", callback)
|
||||
downloadWhisperWeight("./", "large-v1", callback)
|
||||
downloadWhisperWeight("./", "large-v2", callback)
|
||||
downloadWhisperWeight("./", "large-v3", callback)
|
||||
@@ -1,8 +1,9 @@
|
||||
import gc
|
||||
import os
|
||||
from deepl import Translator as deepl_Translator
|
||||
from translators import translate_text as other_web_Translator
|
||||
from .translation_languages import translation_lang
|
||||
from .utils import ctranslate2_weights
|
||||
from .translation_utils import ctranslate2_weights
|
||||
|
||||
import ctranslate2
|
||||
import transformers
|
||||
@@ -27,7 +28,8 @@ class Translator():
|
||||
def changeCTranslate2Model(self, path, model_type):
|
||||
directory_name = ctranslate2_weights[model_type]["directory_name"]
|
||||
tokenizer = ctranslate2_weights[model_type]["tokenizer"]
|
||||
weight_path = os.path.join(path, "weight", directory_name)
|
||||
weight_path = os.path.join(path, "weights", "ctranslate2", directory_name)
|
||||
tokenizer_path = os.path.join(path, "weights", "ctranslate2", directory_name, "tokenizer")
|
||||
self.ctranslate2_translator = ctranslate2.Translator(
|
||||
weight_path,
|
||||
device="cpu",
|
||||
@@ -36,7 +38,19 @@ class Translator():
|
||||
inter_threads=1,
|
||||
intra_threads=4
|
||||
)
|
||||
self.ctranslate2_tokenizer = transformers.AutoTokenizer.from_pretrained(tokenizer)
|
||||
try:
|
||||
self.ctranslate2_tokenizer = transformers.AutoTokenizer.from_pretrained(tokenizer, cache_dir=tokenizer_path)
|
||||
except Exception as e:
|
||||
print("Error: changeCTranslate2Model()", e)
|
||||
tokenizer_path = os.path.join("./weights", "ctranslate2", directory_name, "tokenizer")
|
||||
self.ctranslate2_tokenizer = transformers.AutoTokenizer.from_pretrained(tokenizer, cache_dir=tokenizer_path)
|
||||
|
||||
def clearCTranslate2Model(self):
|
||||
del self.ctranslate2_translator
|
||||
del self.ctranslate2_tokenizer
|
||||
gc.collect()
|
||||
self.ctranslate2_translator = None
|
||||
self.ctranslate2_tokenizer = None
|
||||
|
||||
@staticmethod
|
||||
def getLanguageCode(translator_name, target_country, source_language, target_language):
|
||||
|
||||
@@ -39,36 +39,36 @@ def calculate_file_hash(file_path, block_size=65536):
|
||||
return hash_object.hexdigest()
|
||||
|
||||
def checkCTranslate2Weight(path, weight_type="Small"):
|
||||
directory_name = 'weight'
|
||||
current_directory = path
|
||||
weight_directory_name = ctranslate2_weights[weight_type]["directory_name"]
|
||||
hash_data = ctranslate2_weights[weight_type]["hash"]
|
||||
files = ["model.bin", "sentencepiece.model", "shared_vocabulary.txt"]
|
||||
files = [
|
||||
"model.bin",
|
||||
"sentencepiece.model",
|
||||
"shared_vocabulary.txt"
|
||||
]
|
||||
|
||||
# check already downloaded
|
||||
already_downloaded = False
|
||||
if all(os_path.exists(os_path.join(current_directory, directory_name, weight_directory_name, file)) for file in files):
|
||||
if all(os_path.exists(os_path.join(path, weight_directory_name, file)) for file in files):
|
||||
# check hash
|
||||
for file in files:
|
||||
original_hash = hash_data[file]
|
||||
current_hash = calculate_file_hash(os_path.join(current_directory, directory_name, weight_directory_name, file))
|
||||
current_hash = calculate_file_hash(os_path.join(path, weight_directory_name, file))
|
||||
if original_hash != current_hash:
|
||||
break
|
||||
already_downloaded = True
|
||||
return already_downloaded
|
||||
|
||||
def downloadCTranslate2Weight(path, weight_type="Small", func=None):
|
||||
def downloadCTranslate2Weight(root, weight_type="Small", func=None):
|
||||
url = ctranslate2_weights[weight_type]["url"]
|
||||
filename = 'weight.zip'
|
||||
directory_name = 'weight'
|
||||
current_directory = path
|
||||
filename = "weight.zip"
|
||||
path = os_path.join(root, "weights", "ctranslate2")
|
||||
os_makedirs(path, exist_ok=True)
|
||||
|
||||
if checkCTranslate2Weight(path, weight_type):
|
||||
return
|
||||
|
||||
try:
|
||||
os_makedirs(os_path.join(current_directory, directory_name), exist_ok=True)
|
||||
print(os_path.join(current_directory, directory_name))
|
||||
with tempfile.TemporaryDirectory() as tmp_path:
|
||||
res = requests_get(url, stream=True)
|
||||
file_size = int(res.headers.get('content-length', 0))
|
||||
@@ -81,6 +81,6 @@ def downloadCTranslate2Weight(path, weight_type="Small", func=None):
|
||||
func(total_chunk/file_size)
|
||||
|
||||
with ZipFile(os_path.join(tmp_path, filename)) as zf:
|
||||
zf.extractall(os_path.join(current_directory, directory_name))
|
||||
zf.extractall(path)
|
||||
except Exception as e:
|
||||
print("error:downloadCTranslate2Weight()", e)
|
||||
@@ -8,6 +8,10 @@ pyyaml == 6.0.1
|
||||
python-i18n == 0.3.9
|
||||
CTkToolTip == 0.8
|
||||
pyinstaller==6.2.0
|
||||
transformers[torch]
|
||||
transformers[torch]==4.37.2
|
||||
sentencepiece==0.1.99
|
||||
ctranslate2==3.21.0
|
||||
ctranslate2==3.24.0
|
||||
faster-whisper==0.10.0
|
||||
translators @ git+https://github.com/misyaguziya/translators@5.8.9
|
||||
SpeechRecognition @ git+https://github.com/misyaguziya/custom_speech_recognition@3.10.2
|
||||
tinyoscquery @ git+https://github.com/cyberkitsune/tinyoscquery@0.1.2
|
||||
10
utils.py
10
utils.py
@@ -1,5 +1,5 @@
|
||||
from typing import Union
|
||||
from os import path as os_path
|
||||
from os import path as os_path, rename as os_rename
|
||||
from PIL.Image import open as Image_open
|
||||
|
||||
def getImageFile(file_name):
|
||||
@@ -49,4 +49,10 @@ def isUniqueStrings(unique_strings:Union[str, list], input_string:str, require=F
|
||||
return all(count == 1 for count in counts) and counts.count(1) == 2
|
||||
else:
|
||||
# If require is False, check if unique strings are used exactly once
|
||||
return all(count == 1 for count in counts)
|
||||
return all(count == 1 for count in counts)
|
||||
|
||||
# path先のweightフォルダがある場合にはそのフォルダ名をweightsに変更する
|
||||
def renameWeightFolder(path):
|
||||
weight_path = os_path.join(path, "weight")
|
||||
if os_path.exists(weight_path):
|
||||
os_rename(weight_path, os_path.join(path, "weights"))
|
||||
214
view.py
214
view.py
@@ -29,6 +29,7 @@ class View():
|
||||
font_family=config.FONT_FAMILY,
|
||||
ui_language=config.UI_LANGUAGE,
|
||||
is_reset_button_displayed_for_translation=config.IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION,
|
||||
is_reset_button_displayed_for_whisper=config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER,
|
||||
)
|
||||
|
||||
if config.ENABLE_SPEAKER2CHATBOX is False:
|
||||
@@ -36,7 +37,7 @@ class View():
|
||||
else:
|
||||
VERSION_TEXT=i18n.t("config_window.version", version=config.VERSION) + " (Speaker2Chatbox)"
|
||||
|
||||
self.TEXT_TRANSLATOR_CTRANSLATE2 = i18n.t("main_window.translator") + ": " + i18n.t("main_window.translator_ctranslate2")
|
||||
self.TEXT_TRANSLATOR_CTRANSLATE2=i18n.t("main_window.translator") + ": " + i18n.t("main_window.translator_ctranslate2")
|
||||
|
||||
self.settings = SimpleNamespace()
|
||||
theme = get_appearance_mode() if config.APPEARANCE_THEME == "System" else config.APPEARANCE_THEME
|
||||
@@ -102,6 +103,7 @@ class View():
|
||||
CALLBACK_UPDATE_SOFTWARE=None,
|
||||
CALLBACK_OPEN_FILEPATH_LOGS=None,
|
||||
CALLBACK_OPEN_FILEPATH_CONFIG_FILE=None,
|
||||
CALLBACK_OPEN_WEBPAGE_DEEPL_AUTH_KEY=self.openWebPage_DeepL_Auth_Key,
|
||||
|
||||
CALLBACK_DELETE_MAIN_WINDOW=self.quitVRCT,
|
||||
CALLBACK_QUIT_VRCT=None,
|
||||
@@ -157,7 +159,7 @@ class View():
|
||||
CALLBACK_SELECTED_LANGUAGE_PRESET_TAB=None,
|
||||
|
||||
VAR_LABEL_YOUR_LANGUAGE=StringVar(value=i18n.t("main_window.your_language")),
|
||||
VAR_YOUR_LANGUAGE = StringVar(value=f"{config.SOURCE_LANGUAGE}\n({config.SOURCE_COUNTRY})"),
|
||||
VAR_YOUR_LANGUAGE=StringVar(value=f"{config.SOURCE_LANGUAGE}\n({config.SOURCE_COUNTRY})"),
|
||||
CALLBACK_OPEN_SELECTABLE_YOUR_LANGUAGE_WINDOW=None,
|
||||
IS_OPENED_SELECTABLE_YOUR_LANGUAGE_WINDOW=False,
|
||||
CALLBACK_SELECTED_YOUR_LANGUAGE=None,
|
||||
@@ -168,13 +170,13 @@ class View():
|
||||
CALLBACK_LEAVED_SWAP_LANGUAGES_BUTTON=self._leavedSwapLanguagesButton,
|
||||
|
||||
VAR_LABEL_TARGET_LANGUAGE=StringVar(value=i18n.t("main_window.target_language")),
|
||||
VAR_TARGET_LANGUAGE = StringVar(value=f"{config.TARGET_LANGUAGE}\n({config.TARGET_COUNTRY})"),
|
||||
VAR_TARGET_LANGUAGE=StringVar(value=f"{config.TARGET_LANGUAGE}\n({config.TARGET_COUNTRY})"),
|
||||
CALLBACK_OPEN_SELECTABLE_TARGET_LANGUAGE_WINDOW=None,
|
||||
IS_OPENED_SELECTABLE_TARGET_LANGUAGE_WINDOW=False,
|
||||
CALLBACK_SELECTED_TARGET_LANGUAGE=None,
|
||||
|
||||
VAR_SELECTED_TRANSLATION_ENGINE = StringVar(value="Translator: INIT"),
|
||||
CALLBACK_SELECTED_TRANSLATION_ENGINE = None,
|
||||
VAR_SELECTED_TRANSLATION_ENGINE=StringVar(value="Translator: INIT"),
|
||||
CALLBACK_SELECTED_TRANSLATION_ENGINE=None,
|
||||
|
||||
VAR_LABEL_TEXTBOX_ALL=StringVar(value=i18n.t("main_window.textbox_tab_all")),
|
||||
VAR_LABEL_TEXTBOX_SENT=StringVar(value=i18n.t("main_window.textbox_tab_sent")),
|
||||
@@ -184,6 +186,8 @@ class View():
|
||||
VAR_UPDATE_AVAILABLE=StringVar(value=i18n.t("main_window.update_available")),
|
||||
|
||||
|
||||
CALLBACK_MESSAGE_BOX_BIND_KEYSYM__UP=None,
|
||||
CALLBACK_MESSAGE_BOX_BIND_KEYSYM__DOWN=None,
|
||||
# Main Window Cover
|
||||
VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE=StringVar(value=""),
|
||||
|
||||
@@ -211,6 +215,7 @@ class View():
|
||||
VAR_SIDE_MENU_LABEL_TRANSCRIPTION=StringVar(value=i18n.t("config_window.side_menu_labels.transcription")),
|
||||
VAR_SECOND_TITLE_TRANSCRIPTION_MIC=StringVar(value=i18n.t("config_window.side_menu_labels.transcription_mic")),
|
||||
VAR_SECOND_TITLE_TRANSCRIPTION_SPEAKER=StringVar(value=i18n.t("config_window.side_menu_labels.transcription_speaker")),
|
||||
VAR_SECOND_TITLE_TRANSCRIPTION_INTERNAL_MODEL=StringVar(value=i18n.t("config_window.side_menu_labels.transcription_internal_model")),
|
||||
VAR_SIDE_MENU_LABEL_OTHERS=StringVar(value=i18n.t("config_window.side_menu_labels.others")),
|
||||
VAR_SIDE_MENU_LABEL_ADVANCED_SETTINGS=StringVar(value=i18n.t("config_window.side_menu_labels.advanced_settings")),
|
||||
|
||||
@@ -280,7 +285,7 @@ class View():
|
||||
VAR_DESC_CTRANSLATE2_WEIGHT_TYPE=StringVar(value=i18n.t("config_window.ctranslate2_weight_type.desc")),
|
||||
DICT_CTRANSLATE2_WEIGHT_TYPE=self.getSelectableCtranslate2WeightTypeDict(),
|
||||
CALLBACK_SET_CTRANSLATE2_WEIGHT_TYPE=None,
|
||||
VAR_CTRANSLATE2_WEIGHT_TYPE=StringVar(value=self.getSelectableCtranslate2WeightTypeDict()[config.WEIGHT_TYPE]),
|
||||
VAR_CTRANSLATE2_WEIGHT_TYPE=StringVar(value=self.getSelectableCtranslate2WeightTypeDict()[config.CTRANSLATE2_WEIGHT_TYPE]),
|
||||
|
||||
VAR_LABEL_DEEPL_AUTH_KEY=StringVar(value=i18n.t( "config_window.deepl_auth_key.label")),
|
||||
VAR_DESC_DEEPL_AUTH_KEY=StringVar(
|
||||
@@ -291,6 +296,7 @@ class View():
|
||||
),
|
||||
CALLBACK_SET_DEEPL_AUTH_KEY=None,
|
||||
VAR_DEEPL_AUTH_KEY=StringVar(value=config.AUTH_KEYS["DeepL_API"]),
|
||||
VAR_OPEN_DEEPL_WEB_PAGE=StringVar(value=i18n.t( "config_window.deepl_auth_key.open_auth_key_webpage")),
|
||||
|
||||
|
||||
# Transcription Tab (Mic)
|
||||
@@ -381,6 +387,19 @@ class View():
|
||||
CALLBACK_FOCUS_OUT_SPEAKER_MAX_PHRASES=self.callbackBindFocusOut_SpeakerMaxPhrases,
|
||||
|
||||
|
||||
# Transcription Tab (Whisper Internal AI Model)
|
||||
VAR_LABEL_USE_WHISPER_FEATURE=StringVar(value=i18n.t("config_window.use_whisper_feature.label")),
|
||||
VAR_DESC_USE_WHISPER_FEATURE=StringVar(value=i18n.t("config_window.use_whisper_feature.desc")),
|
||||
CALLBACK_SET_USE_WHISPER_FEATURE=None,
|
||||
VAR_USE_WHISPER_FEATURE=BooleanVar(value=config.USE_WHISPER_FEATURE),
|
||||
|
||||
VAR_LABEL_WHISPER_WEIGHT_TYPE=StringVar(value=i18n.t("config_window.whisper_weight_type.label")),
|
||||
VAR_DESC_WHISPER_WEIGHT_TYPE=StringVar(value=i18n.t("config_window.whisper_weight_type.desc")),
|
||||
DICT_WHISPER_WEIGHT_TYPE=self.getSelectableWhisperWeightTypeDict(),
|
||||
CALLBACK_SET_WHISPER_WEIGHT_TYPE=None,
|
||||
VAR_WHISPER_WEIGHT_TYPE=StringVar(value=self.getSelectableWhisperWeightTypeDict()[config.WHISPER_WEIGHT_TYPE]),
|
||||
|
||||
|
||||
# Others Tab
|
||||
VAR_LABEL_ENABLE_AUTO_CLEAR_MESSAGE_BOX=StringVar(value=i18n.t("config_window.auto_clear_the_message_box.label")),
|
||||
VAR_DESC_ENABLE_AUTO_CLEAR_MESSAGE_BOX=None,
|
||||
@@ -527,23 +546,23 @@ class View():
|
||||
|
||||
|
||||
if main_window_registers is not None:
|
||||
self.view_variable.CALLBACK_ENABLE_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = main_window_registers.get("callback_enable_main_window_sidebar_compact_mode", None)
|
||||
self.view_variable.CALLBACK_DISABLE_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = main_window_registers.get("callback_disable_main_window_sidebar_compact_mode", None)
|
||||
self.view_variable.CALLBACK_ENABLE_MAIN_WINDOW_SIDEBAR_COMPACT_MODE=main_window_registers.get("callback_enable_main_window_sidebar_compact_mode", None)
|
||||
self.view_variable.CALLBACK_DISABLE_MAIN_WINDOW_SIDEBAR_COMPACT_MODE=main_window_registers.get("callback_disable_main_window_sidebar_compact_mode", None)
|
||||
|
||||
|
||||
self.view_variable.CALLBACK_TOGGLE_TRANSLATION = main_window_registers.get("callback_toggle_translation", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_TRANSCRIPTION_SEND = main_window_registers.get("callback_toggle_transcription_send", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_TRANSCRIPTION_RECEIVE = main_window_registers.get("callback_toggle_transcription_receive", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_FOREGROUND = main_window_registers.get("callback_toggle_foreground", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_TRANSLATION=main_window_registers.get("callback_toggle_translation", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_TRANSCRIPTION_SEND=main_window_registers.get("callback_toggle_transcription_send", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_TRANSCRIPTION_RECEIVE=main_window_registers.get("callback_toggle_transcription_receive", None)
|
||||
self.view_variable.CALLBACK_TOGGLE_FOREGROUND=main_window_registers.get("callback_toggle_foreground", None)
|
||||
|
||||
self.view_variable.CALLBACK_SELECTED_YOUR_LANGUAGE = main_window_registers.get("callback_your_language", None)
|
||||
self.view_variable.CALLBACK_SELECTED_TARGET_LANGUAGE = main_window_registers.get("callback_target_language", None)
|
||||
self.view_variable.CALLBACK_SELECTED_YOUR_LANGUAGE=main_window_registers.get("callback_your_language", None)
|
||||
self.view_variable.CALLBACK_SELECTED_TARGET_LANGUAGE=main_window_registers.get("callback_target_language", None)
|
||||
main_window_registers.get("values", None) and self.updateList_selectableLanguages(main_window_registers["values"])
|
||||
self.view_variable.CALLBACK_SWAP_LANGUAGES = main_window_registers.get("callback_swap_languages", None)
|
||||
self.view_variable.CALLBACK_SWAP_LANGUAGES=main_window_registers.get("callback_swap_languages", None)
|
||||
|
||||
self.view_variable.CALLBACK_SELECTED_LANGUAGE_PRESET_TAB = main_window_registers.get("callback_selected_language_preset_tab", None)
|
||||
self.view_variable.CALLBACK_SELECTED_LANGUAGE_PRESET_TAB=main_window_registers.get("callback_selected_language_preset_tab", None)
|
||||
|
||||
self.view_variable.CALLBACK_SELECTED_TRANSLATION_ENGINE = main_window_registers.get("callback_selected_translation_engine", None)
|
||||
self.view_variable.CALLBACK_SELECTED_TRANSLATION_ENGINE=main_window_registers.get("callback_selected_translation_engine", None)
|
||||
|
||||
def adjustedMessageBoxReturnFunction(_e):
|
||||
if self.view_variable.IS_ENTRY_MESSAGE_BOX_DISABLED is True:
|
||||
@@ -555,11 +574,15 @@ class View():
|
||||
main_window_registers.get("message_box_bind_Return")()
|
||||
vrct_gui.entry_message_box.focus()
|
||||
|
||||
entry_message_box = getattr(vrct_gui, "entry_message_box")
|
||||
entry_message_box=getattr(vrct_gui, "entry_message_box")
|
||||
entry_message_box.bind("<Shift-Return>", lambda _e: None) # This is to prevent message sending on Shift + Enter key press and just add a new line.
|
||||
entry_message_box.bind("<Return>", adjustedMessageBoxReturnFunction)
|
||||
entry_message_box.bind("<Any-KeyPress>", main_window_registers.get("message_box_bind_Any_KeyPress"))
|
||||
self.view_variable.CALLBACK_CLICKED_SEND_MESSAGE_BUTTON = pressedSendMessageButtonFunction
|
||||
self.view_variable.CALLBACK_CLICKED_SEND_MESSAGE_BUTTON=pressedSendMessageButtonFunction
|
||||
|
||||
|
||||
self.view_variable.CALLBACK_MESSAGE_BOX_BIND_KEYSYM__UP=main_window_registers.get("message_box_bind_Up_KeyPress")
|
||||
self.view_variable.CALLBACK_MESSAGE_BOX_BIND_KEYSYM__DOWN=main_window_registers.get("message_box_bind_Down_KeyPress")
|
||||
|
||||
|
||||
entry_message_box.bind("<FocusIn>", main_window_registers.get("message_box_bind_FocusIn"))
|
||||
@@ -569,8 +592,8 @@ class View():
|
||||
self.updateGuiVariableByPresetTabNo(config.SELECTED_TAB_NO)
|
||||
vrct_gui._setDefaultActiveLanguagePresetTab(tab_no=config.SELECTED_TAB_NO)
|
||||
|
||||
self.view_variable.CALLBACK_OPEN_SELECTABLE_YOUR_LANGUAGE_WINDOW = self.openSelectableLanguagesWindow_YourLanguage
|
||||
self.view_variable.CALLBACK_OPEN_SELECTABLE_TARGET_LANGUAGE_WINDOW = self.openSelectableLanguagesWindow_TargetLanguage
|
||||
self.view_variable.CALLBACK_OPEN_SELECTABLE_YOUR_LANGUAGE_WINDOW=self.openSelectableLanguagesWindow_YourLanguage
|
||||
self.view_variable.CALLBACK_OPEN_SELECTABLE_TARGET_LANGUAGE_WINDOW=self.openSelectableLanguagesWindow_TargetLanguage
|
||||
|
||||
|
||||
# Config Window
|
||||
@@ -579,74 +602,79 @@ class View():
|
||||
|
||||
if config_window_registers is not None:
|
||||
# Compact Mode Switch
|
||||
self.view_variable.CALLBACK_ENABLE_CONFIG_WINDOW_COMPACT_MODE = config_window_registers.get("callback_disable_config_window_compact_mode", None)
|
||||
self.view_variable.CALLBACK_DISABLE_CONFIG_WINDOW_COMPACT_MODE = config_window_registers.get("callback_enable_config_window_compact_mode", None)
|
||||
self.view_variable.CALLBACK_ENABLE_CONFIG_WINDOW_COMPACT_MODE=config_window_registers.get("callback_disable_config_window_compact_mode", None)
|
||||
self.view_variable.CALLBACK_DISABLE_CONFIG_WINDOW_COMPACT_MODE=config_window_registers.get("callback_enable_config_window_compact_mode", None)
|
||||
|
||||
|
||||
# Appearance Tab
|
||||
self.view_variable.CALLBACK_SET_TRANSPARENCY = config_window_registers.get("callback_set_transparency", None)
|
||||
self.view_variable.CALLBACK_SET_TRANSPARENCY=config_window_registers.get("callback_set_transparency", None)
|
||||
|
||||
self.view_variable.CALLBACK_SET_APPEARANCE = config_window_registers.get("callback_set_appearance", None)
|
||||
self.view_variable.CALLBACK_SET_UI_SCALING = config_window_registers.get("callback_set_ui_scaling", None)
|
||||
self.view_variable.CALLBACK_SET_TEXTBOX_UI_SCALING = config_window_registers.get("callback_set_textbox_ui_scaling", None)
|
||||
self.view_variable.CALLBACK_SET_MESSAGE_BOX_RATIO = config_window_registers.get("callback_set_message_box_ratio", None)
|
||||
self.view_variable.CALLBACK_SET_FONT_FAMILY = config_window_registers.get("callback_set_font_family", None)
|
||||
self.view_variable.CALLBACK_SET_UI_LANGUAGE = config_window_registers.get("callback_set_ui_language", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY = config_window_registers.get("callback_set_enable_restore_main_window_geometry", None)
|
||||
self.view_variable.CALLBACK_SET_APPEARANCE=config_window_registers.get("callback_set_appearance", None)
|
||||
self.view_variable.CALLBACK_SET_UI_SCALING=config_window_registers.get("callback_set_ui_scaling", None)
|
||||
self.view_variable.CALLBACK_SET_TEXTBOX_UI_SCALING=config_window_registers.get("callback_set_textbox_ui_scaling", None)
|
||||
self.view_variable.CALLBACK_SET_MESSAGE_BOX_RATIO=config_window_registers.get("callback_set_message_box_ratio", None)
|
||||
self.view_variable.CALLBACK_SET_FONT_FAMILY=config_window_registers.get("callback_set_font_family", None)
|
||||
self.view_variable.CALLBACK_SET_UI_LANGUAGE=config_window_registers.get("callback_set_ui_language", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY=config_window_registers.get("callback_set_enable_restore_main_window_geometry", None)
|
||||
|
||||
|
||||
# Translation Tab
|
||||
self.view_variable.CALLBACK_SET_USE_TRANSLATION_FEATURE = config_window_registers.get("callback_set_use_translation_feature", None)
|
||||
self.view_variable.CALLBACK_SET_CTRANSLATE2_WEIGHT_TYPE = config_window_registers.get("callback_set_ctranslate2_weight_type", None)
|
||||
self.view_variable.CALLBACK_SET_DEEPL_AUTH_KEY = config_window_registers.get("callback_set_deepl_auth_key", None)
|
||||
self.view_variable.CALLBACK_SET_USE_TRANSLATION_FEATURE=config_window_registers.get("callback_set_use_translation_feature", None)
|
||||
self.view_variable.CALLBACK_SET_CTRANSLATE2_WEIGHT_TYPE=config_window_registers.get("callback_set_ctranslate2_weight_type", None)
|
||||
self.view_variable.CALLBACK_SET_DEEPL_AUTH_KEY=config_window_registers.get("callback_set_deepl_auth_key", None)
|
||||
|
||||
# Transcription Tab (Mic)
|
||||
self.view_variable.CALLBACK_SET_MIC_HOST = config_window_registers.get("callback_set_mic_host", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_HOST=config_window_registers.get("callback_set_mic_host", None)
|
||||
config_window_registers.get("list_mic_host", None) and self.updateList_MicHost(config_window_registers["list_mic_host"])
|
||||
|
||||
self.view_variable.CALLBACK_SET_MIC_DEVICE = config_window_registers.get("callback_set_mic_device", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_DEVICE=config_window_registers.get("callback_set_mic_device", None)
|
||||
config_window_registers.get("list_mic_device", None) and self.updateList_MicDevice(config_window_registers["list_mic_device"])
|
||||
|
||||
self.view_variable.CALLBACK_SET_MIC_ENERGY_THRESHOLD = config_window_registers.get("callback_set_mic_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_DYNAMIC_ENERGY_THRESHOLD = config_window_registers.get("callback_set_mic_dynamic_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_CHECK_MIC_THRESHOLD = config_window_registers.get("callback_check_mic_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_RECORD_TIMEOUT = config_window_registers.get("callback_set_mic_record_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_PHRASE_TIMEOUT = config_window_registers.get("callback_set_mic_phrase_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_MAX_PHRASES = config_window_registers.get("callback_set_mic_max_phrases", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_WORD_FILTER = config_window_registers.get("callback_set_mic_word_filter", None)
|
||||
self.view_variable.CALLBACK_DELETE_MIC_WORD_FILTER = config_window_registers.get("callback_delete_mic_word_filter", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_ENERGY_THRESHOLD=config_window_registers.get("callback_set_mic_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_DYNAMIC_ENERGY_THRESHOLD=config_window_registers.get("callback_set_mic_dynamic_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_CHECK_MIC_THRESHOLD=config_window_registers.get("callback_check_mic_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_RECORD_TIMEOUT=config_window_registers.get("callback_set_mic_record_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_PHRASE_TIMEOUT=config_window_registers.get("callback_set_mic_phrase_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_MAX_PHRASES=config_window_registers.get("callback_set_mic_max_phrases", None)
|
||||
self.view_variable.CALLBACK_SET_MIC_WORD_FILTER=config_window_registers.get("callback_set_mic_word_filter", None)
|
||||
self.view_variable.CALLBACK_DELETE_MIC_WORD_FILTER=config_window_registers.get("callback_delete_mic_word_filter", None)
|
||||
|
||||
# Transcription Tab (Speaker)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_ENERGY_THRESHOLD = config_window_registers.get("callback_set_speaker_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_DYNAMIC_ENERGY_THRESHOLD = config_window_registers.get("callback_set_speaker_dynamic_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_CHECK_SPEAKER_THRESHOLD = config_window_registers.get("callback_check_speaker_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_RECORD_TIMEOUT = config_window_registers.get("callback_set_speaker_record_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_PHRASE_TIMEOUT = config_window_registers.get("callback_set_speaker_phrase_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_MAX_PHRASES = config_window_registers.get("callback_set_speaker_max_phrases", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_ENERGY_THRESHOLD=config_window_registers.get("callback_set_speaker_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_DYNAMIC_ENERGY_THRESHOLD=config_window_registers.get("callback_set_speaker_dynamic_energy_threshold", None)
|
||||
self.view_variable.CALLBACK_CHECK_SPEAKER_THRESHOLD=config_window_registers.get("callback_check_speaker_threshold", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_RECORD_TIMEOUT=config_window_registers.get("callback_set_speaker_record_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_PHRASE_TIMEOUT=config_window_registers.get("callback_set_speaker_phrase_timeout", None)
|
||||
self.view_variable.CALLBACK_SET_SPEAKER_MAX_PHRASES=config_window_registers.get("callback_set_speaker_max_phrases", None)
|
||||
|
||||
# Transcription Tab (Internal AI Model)
|
||||
self.view_variable.CALLBACK_SET_USE_WHISPER_FEATURE=config_window_registers.get("callback_set_use_whisper_feature", None)
|
||||
self.view_variable.CALLBACK_SET_WHISPER_WEIGHT_TYPE=config_window_registers.get("callback_set_whisper_weight_type", None)
|
||||
|
||||
|
||||
# Others Tab
|
||||
self.view_variable.CALLBACK_SET_ENABLE_AUTO_CLEAR_MESSAGE_BOX = config_window_registers.get("callback_set_enable_auto_clear_chatbox", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_SEND_ONLY_TRANSLATED_MESSAGES = config_window_registers.get("callback_set_send_only_translated_messages", None)
|
||||
self.view_variable.CALLBACK_SET_SEND_MESSAGE_BUTTON_TYPE = config_window_registers.get("callback_set_send_message_button_type", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_NOTICE_XSOVERLAY = config_window_registers.get("callback_set_enable_notice_xsoverlay", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_AUTO_EXPORT_MESSAGE_LOGS = config_window_registers.get("callback_set_enable_auto_export_message_logs", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_AUTO_CLEAR_MESSAGE_BOX=config_window_registers.get("callback_set_enable_auto_clear_chatbox", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_SEND_ONLY_TRANSLATED_MESSAGES=config_window_registers.get("callback_set_send_only_translated_messages", None)
|
||||
self.view_variable.CALLBACK_SET_SEND_MESSAGE_BUTTON_TYPE=config_window_registers.get("callback_set_send_message_button_type", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_NOTICE_XSOVERLAY=config_window_registers.get("callback_set_enable_notice_xsoverlay", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_AUTO_EXPORT_MESSAGE_LOGS=config_window_registers.get("callback_set_enable_auto_export_message_logs", None)
|
||||
|
||||
self.view_variable.CALLBACK_SET_ENABLE_SEND_MESSAGE_TO_VRC = config_window_registers.get("callback_set_enable_send_message_to_vrc", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_SEND_MESSAGE_TO_VRC=config_window_registers.get("callback_set_enable_send_message_to_vrc", None)
|
||||
|
||||
self.view_variable.CALLBACK_SET_SEND_MESSAGE_FORMAT = config_window_registers.get("callback_set_send_message_format", None)
|
||||
self.view_variable.CALLBACK_SET_SEND_MESSAGE_FORMAT_WITH_T = config_window_registers.get("callback_set_send_message_format_with_t", None)
|
||||
self.view_variable.CALLBACK_SET_RECEIVED_MESSAGE_FORMAT = config_window_registers.get("callback_set_received_message_format", None)
|
||||
self.view_variable.CALLBACK_SET_RECEIVED_MESSAGE_FORMAT_WITH_T = config_window_registers.get("callback_set_received_message_format_with_t", None)
|
||||
self.view_variable.CALLBACK_SET_SEND_MESSAGE_FORMAT=config_window_registers.get("callback_set_send_message_format", None)
|
||||
self.view_variable.CALLBACK_SET_SEND_MESSAGE_FORMAT_WITH_T=config_window_registers.get("callback_set_send_message_format_with_t", None)
|
||||
self.view_variable.CALLBACK_SET_RECEIVED_MESSAGE_FORMAT=config_window_registers.get("callback_set_received_message_format", None)
|
||||
self.view_variable.CALLBACK_SET_RECEIVED_MESSAGE_FORMAT_WITH_T=config_window_registers.get("callback_set_received_message_format_with_t", None)
|
||||
|
||||
# Speaker2Chatbox----------------
|
||||
self.view_variable.CALLBACK_SET_ENABLE_SEND_RECEIVED_MESSAGE_TO_VRC = config_window_registers.get("callback_set_enable_send_received_message_to_vrc", None)
|
||||
self.view_variable.CALLBACK_SET_ENABLE_SEND_RECEIVED_MESSAGE_TO_VRC=config_window_registers.get("callback_set_enable_send_received_message_to_vrc", None)
|
||||
# Speaker2Chatbox----------------
|
||||
|
||||
|
||||
|
||||
# Advanced Settings Tab
|
||||
self.view_variable.CALLBACK_SET_OSC_IP_ADDRESS = config_window_registers.get("callback_set_osc_ip_address", None)
|
||||
self.view_variable.CALLBACK_SET_OSC_PORT = config_window_registers.get("callback_set_osc_port", None)
|
||||
self.view_variable.CALLBACK_SET_OSC_IP_ADDRESS=config_window_registers.get("callback_set_osc_ip_address", None)
|
||||
self.view_variable.CALLBACK_SET_OSC_PORT=config_window_registers.get("callback_set_osc_port", None)
|
||||
|
||||
# The initial processing after registration.
|
||||
if config.IS_CONFIG_WINDOW_COMPACT_MODE is True:
|
||||
@@ -678,6 +706,11 @@ class View():
|
||||
)
|
||||
self.replaceMicThresholdCheckButton_Disabled()
|
||||
|
||||
if config.USE_WHISPER_FEATURE is True:
|
||||
self.openWhisperWeightTypeWidget()
|
||||
else:
|
||||
self.closeWhisperWeightTypeWidget()
|
||||
|
||||
if config.ENABLE_SPEAKER2CHATBOX is False:
|
||||
vrct_gui._changeConfigWindowWidgetsStatus(
|
||||
status="disabled",
|
||||
@@ -882,8 +915,8 @@ class View():
|
||||
@staticmethod
|
||||
def getSelectableCtranslate2WeightTypeDict():
|
||||
return {
|
||||
config._SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT["Small"]: i18n.t("config_window.ctranslate2_weight_type.small", capacity="418MB"),
|
||||
config._SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT["Large"]: i18n.t("config_window.ctranslate2_weight_type.large", capacity="1.2GB"),
|
||||
config.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT["Small"]: i18n.t("config_window.ctranslate2_weight_type.small", capacity="418MB"),
|
||||
config.SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT["Large"]: i18n.t("config_window.ctranslate2_weight_type.large", capacity="1.2GB"),
|
||||
}
|
||||
|
||||
def useTranslationFeatureProcess(self, state:str):
|
||||
@@ -919,6 +952,24 @@ class View():
|
||||
vrct_gui.update()
|
||||
vrct_gui.config_window.lift()
|
||||
|
||||
@staticmethod
|
||||
def getSelectableWhisperWeightTypeDict():
|
||||
def callI18n(model_name, capacity, is_recommended=False):
|
||||
if is_recommended is True:
|
||||
return i18n.t("config_window.whisper_weight_type.recommended_model_template", model_name=model_name, capacity=capacity)
|
||||
else:
|
||||
return i18n.t("config_window.whisper_weight_type.model_template", model_name=model_name, capacity=capacity)
|
||||
|
||||
DICT_DATA = config.SELECTABLE_WHISPER_WEIGHT_TYPE_DICT
|
||||
return {
|
||||
DICT_DATA["tiny"]: callI18n("tiny", "74.5MB"),
|
||||
DICT_DATA["base"]: callI18n("base", "141MB", True),
|
||||
DICT_DATA["small"]: callI18n("small", "463MB"),
|
||||
DICT_DATA["medium"]: callI18n("medium", "1.42GB"),
|
||||
DICT_DATA["large-v1"]: callI18n("large-v1", "2.87GB"),
|
||||
DICT_DATA["large-v2"]: callI18n("large-v2", "2.87GB"),
|
||||
DICT_DATA["large-v3"]: callI18n("large-v3", "2.87GB"),
|
||||
}
|
||||
|
||||
# Open Webpage Functions
|
||||
def openWebPage_Booth(self):
|
||||
@@ -929,6 +980,10 @@ class View():
|
||||
self.openWebPage(config.DOCUMENTS_URL)
|
||||
self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.opened_web_page_vrct_documents"))
|
||||
|
||||
def openWebPage_DeepL_Auth_Key(self):
|
||||
self.openWebPage(config.DEEPL_AUTH_KEY_PAGE_URL)
|
||||
|
||||
|
||||
# Widget Control
|
||||
# Common
|
||||
|
||||
@@ -1014,7 +1069,8 @@ class View():
|
||||
self.restart_required_configs_pre_data.ui_scaling == config.UI_SCALING and
|
||||
self.restart_required_configs_pre_data.font_family == config.FONT_FAMILY and
|
||||
self.restart_required_configs_pre_data.ui_language == config.UI_LANGUAGE and
|
||||
self.restart_required_configs_pre_data.is_reset_button_displayed_for_translation == config.IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION
|
||||
self.restart_required_configs_pre_data.is_reset_button_displayed_for_translation == config.IS_RESET_BUTTON_DISPLAYED_FOR_TRANSLATION and
|
||||
self.restart_required_configs_pre_data.is_reset_button_displayed_for_whisper == config.IS_RESET_BUTTON_DISPLAYED_FOR_WHISPER
|
||||
)
|
||||
|
||||
if locale is None:
|
||||
@@ -1069,7 +1125,7 @@ class View():
|
||||
self.view_variable.VAR_CTRANSLATE2_WEIGHT_TYPE.set(self.getSelectableCtranslate2WeightTypeDict()[selected_weight_type])
|
||||
|
||||
def setLatestCTranslate2WeightType(self):
|
||||
selected_weight_type = self.getSelectableCtranslate2WeightTypeDict()[config.WEIGHT_TYPE]
|
||||
selected_weight_type = self.getSelectableCtranslate2WeightTypeDict()[config.CTRANSLATE2_WEIGHT_TYPE]
|
||||
self.view_variable.VAR_CTRANSLATE2_WEIGHT_TYPE.set(selected_weight_type)
|
||||
|
||||
|
||||
@@ -1082,6 +1138,23 @@ class View():
|
||||
vrct_gui.config_window.sb__ctranslate2_weight_type.grid_remove()
|
||||
|
||||
|
||||
def openWhisperWeightTypeWidget(self):
|
||||
vrct_gui.config_window.sb__use_whisper_feature.grid()
|
||||
vrct_gui.config_window.sb__whisper_weight_type.grid()
|
||||
|
||||
def closeWhisperWeightTypeWidget(self):
|
||||
vrct_gui.config_window.sb__use_whisper_feature.grid()
|
||||
vrct_gui.config_window.sb__whisper_weight_type.grid_remove()
|
||||
|
||||
|
||||
def updateSelectedWhisperWeightType(self, selected_weight_type:str):
|
||||
self.view_variable.VAR_WHISPER_WEIGHT_TYPE.set(self.getSelectableWhisperWeightTypeDict()[selected_weight_type])
|
||||
|
||||
def setLatestCTranslate2WeightType(self):
|
||||
selected_weight_type = self.getSelectableWhisperWeightTypeDict()[config.WHISPER_WEIGHT_TYPE]
|
||||
self.view_variable.VAR_WHISPER_WEIGHT_TYPE.set(selected_weight_type)
|
||||
|
||||
|
||||
def openMicEnergyThresholdWidget(self):
|
||||
self.view_variable.VAR_LABEL_MIC_DYNAMIC_ENERGY_THRESHOLD.set(i18n.t("config_window.mic_dynamic_energy_threshold.label_for_manual"))
|
||||
self.view_variable.VAR_DESC_MIC_DYNAMIC_ENERGY_THRESHOLD.set(i18n.t("config_window.mic_dynamic_energy_threshold.desc_for_manual"))
|
||||
@@ -1637,6 +1710,13 @@ class View():
|
||||
def clearMessageBox(self):
|
||||
self._clearTextBox(vrct_gui.entry_message_box)
|
||||
|
||||
@staticmethod
|
||||
def insertMessageBox(text):
|
||||
vrct_gui.entry_message_box.insert("end", text)
|
||||
|
||||
def replaceMessageBox(self, text):
|
||||
self.clearMessageBox()
|
||||
self.insertMessageBox(text)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from ._createSettingBoxContainer import _createSettingBoxContainer
|
||||
|
||||
|
||||
from .setting_box_containers.setting_box_appearance import createSettingBox_Appearance
|
||||
from .setting_box_containers.setting_box_transcription import createSettingBox_Mic, createSettingBox_Speaker
|
||||
from .setting_box_containers.setting_box_transcription import createSettingBox_Mic, createSettingBox_Speaker, createSettingBox_InternalModel
|
||||
from .setting_box_containers.setting_box_others import createSettingBox_Others, createSettingBox_Others_SendMessageFormats, createSettingBox_Others_ReceivedMessageFormats, createSettingBox_Others_Additional
|
||||
from .setting_box_containers.setting_box_advanced_settings import createSettingBox_AdvancedSettings
|
||||
from .setting_box_containers.setting_box_translation import createSettingBox_Translation
|
||||
@@ -94,6 +94,10 @@ def createSideMenuAndSettingsBoxContainers(config_window, settings, view_variabl
|
||||
"var_section_title": view_variable.VAR_SECOND_TITLE_TRANSCRIPTION_SPEAKER,
|
||||
"setting_box": createSettingBox_Speaker
|
||||
},
|
||||
{
|
||||
"var_section_title": view_variable.VAR_SECOND_TITLE_TRANSCRIPTION_INTERNAL_MODEL,
|
||||
"setting_box": createSettingBox_InternalModel
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import Union
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkEntry, CTkSlider, CTkSwitch, CTkCheckBox, CTkProgressBar, CTkImage, CTkRadioButton
|
||||
from CTkToolTip import *
|
||||
|
||||
from vrct_gui.ui_utils import createButtonWithImage, getLatestWidth, createOptionMenuBox, getLatestHeight, bindButtonFunctionAndColor, bindEnterAndLeaveFunction, bindButtonReleaseFunction, bindButtonPressFunction
|
||||
from vrct_gui.ui_utils import createButtonWithImage, getLatestWidth, createOptionMenuBox, getLatestHeight, bindButtonFunctionAndColor, bindEnterAndLeaveFunction, bindButtonReleaseFunction, bindButtonPressFunction, createLabelButton
|
||||
from vrct_gui import vrct_gui
|
||||
from utils import isEven, callFunctionIfCallable
|
||||
|
||||
@@ -615,6 +615,75 @@ class _SettingBoxGenerator():
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
def createSettingBoxEntry_AuthKey(self,
|
||||
for_var_label_text, for_var_desc_text,
|
||||
entry_attr_name,
|
||||
entry_width,
|
||||
entry_textvariable,
|
||||
entry_bind__Any_KeyRelease,
|
||||
entry_bind__FocusOut=None,
|
||||
open_authkey_page_command=None,
|
||||
open_authkey_text_variable=None,
|
||||
image_file=None,
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(entry_attr_name, for_var_label_text, for_var_desc_text)
|
||||
|
||||
|
||||
all_wrapper = CTkFrame(setting_box_item_frame, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0)
|
||||
all_wrapper.grid(row=1, column=0, sticky="ew")
|
||||
|
||||
all_wrapper.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
def adjusted_command__for_entry_bind__Any_KeyRelease(e):
|
||||
entry_bind__Any_KeyRelease(e.widget.get())
|
||||
|
||||
entry_widget = CTkEntry(
|
||||
all_wrapper,
|
||||
text_color=self.settings.ctm.SB__ENTRY_TEXT_COLOR,
|
||||
fg_color=self.settings.ctm.SB__ENTRY_BG_COLOR,
|
||||
border_color=self.settings.ctm.SB__ENTRY_BORDER_COLOR,
|
||||
width=entry_width,
|
||||
height=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT,
|
||||
textvariable=entry_textvariable,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__ENTRY_FONT_SIZE, weight="normal"),
|
||||
)
|
||||
entry_widget.bind("<Any-KeyRelease>", adjusted_command__for_entry_bind__Any_KeyRelease)
|
||||
setattr(self.config_window, entry_attr_name, entry_widget)
|
||||
|
||||
|
||||
entry_widget.grid(row=0, column=SETTING_BOX_COLUMN, sticky="e")
|
||||
|
||||
if entry_bind__FocusOut is not None:
|
||||
entry_widget.bind("<FocusOut>", entry_bind__FocusOut, "+")
|
||||
|
||||
|
||||
|
||||
(open_page_button, label_button_label_widget, label_button_img_widget) = createLabelButton(
|
||||
parent_widget=all_wrapper,
|
||||
label_button_bg_color=self.settings.ctm.SB__BUTTON_COLOR,
|
||||
label_button_hovered_bg_color=self.settings.ctm.SB__BUTTON_HOVERED_COLOR,
|
||||
label_button_clicked_bg_color=self.settings.ctm.SB__BUTTON_CLICKED_COLOR,
|
||||
label_button_ipadx=self.settings.uism.SB__AUTHKEY_WEBPAGE_BUTTON_IPADX,
|
||||
label_button_ipady=self.settings.uism.SB__AUTHKEY_WEBPAGE_BUTTON_IPADY,
|
||||
variable=open_authkey_text_variable,
|
||||
font_family=self.settings.FONT_FAMILY,
|
||||
font_size=self.settings.uism.SB__AUTHKEY_WEBPAGE_BUTTON_LABEL_FONT_SIZE,
|
||||
text_color=self.settings.ctm.LABELS_TEXT_COLOR,
|
||||
label_button_clicked_command=open_authkey_page_command,
|
||||
|
||||
label_button_position="center",
|
||||
|
||||
image_file=image_file,
|
||||
image_size=self.settings.uism.SB__AUTHKEY_WEBPAGE_BUTTON_IMG_SIZE,
|
||||
label_button_padx_between_img=self.settings.uism.SB__AUTHKEY_WEBPAGE_PADX_BETWEEN_LABEL_AND_ICON,
|
||||
)
|
||||
open_page_button.grid(row=1, column=SETTING_BOX_COLUMN, pady=(self.settings.uism.SB__AUTHKEY_WEBPAGE_BUTTON_TOP_PADY,0))
|
||||
|
||||
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
from .createSettingBox_Mic import createSettingBox_Mic
|
||||
from .createSettingBox_Speaker import createSettingBox_Speaker
|
||||
from .createSettingBox_Speaker import createSettingBox_Speaker
|
||||
from .createSettingBox_InternalModel import createSettingBox_InternalModel
|
||||
@@ -0,0 +1,37 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_InternalModel(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxSwitch = sbg.createSettingBoxSwitch
|
||||
createSettingBoxDropdownMenu = sbg.createSettingBoxDropdownMenu
|
||||
|
||||
def switchUseWhisperFeatureCallback(switch_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_USE_WHISPER_FEATURE, switch_widget.get())
|
||||
|
||||
def optionmenuWhisperWeightTypeCallback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_WHISPER_WEIGHT_TYPE, value)
|
||||
|
||||
|
||||
row=0
|
||||
config_window.sb__use_whisper_feature = createSettingBoxSwitch(
|
||||
for_var_label_text=view_variable.VAR_LABEL_USE_WHISPER_FEATURE,
|
||||
for_var_desc_text=view_variable.VAR_DESC_USE_WHISPER_FEATURE,
|
||||
switch_attr_name="sb__switch_use_whisper_feature",
|
||||
command=lambda: switchUseWhisperFeatureCallback(config_window.sb__switch_use_whisper_feature),
|
||||
variable=view_variable.VAR_USE_WHISPER_FEATURE
|
||||
)
|
||||
config_window.sb__use_whisper_feature.grid(row=row, pady=0)
|
||||
row+=1
|
||||
|
||||
config_window.sb__whisper_weight_type = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_WHISPER_WEIGHT_TYPE,
|
||||
for_var_desc_text=view_variable.VAR_DESC_WHISPER_WEIGHT_TYPE,
|
||||
optionmenu_attr_name="sb__optionmenu_whisper_weight_type",
|
||||
dropdown_menu_values=view_variable.DICT_WHISPER_WEIGHT_TYPE,
|
||||
command=lambda value: optionmenuWhisperWeightTypeCallback(value),
|
||||
variable=view_variable.VAR_WHISPER_WEIGHT_TYPE,
|
||||
)
|
||||
config_window.sb__whisper_weight_type.grid(row=row, pady=0)
|
||||
row+=1
|
||||
@@ -6,7 +6,7 @@ def createSettingBox_Translation(setting_box_wrapper, config_window, settings, v
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxSwitch = sbg.createSettingBoxSwitch
|
||||
createSettingBoxDropdownMenu = sbg.createSettingBoxDropdownMenu
|
||||
createSettingBoxEntry = sbg.createSettingBoxEntry
|
||||
createSettingBoxEntry_AuthKey = sbg.createSettingBoxEntry_AuthKey
|
||||
|
||||
def switchUseTranslationFeatureCallback(switch_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_USE_TRANSLATION_FEATURE, switch_widget.get())
|
||||
@@ -41,13 +41,16 @@ def createSettingBox_Translation(setting_box_wrapper, config_window, settings, v
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__deepl_auth_key = createSettingBoxEntry(
|
||||
config_window.sb__deepl_auth_key = createSettingBoxEntry_AuthKey(
|
||||
for_var_label_text=view_variable.VAR_LABEL_DEEPL_AUTH_KEY,
|
||||
for_var_desc_text=view_variable.VAR_DESC_DEEPL_AUTH_KEY,
|
||||
entry_attr_name="sb__entry_deepl_auth_key",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_300,
|
||||
entry_bind__Any_KeyRelease=lambda value: deeplAuthKeyCallback(value),
|
||||
entry_textvariable=view_variable.VAR_DEEPL_AUTH_KEY,
|
||||
open_authkey_page_command=lambda _e: callFunctionIfCallable(view_variable.CALLBACK_OPEN_WEBPAGE_DEEPL_AUTH_KEY),
|
||||
open_authkey_text_variable=view_variable.VAR_OPEN_DEEPL_WEB_PAGE,
|
||||
image_file=settings.image_file.LINK_ICON
|
||||
)
|
||||
config_window.sb__deepl_auth_key.grid(row=row, pady=0)
|
||||
row+=1
|
||||
@@ -19,6 +19,9 @@ def createEntryMessageBox(settings, main_window, view_variable):
|
||||
border_width=settings.uism.TEXTBOX_ENTRY_BORDER_SIZE,
|
||||
height=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_ENTRY_FONT_SIZE, weight="normal"),
|
||||
undo=True,
|
||||
autoseparators=True,
|
||||
maxundo=64,
|
||||
)
|
||||
main_window.entry_message_box.grid(row=0, column=0, padx=settings.uism.TEXTBOX_ENTRY_PADX, pady=settings.uism.TEXTBOX_ENTRY_PADY, sticky="nsew")
|
||||
|
||||
@@ -28,6 +31,14 @@ def createEntryMessageBox(settings, main_window, view_variable):
|
||||
"Delete", "Select", "Up", "Down", "Next", "End", "Print",
|
||||
"Prior","Insert","Home", "Left", "Clear", "Right", "Linefeed"
|
||||
]
|
||||
if e.keysym == "Up":
|
||||
callFunctionIfCallable(view_variable.CALLBACK_MESSAGE_BOX_BIND_KEYSYM__UP)
|
||||
return "break"
|
||||
|
||||
if e.keysym == "Down":
|
||||
callFunctionIfCallable(view_variable.CALLBACK_MESSAGE_BOX_BIND_KEYSYM__DOWN)
|
||||
return "break"
|
||||
|
||||
if e.keysym != "??":
|
||||
if len(e.char) != 0 and e.keysym in BREAK_KEYSYM_LIST:
|
||||
main_window.entry_message_box.insert("end", e.char)
|
||||
@@ -35,6 +46,15 @@ def createEntryMessageBox(settings, main_window, view_variable):
|
||||
|
||||
main_window.entry_message_box.bind("<Any-KeyPress>", messageBoxAnyKeyPress)
|
||||
|
||||
def messageBoxRedoFunction(_e):
|
||||
try:
|
||||
main_window.entry_message_box.edit_redo()
|
||||
except:
|
||||
pass
|
||||
|
||||
main_window.entry_message_box.bind("<Control-Shift-Z>", messageBoxRedoFunction, "+")
|
||||
main_window.entry_message_box.bind("<Control-Y>", messageBoxRedoFunction, "+")
|
||||
|
||||
|
||||
main_window.main_send_message_button_container = CTkFrame(main_window.main_entry_message_container, corner_radius=settings.uism.SEND_MESSAGE_BUTTON_CORNER_RADIUS, fg_color=settings.ctm.SEND_MESSAGE_BUTTON_BG_COLOR, width=0, height=0)
|
||||
main_window.main_send_message_button_container.grid(row=0, column=1, padx=(0, settings.uism.TEXTBOX_ENTRY_PADX), pady=settings.uism.TEXTBOX_ENTRY_PADY, sticky="nsew")
|
||||
|
||||
@@ -330,6 +330,7 @@ def _darkTheme(base_color):
|
||||
REDO_ICON = getImageFileFromUiUtils("redo_icon_white.png"),
|
||||
SWAP_ICON = getImageFileFromUiUtils("swap_icon_white.png"),
|
||||
FOLDER_OPEN_ICON = getImageFileFromUiUtils("folder_open_icon_white.png"),
|
||||
LINK_ICON = getImageFileFromUiUtils("link_icon_white.png"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -324,6 +324,7 @@ def _lightTheme(base_color):
|
||||
REDO_ICON = getImageFileFromUiUtils("redo_icon_black.png"),
|
||||
SWAP_ICON = getImageFileFromUiUtils("swap_icon_black.png"),
|
||||
FOLDER_OPEN_ICON = getImageFileFromUiUtils("folder_open_icon_black.png"),
|
||||
LINK_ICON = getImageFileFromUiUtils("link_icon_black.png"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -349,6 +349,13 @@ class UiScalingManager():
|
||||
|
||||
self.config_window.SB__MESSAGE_FORMAT__ENTRIES_BOTTOM_PADY = (0, self._calculateUiSize(14))
|
||||
|
||||
self.config_window.SB__AUTHKEY_WEBPAGE_BUTTON_IPADX = self._calculateUiSize(12)
|
||||
self.config_window.SB__AUTHKEY_WEBPAGE_BUTTON_IPADY = self._calculateUiSize(6)
|
||||
self.config_window.SB__AUTHKEY_WEBPAGE_BUTTON_LABEL_FONT_SIZE = self._calculateUiSize(12)
|
||||
self.config_window.SB__AUTHKEY_WEBPAGE_BUTTON_IMG_SIZE = self.dupTuple(self._calculateUiSize(12))
|
||||
self.config_window.SB__AUTHKEY_WEBPAGE_PADX_BETWEEN_LABEL_AND_ICON = self._calculateUiSize(10)
|
||||
self.config_window.SB__AUTHKEY_WEBPAGE_BUTTON_TOP_PADY = self._calculateUiSize(10)
|
||||
|
||||
|
||||
self.config_window.SB__BUTTON_IPADXY = self._calculateUiSize(16)
|
||||
self.config_window.SB__BUTTON_ICON_SIZE = self._calculateUiSize(24)
|
||||
|
||||
@@ -168,7 +168,27 @@ def createButtonWithImage(parent_widget, button_image_size, button_ipadxy, butto
|
||||
return button_wrapper
|
||||
|
||||
|
||||
def createLabelButton(parent_widget, label_button_bg_color, label_button_hovered_bg_color, label_button_clicked_bg_color, label_button_ipadx, label_button_ipady, variable, font_family, font_size, text_color, label_button_clicked_command, label_button_position=None, label_button_padx_between_img=0, label_button_min_height=None, label_button_min_width=None):
|
||||
def createLabelButton(
|
||||
parent_widget,
|
||||
label_button_bg_color,
|
||||
label_button_hovered_bg_color,
|
||||
label_button_clicked_bg_color,
|
||||
label_button_ipadx,
|
||||
label_button_ipady,
|
||||
variable,
|
||||
font_family,
|
||||
font_size,
|
||||
text_color,
|
||||
label_button_clicked_command,
|
||||
label_button_position=None,
|
||||
label_button_padx_between_img=0,
|
||||
image_file=None,
|
||||
image_size=None,
|
||||
image_widget_attr_name=None,
|
||||
label_button_min_height=None,
|
||||
label_button_min_width=None,
|
||||
setattr_widget=None,
|
||||
):
|
||||
|
||||
label_button_box = CTkFrame(parent_widget, corner_radius=6, fg_color=label_button_bg_color, cursor="hand2")
|
||||
|
||||
@@ -181,7 +201,7 @@ def createLabelButton(parent_widget, label_button_bg_color, label_button_hovered
|
||||
label_button_box.grid_columnconfigure(0, minsize=label_button_min_width)
|
||||
|
||||
label_button_label_wrapper = CTkFrame(label_button_box, corner_radius=0, fg_color=label_button_bg_color)
|
||||
label_button_label_wrapper.grid(row=0, column=0, padx=label_button_ipadx, pady=label_button_ipady, sticky="ew")
|
||||
label_button_label_wrapper.grid(row=0, column=0, padx=label_button_ipadx, pady=label_button_ipady)
|
||||
|
||||
LABEL_COLUMN=0
|
||||
if label_button_position == "center":
|
||||
@@ -198,25 +218,46 @@ def createLabelButton(parent_widget, label_button_bg_color, label_button_hovered
|
||||
label_button_label_widget.grid(row=0, column=LABEL_COLUMN, padx=(0, label_button_padx_between_img))
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([label_button_label_wrapper, label_button_box, label_button_label_widget], label_button_hovered_bg_color, label_button_bg_color)
|
||||
bindButtonPressColor([label_button_label_wrapper, label_button_box, label_button_label_widget], label_button_clicked_bg_color, label_button_hovered_bg_color)
|
||||
register_widgets = [label_button_label_wrapper, label_button_box, label_button_label_widget]
|
||||
if image_file is not None:
|
||||
label_button_label_wrapper.grid_columnconfigure((0,3), weight=1)
|
||||
label_button_img_widget = CTkLabel(
|
||||
label_button_label_wrapper,
|
||||
text=None,
|
||||
corner_radius=0,
|
||||
height=0,
|
||||
image=CTkImage(image_file, size=image_size)
|
||||
)
|
||||
|
||||
if image_widget_attr_name is not None:
|
||||
setattr(setattr_widget, image_widget_attr_name, label_button_img_widget)
|
||||
|
||||
label_button_img_widget.grid(row=0, column=LABEL_COLUMN+1)
|
||||
register_widgets.append(label_button_img_widget)
|
||||
|
||||
|
||||
bindEnterAndLeaveColor(register_widgets, label_button_hovered_bg_color, label_button_bg_color)
|
||||
bindButtonPressColor(register_widgets, label_button_clicked_bg_color, label_button_hovered_bg_color)
|
||||
|
||||
|
||||
bindButtonReleaseFunction([label_button_label_wrapper, label_button_box, label_button_label_widget], label_button_clicked_command)
|
||||
|
||||
def bindEventFromWidgets():
|
||||
bindButtonReleaseFunction([label_button_label_wrapper, label_button_box, label_button_label_widget], label_button_clicked_command)
|
||||
bindEventFromWidgets()
|
||||
bindButtonReleaseFunction(register_widgets, label_button_clicked_command)
|
||||
|
||||
def unbindEventFromWidgets():
|
||||
unbindEnterLEaveButtonPressButtonReleaseFunction([label_button_label_wrapper, label_button_box, label_button_label_widget])
|
||||
unbindEnterLEaveButtonPressButtonReleaseFunction(register_widgets)
|
||||
|
||||
bindEventFromWidgets()
|
||||
|
||||
label_button_box.unbindFunction = unbindEventFromWidgets
|
||||
label_button_box.bindFunction = bindEventFromWidgets
|
||||
|
||||
if image_file is not None:
|
||||
return (label_button_box, label_button_label_widget, label_button_img_widget)
|
||||
else:
|
||||
return (label_button_box, label_button_label_widget)
|
||||
|
||||
|
||||
return (label_button_box, label_button_label_widget)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user