From 19b29b4955190f805f66dbf66fb63810feb887d0 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Wed, 16 Aug 2023 01:59:07 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[Update]=20=E5=87=A6=E7=90=86=E3=82=92?= =?UTF-8?q?=E5=88=86=E5=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VRCT.py | 244 +++++++++++++++++++++++------------------------------- config.py | 25 ++++++ 2 files changed, 128 insertions(+), 141 deletions(-) diff --git a/VRCT.py b/VRCT.py index d52398eb..d62184f0 100644 --- a/VRCT.py +++ b/VRCT.py @@ -34,10 +34,6 @@ class App(CTk): customtkinter.set_appearance_mode(config.APPEARANCE_THEME) customtkinter.set_default_color_theme("blue") - ## flags - self.ENABLE_OSC = False - self.UPDATE_FLAG = False - # init main window self.iconbitmap(os_path.join(os_path.dirname(__file__), "img", "app.ico")) self.title("VRCT") @@ -45,82 +41,12 @@ class App(CTk): self.minsize(400, 175) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) + self.wm_attributes("-alpha", config.TRANSPARENCY/100) + customtkinter.set_widget_scaling(int(config.UI_SCALING.replace("%", "")) / 100) + self.protocol("WM_DELETE_WINDOW", self.delete_window) - # add sidebar left - self.sidebar_frame = CTkFrame(self, corner_radius=0) - self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsw") - self.sidebar_frame.grid_rowconfigure(5, weight=1) - - init_lang_text = "Loading..." - - # add checkbox translation - self.checkbox_translation = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_translation_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - self.checkbox_translation.grid(row=0, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - - # add checkbox transcription send - self.checkbox_transcription_send = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_transcription_send_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - self.checkbox_transcription_send.grid(row=1, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - - # add checkbox transcription receive - self.checkbox_transcription_receive = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_transcription_receive_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - self.checkbox_transcription_receive.grid(row=2, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - - # add checkbox foreground - self.checkbox_foreground = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_foreground_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - self.checkbox_foreground.grid(row=3, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - - # add button information - self.button_information = CTkButton( - self.sidebar_frame, - text=None, - width=36, - command=self.button_information_callback, - image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "info-icon-white.png"))) - ) - self.button_information.grid(row=5, column=0, padx=(10, 5), pady=(5, 5), sticky="wse") - - # add button config - self.button_config = CTkButton( - self.sidebar_frame, - text=None, - width=36, - command=self.button_config_callback, - image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "config-icon-white.png"))) - ) - self.button_config.grid(row=5, column=1, padx=(5, 10), pady=(5, 5), sticky="wse") - - # load ui language data - language_yaml_data = get_localized_text(f"{config.UI_LANGUAGE}") - # add tabview textbox - self.add_tabview_logs(language_yaml_data) + # add sidebar + self.add_sidebar() # add entry message box self.entry_message_box = CTkEntry( @@ -129,64 +55,28 @@ class App(CTk): font=CTkFont(family=config.FONT_FAMILY), ) self.entry_message_box.grid(row=1, column=1, columnspan=2, padx=5, pady=(5, 10), sticky="nsew") + self.entry_message_box.bind("", self.entry_message_box_press_key_enter) + self.entry_message_box.bind("", self.entry_message_box_press_key_any) + self.entry_message_box.bind("", self.entry_message_box_leave) - # set default values - ## set translator + # add tabview textbox + self.add_tabview_logs(get_localized_text(f"{config.UI_LANGUAGE}")) + + self.config_window = ToplevelWindowConfig(self) + self.information_window = ToplevelWindowInformation(self) + self.init_process() + + def init_process(self): + # set translator if self.translator.authentication(config.CHOICE_TRANSLATOR, config.AUTH_KEYS[config.CHOICE_TRANSLATOR]) is False: # error update Auth key print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") - # ## set checkbox enable translation - # if self.ENABLE_TRANSLATION: - # self.checkbox_translation.select() - # self.checkbox_translation_callback() - # else: - # self.checkbox_translation.deselect() - - # ## set checkbox enable transcription send - # if self.ENABLE_TRANSCRIPTION_SEND: - # self.checkbox_transcription_send.select() - # self.checkbox_transcription_send_callback() - # else: - # self.checkbox_transcription_send.deselect() - - # ## set checkbox enable transcription receive - # if self.ENABLE_TRANSCRIPTION_RECEIVE: - # self.checkbox_transcription_receive.select() - # self.checkbox_transcription_receive_callback() - # else: - # self.checkbox_transcription_receive.deselect() - - # ## set set checkbox enable foreground - # if self.ENABLE_FOREGROUND: - # self.checkbox_foreground.select() - # self.checkbox_foreground_callback() - # else: - # self.checkbox_foreground.deselect() - - ## set word filter + # set word filter for f in config.INPUT_MIC_WORD_FILTER: self.keyword_processor.add_keyword(f) - ## set bind entry message box - self.entry_message_box.bind("", self.entry_message_box_press_key_enter) - self.entry_message_box.bind("", self.entry_message_box_press_key_any) - self.entry_message_box.bind("", self.entry_message_box_leave) - - ## set transparency for main window - self.wm_attributes("-alpha", config.TRANSPARENCY/100) - - ## set UI scale - new_scaling_float = int(config.UI_SCALING.replace("%", "")) / 100 - customtkinter.set_widget_scaling(new_scaling_float) - - # delete window - self.protocol("WM_DELETE_WINDOW", self.delete_window) - - self.config_window = ToplevelWindowConfig(self) - self.information_window = ToplevelWindowInformation(self) - # start receive osc th_receive_osc_parameters = Thread(target=receive_osc_parameters, args=(self.check_osc_receive,)) th_receive_osc_parameters.daemon = True @@ -196,10 +86,10 @@ class App(CTk): send_test_action() # check update - response = requests_get("https://api.github.com/repos/misyaguziya/VRCT/releases/latest") + response = requests_get(config.GITHUB_URL) tag_name = response.json()["tag_name"] if tag_name != __version__: - self.UPDATE_FLAG = True + config.UPDATE_FLAG = True def button_config_callback(self): self.foreground_stop() @@ -277,7 +167,7 @@ class App(CTk): voice_message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) if self.checkbox_transcription_send.get() is True: - if self.ENABLE_OSC is True: + if config.ENABLE_OSC is True: # send OSC message send_message(voice_message, config.OSC_IP_ADDRESS, config.OSC_PORT) else: @@ -492,7 +382,7 @@ class App(CTk): chat_message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - if self.ENABLE_OSC is True: + if config.ENABLE_OSC is True: send_message(chat_message, config.OSC_IP_ADDRESS, config.OSC_PORT) else: print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") @@ -531,6 +421,77 @@ class App(CTk): self.quit() self.destroy() + def add_sidebar(self): + init_lang_text = "Loading..." + self.sidebar_frame = CTkFrame(master=self, corner_radius=0) + + # add checkbox translation + self.checkbox_translation = CTkCheckBox( + self.sidebar_frame, + text=init_lang_text, + onvalue=True, + offvalue=False, + command=self.checkbox_translation_callback, + font=CTkFont(family=config.FONT_FAMILY) + ) + + # add checkbox transcription send + self.checkbox_transcription_send = CTkCheckBox( + self.sidebar_frame, + text=init_lang_text, + onvalue=True, + offvalue=False, + command=self.checkbox_transcription_send_callback, + font=CTkFont(family=config.FONT_FAMILY) + ) + + # add checkbox transcription receive + self.checkbox_transcription_receive = CTkCheckBox( + self.sidebar_frame, + text=init_lang_text, + onvalue=True, + offvalue=False, + command=self.checkbox_transcription_receive_callback, + font=CTkFont(family=config.FONT_FAMILY) + ) + + # add checkbox foreground + self.checkbox_foreground = CTkCheckBox( + self.sidebar_frame, + text=init_lang_text, + onvalue=True, + offvalue=False, + command=self.checkbox_foreground_callback, + font=CTkFont(family=config.FONT_FAMILY) + ) + + # add button information + self.button_information = CTkButton( + self.sidebar_frame, + text=None, + width=36, + command=self.button_information_callback, + image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "info-icon-white.png"))) + ) + + # add button config + self.button_config = CTkButton( + self.sidebar_frame, + text=None, + width=36, + command=self.button_config_callback, + image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "config-icon-white.png"))) + ) + + self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsw") + self.sidebar_frame.grid_rowconfigure(5, weight=1) + self.checkbox_translation.grid(row=0, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") + self.checkbox_transcription_send.grid(row=1, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") + self.checkbox_transcription_receive.grid(row=2, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") + self.checkbox_foreground.grid(row=3, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") + self.button_information.grid(row=5, column=0, padx=(10, 5), pady=(5, 5), sticky="wse") + self.button_config.grid(row=5, column=1, padx=(5, 10), pady=(5, 5), sticky="wse") + def delete_tabview_logs(self, pre_language_yaml_data): self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_log"]) self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_send"]) @@ -567,39 +528,40 @@ class App(CTk): self.tabview_logs.tab(main_tab_title_log), font=CTkFont(family=config.FONT_FAMILY) ) - self.textbox_message_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_log.configure(state='disabled') # add textbox message send log self.textbox_message_send_log = CTkTextbox( self.tabview_logs.tab(main_tab_title_send), font=CTkFont(family=config.FONT_FAMILY) ) - self.textbox_message_send_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_send_log.configure(state='disabled') # add textbox message receive log self.textbox_message_receive_log = CTkTextbox( self.tabview_logs.tab(main_tab_title_receive), font=CTkFont(family=config.FONT_FAMILY) ) - self.textbox_message_receive_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_receive_log.configure(state='disabled') # add textbox message system log self.textbox_message_system_log = CTkTextbox( self.tabview_logs.tab(main_tab_title_system), font=CTkFont(family=config.FONT_FAMILY) ) + + self.textbox_message_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") + self.textbox_message_send_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") + self.textbox_message_receive_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") self.textbox_message_system_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") + self.textbox_message_log.configure(state='disabled') + self.textbox_message_send_log.configure(state='disabled') + self.textbox_message_receive_log.configure(state='disabled') self.textbox_message_system_log.configure(state='disabled') widget_main_window_label_setter(self, language_yaml_data) def check_osc_receive(self, address, osc_arguments): - if self.ENABLE_OSC is False: - self.ENABLE_OSC = True - # print(address, osc_arguments) + print(address, osc_arguments) + if config.ENABLE_OSC is False: + config.ENABLE_OSC = True if __name__ == "__main__": try: diff --git a/config.py b/config.py index cf5075b2..753cc7f2 100644 --- a/config.py +++ b/config.py @@ -349,6 +349,28 @@ class Config: self._ENABLE_NOTICE_XSOVERLAY = value save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + @property + def ENABLE_OSC(self): + return self._ENABLE_OSC + + @ENABLE_OSC.setter + def ENABLE_OSC(self, value): + if type(value) is bool: + self._ENABLE_OSC = value + + @property + def UPDATE_FLAG(self): + return self._UPDATE_FLAG + + @UPDATE_FLAG.setter + def UPDATE_FLAG(self, value): + if type(value) is bool: + self._UPDATE_FLAG = value + + @property + def GITHUB_URL(self): + return self._GITHUB_URL + def init_config(self): self._PATH_CONFIG = "./config.json" self._TRANSPARENCY = 100 @@ -388,6 +410,9 @@ class Config: self._MESSAGE_FORMAT = "[message]([translation])" self._ENABLE_AUTO_CLEAR_CHATBOX = False self._ENABLE_NOTICE_XSOVERLAY = False + self._ENABLE_OSC = False + self._UPDATE_FLAG = False + self._GITHUB_URL = "https://api.github.com/repos/misyaguziya/VRCT/releases/latest" def load_config(self): if os_path.isfile(self.PATH_CONFIG) is not False: From 027e9397d5bb60f29d84380ca1bd80ce3815f1b3 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Fri, 18 Aug 2023 15:39:57 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[Update]=20=E8=A6=81=E7=B4=A0=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92model.py=E3=82=92=E9=80=9A=E3=81=97=E3=81=A6?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VRCT.py | 240 +++++++------------------------------ config.py | 63 ++++++++++ model.py | 304 +++++++++++++++++++++++++++++++++++++++++++++++ window_config.py | 137 ++++++--------------- 4 files changed, 445 insertions(+), 299 deletions(-) create mode 100644 model.py diff --git a/VRCT.py b/VRCT.py index d62184f0..af03393a 100644 --- a/VRCT.py +++ b/VRCT.py @@ -1,35 +1,21 @@ from time import sleep from os import path as os_path -from requests import get as requests_get -from queue import Queue + import customtkinter from customtkinter import CTk, CTkFrame, CTkCheckBox, CTkFont, CTkButton, CTkImage, CTkTabview, CTkTextbox, CTkEntry from PIL.Image import open as Image_open -from flashtext import KeywordProcessor from threading import Thread -from utils import print_textbox, thread_fnc, get_localized_text, widget_main_window_label_setter -from osc_tools import send_typing, send_message, send_test_action, receive_osc_parameters +from utils import print_textbox, get_localized_text, widget_main_window_label_setter from window_config import ToplevelWindowConfig from window_information import ToplevelWindowInformation -from languages import transcription_lang -from audio_utils import get_input_device_list, get_output_device_list -from audio_recorder import SelectedMicRecorder, SelectedSpeakerRecorder -from audio_transcriber import AudioTranscriber -from translation import Translator from config import config -from notification import notification_xsoverlay_for_vrct - -__version__ = "1.3.2" +from model import model class App(CTk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # init instance - self.translator = Translator() - self.keyword_processor = KeywordProcessor() - ## set UI theme customtkinter.set_appearance_mode(config.APPEARANCE_THEME) customtkinter.set_default_color_theme("blue") @@ -68,28 +54,16 @@ class App(CTk): def init_process(self): # set translator - if self.translator.authentication(config.CHOICE_TRANSLATOR, config.AUTH_KEYS[config.CHOICE_TRANSLATOR]) is False: + if model.authenticationTranslator() is False: # error update Auth key print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") # set word filter - for f in config.INPUT_MIC_WORD_FILTER: - self.keyword_processor.add_keyword(f) + model.addKeywords() - # start receive osc - th_receive_osc_parameters = Thread(target=receive_osc_parameters, args=(self.check_osc_receive,)) - th_receive_osc_parameters.daemon = True - th_receive_osc_parameters.start() - - # check osc started - send_test_action() - - # check update - response = requests_get(config.GITHUB_URL) - tag_name = response.json()["tag_name"] - if tag_name != __version__: - config.UPDATE_FLAG = True + # check OSC started + model.oscCheck() def button_config_callback(self): self.foreground_stop() @@ -117,7 +91,8 @@ class App(CTk): self.information_window.focus() def checkbox_translation_callback(self): - if self.checkbox_translation.get() is True: + config.ENABLE_TRANSLATION = self.checkbox_translation.get() + if config.ENABLE_TRANSLATION is True: print_textbox(self.textbox_message_log, "Start translation", "INFO") print_textbox(self.textbox_message_system_log, "Start translation", "INFO") else: @@ -125,61 +100,7 @@ class App(CTk): print_textbox(self.textbox_message_system_log, "Stop translation", "INFO") def transcription_send_start(self): - self.mic_audio_queue = Queue() - mic_device = [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] - self.mic_audio_recorder = SelectedMicRecorder( - mic_device, - config.INPUT_MIC_ENERGY_THRESHOLD, - config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD, - config.INPUT_MIC_RECORD_TIMEOUT, - ) - self.mic_audio_recorder.record_into_queue(self.mic_audio_queue) - self.mic_transcriber = AudioTranscriber( - speaker=False, - source=self.mic_audio_recorder.source, - phrase_timeout=config.INPUT_MIC_PHRASE_TIMEOUT, - max_phrases=config.INPUT_MIC_MAX_PHRASES, - ) - def mic_transcript_to_chatbox(): - self.mic_transcriber.transcribe_audio_queue(self.mic_audio_queue, transcription_lang[config.INPUT_MIC_VOICE_LANGUAGE]) - message = self.mic_transcriber.get_transcript() - if len(message) > 0: - # word filter - if len(self.keyword_processor.extract_keywords(message)) != 0: - print_textbox(self.textbox_message_log, f"Detect WordFilter :{message}", "INFO") - print_textbox(self.textbox_message_system_log, f"Detect WordFilter :{message}", "INFO") - return - - # translate - if self.checkbox_translation.get() is False: - voice_message = f"{message}" - elif self.translator.translator_status[config.CHOICE_TRANSLATOR] is False: - print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") - voice_message = f"{message}" - else: - result = self.translator.translate( - translator_name=config.CHOICE_TRANSLATOR, - source_language=config.INPUT_SOURCE_LANG, - target_language=config.INPUT_TARGET_LANG, - message=message - ) - voice_message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) - - if self.checkbox_transcription_send.get() is True: - if config.ENABLE_OSC is True: - # send OSC message - send_message(voice_message, config.OSC_IP_ADDRESS, config.OSC_PORT) - else: - print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - # update textbox message log - print_textbox(self.textbox_message_log, f"{voice_message}", "SEND") - print_textbox(self.textbox_message_send_log, f"{voice_message}", "SEND") - - self.mic_print_transcript = thread_fnc(mic_transcript_to_chatbox) - self.mic_print_transcript.daemon = True - self.mic_print_transcript.start() + model.startMicTranscript(self.textbox_message_log, self.textbox_message_send_log, self.textbox_message_system_log) print_textbox(self.textbox_message_log, "Start voice2chatbox", "INFO") print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO") self.checkbox_transcription_send.configure(state="normal") @@ -187,12 +108,7 @@ class App(CTk): self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_send_stop(self): - if isinstance(self.mic_print_transcript, thread_fnc): - self.mic_print_transcript.stop() - if self.mic_audio_recorder.stop != None: - self.mic_audio_recorder.stop() - self.mic_audio_recorder.stop = None - + model.stopMicTranscript() print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") self.checkbox_transcription_send.configure(state="normal") @@ -200,20 +116,16 @@ class App(CTk): self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_send_stop_for_config(self): - if isinstance(self.mic_print_transcript, thread_fnc): - self.mic_print_transcript.stop() - if self.mic_audio_recorder.stop != None: - self.mic_audio_recorder.stop() - self.mic_audio_recorder.stop = None - + model.stopMicTranscript() print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") def checkbox_transcription_send_callback(self): + config.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() self.checkbox_transcription_send.configure(state="disabled") self.checkbox_transcription_receive.configure(state="disabled") self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"]) - if self.checkbox_transcription_send.get() is True: + if config.ENABLE_TRANSCRIPTION_SEND is True: th_transcription_send_start = Thread(target=self.transcription_send_start) th_transcription_send_start.daemon = True th_transcription_send_start.start() @@ -223,54 +135,7 @@ class App(CTk): th_transcription_send_stop.start() def transcription_receive_start(self): - self.spk_audio_queue = Queue() - spk_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] - self.spk_audio_recorder = SelectedSpeakerRecorder( - spk_device, - config.INPUT_SPEAKER_ENERGY_THRESHOLD, - config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD, - config.INPUT_SPEAKER_RECORD_TIMEOUT, - ) - self.spk_audio_recorder.record_into_queue(self.spk_audio_queue) - self.spk_transcriber = AudioTranscriber( - speaker=True, - source=self.spk_audio_recorder.source, - phrase_timeout=config.INPUT_SPEAKER_PHRASE_TIMEOUT, - max_phrases=config.INPUT_SPEAKER_MAX_PHRASES, - ) - - def spk_transcript_to_textbox(): - self.spk_transcriber.transcribe_audio_queue(self.spk_audio_queue, transcription_lang[config.INPUT_SPEAKER_VOICE_LANGUAGE]) - message = self.spk_transcriber.get_transcript() - if len(message) > 0: - # translate - if self.checkbox_translation.get() is False: - voice_message = f"{message}" - elif self.translator.translator_status[config.CHOICE_TRANSLATOR] is False: - print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") - voice_message = f"{message}" - else: - result = self.translator.translate( - translator_name=config.CHOICE_TRANSLATOR, - source_language=config.OUTPUT_SOURCE_LANG, - target_language=config.OUTPUT_TARGET_LANG, - message=message - ) - voice_message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) - # send OSC message - # send_message(voice_message, config.OSC_IP_ADDRESS, self.OSC_PORT) - - if self.checkbox_transcription_receive.get() is True: - # update textbox message receive log - print_textbox(self.textbox_message_log, f"{voice_message}", "RECEIVE") - print_textbox(self.textbox_message_receive_log, f"{voice_message}", "RECEIVE") - if config.ENABLE_NOTICE_XSOVERLAY is True: - notification_xsoverlay_for_vrct(content=f"{voice_message}") - - self.spk_print_transcript = thread_fnc(spk_transcript_to_textbox) - self.spk_print_transcript.daemon = True - self.spk_print_transcript.start() + model.startSpeakerTranscript(self.textbox_message_log, self.textbox_message_receive_log, self.textbox_message_system_log) print_textbox(self.textbox_message_log, "Start speaker2log", "INFO") print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO") self.checkbox_transcription_send.configure(state="normal") @@ -278,12 +143,7 @@ class App(CTk): self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_receive_stop(self): - if isinstance(self.spk_print_transcript, thread_fnc): - self.spk_print_transcript.stop() - if self.spk_audio_recorder.stop != None: - self.spk_audio_recorder.stop() - self.spk_audio_recorder.stop = None - + model.stopSpeakerTranscript() print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") self.checkbox_transcription_send.configure(state="normal") @@ -291,20 +151,16 @@ class App(CTk): self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_receive_stop_for_config(self): - if isinstance(self.spk_print_transcript, thread_fnc): - self.spk_print_transcript.stop() - if self.spk_audio_recorder.stop != None: - self.spk_audio_recorder.stop() - self.spk_audio_recorder.stop = None - + model.stopSpeakerTranscript() print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") def checkbox_transcription_receive_callback(self): + config.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get() self.checkbox_transcription_send.configure(state="disabled") self.checkbox_transcription_receive.configure(state="disabled") self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"]) - if self.checkbox_transcription_receive.get() is True: + if config.ENABLE_TRANSCRIPTION_RECEIVE is True: th_transcription_receive_start = Thread(target=self.transcription_receive_start) th_transcription_receive_start.daemon = True th_transcription_receive_start.start() @@ -314,28 +170,29 @@ class App(CTk): th_transcription_receive_stop.start() def transcription_start(self): - if self.checkbox_transcription_send.get() is True: + if config.ENABLE_TRANSCRIPTION_SEND is True: th_transcription_send_start = Thread(target=self.transcription_send_start) th_transcription_send_start.daemon = True th_transcription_send_start.start() sleep(2) - if self.checkbox_transcription_receive.get() is True: + if config.ENABLE_TRANSCRIPTION_RECEIVE is True: th_transcription_receive_start = Thread(target=self.transcription_receive_start) th_transcription_receive_start.daemon = True th_transcription_receive_start.start() def transcription_stop(self): - if self.checkbox_transcription_send.get() is True: + if config.ENABLE_TRANSCRIPTION_SEND is True: th_transcription_send_stop = Thread(target=self.transcription_send_stop_for_config) th_transcription_send_stop.daemon = True th_transcription_send_stop.start() - if self.checkbox_transcription_receive.get() is True: + if config.ENABLE_TRANSCRIPTION_RECEIVE is True: th_transcription_receive_stop = Thread(target=self.transcription_receive_stop_for_config) th_transcription_receive_stop.daemon = True th_transcription_receive_stop.start() def checkbox_foreground_callback(self): - if self.checkbox_foreground.get(): + config.ENABLE_FOREGROUND = self.checkbox_foreground.get() + if config.ENABLE_FOREGROUND: self.attributes("-topmost", True) print_textbox(self.textbox_message_log, "Start foreground", "INFO") print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") @@ -345,45 +202,39 @@ class App(CTk): print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") def foreground_start(self): - if self.checkbox_foreground.get(): + if config.ENABLE_FOREGROUND: self.attributes("-topmost", True) print_textbox(self.textbox_message_log, "Start foreground", "INFO") print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") def foreground_stop(self): - if self.checkbox_foreground.get(): + if config.ENABLE_FOREGROUND: self.attributes("-topmost", False) print_textbox(self.textbox_message_log, "Stop foreground", "INFO") print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") def entry_message_box_press_key_enter(self, event): - # send OSC typing - send_typing(False, config.OSC_IP_ADDRESS, config.OSC_PORT) + # osc stop send typing + model.oscStopSendTyping() - if self.checkbox_foreground.get(): + if config.ENABLE_FOREGROUND: self.attributes("-topmost", True) message = self.entry_message_box.get() if len(message) > 0: # translate - if self.checkbox_translation.get() is False: + if config.ENABLE_TRANSLATION is False: chat_message = f"{message}" - elif self.translator.translator_status[config.CHOICE_TRANSLATOR] is False: + elif model.getTranslatorStatus() is False: print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") chat_message = f"{message}" else: - result = self.translator.translate( - translator_name=config.CHOICE_TRANSLATOR, - source_language=config.INPUT_SOURCE_LANG, - target_language=config.INPUT_TARGET_LANG, - message=message - ) - chat_message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + chat_message = model.getInputTranslate(message) # send OSC message if config.ENABLE_OSC is True: - send_message(chat_message, config.OSC_IP_ADDRESS, config.OSC_PORT) + model.oscSendMessage(chat_message) else: print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") @@ -396,25 +247,21 @@ class App(CTk): if config.ENABLE_AUTO_CLEAR_CHATBOX is True: self.entry_message_box.delete(0, customtkinter.END) - BREAK_KEYSYM_LIST = [ - "Delete", "Select", "Up", "Down", "Next", "End", "Print", - "Prior","Insert","Home", "Left", "Clear", "Right", "Linefeed" - ] def entry_message_box_press_key_any(self, event): - # send OSC typing - send_typing(True, config.OSC_IP_ADDRESS, config.OSC_PORT) - if self.checkbox_foreground.get(): + # osc start send typing + model.oscStartSendTyping() + if config.ENABLE_FOREGROUND: self.attributes("-topmost", False) if event.keysym != "??": - if len(event.char) != 0 and event.keysym in self.BREAK_KEYSYM_LIST: + if len(event.char) != 0 and event.keysym in config.BREAK_KEYSYM_LIST: self.entry_message_box.insert("end", event.char) return "break" def entry_message_box_leave(self, event): - # send OSC typing - send_typing(False, config.OSC_IP_ADDRESS, config.OSC_PORT) - if self.checkbox_foreground.get(): + # osc stop send typing + model.oscStopSendTyping() + if config.ENABLE_FOREGROUND: self.attributes("-topmost", True) def delete_window(self): @@ -558,11 +405,6 @@ class App(CTk): widget_main_window_label_setter(self, language_yaml_data) - def check_osc_receive(self, address, osc_arguments): - print(address, osc_arguments) - if config.ENABLE_OSC is False: - config.ENABLE_OSC = True - if __name__ == "__main__": try: app = App() diff --git a/config.py b/config.py index 753cc7f2..0cb6f299 100644 --- a/config.py +++ b/config.py @@ -18,10 +18,50 @@ class Config: cls._instance.load_config() return cls._instance + @property + def VERSION(self): + return self._VERSION + @property def PATH_CONFIG(self): return self._PATH_CONFIG + @property + def ENABLE_TRANSLATION(self): + return self._ENABLE_TRANSLATION + + @ENABLE_TRANSLATION.setter + def ENABLE_TRANSLATION(self, value): + if type(value) is bool: + self._ENABLE_TRANSLATION = value + + @property + def ENABLE_TRANSCRIPTION_SEND(self): + return self._ENABLE_TRANSCRIPTION_SEND + + @ENABLE_TRANSCRIPTION_SEND.setter + def ENABLE_TRANSCRIPTION_SEND(self, value): + if type(value) is bool: + self._ENABLE_TRANSCRIPTION_SEND = value + + @property + def ENABLE_TRANSCRIPTION_RECEIVE(self): + return self._ENABLE_TRANSCRIPTION_RECEIVE + + @ENABLE_TRANSCRIPTION_RECEIVE.setter + def ENABLE_TRANSCRIPTION_RECEIVE(self, value): + if type(value) is bool: + self._ENABLE_TRANSCRIPTION_RECEIVE = value + + @property + def ENABLE_FOREGROUND(self): + return self._ENABLE_FOREGROUND + + @ENABLE_FOREGROUND.setter + def ENABLE_FOREGROUND(self, value): + if type(value) is bool: + self._ENABLE_FOREGROUND = value + @property def TRANSPARENCY(self): return self._TRANSPARENCY @@ -371,8 +411,25 @@ class Config: def GITHUB_URL(self): return self._GITHUB_URL + @property + def BREAK_KEYSYM_LIST(self): + return self._BREAK_KEYSYM_LIST + + @property + def MAX_MIC_ENERGY_THRESHOLD(self): + return self._MAX_MIC_ENERGY_THRESHOLD + + @property + def MAX_SPEAKER_ENERGY_THRESHOLD(self): + return self._MAX_SPEAKER_ENERGY_THRESHOLD + def init_config(self): + self._VERSION = "1.3.2" self._PATH_CONFIG = "./config.json" + self._ENABLE_TRANSLATION = False + self._ENABLE_TRANSCRIPTION_SEND = False + self._ENABLE_TRANSCRIPTION_RECEIVE = False + self._ENABLE_FOREGROUND = False self._TRANSPARENCY = 100 self._APPEARANCE_THEME = "System" self._UI_SCALING = "100%" @@ -413,6 +470,12 @@ class Config: self._ENABLE_OSC = False self._UPDATE_FLAG = False self._GITHUB_URL = "https://api.github.com/repos/misyaguziya/VRCT/releases/latest" + self._BREAK_KEYSYM_LIST = [ + "Delete", "Select", "Up", "Down", "Next", "End", "Print", + "Prior","Insert","Home", "Left", "Clear", "Right", "Linefeed" + ] + self._MAX_MIC_ENERGY_THRESHOLD = 2000 + self._MAX_SPEAKER_ENERGY_THRESHOLD = 4000 def load_config(self): if os_path.isfile(self.PATH_CONFIG) is not False: diff --git a/model.py b/model.py new file mode 100644 index 00000000..c550f43e --- /dev/null +++ b/model.py @@ -0,0 +1,304 @@ +from time import sleep +from queue import Queue +from threading import Thread +from requests import get as requests_get + +from translation import Translator +from flashtext import KeywordProcessor +from osc_tools import send_typing, send_message, send_test_action, receive_osc_parameters +from languages import transcription_lang +from audio_utils import get_input_device_list, get_output_device_list, get_default_output_device +from audio_recorder import SelectedMicRecorder, SelectedSpeakerRecorder +from audio_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder +from audio_transcriber import AudioTranscriber +from utils import print_textbox, thread_fnc +from config import config +from notification import notification_xsoverlay_for_vrct + +class Model: + _instance = None + + def __new__(cls): + if cls._instance is None: + cls._instance = super(Model, cls).__new__(cls) + cls._instance.init() + return cls._instance + + def init(self): + self.mic_energy_recorder = None + self.mic_energy_plot_progressbar = None + self.speaker_energy_get_progressbar = None + self.speaker_energy_plot_progressbar = None + self.translator = Translator() + self.keyword_processor = KeywordProcessor() + + def resetTranslator(self): + del self.translator + self.translator = Translator() + + def resetKeywordProcessor(self): + del self.translator + self.keyword_processor = KeywordProcessor() + + def authenticationTranslator(self, choice_translator=None, auth_key=None): + if choice_translator == None: + choice_translator = config.CHOICE_TRANSLATOR + if auth_key == None: + auth_key = config.AUTH_KEYS[choice_translator] + + result = self.translator.authentication(choice_translator, auth_key) + if result: + auth_keys = config.AUTH_KEYS + auth_keys[choice_translator] = auth_key + config.AUTH_KEYS = auth_keys + return result + + def getTranslatorStatus(self): + return self.translator.translator_status[config.CHOICE_TRANSLATOR] + + def getListTranslatorName(self): + return list(self.translator.translator_status.keys()) + + def getInputTranslate(self, message): + translation = self.translator.translate( + translator_name=config.CHOICE_TRANSLATOR, + source_language=config.INPUT_SOURCE_LANG, + target_language=config.INPUT_TARGET_LANG, + message=message + ) + message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", translation) + return message + + def getOutputTranslate(self, message): + translation = self.translator.translate( + translator_name=config.CHOICE_TRANSLATOR, + source_language=config.OUTPUT_SOURCE_LANG, + target_language=config.OUTPUT_TARGET_LANG, + message=message + ) + message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", translation) + return message + + def addKeywords(self): + for f in config.INPUT_MIC_WORD_FILTER: + self.keyword_processor.add_keyword(f) + + def checkKeywords(self, message): + return len(self.keyword_processor.extract_keywords(message)) != 0 + + @staticmethod + def oscStartSendTyping(): + send_typing(True, config.OSC_IP_ADDRESS, config.OSC_PORT) + + @staticmethod + def oscStopSendTyping(): + send_typing(False, config.OSC_IP_ADDRESS, config.OSC_PORT) + + @staticmethod + def oscSendMessage(message): + send_message(message, config.OSC_IP_ADDRESS, config.OSC_PORT) + + @staticmethod + def oscCheck(): + def check_osc_receive(address, osc_arguments): + if config.ENABLE_OSC is False: + config.ENABLE_OSC = True + + # start receive osc + th_receive_osc_parameters = Thread(target=receive_osc_parameters, args=(check_osc_receive,)) + th_receive_osc_parameters.daemon = True + th_receive_osc_parameters.start() + + # check osc started + send_test_action() + + # check update + response = requests_get(config.GITHUB_URL) + tag_name = response.json()["tag_name"] + if tag_name != config.VERSION: + config.UPDATE_FLAG = True + + @staticmethod + def getListInputHost(): + return [host for host in get_input_device_list().keys()] + + @staticmethod + def getListInputDevice(): + return [device["name"] for device in get_input_device_list()[config.CHOICE_MIC_HOST]] + + @staticmethod + def getInputDefaultDevice(): + return [device["name"] for device in get_input_device_list()[config.CHOICE_MIC_HOST]][0] + + @staticmethod + def getListOutputDevice(): + return [device["name"] for device in get_output_device_list()] + + @staticmethod + def checkSpeakerStatus(choice=config.CHOICE_SPEAKER_DEVICE): + speaker_device = [device for device in get_output_device_list() if device["name"] == choice][0] + if get_default_output_device()["index"] == speaker_device["index"]: + return True + return False + + def startMicTranscript(self, log, send_log, system_log): + mic_audio_queue = Queue() + self.mic_audio_recorder = SelectedMicRecorder( + [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0], + config.INPUT_MIC_ENERGY_THRESHOLD, + config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD, + config.INPUT_MIC_RECORD_TIMEOUT, + ) + self.mic_audio_recorder.record_into_queue(mic_audio_queue) + mic_transcriber = AudioTranscriber( + speaker=False, + source=self.mic_audio_recorder.source, + phrase_timeout=config.INPUT_MIC_PHRASE_TIMEOUT, + max_phrases=config.INPUT_MIC_MAX_PHRASES, + ) + def mic_transcript_to_chatbox(): + mic_transcriber.transcribe_audio_queue(mic_audio_queue, transcription_lang[config.INPUT_MIC_VOICE_LANGUAGE]) + message = mic_transcriber.get_transcript() + if len(message) > 0: + print(message) + # word filter + if self.checkKeywords(message): + print_textbox(log, f"Detect WordFilter :{message}", "INFO") + print_textbox(system_log, f"Detect WordFilter :{message}", "INFO") + return + + # translate + if config.ENABLE_TRANSLATION is False: + voice_message = f"{message}" + elif self.getTranslatorStatus() is False: + print_textbox(log, "Auth Key or language setting is incorrect", "ERROR") + print_textbox(system_log, "Auth Key or language setting is incorrect", "ERROR") + voice_message = f"{message}" + else: + voice_message = self.getInputTranslate(message) + + if config.ENABLE_TRANSCRIPTION_SEND is True: + if config.ENABLE_OSC is True: + # osc send message + model.oscSendMessage(voice_message) + else: + print_textbox(log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") + print_textbox(system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") + # update textbox message log + print_textbox(log, f"{voice_message}", "SEND") + print_textbox(send_log, f"{voice_message}", "SEND") + + self.mic_print_transcript = thread_fnc(mic_transcript_to_chatbox) + self.mic_print_transcript.daemon = True + self.mic_print_transcript.start() + + def stopMicTranscript(self): + if isinstance(self.mic_print_transcript, thread_fnc): + self.mic_print_transcript.stop() + if self.mic_audio_recorder.stop != None: + self.mic_audio_recorder.stop() + self.mic_audio_recorder.stop = None + + def startCheckMicEnergy(self, progressBar): + def progressBarInputMicEnergyPlot(): + if mic_energy_queue.empty() is False: + energy = mic_energy_queue.get() + try: + progressBar.set(energy/config.MAX_MIC_ENERGY_THRESHOLD) + except: + pass + sleep(0.01) + mic_energy_queue = Queue() + mic_device = [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] + self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device) + self.mic_energy_recorder.record_into_queue(mic_energy_queue) + self.mic_energy_plot_progressbar = thread_fnc(progressBarInputMicEnergyPlot) + self.mic_energy_plot_progressbar.daemon = True + self.mic_energy_plot_progressbar.start() + + def stopCheckMicEnergy(self): + if self.mic_energy_recorder != None: + self.mic_energy_recorder.stop() + if self.mic_energy_plot_progressbar != None: + self.mic_energy_plot_progressbar.stop() + + def startSpeakerTranscript(self, log, receive_log, system_log): + spk_audio_queue = Queue() + spk_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] + self.spk_audio_recorder = SelectedSpeakerRecorder( + spk_device, + config.INPUT_SPEAKER_ENERGY_THRESHOLD, + config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD, + config.INPUT_SPEAKER_RECORD_TIMEOUT, + ) + self.spk_audio_recorder.record_into_queue(spk_audio_queue) + spk_transcriber = AudioTranscriber( + speaker=True, + source=self.spk_audio_recorder.source, + phrase_timeout=config.INPUT_SPEAKER_PHRASE_TIMEOUT, + max_phrases=config.INPUT_SPEAKER_MAX_PHRASES, + ) + def spk_transcript_to_textbox(): + spk_transcriber.transcribe_audio_queue(spk_audio_queue, transcription_lang[config.INPUT_SPEAKER_VOICE_LANGUAGE]) + message = spk_transcriber.get_transcript() + if len(message) > 0: + # translate + if config.ENABLE_TRANSLATION is False: + voice_message = f"{message}" + elif model.getTranslatorStatus() is False: + print_textbox(log, "Auth Key or language setting is incorrect", "ERROR") + print_textbox(system_log, "Auth Key or language setting is incorrect", "ERROR") + voice_message = f"{message}" + else: + voice_message = model.getOutputTranslate(message) + + if config.ENABLE_TRANSCRIPTION_RECEIVE is True: + # update textbox message receive log + print_textbox(log, f"{voice_message}", "RECEIVE") + print_textbox(receive_log, f"{voice_message}", "RECEIVE") + if config.ENABLE_NOTICE_XSOVERLAY is True: + notification_xsoverlay_for_vrct(content=f"{voice_message}") + + self.spk_print_transcript = thread_fnc(spk_transcript_to_textbox) + self.spk_print_transcript.daemon = True + self.spk_print_transcript.start() + + def stopSpeakerTranscript(self): + if isinstance(self.spk_print_transcript, thread_fnc): + self.spk_print_transcript.stop() + if self.spk_audio_recorder.stop != None: + self.spk_audio_recorder.stop() + self.spk_audio_recorder.stop = None + + def startCheckSpeakerEnergy(self, progressBar): + def progressBar_input_speaker_energy_plot(): + if speaker_energy_queue.empty() is False: + energy = speaker_energy_queue.get() + try: + progressBar.set(energy/config.MAX_SPEAKER_ENERGY_THRESHOLD) + except: + pass + sleep(0.01) + + def progressBar_input_speaker_energy_get(): + with self.speaker_energy_recorder.source as source: + energy = self.speaker_energy_recorder.recorder.listen_energy(source) + self.speaker_energy_queue.put(energy) + + speaker_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] + speaker_energy_queue = Queue() + self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device) + self.speaker_energy_get_progressbar = thread_fnc(progressBar_input_speaker_energy_get) + self.speaker_energy_get_progressbar.daemon = True + self.speaker_energy_get_progressbar.start() + self.speaker_energy_plot_progressbar = thread_fnc(progressBar_input_speaker_energy_plot) + self.speaker_energy_plot_progressbar.daemon = True + self.speaker_energy_plot_progressbar.start() + + def stopCheckSpeakerEnergy(self): + if self.speaker_energy_get_progressbar != None: + self.speaker_energy_get_progressbar.stop() + if self.speaker_energy_plot_progressbar != None: + self.speaker_energy_plot_progressbar.stop() + +model = Model() diff --git a/window_config.py b/window_config.py index 8b28937e..b54429cf 100644 --- a/window_config.py +++ b/window_config.py @@ -1,17 +1,13 @@ -from time import sleep -from queue import Queue from os import path as os_path from tkinter import DoubleVar, IntVar from tkinter import font as tk_font import customtkinter from customtkinter import CTkToplevel, CTkTabview, CTkFont, CTkLabel, CTkSlider, CTkOptionMenu, StringVar, CTkEntry, CTkCheckBox, CTkProgressBar -from flashtext import KeywordProcessor from threading import Thread from config import config -from utils import print_textbox, thread_fnc, get_localized_text, get_key_by_value, widget_config_window_label_setter -from audio_utils import get_input_device_list, get_output_device_list, get_default_output_device -from audio_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder +from model import model +from utils import print_textbox, get_localized_text, get_key_by_value, widget_config_window_label_setter from languages import translation_lang, transcription_lang, selectable_languages from ctk_scrollable_dropdown import CTkScrollableDropdown @@ -33,15 +29,6 @@ class ToplevelWindowConfig(CTkToplevel): self.after(200, lambda: self.iconbitmap(os_path.join(os_path.dirname(__file__), "img", "app.ico"))) self.title("Config") - # init parameter - self.MAX_MIC_ENERGY_THRESHOLD = 2000 - self.MAX_SPEAKER_ENERGY_THRESHOLD = 4000 - self.mic_energy_recorder = None - self.mic_energy_plot_progressbar = None - self.speaker_energy_recorder = None - self.speaker_energy_get_progressbar = None - self.speaker_energy_plot_progressbar = None - # load ui language data language_yaml_data = get_localized_text(f"{config.UI_LANGUAGE}") # add tabview config @@ -202,7 +189,7 @@ class ToplevelWindowConfig(CTkToplevel): def optionmenu_translation_translator_callback(self, choice): self.optionmenu_translation_translator.set(choice) - if self.parent.translator.authentication(choice, config.AUTH_KEYS[choice]) is False: + if model.authenticationTranslator(choice_translator=choice) is False: print_textbox(self.parent.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") print_textbox(self.parent.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") else: @@ -253,15 +240,15 @@ class ToplevelWindowConfig(CTkToplevel): def optionmenu_input_mic_host_callback(self, choice): self.optionmenu_input_mic_host.set(choice) + config.CHOICE_MIC_HOST = choice + config.CHOICE_MIC_DEVICE = model.getInputDefaultDevice() + self.optionmenu_input_mic_device.configure( - values=[device["name"] for device in get_input_device_list()[choice]], - variable=StringVar(value=[device["name"] for device in get_input_device_list()[choice]][0])) + values=model.getListInputDevice(), + variable=StringVar(value=model.getInputDefaultDevice())) if SCROLLABLE_DROPDOWN: - self.scrollableDropdown_input_mic_device.configure(values=[device["name"] for device in get_input_device_list()[choice]]) - - config.CHOICE_MIC_HOST = choice - config.CHOICE_MIC_DEVICE = [device["name"] for device in get_input_device_list()[choice]][0] + self.scrollableDropdown_input_mic_device.configure(values=model.getListInputDevice()) def optionmenu_input_mic_device_callback(self, choice): self.optionmenu_input_mic_device.set(choice) @@ -273,31 +260,13 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_mic_voice_language.set(choice) config.INPUT_MIC_VOICE_LANGUAGE = choice - def progressBar_input_mic_energy_plot(self): - if self.mic_energy_queue.empty() is False: - energy = self.mic_energy_queue.get() - try: - self.progressBar_input_mic_energy_threshold.set(energy/self.MAX_MIC_ENERGY_THRESHOLD) - except: - pass - sleep(0.01) - def mic_threshold_check_start(self): - self.mic_energy_queue = Queue() - mic_device = [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] - self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device) - self.mic_energy_recorder.record_into_queue(self.mic_energy_queue) - self.mic_energy_plot_progressbar = thread_fnc(self.progressBar_input_mic_energy_plot) - self.mic_energy_plot_progressbar.daemon = True - self.mic_energy_plot_progressbar.start() + model.startCheckMicEnergy(self.progressBar_input_mic_energy_threshold) self.checkbox_input_mic_threshold_check.configure(state="normal") self.checkbox_input_speaker_threshold_check.configure(state="normal") def mic_threshold_check_stop(self): - if self.mic_energy_recorder != None: - self.mic_energy_recorder.stop() - if self.mic_energy_plot_progressbar != None: - self.mic_energy_plot_progressbar.stop() + model.stopCheckMicEnergy() self.progressBar_input_mic_energy_threshold.set(0) self.checkbox_input_mic_threshold_check.configure(state="normal") self.checkbox_input_speaker_threshold_check.configure(state="normal") @@ -338,13 +307,11 @@ class ToplevelWindowConfig(CTkToplevel): config.INPUT_MIC_WORD_FILTER = word_filter.split(",") else: config.INPUT_MIC_WORD_FILTER = [] - self.parent.keyword_processor = KeywordProcessor() - for f in self.parent.INPUT_MIC_WORD_FILTER: - self.parent.keyword_processor.add_keyword(f) + model.resetKeywordProcessor() + model.addKeywords() def optionmenu_input_speaker_device_callback(self, choice): - speaker_device = [device for device in get_output_device_list() if device["name"] == choice][0] - if get_default_output_device()["index"] == speaker_device["index"]: + if model.checkSpeakerStatus(choice): self.optionmenu_input_speaker_device.set(choice) config.CHOICE_SPEAKER_DEVICE = choice else: @@ -356,45 +323,13 @@ class ToplevelWindowConfig(CTkToplevel): self.optionmenu_input_speaker_voice_language.set(choice) config.INPUT_SPEAKER_VOICE_LANGUAGE = choice - def progressBar_input_speaker_energy_plot(self): - if self.speaker_energy_queue.empty() is False: - energy = self.speaker_energy_queue.get() - try: - self.progressBar_input_speaker_energy_threshold.set(energy/self.MAX_SPEAKER_ENERGY_THRESHOLD) - except: - pass - sleep(0.01) - - def progressBar_input_speaker_energy_get(self): - with self.speaker_energy_recorder.source as source: - energy = self.speaker_energy_recorder.recorder.listen_energy(source) - self.speaker_energy_queue.put(energy) - def speaker_threshold_check_start(self): - speaker_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] - - if get_default_output_device()["index"] == speaker_device["index"]: - self.speaker_energy_queue = Queue() - self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device) - self.speaker_energy_get_progressbar = thread_fnc(self.progressBar_input_speaker_energy_get) - self.speaker_energy_get_progressbar.daemon = True - self.speaker_energy_get_progressbar.start() - self.speaker_energy_plot_progressbar = thread_fnc(self.progressBar_input_speaker_energy_plot) - self.speaker_energy_plot_progressbar.daemon = True - self.speaker_energy_plot_progressbar.start() - else: - print_textbox(self.parent.textbox_message_log, "Windows playback device and selected device do not match. Change the Windows playback device.", "ERROR") - print_textbox(self.parent.textbox_message_system_log, "Windows playback device and selected device do not match. Change the Windows playback device.", "ERROR") - self.checkbox_input_speaker_threshold_check.deselect() + model.startCheckSpeakerEnergy(self.progressBar_input_speaker_energy_threshold) self.checkbox_input_mic_threshold_check.configure(state="normal") self.checkbox_input_speaker_threshold_check.configure(state="normal") def speaker_threshold_check_stop(self): - if self.speaker_energy_get_progressbar != None: - self.speaker_energy_get_progressbar.stop() - if self.speaker_energy_plot_progressbar != None: - self.speaker_energy_plot_progressbar.stop() - + model.stopCheckSpeakerEnergy() self.progressBar_input_speaker_energy_threshold.set(0) self.checkbox_input_mic_threshold_check.configure(state="normal") self.checkbox_input_speaker_threshold_check.configure(state="normal") @@ -404,9 +339,14 @@ class ToplevelWindowConfig(CTkToplevel): self.checkbox_input_speaker_threshold_check.configure(state="disabled") self.update() if self.checkbox_input_speaker_threshold_check.get(): - th_speaker_threshold_check_start = Thread(target=self.speaker_threshold_check_start) - th_speaker_threshold_check_start.daemon = True - th_speaker_threshold_check_start.start() + if model.checkSpeakerStatus(): + th_speaker_threshold_check_start = Thread(target=self.speaker_threshold_check_start) + th_speaker_threshold_check_start.daemon = True + th_speaker_threshold_check_start.start() + else: + print_textbox(self.parent.textbox_message_log, "Windows playback device and selected device do not match. Change the Windows playback device.", "ERROR") + print_textbox(self.parent.textbox_message_system_log, "Windows playback device and selected device do not match. Change the Windows playback device.", "ERROR") + self.checkbox_input_speaker_threshold_check.deselect() else: th_speaker_threshold_check_stop = Thread(target=self.speaker_threshold_check_stop) th_speaker_threshold_check_stop.daemon = True @@ -436,10 +376,7 @@ class ToplevelWindowConfig(CTkToplevel): def entry_authkey_callback(self, event): value = self.entry_authkey.get() if len(value) > 0: - if self.parent.translator.authentication("DeepL(auth)", value) is True: - auth_keys = config.AUTH_KEYS - auth_keys["DeepL(auth)"] = value - config.AUTH_KEYS = auth_keys + if model.authenticationTranslator(choice_translator="DeepL(auth)", auth_key=value) is True: print_textbox(self.parent.textbox_message_log, "Auth key update completed", "INFO") print_textbox(self.parent.textbox_message_system_log, "Auth key update completed", "INFO") else: @@ -683,7 +620,7 @@ class ToplevelWindowConfig(CTkToplevel): self.label_translation_translator.grid(row=row, column=0, columnspan=1, padx=padx, pady=pady, sticky="nsw") self.optionmenu_translation_translator = CTkOptionMenu( self.tabview_config.tab(config_tab_title_translation), - values=list(self.parent.translator.translator_status.keys()), + values=model.getListTranslatorName(), command=self.optionmenu_translation_translator_callback, variable=StringVar(value=config.CHOICE_TRANSLATOR), font=CTkFont(family=config.FONT_FAMILY), @@ -695,7 +632,7 @@ class ToplevelWindowConfig(CTkToplevel): if SCROLLABLE_DROPDOWN: self.scrollableDropdown_translation_translator = CTkScrollableDropdown( self.optionmenu_translation_translator, - values=list(self.parent.translator.translator_status.keys()), + values=model.getListTranslatorName(), justify="left", button_color="transparent", command=self.optionmenu_translation_translator_callback, @@ -862,7 +799,7 @@ class ToplevelWindowConfig(CTkToplevel): self.label_input_mic_host.grid(row=row, column=0, columnspan=1, padx=padx, pady=pady, sticky="nsw") self.optionmenu_input_mic_host = CTkOptionMenu( self.tabview_config.tab(config_tab_title_transcription), - values=[host for host in get_input_device_list().keys()], + values=model.getListInputHost(), command=self.optionmenu_input_mic_host_callback, variable=StringVar(value=config.CHOICE_MIC_HOST), font=CTkFont(family=config.FONT_FAMILY), @@ -874,7 +811,7 @@ class ToplevelWindowConfig(CTkToplevel): if SCROLLABLE_DROPDOWN: self.scrollableDropdown_input_mic_host = CTkScrollableDropdown( self.optionmenu_input_mic_host, - values=[host for host in get_input_device_list().keys()], + values=model.getListInputHost(), justify="left", button_color="transparent", command=self.optionmenu_input_mic_host_callback, @@ -896,7 +833,7 @@ class ToplevelWindowConfig(CTkToplevel): self.label_input_mic_device.grid(row=row, column=0, columnspan=1, padx=padx, pady=pady, sticky="nsw") self.optionmenu_input_mic_device = CTkOptionMenu( self.tabview_config.tab(config_tab_title_transcription), - values=[device["name"] for device in get_input_device_list()[config.CHOICE_MIC_HOST]], + values=model.getListInputDevice(), command=self.optionmenu_input_mic_device_callback, variable=StringVar(value=config.CHOICE_MIC_DEVICE), font=CTkFont(family=config.FONT_FAMILY), @@ -908,7 +845,7 @@ class ToplevelWindowConfig(CTkToplevel): if SCROLLABLE_DROPDOWN: self.scrollableDropdown_input_mic_device = CTkScrollableDropdown( self.optionmenu_input_mic_device, - values=[device["name"] for device in get_input_device_list()[config.CHOICE_MIC_HOST]], + values=model.getListInputDevice(), justify="left", button_color="transparent", command=self.optionmenu_input_mic_device_callback, @@ -966,11 +903,11 @@ class ToplevelWindowConfig(CTkToplevel): self.slider_input_mic_energy_threshold = CTkSlider( self.tabview_config.tab(config_tab_title_transcription), from_=0, - to=self.MAX_MIC_ENERGY_THRESHOLD, + to=config.MAX_MIC_ENERGY_THRESHOLD, border_width=7, button_length=0, button_corner_radius=3, - number_of_steps=self.MAX_MIC_ENERGY_THRESHOLD, + number_of_steps=config.MAX_MIC_ENERGY_THRESHOLD, command=self.slider_input_mic_energy_threshold_callback, variable=IntVar(value=config.INPUT_MIC_ENERGY_THRESHOLD), ) @@ -1102,7 +1039,7 @@ class ToplevelWindowConfig(CTkToplevel): self.label_input_speaker_device.grid(row=row, column=0, columnspan=1, padx=padx, pady=pady, sticky="nsw") self.optionmenu_input_speaker_device = CTkOptionMenu( self.tabview_config.tab(config_tab_title_transcription), - values=[device["name"] for device in get_output_device_list()], + values=model.getListOutputDevice(), command=self.optionmenu_input_speaker_device_callback, variable=StringVar(value=config.CHOICE_SPEAKER_DEVICE), font=CTkFont(family=config.FONT_FAMILY), @@ -1114,7 +1051,7 @@ class ToplevelWindowConfig(CTkToplevel): if SCROLLABLE_DROPDOWN: self.scrollableDropdown_input_speaker_device = CTkScrollableDropdown( self.optionmenu_input_speaker_device, - values=[device["name"] for device in get_output_device_list()], + values=model.getListOutputDevice(), justify="left", button_color="transparent", command=self.optionmenu_input_speaker_device_callback, @@ -1173,11 +1110,11 @@ class ToplevelWindowConfig(CTkToplevel): self.slider_input_speaker_energy_threshold = CTkSlider( self.tabview_config.tab(config_tab_title_transcription), from_=0, - to=self.MAX_SPEAKER_ENERGY_THRESHOLD, + to=config.MAX_SPEAKER_ENERGY_THRESHOLD, border_width=7, button_length=0, button_corner_radius=3, - number_of_steps=self.MAX_SPEAKER_ENERGY_THRESHOLD, + number_of_steps=config.MAX_SPEAKER_ENERGY_THRESHOLD, command=self.slider_input_speaker_energy_threshold_callback, variable=IntVar(value=config.INPUT_SPEAKER_ENERGY_THRESHOLD), ) From e3a37c576cd66631bb05b9a3d37716a0301d3d80 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Fri, 18 Aug 2023 15:46:52 +0900 Subject: [PATCH 3/8] [typo] remove print command --- model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/model.py b/model.py index c550f43e..348da461 100644 --- a/model.py +++ b/model.py @@ -160,7 +160,6 @@ class Model: mic_transcriber.transcribe_audio_queue(mic_audio_queue, transcription_lang[config.INPUT_MIC_VOICE_LANGUAGE]) message = mic_transcriber.get_transcript() if len(message) > 0: - print(message) # word filter if self.checkKeywords(message): print_textbox(log, f"Detect WordFilter :{message}", "INFO") From 31e786f2a83c91b074656560e729225e4b08c9dd Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sat, 19 Aug 2023 19:09:01 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[Update]=20model.py=E3=81=8B=E3=82=89print?= =?UTF-8?q?=5Ftextbox=E3=82=92=E3=81=99=E3=81=B9=E3=81=A6=E5=BC=95?= =?UTF-8?q?=E3=81=8D=E5=89=A5=E3=81=8C=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UIの依存関係はなくなったはず --- VRCT.py | 187 ++++++++++++++++++++++++++++++++++++++---------------- config.py | 73 +++++++++++---------- model.py | 57 +++-------------- utils.py | 10 +-- 4 files changed, 184 insertions(+), 143 deletions(-) diff --git a/VRCT.py b/VRCT.py index af03393a..fbc71654 100644 --- a/VRCT.py +++ b/VRCT.py @@ -56,8 +56,7 @@ class App(CTk): # set translator if model.authenticationTranslator() is False: # error update Auth key - print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") + self.printLogAuthenticationError() # set word filter model.addKeywords() @@ -93,32 +92,27 @@ class App(CTk): def checkbox_translation_callback(self): config.ENABLE_TRANSLATION = self.checkbox_translation.get() if config.ENABLE_TRANSLATION is True: - print_textbox(self.textbox_message_log, "Start translation", "INFO") - print_textbox(self.textbox_message_system_log, "Start translation", "INFO") + self.printLogStartTranslation() else: - print_textbox(self.textbox_message_log, "Stop translation", "INFO") - print_textbox(self.textbox_message_system_log, "Stop translation", "INFO") + self.printLogStopTranslation() def transcription_send_start(self): - model.startMicTranscript(self.textbox_message_log, self.textbox_message_send_log, self.textbox_message_system_log) - print_textbox(self.textbox_message_log, "Start voice2chatbox", "INFO") - print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO") + model.startMicTranscript(self.sendMicMessage) + self.printLogStartVoice2chatbox() self.checkbox_transcription_send.configure(state="normal") self.checkbox_transcription_receive.configure(state="normal") self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_send_stop(self): model.stopMicTranscript() - print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") - print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") + self.printLogStopVoice2chatbox() self.checkbox_transcription_send.configure(state="normal") self.checkbox_transcription_receive.configure(state="normal") self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_send_stop_for_config(self): model.stopMicTranscript() - print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") - print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") + self.printLogStopVoice2chatbox() def checkbox_transcription_send_callback(self): config.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() @@ -135,25 +129,22 @@ class App(CTk): th_transcription_send_stop.start() def transcription_receive_start(self): - model.startSpeakerTranscript(self.textbox_message_log, self.textbox_message_receive_log, self.textbox_message_system_log) - print_textbox(self.textbox_message_log, "Start speaker2log", "INFO") - print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO") + model.startSpeakerTranscript(self.receiveSpeakerMessage) + self.printLogStartSpeaker2log() self.checkbox_transcription_send.configure(state="normal") self.checkbox_transcription_receive.configure(state="normal") self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_receive_stop(self): model.stopSpeakerTranscript() - print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") - print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") + self.printLogStopSpeaker2log() self.checkbox_transcription_send.configure(state="normal") self.checkbox_transcription_receive.configure(state="normal") self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) def transcription_receive_stop_for_config(self): model.stopSpeakerTranscript() - print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") - print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") + self.printLogStopSpeaker2log() def checkbox_transcription_receive_callback(self): config.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get() @@ -194,24 +185,20 @@ class App(CTk): config.ENABLE_FOREGROUND = self.checkbox_foreground.get() if config.ENABLE_FOREGROUND: self.attributes("-topmost", True) - print_textbox(self.textbox_message_log, "Start foreground", "INFO") - print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") + self.printLogStartForeground() else: self.attributes("-topmost", False) - print_textbox(self.textbox_message_log, "Stop foreground", "INFO") - print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") + self.printLogStopForeground() def foreground_start(self): if config.ENABLE_FOREGROUND: self.attributes("-topmost", True) - print_textbox(self.textbox_message_log, "Start foreground", "INFO") - print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") + self.printLogStartForeground() def foreground_stop(self): if config.ENABLE_FOREGROUND: self.attributes("-topmost", False) - print_textbox(self.textbox_message_log, "Stop foreground", "INFO") - print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") + self.printLogStopForeground() def entry_message_box_press_key_enter(self, event): # osc stop send typing @@ -221,31 +208,7 @@ class App(CTk): self.attributes("-topmost", True) message = self.entry_message_box.get() - if len(message) > 0: - # translate - if config.ENABLE_TRANSLATION is False: - chat_message = f"{message}" - elif model.getTranslatorStatus() is False: - print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") - chat_message = f"{message}" - else: - chat_message = model.getInputTranslate(message) - - # send OSC message - if config.ENABLE_OSC is True: - model.oscSendMessage(chat_message) - else: - print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - - # update textbox message log - print_textbox(self.textbox_message_log, f"{chat_message}", "SEND") - print_textbox(self.textbox_message_send_log, f"{chat_message}", "SEND") - - # delete message in entry message box - if config.ENABLE_AUTO_CLEAR_CHATBOX is True: - self.entry_message_box.delete(0, customtkinter.END) + self.sendChatMessage(message) def entry_message_box_press_key_any(self, event): # osc start send typing @@ -405,6 +368,124 @@ class App(CTk): widget_main_window_label_setter(self, language_yaml_data) + def printLogAuthenticationError(self): + print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") + + def printLogStartTranslation(self): + print_textbox(self.textbox_message_log, "Start translation", "INFO") + print_textbox(self.textbox_message_system_log, "Start translation", "INFO") + + def printLogStopTranslation(self): + print_textbox(self.textbox_message_log, "Stop translation", "INFO") + print_textbox(self.textbox_message_system_log, "Stop translation", "INFO") + + def printLogStartVoice2chatbox(self): + print_textbox(self.textbox_message_log, "Start voice2chatbox", "INFO") + print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO") + + def printLogStopVoice2chatbox(self): + print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") + print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") + + def printLogStartSpeaker2log(self): + print_textbox(self.textbox_message_log, "Start speaker2log", "INFO") + print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO") + + def printLogStopSpeaker2log(self): + print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") + print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") + + def printLogStartForeground(self): + print_textbox(self.textbox_message_log, "Start foreground", "INFO") + print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") + + def printLogStopForeground(self): + print_textbox(self.textbox_message_log, "Stop foreground", "INFO") + print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") + + def printLogDetectWordFilter(self, message): + print_textbox(self.textbox_message_log, f"Detect WordFilter :{message}", "INFO") + print_textbox(self.textbox_message_system_log, f"Detect WordFilter :{message}", "INFO") + + def printLogOSCError(self): + print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") + print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") + + def printLogSendMessage(self, message): + print_textbox(self.textbox_message_log, f"{message}", "SEND") + print_textbox(self.textbox_message_send_log, f"{message}", "SEND") + + def printLogReceiveMessage(self, message): + print_textbox(self.textbox_message_log, f"{message}", "RECEIVE") + print_textbox(self.textbox_message_receive_log, f"{message}", "RECEIVE") + + def sendChatMessage(self, message): + if len(message) > 0: + # translate + if config.ENABLE_TRANSLATION is False: + chat_message = f"{message}" + elif model.getTranslatorStatus() is False: + self.printLogAuthenticationError() + chat_message = f"{message}" + else: + chat_message = model.getInputTranslate(message) + + # send OSC message + if config.ENABLE_OSC is True: + model.oscSendMessage(chat_message) + else: + self.printLogOSCError() + + # update textbox message log + self.printLogSendMessage(chat_message) + + # delete message in entry message box + if config.ENABLE_AUTO_CLEAR_CHATBOX is True: + self.entry_message_box.delete(0, customtkinter.END) + + def sendMicMessage(self, message): + if len(message) > 0: + # word filter + if model.checkKeywords(message): + self.printLogDetectWordFilter(message) + return + + # translate + if config.ENABLE_TRANSLATION is False: + voice_message = f"{message}" + elif model.getTranslatorStatus() is False: + self.printLogAuthenticationError() + voice_message = f"{message}" + else: + voice_message = model.getInputTranslate(message) + + if config.ENABLE_TRANSCRIPTION_SEND is True: + if config.ENABLE_OSC is True: + # osc send message + model.oscSendMessage(voice_message) + else: + self.printLogOSCError() + # update textbox message log + self.printLogSendMessage(voice_message) + + def receiveSpeakerMessage(self, message): + if len(message) > 0: + # translate + if config.ENABLE_TRANSLATION is False: + voice_message = f"{message}" + elif model.getTranslatorStatus() is False: + self.printLogAuthenticationError() + voice_message = f"{message}" + else: + voice_message = model.getOutputTranslate(message) + + if config.ENABLE_TRANSCRIPTION_RECEIVE is True: + # update textbox message receive log + self.printLogReceiveMessage(voice_message) + if config.ENABLE_NOTICE_XSOVERLAY is True: + model.notificationXsoverlay(voice_message) + if __name__ == "__main__": try: app = App() diff --git a/config.py b/config.py index 0cb6f299..c4edc384 100644 --- a/config.py +++ b/config.py @@ -1,13 +1,20 @@ +from json import load, dump import inspect from os import path as os_path from json import load as json_load from json import dump as json_dump import tkinter as tk from tkinter import font -from utils import save_json from languages import transcription_lang, translators, translation_lang, selectable_languages from audio_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device +def saveJson(path, key, value): + with open(path, "r") as fp: + json_data = load(fp) + json_data[key] = value + with open(path, "w") as fp: + dump(json_data, fp, indent=4) + class Config: _instance = None @@ -70,7 +77,7 @@ class Config: def TRANSPARENCY(self, value): if type(value) is int and 0 <= value <= 100: self._TRANSPARENCY = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def APPEARANCE_THEME(self): @@ -80,7 +87,7 @@ class Config: def APPEARANCE_THEME(self, value): if value in ["Light", "Dark", "System"]: self._APPEARANCE_THEME = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def UI_SCALING(self): @@ -90,7 +97,7 @@ class Config: def UI_SCALING(self, value): if value in ["80%", "90%", "100%", "110%", "120%"]: self._UI_SCALING = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def FONT_FAMILY(self): @@ -102,7 +109,7 @@ class Config: root.withdraw() if value in list(font.families()): self._FONT_FAMILY = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) root.destroy() @property @@ -113,7 +120,7 @@ class Config: def UI_LANGUAGE(self, value): if value in list(selectable_languages.keys()): self._UI_LANGUAGE = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def CHOICE_TRANSLATOR(self): @@ -123,7 +130,7 @@ class Config: def CHOICE_TRANSLATOR(self, value): if value in translators: self._CHOICE_TRANSLATOR = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SOURCE_LANG(self): @@ -133,7 +140,7 @@ class Config: def INPUT_SOURCE_LANG(self, value): if value in list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys()): self._INPUT_SOURCE_LANG = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_TARGET_LANG(self): @@ -143,7 +150,7 @@ class Config: def INPUT_TARGET_LANG(self, value): if value in list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys()): self._INPUT_TARGET_LANG = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def OUTPUT_SOURCE_LANG(self): @@ -153,7 +160,7 @@ class Config: def OUTPUT_SOURCE_LANG(self, value): if value in list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys()): self._OUTPUT_SOURCE_LANG = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def OUTPUT_TARGET_LANG(self): @@ -163,7 +170,7 @@ class Config: def OUTPUT_TARGET_LANG(self, value): if value in list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys()): self._OUTPUT_TARGET_LANG = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def CHOICE_MIC_HOST(self): @@ -173,7 +180,7 @@ class Config: def CHOICE_MIC_HOST(self, value): if value in [host for host in get_input_device_list().keys()]: self._CHOICE_MIC_HOST = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def CHOICE_MIC_DEVICE(self): @@ -183,7 +190,7 @@ class Config: def CHOICE_MIC_DEVICE(self, value): if value in [device["name"] for device in get_input_device_list()[self.CHOICE_MIC_HOST]]: self._CHOICE_MIC_DEVICE = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_VOICE_LANGUAGE(self): @@ -193,7 +200,7 @@ class Config: def INPUT_MIC_VOICE_LANGUAGE(self, value): if value in list(transcription_lang.keys()): self._INPUT_MIC_VOICE_LANGUAGE = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_ENERGY_THRESHOLD(self): @@ -203,7 +210,7 @@ class Config: def INPUT_MIC_ENERGY_THRESHOLD(self, value): if type(value) is int: self._INPUT_MIC_ENERGY_THRESHOLD = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD(self): @@ -213,7 +220,7 @@ class Config: def INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD(self, value): if type(value) is bool: self._INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_RECORD_TIMEOUT(self): @@ -223,7 +230,7 @@ class Config: def INPUT_MIC_RECORD_TIMEOUT(self, value): if type(value) is int: self._INPUT_MIC_RECORD_TIMEOUT = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_PHRASE_TIMEOUT(self): @@ -233,7 +240,7 @@ class Config: def INPUT_MIC_PHRASE_TIMEOUT(self, value): if type(value) is int: self._INPUT_MIC_PHRASE_TIMEOUT = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_MAX_PHRASES(self): @@ -243,7 +250,7 @@ class Config: def INPUT_MIC_MAX_PHRASES(self, value): if type(value) is int: self._INPUT_MIC_MAX_PHRASES = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_MIC_WORD_FILTER(self): @@ -253,7 +260,7 @@ class Config: def INPUT_MIC_WORD_FILTER(self, value): if type(value) is list: self._INPUT_MIC_WORD_FILTER = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def CHOICE_SPEAKER_DEVICE(self): @@ -265,7 +272,7 @@ class Config: speaker_device = [device for device in get_output_device_list() if device["name"] == value][0] if get_default_output_device()["index"] == speaker_device["index"]: self._CHOICE_SPEAKER_DEVICE = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SPEAKER_VOICE_LANGUAGE(self): @@ -275,7 +282,7 @@ class Config: def INPUT_SPEAKER_VOICE_LANGUAGE(self, value): if value in list(transcription_lang.keys()): self._INPUT_SPEAKER_VOICE_LANGUAGE = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SPEAKER_ENERGY_THRESHOLD(self): @@ -285,7 +292,7 @@ class Config: def INPUT_SPEAKER_ENERGY_THRESHOLD(self, value): if type(value) is int: self._INPUT_SPEAKER_ENERGY_THRESHOLD = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD(self): @@ -295,7 +302,7 @@ class Config: def INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD(self, value): if type(value) is bool: self._INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SPEAKER_RECORD_TIMEOUT(self): @@ -305,7 +312,7 @@ class Config: def INPUT_SPEAKER_RECORD_TIMEOUT(self, value): if type(value) is int: self._INPUT_SPEAKER_RECORD_TIMEOUT = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SPEAKER_PHRASE_TIMEOUT(self): @@ -315,7 +322,7 @@ class Config: def INPUT_SPEAKER_PHRASE_TIMEOUT(self, value): if type(value) is int: self._INPUT_SPEAKER_PHRASE_TIMEOUT = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def INPUT_SPEAKER_MAX_PHRASES(self): @@ -325,7 +332,7 @@ class Config: def INPUT_SPEAKER_MAX_PHRASES(self, value): if type(value) is int: self._INPUT_SPEAKER_MAX_PHRASES = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def OSC_IP_ADDRESS(self): @@ -335,7 +342,7 @@ class Config: def OSC_IP_ADDRESS(self, value): if type(value) is str: self._OSC_IP_ADDRESS = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def OSC_PORT(self): @@ -345,7 +352,7 @@ class Config: def OSC_PORT(self, value): if type(value) is int: self._OSC_PORT = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def AUTH_KEYS(self): @@ -357,7 +364,7 @@ class Config: for key, value in value.items(): if type(value) is str: self._AUTH_KEYS[key] = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, self.AUTH_KEYS) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, self.AUTH_KEYS) @property def MESSAGE_FORMAT(self): @@ -367,7 +374,7 @@ class Config: def MESSAGE_FORMAT(self, value): if type(value) is str: self._MESSAGE_FORMAT = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def ENABLE_AUTO_CLEAR_CHATBOX(self): @@ -377,7 +384,7 @@ class Config: def ENABLE_AUTO_CLEAR_CHATBOX(self, value): if type(value) is bool: self._ENABLE_AUTO_CLEAR_CHATBOX = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def ENABLE_NOTICE_XSOVERLAY(self): @@ -387,7 +394,7 @@ class Config: def ENABLE_NOTICE_XSOVERLAY(self, value): if type(value) is bool: self._ENABLE_NOTICE_XSOVERLAY = value - save_json(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property def ENABLE_OSC(self): diff --git a/model.py b/model.py index 348da461..1356c372 100644 --- a/model.py +++ b/model.py @@ -11,9 +11,9 @@ from audio_utils import get_input_device_list, get_output_device_list, get_defau from audio_recorder import SelectedMicRecorder, SelectedSpeakerRecorder from audio_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder from audio_transcriber import AudioTranscriber -from utils import print_textbox, thread_fnc -from config import config from notification import notification_xsoverlay_for_vrct +from utils import thread_fnc +from config import config class Model: _instance = None @@ -141,7 +141,7 @@ class Model: return True return False - def startMicTranscript(self, log, send_log, system_log): + def startMicTranscript(self, fnc): mic_audio_queue = Queue() self.mic_audio_recorder = SelectedMicRecorder( [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0], @@ -159,33 +159,7 @@ class Model: def mic_transcript_to_chatbox(): mic_transcriber.transcribe_audio_queue(mic_audio_queue, transcription_lang[config.INPUT_MIC_VOICE_LANGUAGE]) message = mic_transcriber.get_transcript() - if len(message) > 0: - # word filter - if self.checkKeywords(message): - print_textbox(log, f"Detect WordFilter :{message}", "INFO") - print_textbox(system_log, f"Detect WordFilter :{message}", "INFO") - return - - # translate - if config.ENABLE_TRANSLATION is False: - voice_message = f"{message}" - elif self.getTranslatorStatus() is False: - print_textbox(log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(system_log, "Auth Key or language setting is incorrect", "ERROR") - voice_message = f"{message}" - else: - voice_message = self.getInputTranslate(message) - - if config.ENABLE_TRANSCRIPTION_SEND is True: - if config.ENABLE_OSC is True: - # osc send message - model.oscSendMessage(voice_message) - else: - print_textbox(log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - print_textbox(system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - # update textbox message log - print_textbox(log, f"{voice_message}", "SEND") - print_textbox(send_log, f"{voice_message}", "SEND") + fnc(message) self.mic_print_transcript = thread_fnc(mic_transcript_to_chatbox) self.mic_print_transcript.daemon = True @@ -221,7 +195,7 @@ class Model: if self.mic_energy_plot_progressbar != None: self.mic_energy_plot_progressbar.stop() - def startSpeakerTranscript(self, log, receive_log, system_log): + def startSpeakerTranscript(self, fnc): spk_audio_queue = Queue() spk_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] self.spk_audio_recorder = SelectedSpeakerRecorder( @@ -240,23 +214,7 @@ class Model: def spk_transcript_to_textbox(): spk_transcriber.transcribe_audio_queue(spk_audio_queue, transcription_lang[config.INPUT_SPEAKER_VOICE_LANGUAGE]) message = spk_transcriber.get_transcript() - if len(message) > 0: - # translate - if config.ENABLE_TRANSLATION is False: - voice_message = f"{message}" - elif model.getTranslatorStatus() is False: - print_textbox(log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(system_log, "Auth Key or language setting is incorrect", "ERROR") - voice_message = f"{message}" - else: - voice_message = model.getOutputTranslate(message) - - if config.ENABLE_TRANSCRIPTION_RECEIVE is True: - # update textbox message receive log - print_textbox(log, f"{voice_message}", "RECEIVE") - print_textbox(receive_log, f"{voice_message}", "RECEIVE") - if config.ENABLE_NOTICE_XSOVERLAY is True: - notification_xsoverlay_for_vrct(content=f"{voice_message}") + fnc(message) self.spk_print_transcript = thread_fnc(spk_transcript_to_textbox) self.spk_print_transcript.daemon = True @@ -300,4 +258,7 @@ class Model: if self.speaker_energy_plot_progressbar != None: self.speaker_energy_plot_progressbar.stop() + def notificationXsoverlay(self, message): + notification_xsoverlay_for_vrct(content=f"{message}") + model = Model() diff --git a/utils.py b/utils.py index ac2eb35d..ffe7ade7 100644 --- a/utils.py +++ b/utils.py @@ -1,16 +1,8 @@ -from json import load, dump from os import path as os_path import yaml from datetime import datetime from threading import Thread, Event -def save_json(path, key, value): - with open(path, "r") as fp: - json_data = load(fp) - json_data[key] = value - with open(path, "w") as fp: - dump(json_data, fp, indent=4) - def print_textbox(textbox, message, tags=None): now = datetime.now() now = now.strftime('%H:%M:%S') @@ -58,7 +50,7 @@ def get_localized_text(language): return localized_text else: return None - + def get_key_by_value(dictionary, value): for key, val in dictionary.items(): if val == value: From 02d8fbdb1c4031812cd6e728aa4b40d0385b4ce3 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sun, 20 Aug 2023 01:20:30 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[Update]=20=E6=A9=9F=E8=83=BD=E9=83=A8?= =?UTF-8?q?=E5=88=86=E3=82=92models=E3=83=95=E3=82=A9=E3=83=AB=E3=83=80?= =?UTF-8?q?=E3=81=AB=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VRCT.py | 4 +- config.py | 10 +- languages.py | 336 ------------------ model.py | 53 +-- osc_tools.py => models/osc/osc_tools.py | 0 .../transcription/transcription_languages.py | 91 +++++ .../transcription/transcription_recorder.py | 0 .../transcription_transcriber.py | 3 +- .../transcription/transcription_utils.py | 0 models/translation/translation_languages.py | 243 +++++++++++++ .../translation/translation_translator.py | 4 +- .../xsoverlay/notification.py | 0 utils.py | 16 - window_config.py | 20 +- 14 files changed, 392 insertions(+), 388 deletions(-) rename osc_tools.py => models/osc/osc_tools.py (100%) create mode 100644 models/transcription/transcription_languages.py rename audio_recorder.py => models/transcription/transcription_recorder.py (100%) rename audio_transcriber.py => models/transcription/transcription_transcriber.py (97%) rename audio_utils.py => models/transcription/transcription_utils.py (100%) create mode 100644 models/translation/translation_languages.py rename translation.py => models/translation/translation_translator.py (95%) rename notification.py => models/xsoverlay/notification.py (100%) diff --git a/VRCT.py b/VRCT.py index fbc71654..565c4bdd 100644 --- a/VRCT.py +++ b/VRCT.py @@ -417,8 +417,8 @@ class App(CTk): print_textbox(self.textbox_message_send_log, f"{message}", "SEND") def printLogReceiveMessage(self, message): - print_textbox(self.textbox_message_log, f"{message}", "RECEIVE") - print_textbox(self.textbox_message_receive_log, f"{message}", "RECEIVE") + print_textbox(self.textbox_message_log, f"{message}", "RECEIVE") + print_textbox(self.textbox_message_receive_log, f"{message}", "RECEIVE") def sendChatMessage(self, message): if len(message) > 0: diff --git a/config.py b/config.py index c4edc384..ced57eab 100644 --- a/config.py +++ b/config.py @@ -5,8 +5,10 @@ from json import load as json_load from json import dump as json_dump import tkinter as tk from tkinter import font -from languages import transcription_lang, translators, translation_lang, selectable_languages -from audio_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device +from languages import selectable_languages +from models.translation.translation_languages import translatorEngine, translation_lang +from models.transcription.transcription_languages import transcription_lang +from models.transcription.transcription_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device def saveJson(path, key, value): with open(path, "r") as fp: @@ -128,7 +130,7 @@ class Config: @CHOICE_TRANSLATOR.setter def CHOICE_TRANSLATOR(self, value): - if value in translators: + if value in translatorEngine: self._CHOICE_TRANSLATOR = value saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @@ -442,7 +444,7 @@ class Config: self._UI_SCALING = "100%" self._FONT_FAMILY = "Yu Gothic UI" self._UI_LANGUAGE = "en" - self._CHOICE_TRANSLATOR = translators[0] + self._CHOICE_TRANSLATOR = translatorEngine[0] self._INPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[0] self._INPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[1] self._OUTPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[1] diff --git a/languages.py b/languages.py index 3862f4ff..bac2eb0f 100644 --- a/languages.py +++ b/languages.py @@ -1,339 +1,3 @@ -transcription_lang = { - "Japanese (Japan)":"ja-JP", - "English (United States)":"en-US", - "English (United Kingdom)":"en-GB", - "Afrikaans (South Africa)":"af-ZA", - "Arabic (Algeria)":"ar-DZ", - "Arabic (Bahrain)":"ar-BH", - "Arabic (Egypt)":"ar-EG", - "Arabic (Israel)":"ar-IL", - "Arabic (Iraq)":"ar-IQ", - "Arabic (Jordan)":"ar-JO", - "Arabic (Kuwait)":"ar-KW", - "Arabic (Lebanon)":"ar-LB", - "Arabic (Morocco)":"ar-MA", - "Arabic (Oman)":"ar-OM", - "Arabic (State of Palestine)":"ar-PS", - "Arabic (Qatar)":"ar-QA", - "Arabic (Saudi Arabia)":"ar-SA", - "Arabic (Tunisia)":"ar-TN", - "Arabic (United Arab Emirates)":"ar-AE", - "Basque (Spain)":"eu-ES", - "Bulgarian (Bulgaria)":"bg-BG", - "Catalan (Spain)":"ca-ES", - "Chinese, Mandarin (Simplified, China)":"cmn-Hans-CN", - "Chinese, Mandarin (Simplified, Hong Kong)":"cmn-Hans-HK", - "Chinese, Mandarin (Traditional, Taiwan)":"cmn-Hant-TW", - "Chinese, Cantonese (Traditional Hong Kong)":"yue-Hant-HK", - "Croatian (Croatia)":"hr-HR", - "Czech (Czech Republic)":"cs-CZ", - "Danish (Denmark)":"da-DK", - "English (Australia)":"en-AU", - "English (Canada)":"en-CA", - "English (India)":"en-IN", - "English (Ireland)":"en-IE", - "English (New Zealand)":"en-NZ", - "English (Philippines)":"en-PH", - "English (South Africa)":"en-ZA", - "Persian (Iran)":"fa-IR", - "French (France)":"fr-FR", - "Filipino (Philippines)":"fil-PH", - "Galician (Spain)":"gl-ES", - "German (Germany)":"de-DE", - "Greek (Greece)":"el-GR", - "Finnish (Finland)":"fi-FI", - "Hebrew (Israel)":"he-IL", - "Hindi (India)":"hi-IN", - "Hungarian (Hungary)":"hu-HU", - "Indonesian (Indonesia)":"id-ID", - "Icelandic (Iceland)":"is-IS", - "Italian (Italy)":"it-IT", - "Italian (Switzerland)":"it-CH", - "Korean (South Korea)":"ko-KR", - "Lithuanian (Lithuania)":"lt-LT", - "Malay (Malaysia)":"ms-MY", - "Dutch (Netherlands)":"nl-NL", - "Norwegian Bokmål (Norway)":"nb-NO", - "Polish (Poland)":"pl-PL", - "Portuguese (Brazil)":"pt-BR", - "Portuguese (Portugal)":"pt-PT", - "Romanian (Romania)":"ro-RO", - "Russian (Russia)":"ru-RU", - "Serbian (Serbia)":"sr-RS", - "Slovak (Slovakia)":"sk-SK", - "Slovenian (Slovenia)":"sl-SI", - "Spanish (Argentina)":"es-AR", - "Spanish (Bolivia)":"es-BO", - "Spanish (Chile)":"es-CL", - "Spanish (Colombia)":"es-CO", - "Spanish (Costa Rica)":"es-CR", - "Spanish (Dominican Republic)":"es-DO", - "Spanish (Ecuador)":"es-EC", - "Spanish (El Salvador)":"es-SV", - "Spanish (Guatemala)":"es-GT", - "Spanish (Honduras)":"es-HN", - "Spanish (Mexico)":"es-MX", - "Spanish (Nicaragua)":"es-NI", - "Spanish (Panama)":"es-PA", - "Spanish (Paraguay)":"es-PY", - "Spanish (Peru)":"es-PE", - "Spanish (Puerto Rico)":"es-PR", - "Spanish (Spain)":"es-ES", - "Spanish (Uruguay)":"es-UY", - "Spanish (United States)":"es-US", - "Spanish (Venezuela)":"es-VE", - "Swedish (Sweden)":"sv-SE", - "Thai (Thailand)":"th-TH", - "Turkish (Turkey)":"tr-TR", - "Ukrainian (Ukraine)":"uk-UA", - "Vietnamese (Vietnam)":"vi-VN", - "Zulu (South Africa)":"zu-ZA" -} - -translators = ["DeepL(web)", "DeepL(auth)", "Google(web)", "Bing(web)"] -translation_lang = {} -dict_deepl_web_languages = { - "Japanese":"JA", - "English":"EN", - "Korean":"KO", - "Bulgarian":"BG", - "Chinese":"ZH", - "Czech":"CS", - "Danish":"DA", - "Dutch":"NL", - "Estonian":"ET", - "Finnish":"FI", - "French":"FR", - "German":"DE", - "Greek":"EL", - "Hungarian":"HU", - "Italian":"IT", - "Latvian":"LV", - "Lithuanian":"LT", - "Polish":"PL", - "Portuguese":"PT", - "Romanian":"RO", - "Russian":"RU", - "Slovak":"SK", - "Slovenian":"SL", - "Spanish":"ES", - "Swedish":"SV", - "Indonesian":"ID", - "Ukrainian":"UK", - "Turkish":"TR", - "Norwegian":"NB", -} -translation_lang["DeepL(web)"] = { - "source":dict_deepl_web_languages, - "target":dict_deepl_web_languages, -} - -dict_deepl_auth_source_languages = { - "Japanese":"ja", - "English":"en", - "Bulgarian":"bg", - "Czech":"cs", - "Danish":"da", - "German":"de", - "Greek":"el", - "Spanish":"es", - "Estonian":"et", - "Finnish":"fi", - "French":"fr", - "Hungarian":"hu", - "Indonesian":"id", - "Italian":"it", - "Korean":"ko", - "Lithuanian":"lt", - "Latvian":"lv", - "Norwegian":"nb", - "Dutch":"nl", - "Polish":"pl", - "Portuguese":"pt", - "Romanian":"ro", - "Russian":"ru", - "Slovak":"sk", - "Slovenian":"sl", - "Swedish":"sv", - "Turkish":"tr", - "Ukrainian":"uk", - "Chinese":"zh" -} -dict_deepl_auth_target_languages = { - "Japanese":"ja", - "English American":"en-US", - "English British":"en-GB", - "Bulgarian":"bg", - "Czech":"cs", - "Danish":"da", - "German":"de", - "Greek":"el", - "English":"en", - "Spanish":"es", - "Estonian":"et", - "Finnish":"fi", - "French":"fr", - "Hungarian":"hu", - "Indonesian":"id", - "Italian":"it", - "Korean":"ko", - "Lithuanian":"lt", - "Latvian":"lv", - "Norwegian":"nb", - "Dutch":"nl", - "Polish":"pl", - "Portuguese Brazilian":"pt-BR", - "Portuguese European":"pt-PT", - "Romanian":"ro", - "Russian":"ru", - "Slovak":"sk", - "Slovenian":"sl", - "Swedish":"sv", - "Turkish":"tr", - "Ukrainian":"uk", - "Chinese":"zh" -} -translation_lang["DeepL(auth)"] = { - "source": dict_deepl_auth_source_languages, - "target": dict_deepl_auth_target_languages, -} - -dict_google_web_languages = { - "Japanese":"ja", - "English":"en", - "Chinese":"zh", - "Arabic":"ar", - "Russian":"ru", - "French":"fr", - "German":"de", - "Spanish":"es", - "Portuguese":"pt", - "Italian":"it", - "Korean":"ko", - "Greek":"el", - "Dutch":"nl", - "Hindi":"hi", - "Turkish":"tr", - "Malay":"ms", - "Thai":"th", - "Vietnamese":"vi", - "Indonesian":"id", - "Hebrew":"he", - "Polish":"pl", - "Mongolian":"mn", - "Czech":"cs", - "Hungarian":"hu", - "Estonian":"et", - "Bulgarian":"bg", - "Danish":"da", - "Finnish":"fi", - "Romanian":"ro", - "Swedish":"sv", - "Slovenian":"sl", - "Persian/Farsi":"fa", - "Bosnian":"bs", - "Serbian":"sr", - "Filipino":"tl", - "Haitiancreole":"ht", - "Catalan":"ca", - "Croatian":"hr", - "Latvian":"lv", - "Lithuanian":"lt", - "Urdu":"ur", - "Ukrainian":"uk", - "Welsh":"cy", - "Swahili":"sw", - "Samoan":"sm", - "Slovak":"sk", - "Afrikaans":"af", - "Norwegian":"no", - "Bengali":"bn", - "Malagasy":"mg", - "Maltese":"mt", - "Gujarati":"gu", - "Tamil":"ta", - "Telugu":"te", - "Punjabi":"pa", - "Amharic":"am", - "Azerbaijani":"az", - "Belarusian":"be", - "Cebuano":"ceb", - "Esperanto":"eo", - "Basque":"eu", - "Irish":"ga" -} -translation_lang["Google(web)"] = { - "source":dict_google_web_languages, - "target":dict_google_web_languages, -} - -dict_bing_web_languages = { - "Japanese":"ja", - "English":"en", - "Chinese":"zh", - "Arabic":"ar", - "Russian":"ru", - "French":"fr", - "German":"de", - "Spanish":"es", - "Portuguese":"pt", - "Italian":"it", - "Korean":"ko", - "Greek":"el", - "Dutch":"nl", - "Hindi":"hi", - "Turkish":"tr", - "Malay":"ms", - "Thai":"th", - "Vietnamese":"vi", - "Indonesian":"id", - "Hebrew":"he", - "Polish":"pl", - "Czech":"cs", - "Hungarian":"hu", - "Estonian":"et", - "Bulgarian":"bg", - "Danish":"da", - "Finnish":"fi", - "Romanian":"ro", - "Swedish":"sv", - "Slovenian":"sl", - "Persian/Farsi":"fa", - "Bosnian":"bs", - "Serbian":"sr", - "Fijian":"fj", - "Filipino":"tl", - "Haitiancreole":"ht", - "Catalan":"ca", - "Croatian":"hr", - "Latvian":"lv", - "Lithuanian":"lt", - "Urdu":"ur", - "Ukrainian":"uk", - "Welsh":"cy", - "Tahiti":"ty", - "Tongan":"to", - "Swahili":"sw", - "Samoan":"sm", - "Slovak":"sk", - "Afrikaans":"af", - "Norwegian":"no", - "Bengali":"bn", - "Malagasy":"mg", - "Maltese":"mt", - "Queretaro otomi":"otq", - "Klingon/tlhingan Hol":"tlh", - "Gujarati":"gu", - "Tamil":"ta", - "Telugu":"te", - "Punjabi":"pa", - "Irish":"ga" -} -translation_lang["Bing(web)"] = { - "source":dict_bing_web_languages, - "target":dict_bing_web_languages, -} - selectable_languages = { "en": "English", "ja": "日本語", diff --git a/model.py b/model.py index 1356c372..ef5057a4 100644 --- a/model.py +++ b/model.py @@ -1,20 +1,33 @@ from time import sleep from queue import Queue -from threading import Thread +from threading import Thread, Event from requests import get as requests_get -from translation import Translator from flashtext import KeywordProcessor -from osc_tools import send_typing, send_message, send_test_action, receive_osc_parameters -from languages import transcription_lang -from audio_utils import get_input_device_list, get_output_device_list, get_default_output_device -from audio_recorder import SelectedMicRecorder, SelectedSpeakerRecorder -from audio_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder -from audio_transcriber import AudioTranscriber -from notification import notification_xsoverlay_for_vrct -from utils import thread_fnc +from models.translation.translation_translator import Translator +from models.osc.osc_tools import send_typing, send_message, send_test_action, receive_osc_parameters +from models.transcription.transcription_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device +from models.transcription.transcription_recorder import SelectedMicRecorder, SelectedSpeakerRecorder +from models.transcription.transcription_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder +from models.transcription.transcription_transcriber import AudioTranscriber +from models.xsoverlay.notification import notification_xsoverlay_for_vrct from config import config +class thread_fnc(Thread): + def __init__(self, fnc, daemon=True, *args, **kwargs): + super(thread_fnc, self).__init__(daemon=daemon, *args, **kwargs) + self.fnc = fnc + self._stop = Event() + def stop(self): + self._stop.set() + def stopped(self): + return self._stop.isSet() + def run(self): + while True: + if self.stopped(): + return + self.fnc(*self._args, **self._kwargs) + class Model: _instance = None @@ -157,7 +170,7 @@ class Model: max_phrases=config.INPUT_MIC_MAX_PHRASES, ) def mic_transcript_to_chatbox(): - mic_transcriber.transcribe_audio_queue(mic_audio_queue, transcription_lang[config.INPUT_MIC_VOICE_LANGUAGE]) + mic_transcriber.transcribe_audio_queue(mic_audio_queue, config.INPUT_MIC_VOICE_LANGUAGE) message = mic_transcriber.get_transcript() fnc(message) @@ -172,14 +185,11 @@ class Model: self.mic_audio_recorder.stop() self.mic_audio_recorder.stop = None - def startCheckMicEnergy(self, progressBar): + def startCheckMicEnergy(self, fnc): def progressBarInputMicEnergyPlot(): if mic_energy_queue.empty() is False: energy = mic_energy_queue.get() - try: - progressBar.set(energy/config.MAX_MIC_ENERGY_THRESHOLD) - except: - pass + fnc(energy) sleep(0.01) mic_energy_queue = Queue() mic_device = [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] @@ -212,7 +222,7 @@ class Model: max_phrases=config.INPUT_SPEAKER_MAX_PHRASES, ) def spk_transcript_to_textbox(): - spk_transcriber.transcribe_audio_queue(spk_audio_queue, transcription_lang[config.INPUT_SPEAKER_VOICE_LANGUAGE]) + spk_transcriber.transcribe_audio_queue(spk_audio_queue, config.INPUT_SPEAKER_VOICE_LANGUAGE) message = spk_transcriber.get_transcript() fnc(message) @@ -227,20 +237,17 @@ class Model: self.spk_audio_recorder.stop() self.spk_audio_recorder.stop = None - def startCheckSpeakerEnergy(self, progressBar): + def startCheckSpeakerEnergy(self, fnc): def progressBar_input_speaker_energy_plot(): if speaker_energy_queue.empty() is False: energy = speaker_energy_queue.get() - try: - progressBar.set(energy/config.MAX_SPEAKER_ENERGY_THRESHOLD) - except: - pass + fnc(energy) sleep(0.01) def progressBar_input_speaker_energy_get(): with self.speaker_energy_recorder.source as source: energy = self.speaker_energy_recorder.recorder.listen_energy(source) - self.speaker_energy_queue.put(energy) + speaker_energy_queue.put(energy) speaker_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] speaker_energy_queue = Queue() diff --git a/osc_tools.py b/models/osc/osc_tools.py similarity index 100% rename from osc_tools.py rename to models/osc/osc_tools.py diff --git a/models/transcription/transcription_languages.py b/models/transcription/transcription_languages.py new file mode 100644 index 00000000..2cf6ebd3 --- /dev/null +++ b/models/transcription/transcription_languages.py @@ -0,0 +1,91 @@ +transcription_lang = { + "Japanese (Japan)":"ja-JP", + "English (United States)":"en-US", + "English (United Kingdom)":"en-GB", + "Afrikaans (South Africa)":"af-ZA", + "Arabic (Algeria)":"ar-DZ", + "Arabic (Bahrain)":"ar-BH", + "Arabic (Egypt)":"ar-EG", + "Arabic (Israel)":"ar-IL", + "Arabic (Iraq)":"ar-IQ", + "Arabic (Jordan)":"ar-JO", + "Arabic (Kuwait)":"ar-KW", + "Arabic (Lebanon)":"ar-LB", + "Arabic (Morocco)":"ar-MA", + "Arabic (Oman)":"ar-OM", + "Arabic (State of Palestine)":"ar-PS", + "Arabic (Qatar)":"ar-QA", + "Arabic (Saudi Arabia)":"ar-SA", + "Arabic (Tunisia)":"ar-TN", + "Arabic (United Arab Emirates)":"ar-AE", + "Basque (Spain)":"eu-ES", + "Bulgarian (Bulgaria)":"bg-BG", + "Catalan (Spain)":"ca-ES", + "Chinese, Mandarin (Simplified, China)":"cmn-Hans-CN", + "Chinese, Mandarin (Simplified, Hong Kong)":"cmn-Hans-HK", + "Chinese, Mandarin (Traditional, Taiwan)":"cmn-Hant-TW", + "Chinese, Cantonese (Traditional Hong Kong)":"yue-Hant-HK", + "Croatian (Croatia)":"hr-HR", + "Czech (Czech Republic)":"cs-CZ", + "Danish (Denmark)":"da-DK", + "English (Australia)":"en-AU", + "English (Canada)":"en-CA", + "English (India)":"en-IN", + "English (Ireland)":"en-IE", + "English (New Zealand)":"en-NZ", + "English (Philippines)":"en-PH", + "English (South Africa)":"en-ZA", + "Persian (Iran)":"fa-IR", + "French (France)":"fr-FR", + "Filipino (Philippines)":"fil-PH", + "Galician (Spain)":"gl-ES", + "German (Germany)":"de-DE", + "Greek (Greece)":"el-GR", + "Finnish (Finland)":"fi-FI", + "Hebrew (Israel)":"he-IL", + "Hindi (India)":"hi-IN", + "Hungarian (Hungary)":"hu-HU", + "Indonesian (Indonesia)":"id-ID", + "Icelandic (Iceland)":"is-IS", + "Italian (Italy)":"it-IT", + "Italian (Switzerland)":"it-CH", + "Korean (South Korea)":"ko-KR", + "Lithuanian (Lithuania)":"lt-LT", + "Malay (Malaysia)":"ms-MY", + "Dutch (Netherlands)":"nl-NL", + "Norwegian Bokmål (Norway)":"nb-NO", + "Polish (Poland)":"pl-PL", + "Portuguese (Brazil)":"pt-BR", + "Portuguese (Portugal)":"pt-PT", + "Romanian (Romania)":"ro-RO", + "Russian (Russia)":"ru-RU", + "Serbian (Serbia)":"sr-RS", + "Slovak (Slovakia)":"sk-SK", + "Slovenian (Slovenia)":"sl-SI", + "Spanish (Argentina)":"es-AR", + "Spanish (Bolivia)":"es-BO", + "Spanish (Chile)":"es-CL", + "Spanish (Colombia)":"es-CO", + "Spanish (Costa Rica)":"es-CR", + "Spanish (Dominican Republic)":"es-DO", + "Spanish (Ecuador)":"es-EC", + "Spanish (El Salvador)":"es-SV", + "Spanish (Guatemala)":"es-GT", + "Spanish (Honduras)":"es-HN", + "Spanish (Mexico)":"es-MX", + "Spanish (Nicaragua)":"es-NI", + "Spanish (Panama)":"es-PA", + "Spanish (Paraguay)":"es-PY", + "Spanish (Peru)":"es-PE", + "Spanish (Puerto Rico)":"es-PR", + "Spanish (Spain)":"es-ES", + "Spanish (Uruguay)":"es-UY", + "Spanish (United States)":"es-US", + "Spanish (Venezuela)":"es-VE", + "Swedish (Sweden)":"sv-SE", + "Thai (Thailand)":"th-TH", + "Turkish (Turkey)":"tr-TR", + "Ukrainian (Ukraine)":"uk-UA", + "Vietnamese (Vietnam)":"vi-VN", + "Zulu (South Africa)":"zu-ZA" +} \ No newline at end of file diff --git a/audio_recorder.py b/models/transcription/transcription_recorder.py similarity index 100% rename from audio_recorder.py rename to models/transcription/transcription_recorder.py diff --git a/audio_transcriber.py b/models/transcription/transcription_transcriber.py similarity index 97% rename from audio_transcriber.py rename to models/transcription/transcription_transcriber.py index 94c858e7..316dd22b 100644 --- a/audio_transcriber.py +++ b/models/transcription/transcription_transcriber.py @@ -4,6 +4,7 @@ import wave from speech_recognition import Recognizer, AudioData, AudioFile from datetime import timedelta from pyaudiowpatch import get_sample_size, paInt16 +from .transcription_languages import transcription_lang PHRASE_TIMEOUT = 3 MAX_PHRASES = 10 @@ -36,7 +37,7 @@ class AudioTranscriber: # 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=language) + text = self.audio_recognizer.recognize_google(audio_data, language=transcription_lang[language]) except Exception as e: pass finally: diff --git a/audio_utils.py b/models/transcription/transcription_utils.py similarity index 100% rename from audio_utils.py rename to models/transcription/transcription_utils.py diff --git a/models/translation/translation_languages.py b/models/translation/translation_languages.py new file mode 100644 index 00000000..1b68bf81 --- /dev/null +++ b/models/translation/translation_languages.py @@ -0,0 +1,243 @@ +translatorEngine = ["DeepL(web)", "DeepL(auth)", "Google(web)", "Bing(web)"] +translation_lang = {} +dict_deepl_web_languages = { + "Japanese":"JA", + "English":"EN", + "Korean":"KO", + "Bulgarian":"BG", + "Chinese":"ZH", + "Czech":"CS", + "Danish":"DA", + "Dutch":"NL", + "Estonian":"ET", + "Finnish":"FI", + "French":"FR", + "German":"DE", + "Greek":"EL", + "Hungarian":"HU", + "Italian":"IT", + "Latvian":"LV", + "Lithuanian":"LT", + "Polish":"PL", + "Portuguese":"PT", + "Romanian":"RO", + "Russian":"RU", + "Slovak":"SK", + "Slovenian":"SL", + "Spanish":"ES", + "Swedish":"SV", + "Indonesian":"ID", + "Ukrainian":"UK", + "Turkish":"TR", + "Norwegian":"NB", +} +translation_lang["DeepL(web)"] = { + "source":dict_deepl_web_languages, + "target":dict_deepl_web_languages, +} + +dict_deepl_auth_source_languages = { + "Japanese":"ja", + "English":"en", + "Bulgarian":"bg", + "Czech":"cs", + "Danish":"da", + "German":"de", + "Greek":"el", + "Spanish":"es", + "Estonian":"et", + "Finnish":"fi", + "French":"fr", + "Hungarian":"hu", + "Indonesian":"id", + "Italian":"it", + "Korean":"ko", + "Lithuanian":"lt", + "Latvian":"lv", + "Norwegian":"nb", + "Dutch":"nl", + "Polish":"pl", + "Portuguese":"pt", + "Romanian":"ro", + "Russian":"ru", + "Slovak":"sk", + "Slovenian":"sl", + "Swedish":"sv", + "Turkish":"tr", + "Ukrainian":"uk", + "Chinese":"zh" +} +dict_deepl_auth_target_languages = { + "Japanese":"ja", + "English American":"en-US", + "English British":"en-GB", + "Bulgarian":"bg", + "Czech":"cs", + "Danish":"da", + "German":"de", + "Greek":"el", + "English":"en", + "Spanish":"es", + "Estonian":"et", + "Finnish":"fi", + "French":"fr", + "Hungarian":"hu", + "Indonesian":"id", + "Italian":"it", + "Korean":"ko", + "Lithuanian":"lt", + "Latvian":"lv", + "Norwegian":"nb", + "Dutch":"nl", + "Polish":"pl", + "Portuguese Brazilian":"pt-BR", + "Portuguese European":"pt-PT", + "Romanian":"ro", + "Russian":"ru", + "Slovak":"sk", + "Slovenian":"sl", + "Swedish":"sv", + "Turkish":"tr", + "Ukrainian":"uk", + "Chinese":"zh" +} +translation_lang["DeepL(auth)"] = { + "source": dict_deepl_auth_source_languages, + "target": dict_deepl_auth_target_languages, +} + +dict_google_web_languages = { + "Japanese":"ja", + "English":"en", + "Chinese":"zh", + "Arabic":"ar", + "Russian":"ru", + "French":"fr", + "German":"de", + "Spanish":"es", + "Portuguese":"pt", + "Italian":"it", + "Korean":"ko", + "Greek":"el", + "Dutch":"nl", + "Hindi":"hi", + "Turkish":"tr", + "Malay":"ms", + "Thai":"th", + "Vietnamese":"vi", + "Indonesian":"id", + "Hebrew":"he", + "Polish":"pl", + "Mongolian":"mn", + "Czech":"cs", + "Hungarian":"hu", + "Estonian":"et", + "Bulgarian":"bg", + "Danish":"da", + "Finnish":"fi", + "Romanian":"ro", + "Swedish":"sv", + "Slovenian":"sl", + "Persian/Farsi":"fa", + "Bosnian":"bs", + "Serbian":"sr", + "Filipino":"tl", + "Haitiancreole":"ht", + "Catalan":"ca", + "Croatian":"hr", + "Latvian":"lv", + "Lithuanian":"lt", + "Urdu":"ur", + "Ukrainian":"uk", + "Welsh":"cy", + "Swahili":"sw", + "Samoan":"sm", + "Slovak":"sk", + "Afrikaans":"af", + "Norwegian":"no", + "Bengali":"bn", + "Malagasy":"mg", + "Maltese":"mt", + "Gujarati":"gu", + "Tamil":"ta", + "Telugu":"te", + "Punjabi":"pa", + "Amharic":"am", + "Azerbaijani":"az", + "Belarusian":"be", + "Cebuano":"ceb", + "Esperanto":"eo", + "Basque":"eu", + "Irish":"ga" +} +translation_lang["Google(web)"] = { + "source":dict_google_web_languages, + "target":dict_google_web_languages, +} + +dict_bing_web_languages = { + "Japanese":"ja", + "English":"en", + "Chinese":"zh", + "Arabic":"ar", + "Russian":"ru", + "French":"fr", + "German":"de", + "Spanish":"es", + "Portuguese":"pt", + "Italian":"it", + "Korean":"ko", + "Greek":"el", + "Dutch":"nl", + "Hindi":"hi", + "Turkish":"tr", + "Malay":"ms", + "Thai":"th", + "Vietnamese":"vi", + "Indonesian":"id", + "Hebrew":"he", + "Polish":"pl", + "Czech":"cs", + "Hungarian":"hu", + "Estonian":"et", + "Bulgarian":"bg", + "Danish":"da", + "Finnish":"fi", + "Romanian":"ro", + "Swedish":"sv", + "Slovenian":"sl", + "Persian/Farsi":"fa", + "Bosnian":"bs", + "Serbian":"sr", + "Fijian":"fj", + "Filipino":"tl", + "Haitiancreole":"ht", + "Catalan":"ca", + "Croatian":"hr", + "Latvian":"lv", + "Lithuanian":"lt", + "Urdu":"ur", + "Ukrainian":"uk", + "Welsh":"cy", + "Tahiti":"ty", + "Tongan":"to", + "Swahili":"sw", + "Samoan":"sm", + "Slovak":"sk", + "Afrikaans":"af", + "Norwegian":"no", + "Bengali":"bn", + "Malagasy":"mg", + "Maltese":"mt", + "Queretaro otomi":"otq", + "Klingon/tlhingan Hol":"tlh", + "Gujarati":"gu", + "Tamil":"ta", + "Telugu":"te", + "Punjabi":"pa", + "Irish":"ga" +} +translation_lang["Bing(web)"] = { + "source":dict_bing_web_languages, + "target":dict_bing_web_languages, +} \ No newline at end of file diff --git a/translation.py b/models/translation/translation_translator.py similarity index 95% rename from translation.py rename to models/translation/translation_translator.py index e251c8a9..b386835e 100644 --- a/translation.py +++ b/models/translation/translation_translator.py @@ -1,13 +1,13 @@ from deepl import Translator as deepl_Translator from deepl_translate import translate as deepl_web_Translator from translators import translate_text as other_web_Translator -from languages import translators, translation_lang +from .translation_languages import translatorEngine, translation_lang # Translator class Translator(): def __init__(self): self.translator_status = {} - for translator in translators: + for translator in translatorEngine: self.translator_status[translator] = False self.deepl_client = None diff --git a/notification.py b/models/xsoverlay/notification.py similarity index 100% rename from notification.py rename to models/xsoverlay/notification.py diff --git a/utils.py b/utils.py index ffe7ade7..2bee5814 100644 --- a/utils.py +++ b/utils.py @@ -1,7 +1,6 @@ from os import path as os_path import yaml from datetime import datetime -from threading import Thread, Event def print_textbox(textbox, message, tags=None): now = datetime.now() @@ -19,21 +18,6 @@ def print_textbox(textbox, message, tags=None): textbox.configure(state='disabled') textbox.see("end") -class thread_fnc(Thread): - def __init__(self, fnc, daemon=True, *args, **kwargs): - super(thread_fnc, self).__init__(daemon=daemon, *args, **kwargs) - self.fnc = fnc - self._stop = Event() - def stop(self): - self._stop.set() - def stopped(self): - return self._stop.isSet() - def run(self): - while True: - if self.stopped(): - return - self.fnc(*self._args, **self._kwargs) - def get_localized_text(language): file_path = os_path.join(os_path.dirname(__file__), "locales.yml") diff --git a/window_config.py b/window_config.py index b54429cf..326a7a11 100644 --- a/window_config.py +++ b/window_config.py @@ -8,8 +8,9 @@ from threading import Thread from config import config from model import model from utils import print_textbox, get_localized_text, get_key_by_value, widget_config_window_label_setter -from languages import translation_lang, transcription_lang, selectable_languages - +from languages import selectable_languages +from models.translation.translation_languages import translation_lang +from models.transcription.transcription_languages import transcription_lang from ctk_scrollable_dropdown import CTkScrollableDropdown SCROLLABLE_DROPDOWN = False @@ -261,7 +262,12 @@ class ToplevelWindowConfig(CTkToplevel): config.INPUT_MIC_VOICE_LANGUAGE = choice def mic_threshold_check_start(self): - model.startCheckMicEnergy(self.progressBar_input_mic_energy_threshold) + def plotProgressBar(energy): + try: + self.progressBar_input_mic_energy_threshold.set(energy/config.MAX_MIC_ENERGY_THRESHOLD) + except: + pass + model.startCheckMicEnergy(plotProgressBar) self.checkbox_input_mic_threshold_check.configure(state="normal") self.checkbox_input_speaker_threshold_check.configure(state="normal") @@ -324,7 +330,13 @@ class ToplevelWindowConfig(CTkToplevel): config.INPUT_SPEAKER_VOICE_LANGUAGE = choice def speaker_threshold_check_start(self): - model.startCheckSpeakerEnergy(self.progressBar_input_speaker_energy_threshold) + def plotProgressBar(energy): + try: + print(energy) + self.progressBar_input_speaker_energy_threshold.set(energy/config.MAX_MIC_ENERGY_THRESHOLD) + except: + pass + model.startCheckSpeakerEnergy(plotProgressBar) self.checkbox_input_mic_threshold_check.configure(state="normal") self.checkbox_input_speaker_threshold_check.configure(state="normal") From 1470187c02cdc279c7fe58d198089e4157302c55 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sun, 20 Aug 2023 01:33:43 +0900 Subject: [PATCH 6/8] [Update] change osc_tools.py func name --- model.py | 30 +++++++++++++++--------------- models/osc/osc_tools.py | 8 ++++---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/model.py b/model.py index ef5057a4..5f2409cb 100644 --- a/model.py +++ b/model.py @@ -5,17 +5,17 @@ from requests import get as requests_get from flashtext import KeywordProcessor from models.translation.translation_translator import Translator -from models.osc.osc_tools import send_typing, send_message, send_test_action, receive_osc_parameters from models.transcription.transcription_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device +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_transcriber import AudioTranscriber from models.xsoverlay.notification import notification_xsoverlay_for_vrct from config import config -class thread_fnc(Thread): +class threadFnc(Thread): def __init__(self, fnc, daemon=True, *args, **kwargs): - super(thread_fnc, self).__init__(daemon=daemon, *args, **kwargs) + super(threadFnc, self).__init__(daemon=daemon, *args, **kwargs) self.fnc = fnc self._stop = Event() def stop(self): @@ -101,15 +101,15 @@ class Model: @staticmethod def oscStartSendTyping(): - send_typing(True, config.OSC_IP_ADDRESS, config.OSC_PORT) + sendTyping(True, config.OSC_IP_ADDRESS, config.OSC_PORT) @staticmethod def oscStopSendTyping(): - send_typing(False, config.OSC_IP_ADDRESS, config.OSC_PORT) + sendTyping(False, config.OSC_IP_ADDRESS, config.OSC_PORT) @staticmethod def oscSendMessage(message): - send_message(message, config.OSC_IP_ADDRESS, config.OSC_PORT) + sendMessage(message, config.OSC_IP_ADDRESS, config.OSC_PORT) @staticmethod def oscCheck(): @@ -118,12 +118,12 @@ class Model: config.ENABLE_OSC = True # start receive osc - th_receive_osc_parameters = Thread(target=receive_osc_parameters, args=(check_osc_receive,)) + th_receive_osc_parameters = Thread(target=receiveOscParameters, args=(check_osc_receive,)) th_receive_osc_parameters.daemon = True th_receive_osc_parameters.start() # check osc started - send_test_action() + sendTestAction() # check update response = requests_get(config.GITHUB_URL) @@ -174,12 +174,12 @@ class Model: message = mic_transcriber.get_transcript() fnc(message) - self.mic_print_transcript = thread_fnc(mic_transcript_to_chatbox) + self.mic_print_transcript = threadFnc(mic_transcript_to_chatbox) self.mic_print_transcript.daemon = True self.mic_print_transcript.start() def stopMicTranscript(self): - if isinstance(self.mic_print_transcript, thread_fnc): + if isinstance(self.mic_print_transcript, threadFnc): self.mic_print_transcript.stop() if self.mic_audio_recorder.stop != None: self.mic_audio_recorder.stop() @@ -195,7 +195,7 @@ class Model: mic_device = [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device) self.mic_energy_recorder.record_into_queue(mic_energy_queue) - self.mic_energy_plot_progressbar = thread_fnc(progressBarInputMicEnergyPlot) + self.mic_energy_plot_progressbar = threadFnc(progressBarInputMicEnergyPlot) self.mic_energy_plot_progressbar.daemon = True self.mic_energy_plot_progressbar.start() @@ -226,12 +226,12 @@ class Model: message = spk_transcriber.get_transcript() fnc(message) - self.spk_print_transcript = thread_fnc(spk_transcript_to_textbox) + self.spk_print_transcript = threadFnc(spk_transcript_to_textbox) self.spk_print_transcript.daemon = True self.spk_print_transcript.start() def stopSpeakerTranscript(self): - if isinstance(self.spk_print_transcript, thread_fnc): + if isinstance(self.spk_print_transcript, threadFnc): self.spk_print_transcript.stop() if self.spk_audio_recorder.stop != None: self.spk_audio_recorder.stop() @@ -252,10 +252,10 @@ class Model: speaker_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] speaker_energy_queue = Queue() self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device) - self.speaker_energy_get_progressbar = thread_fnc(progressBar_input_speaker_energy_get) + self.speaker_energy_get_progressbar = threadFnc(progressBar_input_speaker_energy_get) self.speaker_energy_get_progressbar.daemon = True self.speaker_energy_get_progressbar.start() - self.speaker_energy_plot_progressbar = thread_fnc(progressBar_input_speaker_energy_plot) + self.speaker_energy_plot_progressbar = threadFnc(progressBar_input_speaker_energy_plot) self.speaker_energy_plot_progressbar.daemon = True self.speaker_energy_plot_progressbar.start() diff --git a/models/osc/osc_tools.py b/models/osc/osc_tools.py index 7c7d9504..b44e17cb 100644 --- a/models/osc/osc_tools.py +++ b/models/osc/osc_tools.py @@ -6,7 +6,7 @@ from pythonosc import dispatcher from pythonosc import osc_server # send OSC message typing -def send_typing(flag=False, ip_address="127.0.0.1", port=9000): +def sendTyping(flag=False, ip_address="127.0.0.1", port=9000): typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") typing.add_arg(flag) b_typing = typing.build() @@ -14,7 +14,7 @@ def send_typing(flag=False, ip_address="127.0.0.1", port=9000): client.send(b_typing) # send OSC message -def send_message(message=None, ip_address="127.0.0.1", port=9000): +def sendMessage(message=None, ip_address="127.0.0.1", port=9000): if message != None: msg = osc_message_builder.OscMessageBuilder(address="/chatbox/input") msg.add_arg(f"{message}") @@ -24,13 +24,13 @@ def send_message(message=None, ip_address="127.0.0.1", port=9000): client = udp_client.SimpleUDPClient(ip_address, port) client.send(b_msg) -def send_test_action(ip_address="127.0.0.1", port=9000): +def sendTestAction(ip_address="127.0.0.1", port=9000): client = udp_client.SimpleUDPClient(ip_address, port) client.send_message("/input/Vertical", 1) sleep(0.01) client.send_message("/input/Vertical", False) -def receive_osc_parameters(target, filter="/*", ip_address="127.0.0.1", port=9001): +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) From 2be54f9aee7315cfe64a7b75e4e239f8a380a0a7 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sun, 20 Aug 2023 01:40:01 +0900 Subject: [PATCH 7/8] [Update] change transcription_utils.py func name --- config.py | 18 ++++++++--------- model.py | 22 ++++++++++----------- models/transcription/transcription_utils.py | 8 ++++---- window_config.py | 1 - 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/config.py b/config.py index ced57eab..2b99e4dc 100644 --- a/config.py +++ b/config.py @@ -8,7 +8,7 @@ from tkinter import font from languages import selectable_languages from models.translation.translation_languages import translatorEngine, translation_lang from models.transcription.transcription_languages import transcription_lang -from models.transcription.transcription_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device +from models.transcription.transcription_utils import getInputDevices, getOutputDevices, getDefaultInputDevice, getDefaultOutputDevice def saveJson(path, key, value): with open(path, "r") as fp: @@ -180,7 +180,7 @@ class Config: @CHOICE_MIC_HOST.setter def CHOICE_MIC_HOST(self, value): - if value in [host for host in get_input_device_list().keys()]: + if value in [host for host in getInputDevices().keys()]: self._CHOICE_MIC_HOST = value saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @@ -190,7 +190,7 @@ class Config: @CHOICE_MIC_DEVICE.setter def CHOICE_MIC_DEVICE(self, value): - if value in [device["name"] for device in get_input_device_list()[self.CHOICE_MIC_HOST]]: + if value in [device["name"] for device in getInputDevices()[self.CHOICE_MIC_HOST]]: self._CHOICE_MIC_DEVICE = value saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @@ -270,9 +270,9 @@ class Config: @CHOICE_SPEAKER_DEVICE.setter def CHOICE_SPEAKER_DEVICE(self, value): - if value in [device["name"] for device in get_output_device_list()]: - speaker_device = [device for device in get_output_device_list() if device["name"] == value][0] - if get_default_output_device()["index"] == speaker_device["index"]: + if value in [device["name"] for device in getOutputDevices()]: + speaker_device = [device for device in getOutputDevices() if device["name"] == value][0] + if getDefaultOutputDevice()["index"] == speaker_device["index"]: self._CHOICE_SPEAKER_DEVICE = value saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @@ -449,8 +449,8 @@ class Config: self._INPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[1] self._OUTPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[1] self._OUTPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[0] - self._CHOICE_MIC_HOST = get_default_input_device()["host"]["name"] - self._CHOICE_MIC_DEVICE = get_default_input_device()["device"]["name"] + self._CHOICE_MIC_HOST = getDefaultInputDevice()["host"]["name"] + self._CHOICE_MIC_DEVICE = getDefaultInputDevice()["device"]["name"] self._INPUT_MIC_VOICE_LANGUAGE = list(transcription_lang.keys())[0] self._INPUT_MIC_ENERGY_THRESHOLD = 300 self._INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD = True @@ -458,7 +458,7 @@ class Config: self._INPUT_MIC_PHRASE_TIMEOUT = 3 self._INPUT_MIC_MAX_PHRASES = 10 self._INPUT_MIC_WORD_FILTER = [] - self._CHOICE_SPEAKER_DEVICE = get_default_output_device()["name"] + self._CHOICE_SPEAKER_DEVICE = getDefaultOutputDevice()["name"] self._INPUT_SPEAKER_VOICE_LANGUAGE = list(transcription_lang.keys())[1] self._INPUT_SPEAKER_ENERGY_THRESHOLD = 300 self._INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD = True diff --git a/model.py b/model.py index 5f2409cb..37a488c1 100644 --- a/model.py +++ b/model.py @@ -5,7 +5,7 @@ from requests import get as requests_get from flashtext import KeywordProcessor from models.translation.translation_translator import Translator -from models.transcription.transcription_utils import get_input_device_list, get_output_device_list, get_default_input_device, get_default_output_device +from models.transcription.transcription_utils import getInputDevices, getOutputDevices, getDefaultInputDevice, 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 @@ -133,31 +133,31 @@ class Model: @staticmethod def getListInputHost(): - return [host for host in get_input_device_list().keys()] + return [host for host in getInputDevices().keys()] @staticmethod def getListInputDevice(): - return [device["name"] for device in get_input_device_list()[config.CHOICE_MIC_HOST]] + return [device["name"] for device in getInputDevices()[config.CHOICE_MIC_HOST]] @staticmethod def getInputDefaultDevice(): - return [device["name"] for device in get_input_device_list()[config.CHOICE_MIC_HOST]][0] + return [device["name"] for device in getInputDevices()[config.CHOICE_MIC_HOST]][0] @staticmethod def getListOutputDevice(): - return [device["name"] for device in get_output_device_list()] + return [device["name"] for device in getOutputDevices()] @staticmethod def checkSpeakerStatus(choice=config.CHOICE_SPEAKER_DEVICE): - speaker_device = [device for device in get_output_device_list() if device["name"] == choice][0] - if get_default_output_device()["index"] == speaker_device["index"]: + speaker_device = [device for device in getOutputDevices() if device["name"] == choice][0] + if getDefaultOutputDevice()["index"] == speaker_device["index"]: return True return False def startMicTranscript(self, fnc): mic_audio_queue = Queue() self.mic_audio_recorder = SelectedMicRecorder( - [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0], + [device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0], config.INPUT_MIC_ENERGY_THRESHOLD, config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD, config.INPUT_MIC_RECORD_TIMEOUT, @@ -192,7 +192,7 @@ class Model: fnc(energy) sleep(0.01) mic_energy_queue = Queue() - mic_device = [device for device in get_input_device_list()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] + mic_device = [device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device) self.mic_energy_recorder.record_into_queue(mic_energy_queue) self.mic_energy_plot_progressbar = threadFnc(progressBarInputMicEnergyPlot) @@ -207,7 +207,7 @@ class Model: def startSpeakerTranscript(self, fnc): spk_audio_queue = Queue() - spk_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] + spk_device = [device for device in getOutputDevices() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] self.spk_audio_recorder = SelectedSpeakerRecorder( spk_device, config.INPUT_SPEAKER_ENERGY_THRESHOLD, @@ -249,7 +249,7 @@ class Model: energy = self.speaker_energy_recorder.recorder.listen_energy(source) speaker_energy_queue.put(energy) - speaker_device = [device for device in get_output_device_list() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] + speaker_device = [device for device in getOutputDevices() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] speaker_energy_queue = Queue() self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device) self.speaker_energy_get_progressbar = threadFnc(progressBar_input_speaker_energy_get) diff --git a/models/transcription/transcription_utils.py b/models/transcription/transcription_utils.py index b66172c2..4c72a8fa 100644 --- a/models/transcription/transcription_utils.py +++ b/models/transcription/transcription_utils.py @@ -1,6 +1,6 @@ from pyaudiowpatch import PyAudio, paWASAPI -def get_input_device_list(): +def getInputDevices(): devices = {} with PyAudio() as p: for host_index in range(0, p.get_host_api_count()): @@ -14,7 +14,7 @@ def get_input_device_list(): devices[host["name"]] = [device] return devices -def get_output_device_list(): +def getOutputDevices(): devices =[] with PyAudio() as p: wasapi_info = p.get_host_api_info_by_type(paWASAPI) @@ -23,7 +23,7 @@ def get_output_device_list(): devices.append(device) return devices -def get_default_input_device(): +def getDefaultInputDevice(): with PyAudio() as p: api_info = p.get_default_host_api_info() defaultInputDevice = api_info["defaultInputDevice"] @@ -35,7 +35,7 @@ def get_default_input_device(): if device["index"] == defaultInputDevice: return {"host":host, "device": device} -def get_default_output_device(): +def getDefaultOutputDevice(): with PyAudio() as p: wasapi_info = p.get_host_api_info_by_type(paWASAPI) defaultOutputDevice = wasapi_info["defaultOutputDevice"] diff --git a/window_config.py b/window_config.py index 326a7a11..b45a61c1 100644 --- a/window_config.py +++ b/window_config.py @@ -332,7 +332,6 @@ class ToplevelWindowConfig(CTkToplevel): def speaker_threshold_check_start(self): def plotProgressBar(energy): try: - print(energy) self.progressBar_input_speaker_energy_threshold.set(energy/config.MAX_MIC_ENERGY_THRESHOLD) except: pass From b7d6477228964c1919b4e67cf6d9bc58fb696089 Mon Sep 17 00:00:00 2001 From: misygauziya Date: Sun, 20 Aug 2023 02:28:17 +0900 Subject: [PATCH 8/8] [Update] change transcription_recorder.py/transcription_transcriber.py/notification.py func name --- model.py | 40 +++++++++---------- .../transcription/transcription_recorder.py | 20 +++++----- .../transcription_transcriber.py | 20 +++++----- models/xsoverlay/notification.py | 8 ++-- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/model.py b/model.py index 37a488c1..67f782f4 100644 --- a/model.py +++ b/model.py @@ -10,7 +10,7 @@ from models.osc.osc_tools import sendTyping, sendMessage, sendTestAction, receiv from models.transcription.transcription_recorder import SelectedMicRecorder, SelectedSpeakerRecorder from models.transcription.transcription_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder from models.transcription.transcription_transcriber import AudioTranscriber -from models.xsoverlay.notification import notification_xsoverlay_for_vrct +from models.xsoverlay.notification import xsoverlayForVRCT from config import config class threadFnc(Thread): @@ -162,19 +162,19 @@ class Model: config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD, config.INPUT_MIC_RECORD_TIMEOUT, ) - self.mic_audio_recorder.record_into_queue(mic_audio_queue) + self.mic_audio_recorder.recordIntoQueue(mic_audio_queue) mic_transcriber = AudioTranscriber( speaker=False, source=self.mic_audio_recorder.source, phrase_timeout=config.INPUT_MIC_PHRASE_TIMEOUT, max_phrases=config.INPUT_MIC_MAX_PHRASES, ) - def mic_transcript_to_chatbox(): - mic_transcriber.transcribe_audio_queue(mic_audio_queue, config.INPUT_MIC_VOICE_LANGUAGE) - message = mic_transcriber.get_transcript() + def sendMicTranscript(): + mic_transcriber.transcribeAudioQueue(mic_audio_queue, config.INPUT_MIC_VOICE_LANGUAGE) + message = mic_transcriber.getTranscript() fnc(message) - self.mic_print_transcript = threadFnc(mic_transcript_to_chatbox) + self.mic_print_transcript = threadFnc(sendMicTranscript) self.mic_print_transcript.daemon = True self.mic_print_transcript.start() @@ -186,7 +186,7 @@ class Model: self.mic_audio_recorder.stop = None def startCheckMicEnergy(self, fnc): - def progressBarInputMicEnergyPlot(): + def sendMicEnergy(): if mic_energy_queue.empty() is False: energy = mic_energy_queue.get() fnc(energy) @@ -194,8 +194,8 @@ class Model: mic_energy_queue = Queue() mic_device = [device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0] self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device) - self.mic_energy_recorder.record_into_queue(mic_energy_queue) - self.mic_energy_plot_progressbar = threadFnc(progressBarInputMicEnergyPlot) + self.mic_energy_recorder.recordIntoQueue(mic_energy_queue) + self.mic_energy_plot_progressbar = threadFnc(sendMicEnergy) self.mic_energy_plot_progressbar.daemon = True self.mic_energy_plot_progressbar.start() @@ -214,19 +214,19 @@ class Model: config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD, config.INPUT_SPEAKER_RECORD_TIMEOUT, ) - self.spk_audio_recorder.record_into_queue(spk_audio_queue) + self.spk_audio_recorder.recordIntoQueue(spk_audio_queue) spk_transcriber = AudioTranscriber( speaker=True, source=self.spk_audio_recorder.source, phrase_timeout=config.INPUT_SPEAKER_PHRASE_TIMEOUT, max_phrases=config.INPUT_SPEAKER_MAX_PHRASES, ) - def spk_transcript_to_textbox(): - spk_transcriber.transcribe_audio_queue(spk_audio_queue, config.INPUT_SPEAKER_VOICE_LANGUAGE) - message = spk_transcriber.get_transcript() + def sendSpkTranscript(): + spk_transcriber.transcribeAudioQueue(spk_audio_queue, config.INPUT_SPEAKER_VOICE_LANGUAGE) + message = spk_transcriber.getTranscript() fnc(message) - self.spk_print_transcript = threadFnc(spk_transcript_to_textbox) + self.spk_print_transcript = threadFnc(sendSpkTranscript) self.spk_print_transcript.daemon = True self.spk_print_transcript.start() @@ -238,13 +238,13 @@ class Model: self.spk_audio_recorder.stop = None def startCheckSpeakerEnergy(self, fnc): - def progressBar_input_speaker_energy_plot(): + def sendSpeakerEnergy(): if speaker_energy_queue.empty() is False: energy = speaker_energy_queue.get() fnc(energy) sleep(0.01) - def progressBar_input_speaker_energy_get(): + def getSpeakerEnergy(): with self.speaker_energy_recorder.source as source: energy = self.speaker_energy_recorder.recorder.listen_energy(source) speaker_energy_queue.put(energy) @@ -252,10 +252,10 @@ class Model: speaker_device = [device for device in getOutputDevices() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0] speaker_energy_queue = Queue() self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device) - self.speaker_energy_get_progressbar = threadFnc(progressBar_input_speaker_energy_get) + self.speaker_energy_get_progressbar = threadFnc(getSpeakerEnergy) self.speaker_energy_get_progressbar.daemon = True self.speaker_energy_get_progressbar.start() - self.speaker_energy_plot_progressbar = threadFnc(progressBar_input_speaker_energy_plot) + self.speaker_energy_plot_progressbar = threadFnc(sendSpeakerEnergy) self.speaker_energy_plot_progressbar.daemon = True self.speaker_energy_plot_progressbar.start() @@ -265,7 +265,7 @@ class Model: if self.speaker_energy_plot_progressbar != None: self.speaker_energy_plot_progressbar.stop() - def notificationXsoverlay(self, message): - notification_xsoverlay_for_vrct(content=f"{message}") + def notificationXSOverlay(self, message): + xsoverlayForVRCT(content=f"{message}") model = Model() diff --git a/models/transcription/transcription_recorder.py b/models/transcription/transcription_recorder.py index 5d968062..cf2cec04 100644 --- a/models/transcription/transcription_recorder.py +++ b/models/transcription/transcription_recorder.py @@ -15,11 +15,11 @@ class BaseRecorder: self.source = source - def adjust_for_noise(self): + def adjustForNoise(self): with self.source: self.recorder.adjust_for_ambient_noise(self.source) - def record_into_queue(self, audio_queue): + def recordIntoQueue(self, audio_queue): def record_callback(_, audio): audio_queue.put((audio.get_raw_data(), datetime.now())) @@ -32,7 +32,7 @@ class SelectedMicRecorder(BaseRecorder): sample_rate=int(device["defaultSampleRate"]), ) super().__init__(source=source, energy_threshold=energy_threshold, dynamic_energy_threshold=dynamic_energy_threshold, record_timeout=record_timeout) - # self.adjust_for_noise() + # self.adjustForNoise() class SelectedSpeakerRecorder(BaseRecorder): def __init__(self, device, energy_threshold, dynamic_energy_threshold, record_timeout): @@ -44,7 +44,7 @@ class SelectedSpeakerRecorder(BaseRecorder): channels=device["maxInputChannels"] ) super().__init__(source=source, energy_threshold=energy_threshold, dynamic_energy_threshold=dynamic_energy_threshold, record_timeout=record_timeout) - # self.adjust_for_noise() + # self.adjustForNoise() class BaseEnergyRecorder: def __init__(self, source): @@ -59,15 +59,15 @@ class BaseEnergyRecorder: self.source = source - def adjust_for_noise(self): + def adjustForNoise(self): with self.source: self.recorder.adjust_for_ambient_noise(self.source) - def record_into_queue(self, energy_queue): - def record_callback(_, energy): + def recordIntoQueue(self, energy_queue): + def recordCallback(_, energy): energy_queue.put(energy) - self.stop = self.recorder.listen_energy_in_background(self.source, record_callback) + self.stop = self.recorder.listen_energy_in_background(self.source, recordCallback) class SelectedMicEnergyRecorder(BaseEnergyRecorder): def __init__(self, device): @@ -76,7 +76,7 @@ class SelectedMicEnergyRecorder(BaseEnergyRecorder): sample_rate=int(device["defaultSampleRate"]), ) super().__init__(source=source) - # self.adjust_for_noise() + # self.adjustForNoise() class SelectedSpeakeEnergyRecorder(BaseEnergyRecorder): def __init__(self, device): @@ -88,4 +88,4 @@ class SelectedSpeakeEnergyRecorder(BaseEnergyRecorder): channels=device["maxInputChannels"] ) super().__init__(source=source) - # self.adjust_for_noise() \ No newline at end of file + # self.adjustForNoise() \ No newline at end of file diff --git a/models/transcription/transcription_transcriber.py b/models/transcription/transcription_transcriber.py index 316dd22b..e0b0eb6f 100644 --- a/models/transcription/transcription_transcriber.py +++ b/models/transcription/transcription_transcriber.py @@ -24,13 +24,13 @@ class AudioTranscriber: "last_sample": bytes(), "last_spoken": None, "new_phrase": True, - "process_data_func": self.process_speaker_data if speaker else self.process_speaker_data + "process_data_func": self.processSpeakerData if speaker else self.processSpeakerData } - def transcribe_audio_queue(self, audio_queue, language): + def transcribeAudioQueue(self, audio_queue, language): # while True: audio, time_spoken = audio_queue.get() - self.update_last_sample_and_phrase_status(audio, time_spoken) + self.updateLastSampleAndPhraseStatus(audio, time_spoken) text = '' try: @@ -45,9 +45,9 @@ class AudioTranscriber: # os.unlink(path) if text != '': - self.update_transcript(text) + self.updateTranscript(text) - def update_last_sample_and_phrase_status(self, data, time_spoken): + def updateLastSampleAndPhraseStatus(self, data, time_spoken): source_info = self.audio_sources if source_info["last_spoken"] and time_spoken - source_info["last_spoken"] > timedelta(seconds=self.phrase_timeout): source_info["last_sample"] = bytes() @@ -58,11 +58,11 @@ class AudioTranscriber: source_info["last_sample"] += data source_info["last_spoken"] = time_spoken - def process_mic_data(self): + def processMicData(self): audio_data = AudioData(self.audio_sources["last_sample"], self.audio_sources["sample_rate"], self.audio_sources["sample_width"]) return audio_data - def process_speaker_data(self): + def processSpeakerData(self): temp_file = BytesIO() with wave.open(temp_file, 'wb') as wf: wf.setnchannels(self.audio_sources["channels"]) @@ -74,7 +74,7 @@ class AudioTranscriber: audio = self.audio_recognizer.record(source) return audio - def update_transcript(self, text): + def updateTranscript(self, text): source_info = self.audio_sources transcript = self.transcript_data @@ -85,14 +85,14 @@ class AudioTranscriber: else: transcript[0] = text - def get_transcript(self): + def getTranscript(self): if len(self.transcript_data) > 0: text = self.transcript_data.pop(-1) else: text = "" return text - def clear_transcript_data(self): + def clearTranscriptData(self): self.transcript_data.clear() self.audio_sources["last_sample"] = bytes() self.audio_sources["new_phrase"] = True \ No newline at end of file diff --git a/models/xsoverlay/notification.py b/models/xsoverlay/notification.py index 61e18725..f18adf60 100644 --- a/models/xsoverlay/notification.py +++ b/models/xsoverlay/notification.py @@ -19,7 +19,7 @@ import socket import json import base64 -def notification_xsoverlay( +def XSOverlay( endpoint:tuple=("127.0.0.1", 42069), messageType:int=1, index:int=0, timeout:float=2, height:float=120.0, opacity:float=1.0, volume:float=0.0, audioPath:str="", title:str="", content:str="", useBase64Icon:bool=False, icon:str="default", sourceApp:str="" @@ -58,8 +58,8 @@ def notification_xsoverlay( sock.close() return response -def notification_xsoverlay_for_vrct(content:str="") -> int: - response = notification_xsoverlay( +def xsoverlayForVRCT(content:str="") -> int: + response = XSOverlay( title="VRCT", content=content, useBase64Icon=True, @@ -69,4 +69,4 @@ def notification_xsoverlay_for_vrct(content:str="") -> int: return response if __name__ == "__main__": - notification_xsoverlay_for_vrct(content="notification test") \ No newline at end of file + xsoverlayForVRCT(content="notification test") \ No newline at end of file