From f88ffd826c405fe4c7ec396d49234c78ff020634 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 8 Jun 2023 11:39:35 +0900 Subject: [PATCH 01/35] update gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ebe1be37..ea9ad5fb 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ pyinstaller/ VRCT.build/ VRCT.dist/ VRCT.onefile-build/ -VRCT.exe \ No newline at end of file +VRCT.exe +VRCT.spec +deepl-translate/ +translators/ \ No newline at end of file From 8040bb66a6057a163d1d6875120deb7eddcbcf93 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Fri, 9 Jun 2023 02:02:11 +0900 Subject: [PATCH 02/35] add voice2chat --- VRCT.py | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 159 insertions(+), 10 deletions(-) diff --git a/VRCT.py b/VRCT.py index 1483e25a..001d9435 100644 --- a/VRCT.py +++ b/VRCT.py @@ -1,5 +1,6 @@ import os import json +import threading import deepl import deepl_translate import translators as ts @@ -8,6 +9,8 @@ from pythonosc import udp_client import tkinter as tk import customtkinter from PIL import Image +import pyaudio +import speech_recognition as sr def save_json(path, key, value): with open(path, "r") as fp: @@ -87,6 +90,60 @@ class Translator(): pass return result +# VoiceRecognizer +class VoiceRecognizer(): + def __init__(self): + self.input_device_dict = self.search_input_device() + self.r = sr.Recognizer() + self.mic = None + + def search_input_device(self): + pa = pyaudio.PyAudio() + input_device_dict = {} + + mic_cnt = 1 + for i in range(pa.get_device_count()): + device = pa.get_device_info_by_index(i) + try: + device["name"] = device["name"].encode('shift_jis').decode('utf-8') + except: + device["name"] = device["name"].encode('utf-8').decode('utf-8') + if device["maxInputChannels"] > 0: + input_device_dict[f'No.{mic_cnt}:{device["name"]}'] = device["index"] + mic_cnt += 1 + pa.terminate() + return input_device_dict + + def set_mic(self, device_name): + if device_name in [v for v in self.input_device_dict.keys()]: + index = self.input_device_dict[device_name] + self.mic = sr.Microphone(device_index=index) + return True + else: + return False + + def init_mic(self, threshold=50, is_dynamic=False): + if self.mic is not False: + self.r.energy_threshold = threshold + if is_dynamic: + with self.mic as source: + self.r.adjust_for_ambient_noise(source, 3.0) + return True + else: + return False + + def listen_voice(self): + if self.mic != None: + with self.mic as source: + audio = self.r.listen(source) + try: + text = self.r.recognize_google(audio, language='ja-JP') + return text + except: + return "" + else: + return False + class ToplevelWindowInformation(customtkinter.CTkToplevel): def __init__(self, parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) @@ -254,6 +311,24 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.optionmenu_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") + # optionmenu mic device + self.label_mic_device = customtkinter.CTkLabel( + self.tabview_config.tab("GUI"), + text="Select Mic Device:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + + self.label_mic_device.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_mic_device = customtkinter.CTkOptionMenu( + self.tabview_config.tab("GUI"), + values=list(self.parent.vr.input_device_dict.keys()), + command=self.optionmenu_mic_device_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) + ) + self.optionmenu_mic_device.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + # slider transparency self.label_transparency = customtkinter.CTkLabel( self.tabview_config.tab("GUI"), @@ -261,7 +336,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_transparency.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_transparency.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.slider_transparency = customtkinter.CTkSlider( self.tabview_config.tab("GUI"), from_=50, @@ -269,7 +344,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.slider_transparency_callback, variable=tk.DoubleVar(value=self.parent.TRANSPARENCY), ) - self.slider_transparency.grid(row=2, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") + self.slider_transparency.grid(row=3, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") # optionmenu theme self.label_appearance_theme = customtkinter.CTkLabel( @@ -278,14 +353,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_appearance_theme.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_appearance_theme.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_appearance_theme = customtkinter.CTkOptionMenu( self.tabview_config.tab("GUI"), values=["Light", "Dark", "System"], command=self.optionmenu_theme_callback, variable=customtkinter.StringVar(value=self.parent.APPEARANCE_THEME) ) - self.optionmenu_appearance_theme.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_appearance_theme.grid(row=4, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") # optionmenu UI scaling self.label_ui_scaling = customtkinter.CTkLabel( @@ -294,14 +369,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_ui_scaling.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_ui_scaling.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_ui_scaling = customtkinter.CTkOptionMenu( self.tabview_config.tab("GUI"), values=["80%", "90%", "100%", "110%", "120%"], command=self.optionmenu_ui_scaling_callback, variable=customtkinter.StringVar(value=self.parent.UI_SCALING) ) - self.optionmenu_ui_scaling.grid(row=4, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_ui_scaling.grid(row=5, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") # optionmenu font family self.label_font_family = customtkinter.CTkLabel( @@ -310,7 +385,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_font_family.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_font_family.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") font_families = list(tk.font.families()) self.optionmenu_font_family = customtkinter.CTkOptionMenu( self.tabview_config.tab("GUI"), @@ -318,7 +393,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_font_family_callback, variable=customtkinter.StringVar(value=self.parent.FONT_FAMILY) ) - self.optionmenu_font_family.grid(row=5, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_font_family.grid(row=6, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") # entry ip address self.label_ip_address = customtkinter.CTkLabel( @@ -478,6 +553,11 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.TARGET_LANG = choice save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) + def optionmenu_mic_device_callback(self, choice): + self.parent.CHOICE_MIC_DEVICE = choice + save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) + self.parent.vr.set_mic(choice) + def optionmenu_theme_callback(self, choice): customtkinter.set_appearance_mode(choice) @@ -545,6 +625,8 @@ class App(customtkinter.CTk): "Google(web)": None, } self.MESSAGE_FORMAT = "[message]([translation])" + self.ENABLE_VOICE2CHAT = False + self.CHOICE_MIC_DEVICE = None self.FONT_FAMILY = "Yu Gothic UI" self.TRANSPARENCY = 100 self.APPEARANCE_THEME = "System" @@ -574,6 +656,10 @@ class App(customtkinter.CTk): self.MESSAGE_FORMAT = config["MESSAGE_FORMAT"] if "FONT_FAMILY" in config.keys(): self.FONT_FAMILY = config["FONT_FAMILY"] + if "ENABLE_VOICE2CHAT" in config.keys(): + self.ENABLE_VOICE2CHAT = config["ENABLE_VOICE2CHAT"] + if "CHOICE_MIC_DEVICE" in config.keys(): + self.CHOICE_MIC_DEVICE = config["CHOICE_MIC_DEVICE"] if "TRANSPARENCY" in config.keys(): self.TRANSPARENCY = config["TRANSPARENCY"] if "APPEARANCE_THEME" in config.keys(): @@ -593,6 +679,8 @@ class App(customtkinter.CTk): "AUTH_KEYS": self.AUTH_KEYS, "MESSAGE_FORMAT": self.MESSAGE_FORMAT, "FONT_FAMILY": self.FONT_FAMILY, + "ENABLE_VOICE2CHAT": self.ENABLE_VOICE2CHAT, + "CHOICE_MIC_DEVICE": self.CHOICE_MIC_DEVICE, "TRANSPARENCY": self.TRANSPARENCY, "APPEARANCE_THEME": self.APPEARANCE_THEME, "UI_SCALING": self.UI_SCALING, @@ -602,7 +690,7 @@ class App(customtkinter.CTk): # init main window self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico")) self.title("VRCT") - self.geometry(f"{400}x{110}") + self.geometry(f"{400}x{140}") self.minsize(400, 110) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) @@ -623,6 +711,17 @@ class App(customtkinter.CTk): ) self.checkbox_translation.grid(row=0, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") + # add checkbox voice2chat + self.checkbox_voice2chat = customtkinter.CTkCheckBox( + self.sidebar_frame, + text="voice2chat", + onvalue=True, + offvalue=False, + command=self.checkbox_voice2chat_callback, + font=customtkinter.CTkFont(family=self.FONT_FAMILY) + ) + self.checkbox_voice2chat.grid(row=1, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") + # add checkbox foreground self.checkbox_foreground = customtkinter.CTkCheckBox( self.sidebar_frame, @@ -632,7 +731,7 @@ class App(customtkinter.CTk): command=self.checkbox_foreground_callback, font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.checkbox_foreground.grid(row=1, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") + self.checkbox_foreground.grid(row=2, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") # add button information self.button_information = customtkinter.CTkButton( @@ -700,6 +799,11 @@ class App(customtkinter.CTk): self.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") self.textbox_message_log.configure(state='disabled') + ## set voice2chat: + self.vr = VoiceRecognizer() + self.vr.set_mic(self.CHOICE_MIC_DEVICE) + # self.vr.init_mic() + ## set transparency for main window self.wm_attributes("-alpha", self.TRANSPARENCY/100) @@ -725,6 +829,51 @@ class App(customtkinter.CTk): self.ENABLE_TRANSLATION = self.checkbox_translation.get() save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) + def checkbox_voice2chat_callback(self): + if self.checkbox_voice2chat.get() is True: + # start threading + th = threading.Thread(target = self.voice_input) + th.start() + + def voice_input(self): + mic_status = self.vr.set_mic(self.CHOICE_MIC_DEVICE) + if mic_status: + # start voice_input + while self.checkbox_voice2chat.get() is True: + message = self.vr.listen_voice() + + if len(message) > 0: + # translate + if self.checkbox_translation.get() is False: + chat_message = f"{message}" + elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.SOURCE_LANG == "None") or (self.TARGET_LANG == "None"): + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("0.0", f"Auth Keyもしくは言語の設定が間違っています\n") + self.textbox_message_log.configure(state='disabled') + chat_message = f"{message}" + else: + result = self.translator.translate( + translator_name=self.CHOICE_TRANSLATOR, + source_language=self.SOURCE_LANG, + target_language=self.TARGET_LANG, + message=message + ) + chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + + # send OSC message + message = osc_message_builder.OscMessageBuilder(address="/chatbox/input") + message.add_arg(f"{chat_message}") + message.add_arg(True) + message.add_arg(True) + message = message.build() + client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) + client.send(message) + + # update textbox message log + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("0.0", f"{chat_message}\n") + self.textbox_message_log.configure(state='disabled') + def checkbox_foreground_callback(self): value = self.checkbox_foreground.get() From cd2ef8cd65efb49e344204c2c4a696e8dcb04577 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Fri, 9 Jun 2023 02:43:04 +0900 Subject: [PATCH 03/35] bugfix choice mic device when 1st time --- VRCT.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/VRCT.py b/VRCT.py index 001d9435..8a34ebe1 100644 --- a/VRCT.py +++ b/VRCT.py @@ -801,8 +801,7 @@ class App(customtkinter.CTk): ## set voice2chat: self.vr = VoiceRecognizer() - self.vr.set_mic(self.CHOICE_MIC_DEVICE) - # self.vr.init_mic() + self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else list(self.vr.input_device_dict.keys())[0] ## set transparency for main window self.wm_attributes("-alpha", self.TRANSPARENCY/100) From f8e2ab861c423d3a087e5b97e1c521fee494af95 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Fri, 9 Jun 2023 18:04:58 +0900 Subject: [PATCH 04/35] add transcription config --- VRCT.py | 179 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 135 insertions(+), 44 deletions(-) diff --git a/VRCT.py b/VRCT.py index 8a34ebe1..68baad73 100644 --- a/VRCT.py +++ b/VRCT.py @@ -96,6 +96,16 @@ class VoiceRecognizer(): self.input_device_dict = self.search_input_device() self.r = sr.Recognizer() self.mic = None + self.languages = [ + "ja-JP","en-US","en-GB","af-ZA","ar-DZ","ar-BH","ar-EG","ar-IL","ar-IQ","ar-JO","ar-KW","ar-LB","ar-MA", + "ar-OM","ar-PS","ar-QA","ar-SA","ar-TN","ar-AE","eu-ES","bg-BG","ca-ES","cmn-Hans-CN","cmn-Hans-HK", + "cmn-Hant-TW","yue-Hant-HK","hr_HR","cs-CZ","da-DK","en-AU","en-CA","en-IN","en-IE","en-NZ","en-PH", + "en-ZA","fa-IR","fr-FR","fil-PH","gl-ES","de-DE","el-GR","fi-FI","he-IL","hi-IN","hu-HU","id-ID","is-IS", + "it-IT","it-CH","ko-KR","lt-LT","ms-MY","nl-NL","nb-NO","pl-PL","pt-BR","pt-PT","ro-RO","ru-RU","sr-RS", + "sk-SK","sl-SI","es-AR","es-BO","es-CL","es-CO","es-CR","es-DO","es-EC","es-SV","es-GT","es-HN","es-MX", + "es-NI","es-PA","es-PY","es-PE","es-PR","es-ES","es-UY","es-US","es-VE","sv-SE","th-TH","tr-TR","uk-UA", + "vi-VN","zu-ZA" + ] def search_input_device(self): pa = pyaudio.PyAudio() @@ -114,16 +124,10 @@ class VoiceRecognizer(): pa.terminate() return input_device_dict - def set_mic(self, device_name): + def set_mic(self, device_name, threshold=50, is_dynamic=False): if device_name in [v for v in self.input_device_dict.keys()]: index = self.input_device_dict[device_name] self.mic = sr.Microphone(device_index=index) - return True - else: - return False - - def init_mic(self, threshold=50, is_dynamic=False): - if self.mic is not False: self.r.energy_threshold = threshold if is_dynamic: with self.mic as source: @@ -132,12 +136,22 @@ class VoiceRecognizer(): else: return False - def listen_voice(self): + def init_mic(self, threshold=50, is_dynamic=False): + if isinstance(self.mic, sr.Microphone): + self.r.energy_threshold = threshold + if is_dynamic: + with self.mic as source: + self.r.adjust_for_ambient_noise(source, 3.0) + return True + else: + return False + + def listen_voice(self, language): if self.mic != None: with self.mic as source: audio = self.r.listen(source) try: - text = self.r.recognize_google(audio, language='ja-JP') + text = self.r.recognize_google(audio, language=language) return text except: return "" @@ -251,8 +265,10 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.tabview_config = customtkinter.CTkTabview(self) self.tabview_config.grid(row=0, column=0, padx=5, pady=5, sticky="nsew") self.tabview_config.add("GUI") + self.tabview_config.add("Transcription") self.tabview_config.add("Parameter") self.tabview_config.tab("GUI").grid_columnconfigure(2, weight=1) + self.tabview_config.tab("Transcription").grid_columnconfigure(2, weight=1) self.tabview_config.tab("Parameter").grid_columnconfigure(1, weight=1) self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY)) @@ -311,24 +327,6 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.optionmenu_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") - # optionmenu mic device - self.label_mic_device = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), - text="Select Mic Device:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - - self.label_mic_device.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_mic_device = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), - values=list(self.parent.vr.input_device_dict.keys()), - command=self.optionmenu_mic_device_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) - ) - self.optionmenu_mic_device.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - # slider transparency self.label_transparency = customtkinter.CTkLabel( self.tabview_config.tab("GUI"), @@ -336,7 +334,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_transparency.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_transparency.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.slider_transparency = customtkinter.CTkSlider( self.tabview_config.tab("GUI"), from_=50, @@ -344,7 +342,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.slider_transparency_callback, variable=tk.DoubleVar(value=self.parent.TRANSPARENCY), ) - self.slider_transparency.grid(row=3, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") + self.slider_transparency.grid(row=2, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") # optionmenu theme self.label_appearance_theme = customtkinter.CTkLabel( @@ -353,14 +351,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_appearance_theme.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_appearance_theme.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_appearance_theme = customtkinter.CTkOptionMenu( self.tabview_config.tab("GUI"), values=["Light", "Dark", "System"], command=self.optionmenu_theme_callback, variable=customtkinter.StringVar(value=self.parent.APPEARANCE_THEME) ) - self.optionmenu_appearance_theme.grid(row=4, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_appearance_theme.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") # optionmenu UI scaling self.label_ui_scaling = customtkinter.CTkLabel( @@ -369,14 +367,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_ui_scaling.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_ui_scaling.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_ui_scaling = customtkinter.CTkOptionMenu( self.tabview_config.tab("GUI"), values=["80%", "90%", "100%", "110%", "120%"], command=self.optionmenu_ui_scaling_callback, variable=customtkinter.StringVar(value=self.parent.UI_SCALING) ) - self.optionmenu_ui_scaling.grid(row=5, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_ui_scaling.grid(row=4, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") # optionmenu font family self.label_font_family = customtkinter.CTkLabel( @@ -385,7 +383,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_font_family.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_font_family.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") font_families = list(tk.font.families()) self.optionmenu_font_family = customtkinter.CTkOptionMenu( self.tabview_config.tab("GUI"), @@ -393,7 +391,80 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_font_family_callback, variable=customtkinter.StringVar(value=self.parent.FONT_FAMILY) ) - self.optionmenu_font_family.grid(row=6, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_font_family.grid(row=5, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + + # optionmenu mic device + self.label_mic_device = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Select Mic Device:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_mic_device.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_mic_device = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.input_device_dict.keys()), + command=self.optionmenu_mic_device_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) + ) + self.optionmenu_mic_device.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + # optionmenu input voice language + self.label_input_voice_language = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Select Input Voice Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_voice_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_voice_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.languages), + # command=self.optionmenu_input_voice_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.INPUT_VOICE_LANGUAGE) + ) + self.optionmenu_input_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + # switch mic in dynamic + self.label_mic_is_dynamic = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Select Mic IsDynamic:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_mic_is_dynamic.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.checkbox_mic_is_dynamic = customtkinter.CTkCheckBox( + self.tabview_config.tab("Transcription"), + text="", + onvalue=True, + offvalue=False, + command=self.checkbox_mic_is_dynamic_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.checkbox_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + if self.parent.ENABLE_MIC_IS_DYNAMIC is True: + self.checkbox_mic_is_dynamic.select() + else: + self.checkbox_mic_is_dynamic.deselect() + + # switch mic threshold + self.label_mic_threshold = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Select Mic Threshold:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_mic_threshold.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.slider_mic_threshold = customtkinter.CTkSlider( + self.tabview_config.tab("Transcription"), + from_=0, + to=300, + command=self.slider_mic_threshold_callback, + variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), + ) + self.slider_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") # entry ip address self.label_ip_address = customtkinter.CTkLabel( @@ -558,6 +629,17 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) self.parent.vr.set_mic(choice) + def checkbox_mic_is_dynamic_callback(self): + value = self.checkbox_mic_is_dynamic.get() + self.parent.ENABLE_MIC_IS_DYNAMIC = value + save_json(self.parent.PATH_CONFIG, "ENABLE_MIC_IS_DYNAMIC", self.parent.ENABLE_MIC_IS_DYNAMIC) + self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + + def slider_mic_threshold_callback(self, value): + self.parent.MIC_THRESHOLD = value + save_json(self.parent.PATH_CONFIG, "MIC_THRESHOLD", self.parent.MIC_THRESHOLD) + self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + def optionmenu_theme_callback(self, choice): customtkinter.set_appearance_mode(choice) @@ -627,6 +709,9 @@ class App(customtkinter.CTk): self.MESSAGE_FORMAT = "[message]([translation])" self.ENABLE_VOICE2CHAT = False self.CHOICE_MIC_DEVICE = None + self.ENABLE_MIC_IS_DYNAMIC = False + self.MIC_THRESHOLD = 300 + self.INPUT_VOICE_LANGUAGE = "ja-JP" self.FONT_FAMILY = "Yu Gothic UI" self.TRANSPARENCY = 100 self.APPEARANCE_THEME = "System" @@ -660,6 +745,10 @@ class App(customtkinter.CTk): self.ENABLE_VOICE2CHAT = config["ENABLE_VOICE2CHAT"] if "CHOICE_MIC_DEVICE" in config.keys(): self.CHOICE_MIC_DEVICE = config["CHOICE_MIC_DEVICE"] + if "MIC_THRESHOLD" in config.keys(): + self.MIC_THRESHOLD = config["MIC_THRESHOLD"] + if "INPUT_VOICE_LANGUAGE" in config.keys(): + self.INPUT_VOICE_LANGUAGE = config["INPUT_VOICE_LANGUAGE"] if "TRANSPARENCY" in config.keys(): self.TRANSPARENCY = config["TRANSPARENCY"] if "APPEARANCE_THEME" in config.keys(): @@ -681,6 +770,7 @@ class App(customtkinter.CTk): "FONT_FAMILY": self.FONT_FAMILY, "ENABLE_VOICE2CHAT": self.ENABLE_VOICE2CHAT, "CHOICE_MIC_DEVICE": self.CHOICE_MIC_DEVICE, + "INPUT_VOICE_LANGUAGE": self.INPUT_VOICE_LANGUAGE, "TRANSPARENCY": self.TRANSPARENCY, "APPEARANCE_THEME": self.APPEARANCE_THEME, "UI_SCALING": self.UI_SCALING, @@ -711,16 +801,16 @@ class App(customtkinter.CTk): ) self.checkbox_translation.grid(row=0, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") - # add checkbox voice2chat - self.checkbox_voice2chat = customtkinter.CTkCheckBox( + # add checkbox transcription + self.checkbox_transcription = customtkinter.CTkCheckBox( self.sidebar_frame, - text="voice2chat", + text="Transcription", onvalue=True, offvalue=False, - command=self.checkbox_voice2chat_callback, + command=self.checkbox_transcription_callback, font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.checkbox_voice2chat.grid(row=1, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") + self.checkbox_transcription.grid(row=1, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") # add checkbox foreground self.checkbox_foreground = customtkinter.CTkCheckBox( @@ -828,18 +918,19 @@ class App(customtkinter.CTk): self.ENABLE_TRANSLATION = self.checkbox_translation.get() save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) - def checkbox_voice2chat_callback(self): - if self.checkbox_voice2chat.get() is True: + def checkbox_transcription_callback(self): + if self.checkbox_transcription.get() is True: # start threading th = threading.Thread(target = self.voice_input) th.start() def voice_input(self): mic_status = self.vr.set_mic(self.CHOICE_MIC_DEVICE) + self.vr.init_mic(threshold=self.MIC_THRESHOLD, is_dynamic=self.ENABLE_MIC_IS_DYNAMIC) if mic_status: # start voice_input - while self.checkbox_voice2chat.get() is True: - message = self.vr.listen_voice() + while self.checkbox_transcription.get() is True: + message = self.vr.listen_voice(language=self.INPUT_VOICE_LANGUAGE) if len(message) > 0: # translate From 21a9edd43e908385fd9d9d3cb4873e81a70ac458 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Fri, 9 Jun 2023 18:12:41 +0900 Subject: [PATCH 05/35] add ui font --- VRCT.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/VRCT.py b/VRCT.py index 68baad73..26c8e792 100644 --- a/VRCT.py +++ b/VRCT.py @@ -675,6 +675,12 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.optionmenu_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) self.label_font_family.configure(font=customtkinter.CTkFont(family=choice)) self.optionmenu_font_family.configure(font=customtkinter.CTkFont(family=choice)) + self.label_mic_device.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_mic_device.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_mic_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) + self.label_mic_threshold.configure(font=customtkinter.CTkFont(family=choice)) self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) self.entry_ip_address.configure(font=customtkinter.CTkFont(family=choice)) self.label_port.configure(font=customtkinter.CTkFont(family=choice)) From 723d7d73abbdd9e23224a5c18b04955bccf326df Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 04:19:50 +0900 Subject: [PATCH 06/35] update UI fix config UI --- VRCT.py | 586 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 368 insertions(+), 218 deletions(-) diff --git a/VRCT.py b/VRCT.py index 26c8e792..ebb82f5b 100644 --- a/VRCT.py +++ b/VRCT.py @@ -201,7 +201,7 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ foreground チェックボックス: 最前面表示の有効無効 configウィンドウ - GUIタブ + UIタブ Select translator: 翻訳エンジンの変更 Select Language: 翻訳する言語[source, target]を選択 Transparency: ウィンドウの透過度の調整 @@ -264,209 +264,332 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): # tabwiew config self.tabview_config = customtkinter.CTkTabview(self) self.tabview_config.grid(row=0, column=0, padx=5, pady=5, sticky="nsew") - self.tabview_config.add("GUI") + self.tabview_config.add("UI") + self.tabview_config.add("Translation") self.tabview_config.add("Transcription") self.tabview_config.add("Parameter") - self.tabview_config.tab("GUI").grid_columnconfigure(2, weight=1) - self.tabview_config.tab("Transcription").grid_columnconfigure(2, weight=1) + self.tabview_config.tab("UI").grid_columnconfigure(1, weight=1) + self.tabview_config.tab("Translation").grid_columnconfigure([1,2,3], weight=1) + self.tabview_config.tab("Transcription").grid_columnconfigure(1, weight=1) self.tabview_config.tab("Parameter").grid_columnconfigure(1, weight=1) self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY)) - # optionmenu translator - self.label_translator = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), - text="Select Translator:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_translator.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_translator = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), - values=list(self.parent.translator.translator_status.keys()), - command=self.optionmenu_translator_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.CHOICE_TRANSLATOR) - ) - self.optionmenu_translator.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - - # optionmenu language - self.label_language = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), - text="Select Language:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - - ## select source language - self.optionmenu_source_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), - command=self.optionmenu_source_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.SOURCE_LANG), - ) - self.optionmenu_source_language.grid(row=1, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## label --> - self.label_arrow = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), - text="-->", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_arrow.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## select target language - self.optionmenu_target_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), - command=self.optionmenu_target_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.TARGET_LANG), - ) - self.optionmenu_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") - - # slider transparency + # tab UI + ## slider transparency self.label_transparency = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), text="Transparency:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_transparency.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_transparency.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.slider_transparency = customtkinter.CTkSlider( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), from_=50, to=100, command=self.slider_transparency_callback, variable=tk.DoubleVar(value=self.parent.TRANSPARENCY), ) - self.slider_transparency.grid(row=2, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") + self.slider_transparency.grid(row=0, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") - # optionmenu theme + ## optionmenu theme self.label_appearance_theme = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), text="Appearance Theme:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_appearance_theme.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_appearance_theme.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_appearance_theme = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), values=["Light", "Dark", "System"], command=self.optionmenu_theme_callback, variable=customtkinter.StringVar(value=self.parent.APPEARANCE_THEME) ) - self.optionmenu_appearance_theme.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_appearance_theme.grid(row=1, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") - # optionmenu UI scaling + ## optionmenu UI scaling self.label_ui_scaling = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), text="UI Scaling:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_ui_scaling.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_ui_scaling.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_ui_scaling = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), values=["80%", "90%", "100%", "110%", "120%"], command=self.optionmenu_ui_scaling_callback, variable=customtkinter.StringVar(value=self.parent.UI_SCALING) ) - self.optionmenu_ui_scaling.grid(row=4, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_ui_scaling.grid(row=2, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") - # optionmenu font family + ## optionmenu font family self.label_font_family = customtkinter.CTkLabel( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), text="Font Family:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_font_family.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_font_family.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") font_families = list(tk.font.families()) self.optionmenu_font_family = customtkinter.CTkOptionMenu( - self.tabview_config.tab("GUI"), + self.tabview_config.tab("UI"), values=font_families, command=self.optionmenu_font_family_callback, variable=customtkinter.StringVar(value=self.parent.FONT_FAMILY) ) - self.optionmenu_font_family.grid(row=5, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_font_family.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") - # optionmenu mic device - self.label_mic_device = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Select Mic Device:", + # tab Translation + ## optionmenu translation translator + self.label_translation_translator = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="Select Translator:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_mic_device.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_mic_device = customtkinter.CTkOptionMenu( + self.label_translation_translator.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_translation_translator = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + values=list(self.parent.translator.translator_status.keys()), + command=self.optionmenu_translation_translator_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_TRANSLATOR) + ) + self.optionmenu_translation_translator.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## optionmenu translation input language + self.label_translation_input_language = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="Input Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_input_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + + ## select translation input source language + self.optionmenu_translation_input_source_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + command=self.optionmenu_translation_input_source_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.SOURCE_LANG), + ) + self.optionmenu_translation_input_source_language.grid(row=1, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## label translation input arrow + self.label_translation_input_arrow = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="-->", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_input_arrow.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## select translation input target language + self.optionmenu_translation_input_target_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + command=self.optionmenu_translation_input_target_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.TARGET_LANG), + ) + self.optionmenu_translation_input_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## optionmenu translation output language + self.label_translation_output_language = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="Output Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_translation_output_language.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + + ## select translation output source language + self.optionmenu_translation_output_source_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + # command=self.optionmenu_translation_output_source_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.SOURCE_LANG), + state="disabled", + ) + self.optionmenu_translation_output_source_language.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## label translation output arrow + self.label_translation_output_arrow = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="-->", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_output_arrow.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## select translation output target language + self.optionmenu_translation_output_target_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + # command=self.optionmenu_translation_output_target_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.TARGET_LANG), + state="disabled", + ) + self.optionmenu_translation_output_target_language.grid(row=2, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") + + # tab Transcription + ## optionmenu input mic device + self.label_input_mic_device = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Mic Device:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_mic_device.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_mic_device = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), values=list(self.parent.vr.input_device_dict.keys()), - command=self.optionmenu_mic_device_callback, + command=self.optionmenu_input_mic_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) ) - self.optionmenu_mic_device.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.optionmenu_input_mic_device.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - # optionmenu input voice language - self.label_input_voice_language = customtkinter.CTkLabel( + ## optionmenu input mic voice language + self.label_input_mic_voice_language = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), - text="Select Input Voice Language:", + text="Input Mic Voice Language:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_input_voice_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_input_voice_language = customtkinter.CTkOptionMenu( + self.label_input_mic_voice_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_mic_voice_language = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), values=list(self.parent.vr.languages), - # command=self.optionmenu_input_voice_language_callback, + command=self.optionmenu_input_mic_voice_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.INPUT_VOICE_LANGUAGE) ) - self.optionmenu_input_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.optionmenu_input_mic_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - # switch mic in dynamic - self.label_mic_is_dynamic = customtkinter.CTkLabel( + ## checkbox input mic in dynamic + self.label_input_mic_is_dynamic = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), - text="Select Mic IsDynamic:", + text="Input Mic IsDynamic:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_mic_is_dynamic.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.checkbox_mic_is_dynamic = customtkinter.CTkCheckBox( + self.label_input_mic_is_dynamic.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.checkbox_input_mic_is_dynamic = customtkinter.CTkCheckBox( self.tabview_config.tab("Transcription"), text="", onvalue=True, offvalue=False, - command=self.checkbox_mic_is_dynamic_callback, + command=self.checkbox_input_mic_is_dynamic_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.checkbox_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.checkbox_input_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") if self.parent.ENABLE_MIC_IS_DYNAMIC is True: - self.checkbox_mic_is_dynamic.select() + self.checkbox_input_mic_is_dynamic.select() else: - self.checkbox_mic_is_dynamic.deselect() + self.checkbox_input_mic_is_dynamic.deselect() - # switch mic threshold - self.label_mic_threshold = customtkinter.CTkLabel( + ## slider input mic threshold + self.label_input_mic_threshold = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), - text="Select Mic Threshold:", + text="Input Mic Threshold:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_mic_threshold.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.slider_mic_threshold = customtkinter.CTkSlider( + self.label_input_mic_threshold.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.slider_input_mic_threshold = customtkinter.CTkSlider( self.tabview_config.tab("Transcription"), from_=0, to=300, - command=self.slider_mic_threshold_callback, + command=self.slider_input_mic_threshold_callback, variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), ) - self.slider_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + self.slider_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") - # entry ip address + ## optionmenu input speaker device + self.label_input_speaker_device = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker Device:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.input_device_dict.keys()), + # command=self.optionmenu_input_speaker_device_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE), + state="disabled" + ) + self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## optionmenu input speaker voice language + self.label_input_speaker_voice_language = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker Voice Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_voice_language.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_speaker_voice_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.languages), + # command=self.optionmenu_input_speaker_voice_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.INPUT_VOICE_LANGUAGE), + state="disabled" + ) + self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## checkbox input speaker in dynamic + self.label_input_speaker_is_dynamic = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker IsDynamic:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_is_dynamic.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.checkbox_input_speaker_is_dynamic = customtkinter.CTkCheckBox( + self.tabview_config.tab("Transcription"), + text="", + onvalue=True, + offvalue=False, + # command=self.checkbox_input_speaker_is_dynamic_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + state="disabled" + ) + self.checkbox_input_speaker_is_dynamic.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + if self.parent.ENABLE_MIC_IS_DYNAMIC is True: + self.checkbox_input_speaker_is_dynamic.select() + else: + self.checkbox_input_speaker_is_dynamic.deselect() + + ## slider input speaker threshold + self.label_input_speaker_threshold = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker Threshold:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_threshold.grid(row=7, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.slider_input_speaker_threshold = customtkinter.CTkSlider( + self.tabview_config.tab("Transcription"), + from_=0, + to=300, + # command=self.slider_input_speaker_threshold_callback, + variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), + state="disabled" + ) + self.slider_input_speaker_threshold.grid(row=7, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + + # tab Parameter + ## entry ip address self.label_ip_address = customtkinter.CTkLabel( self.tabview_config.tab("Parameter"), text="OSC IP address:", @@ -489,7 +612,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.button_ip_address.grid(row=0, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - # entry port + ## entry port self.label_port = customtkinter.CTkLabel( self.tabview_config.tab("Parameter"), text="OSC Port:", @@ -512,7 +635,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.button_port.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - # entry authkey + ## entry authkey self.label_authkey = customtkinter.CTkLabel( self.tabview_config.tab("Parameter"), text="DeepL Auth Key:", @@ -535,7 +658,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.button_authkey.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - # entry message format + ## entry message format self.label_message_format = customtkinter.CTkLabel( self.tabview_config.tab("Parameter"), text="Message Format:", @@ -558,6 +681,135 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.button_message_format.grid(row=3, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + def slider_transparency_callback(self, value): + self.parent.wm_attributes("-alpha", value/100) + self.parent.TRANSPARENCY = value + save_json(self.parent.PATH_CONFIG, "TRANSPARENCY", self.parent.TRANSPARENCY) + + def optionmenu_theme_callback(self, choice): + customtkinter.set_appearance_mode(choice) + self.parent.APPEARANCE_THEME = choice + save_json(self.parent.PATH_CONFIG, "APPEARANCE_THEME", self.parent.APPEARANCE_THEME) + + def optionmenu_ui_scaling_callback(self, choice): + new_scaling_float = int(choice.replace("%", "")) / 100 + customtkinter.set_widget_scaling(new_scaling_float) + self.parent.UI_SCALING = choice + save_json(self.parent.PATH_CONFIG, "UI_SCALING", self.parent.UI_SCALING) + + def optionmenu_font_family_callback(self, choice): + # tab menu + self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) + + # tab UI + self.label_transparency.configure(font=customtkinter.CTkFont(family=choice)) + self.label_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) + self.label_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) + self.label_font_family.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_font_family.configure(font=customtkinter.CTkFont(family=choice)) + + # tab Translation + self.label_translation_translator.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_translator.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_input_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_input_source_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_input_arrow.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_input_target_language.configure(font=customtkinter.CTkFont(family=choice)) + # self.label_translation_output_language.configure(font=customtkinter.CTkFont(family=choice)) + # self.optionmenu_translation_output_source_language.configure(font=customtkinter.CTkFont(family=choice)) + # self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) + # self.optionmenu_translation_output_target_language.configure(font=customtkinter.CTkFont(family=choice)) + + # tab Transcription + self.label_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_mic_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_mic_threshold.configure(font=customtkinter.CTkFont(family=choice)) + # self.label_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) + # self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) + # self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + # self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + # self.label_input_speaker_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) + # self.label_input_speaker_threshold.configure(font=customtkinter.CTkFont(family=choice)) + + # tab Parameter + self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_ip_address.configure(font=customtkinter.CTkFont(family=choice)) + self.label_port.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_port.configure(font=customtkinter.CTkFont(family=choice)) + self.label_authkey.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_authkey.configure(font=customtkinter.CTkFont(family=choice)) + self.label_message_format.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_message_format.configure(font=customtkinter.CTkFont(family=choice)) + + # main window + self.parent.checkbox_translation.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) + + # window information + try: + self.parent.information_window.textbox_information.configure(font=customtkinter.CTkFont(family=choice)) + except: + pass + + self.parent.FONT_FAMILY = choice + save_json(self.parent.PATH_CONFIG, "FONT_FAMILY", self.parent.FONT_FAMILY) + + def optionmenu_translation_translator_callback(self, choice): + if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: + self.parent.textbox_message_log.configure(state='normal') + self.parent.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_log.configure(state='disabled') + else: + self.optionmenu_translation_input_source_language.configure( + values=self.parent.translator.languages[choice], + variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][0])) + self.optionmenu_translation_input_target_language.configure( + values=self.parent.translator.languages[choice], + variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) + + self.parent.CHOICE_TRANSLATOR = choice + self.parent.SOURCE_LANG = self.parent.translator.languages[choice][0] + self.parent.TARGET_LANG = self.parent.translator.languages[choice][1] + save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR) + save_json(self.parent.PATH_CONFIG, "SOURCE_LANG", self.parent.SOURCE_LANG) + save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) + + def optionmenu_translation_input_source_language_callback(self, choice): + self.parent.SOURCE_LANG = choice + save_json(self.parent.PATH_CONFIG, "SOURCE_LANG", self.parent.SOURCE_LANG) + + def optionmenu_translation_input_target_language_callback(self, choice): + self.parent.TARGET_LANG = choice + save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) + + def optionmenu_input_mic_device_callback(self, choice): + self.parent.CHOICE_MIC_DEVICE = choice + save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) + self.parent.vr.set_mic(choice) + + def optionmenu_input_mic_voice_language_callback(self, choice): + self.parent.INPUT_VOICE_LANGUAGE = choice + save_json(self.parent.PATH_CONFIG, "INPUT_VOICE_LANGUAGE", self.parent.INPUT_VOICE_LANGUAGE) + self.parent.vr.set_mic(choice) + + def checkbox_input_mic_is_dynamic_callback(self): + value = self.checkbox_input_mic_is_dynamic.get() + self.parent.ENABLE_MIC_IS_DYNAMIC = value + save_json(self.parent.PATH_CONFIG, "ENABLE_MIC_IS_DYNAMIC", self.parent.ENABLE_MIC_IS_DYNAMIC) + self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + + def slider_input_mic_threshold_callback(self, value): + self.parent.MIC_THRESHOLD = value + save_json(self.parent.PATH_CONFIG, "MIC_THRESHOLD", self.parent.MIC_THRESHOLD) + self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + def update_ip_address(self): value = self.entry_ip_address.get() if len(value) > 0: @@ -591,108 +843,6 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.MESSAGE_FORMAT = value save_json(self.parent.PATH_CONFIG, "MESSAGE_FORMAT", self.parent.MESSAGE_FORMAT) - def slider_transparency_callback(self, value): - self.parent.wm_attributes("-alpha", value/100) - self.parent.TRANSPARENCY = value - save_json(self.parent.PATH_CONFIG, "TRANSPARENCY", self.parent.TRANSPARENCY) - - def optionmenu_translator_callback(self, choice): - if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_log.configure(state='disabled') - else: - self.optionmenu_source_language.configure( - values=self.parent.translator.languages[choice], - variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][0])) - self.optionmenu_target_language.configure( - values=self.parent.translator.languages[choice], - variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) - - self.parent.CHOICE_TRANSLATOR = choice - self.parent.SOURCE_LANG = self.parent.translator.languages[choice][0] - self.parent.TARGET_LANG = self.parent.translator.languages[choice][1] - save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR) - save_json(self.parent.PATH_CONFIG, "SOURCE_LANG", self.parent.SOURCE_LANG) - save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) - - def optionmenu_source_language_callback(self, choice): - self.parent.SOURCE_LANG = choice - save_json(self.parent.PATH_CONFIG, "SOURCE_LANG", self.parent.SOURCE_LANG) - - def optionmenu_target_language_callback(self, choice): - self.parent.TARGET_LANG = choice - save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) - - def optionmenu_mic_device_callback(self, choice): - self.parent.CHOICE_MIC_DEVICE = choice - save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) - self.parent.vr.set_mic(choice) - - def checkbox_mic_is_dynamic_callback(self): - value = self.checkbox_mic_is_dynamic.get() - self.parent.ENABLE_MIC_IS_DYNAMIC = value - save_json(self.parent.PATH_CONFIG, "ENABLE_MIC_IS_DYNAMIC", self.parent.ENABLE_MIC_IS_DYNAMIC) - self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) - - def slider_mic_threshold_callback(self, value): - self.parent.MIC_THRESHOLD = value - save_json(self.parent.PATH_CONFIG, "MIC_THRESHOLD", self.parent.MIC_THRESHOLD) - self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) - - def optionmenu_theme_callback(self, choice): - customtkinter.set_appearance_mode(choice) - - self.parent.APPEARANCE_THEME = choice - save_json(self.parent.PATH_CONFIG, "APPEARANCE_THEME", self.parent.APPEARANCE_THEME) - - def optionmenu_ui_scaling_callback(self, choice): - new_scaling_float = int(choice.replace("%", "")) / 100 - customtkinter.set_widget_scaling(new_scaling_float) - self.parent.UI_SCALING = choice - save_json(self.parent.PATH_CONFIG, "UI_SCALING", self.parent.UI_SCALING) - - def optionmenu_font_family_callback(self, choice): - self.parent.checkbox_translation.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) - try: - self.parent.information_window.textbox_information.configure(font=customtkinter.CTkFont(family=choice)) - except: - pass - self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) - self.label_translator.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_translator.configure(font=customtkinter.CTkFont(family=choice)) - self.label_language.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_source_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_arrow.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_target_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_transparency.configure(font=customtkinter.CTkFont(family=choice)) - self.label_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) - self.label_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) - self.label_font_family.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_font_family.configure(font=customtkinter.CTkFont(family=choice)) - self.label_mic_device.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_mic_device.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_input_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_mic_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) - self.label_mic_threshold.configure(font=customtkinter.CTkFont(family=choice)) - self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_ip_address.configure(font=customtkinter.CTkFont(family=choice)) - self.label_port.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_port.configure(font=customtkinter.CTkFont(family=choice)) - self.label_authkey.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_authkey.configure(font=customtkinter.CTkFont(family=choice)) - self.label_message_format.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_message_format.configure(font=customtkinter.CTkFont(family=choice)) - - self.parent.FONT_FAMILY = choice - save_json(self.parent.PATH_CONFIG, "FONT_FAMILY", self.parent.FONT_FAMILY) - class App(customtkinter.CTk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -799,7 +949,7 @@ class App(customtkinter.CTk): # add checkbox translation self.checkbox_translation = customtkinter.CTkCheckBox( self.sidebar_frame, - text="translation", + text="Translation", onvalue=True, offvalue=False, command=self.checkbox_translation_callback, @@ -821,7 +971,7 @@ class App(customtkinter.CTk): # add checkbox foreground self.checkbox_foreground = customtkinter.CTkCheckBox( self.sidebar_frame, - text="foreground", + text="Foreground", onvalue=True, offvalue=False, command=self.checkbox_foreground_callback, From 6dd1734e539f906c93ed1b7f8cac7e4d4bf9ba31 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 05:08:25 +0900 Subject: [PATCH 07/35] update config parameter --- VRCT.py | 196 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 76 deletions(-) diff --git a/VRCT.py b/VRCT.py index ebb82f5b..728a4a9f 100644 --- a/VRCT.py +++ b/VRCT.py @@ -374,7 +374,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_translation_input_source_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.SOURCE_LANG), + variable=customtkinter.StringVar(value=self.parent.INPUT_SOURCE_LANG), ) self.optionmenu_translation_input_source_language.grid(row=1, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") @@ -393,7 +393,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_translation_input_target_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.TARGET_LANG), + variable=customtkinter.StringVar(value=self.parent.INPUT_TARGET_LANG), ) self.optionmenu_translation_input_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") @@ -412,7 +412,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): # command=self.optionmenu_translation_output_source_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.SOURCE_LANG), + variable=customtkinter.StringVar(value=self.parent.OUTPUT_SOURCE_LANG), state="disabled", ) self.optionmenu_translation_output_source_language.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") @@ -432,7 +432,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): # command=self.optionmenu_translation_output_target_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.TARGET_LANG), + variable=customtkinter.StringVar(value=self.parent.OUTPUT_TARGET_LANG), state="disabled", ) self.optionmenu_translation_output_target_language.grid(row=2, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") @@ -468,7 +468,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): values=list(self.parent.vr.languages), command=self.optionmenu_input_mic_voice_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.INPUT_VOICE_LANGUAGE) + variable=customtkinter.StringVar(value=self.parent.INPUT_MIC_VOICE_LANGUAGE) ) self.optionmenu_input_mic_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") @@ -524,7 +524,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): values=list(self.parent.vr.input_device_dict.keys()), # command=self.optionmenu_input_speaker_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE), + variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), state="disabled" ) self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") @@ -542,7 +542,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): values=list(self.parent.vr.languages), # command=self.optionmenu_input_speaker_voice_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.INPUT_VOICE_LANGUAGE), + variable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_VOICE_LANGUAGE), state="disabled" ) self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") @@ -565,7 +565,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): state="disabled" ) self.checkbox_input_speaker_is_dynamic.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - if self.parent.ENABLE_MIC_IS_DYNAMIC is True: + if self.parent.ENABLE_SPEAKER_IS_DYNAMIC is True: self.checkbox_input_speaker_is_dynamic.select() else: self.checkbox_input_speaker_is_dynamic.deselect() @@ -583,7 +583,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): from_=0, to=300, # command=self.slider_input_speaker_threshold_callback, - variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), + variable=tk.DoubleVar(value=self.parent.SPEAKER_THRESHOLD), state="disabled" ) self.slider_input_speaker_threshold.grid(row=7, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") @@ -775,19 +775,19 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) self.parent.CHOICE_TRANSLATOR = choice - self.parent.SOURCE_LANG = self.parent.translator.languages[choice][0] - self.parent.TARGET_LANG = self.parent.translator.languages[choice][1] + self.parent.INPUT_SOURCE_LANG = self.parent.translator.languages[choice][0] + self.parent.INPUT_TARGET_LANG = self.parent.translator.languages[choice][1] save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR) - save_json(self.parent.PATH_CONFIG, "SOURCE_LANG", self.parent.SOURCE_LANG) - save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) + save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) + save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) def optionmenu_translation_input_source_language_callback(self, choice): - self.parent.SOURCE_LANG = choice - save_json(self.parent.PATH_CONFIG, "SOURCE_LANG", self.parent.SOURCE_LANG) + self.parent.INPUT_SOURCE_LANG = choice + save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) def optionmenu_translation_input_target_language_callback(self, choice): - self.parent.TARGET_LANG = choice - save_json(self.parent.PATH_CONFIG, "TARGET_LANG", self.parent.TARGET_LANG) + self.parent.INPUT_TARGET_LANG = choice + save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) def optionmenu_input_mic_device_callback(self, choice): self.parent.CHOICE_MIC_DEVICE = choice @@ -795,8 +795,8 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.vr.set_mic(choice) def optionmenu_input_mic_voice_language_callback(self, choice): - self.parent.INPUT_VOICE_LANGUAGE = choice - save_json(self.parent.PATH_CONFIG, "INPUT_VOICE_LANGUAGE", self.parent.INPUT_VOICE_LANGUAGE) + self.parent.INPUT_MIC_VOICE_LANGUAGE = choice + save_json(self.parent.PATH_CONFIG, "INPUT_MIC_VOICE_LANGUAGE", self.parent.INPUT_MIC_VOICE_LANGUAGE) self.parent.vr.set_mic(choice) def checkbox_input_mic_is_dynamic_callback(self): @@ -849,13 +849,33 @@ class App(customtkinter.CTk): # init config self.PATH_CONFIG = "./config.json" + ## main window + self.ENABLE_TRANSLATION = False + self.ENABLE_TRANSCRIPTION = False + self.ENABLE_FOREGROUND = False + ## UI + self.TRANSPARENCY = 100 + self.APPEARANCE_THEME = "System" + self.UI_SCALING = "100%" + self.FONT_FAMILY = "Yu Gothic UI" + ## Translation + self.CHOICE_TRANSLATOR = "DeepL(web)" + self.INPUT_SOURCE_LANG = "JA" + self.INPUT_TARGET_LANG = "EN" + self.OUTPUT_SOURCE_LANG = "JA" + self.OUTPUT_TARGET_LANG = "EN" + ## Transcription + self.CHOICE_MIC_DEVICE = None + self.INPUT_MIC_VOICE_LANGUAGE = "ja-JP" + self.ENABLE_MIC_IS_DYNAMIC = False + self.MIC_THRESHOLD = 300 + self.CHOICE_SPEAKER_DEVICE = None + self.INPUT_SPEAKER_VOICE_LANGUAGE = "ja-JP" + self.ENABLE_SPEAKER_IS_DYNAMIC = False + self.SPEAKER_THRESHOLD = 300 + ## Parameter self.OSC_IP_ADDRESS = "127.0.0.1" self.OSC_PORT = 9000 - self.ENABLE_TRANSLATION = True - self.CHOICE_TRANSLATOR = "DeepL(web)" - self.SOURCE_LANG = "JA" - self.TARGET_LANG = "EN" - self.ENABLE_FOREGROUND = False self.AUTH_KEYS = { "DeepL(web)": None, "DeepL(auth)": None, @@ -863,73 +883,95 @@ class App(customtkinter.CTk): "Google(web)": None, } self.MESSAGE_FORMAT = "[message]([translation])" - self.ENABLE_VOICE2CHAT = False - self.CHOICE_MIC_DEVICE = None - self.ENABLE_MIC_IS_DYNAMIC = False - self.MIC_THRESHOLD = 300 - self.INPUT_VOICE_LANGUAGE = "ja-JP" - self.FONT_FAMILY = "Yu Gothic UI" - self.TRANSPARENCY = 100 - self.APPEARANCE_THEME = "System" - self.UI_SCALING = "100%" # load config if os.path.isfile(self.PATH_CONFIG) is not False: with open(self.PATH_CONFIG, 'r') as fp: config = json.load(fp) - if "OSC_IP_ADDRESS" in config.keys(): - self.OSC_IP_ADDRESS = config["OSC_IP_ADDRESS"] - if "OSC_PORT" in config.keys(): - self.OSC_PORT = config["OSC_PORT"] + # main window if "ENABLE_TRANSLATION" in config.keys(): self.ENABLE_TRANSLATION = config["ENABLE_TRANSLATION"] - if "CHOICE_TRANSLATOR" in config.keys(): - self.CHOICE_TRANSLATOR = config["CHOICE_TRANSLATOR"] - if "SOURCE_LANG" in config.keys(): - self.SOURCE_LANG = config["SOURCE_LANG"] - if "TARGET_LANG" in config.keys(): - self.TARGET_LANG = config["TARGET_LANG"] + if "ENABLE_TRANSCRIPTION" in config.keys(): + self.ENABLE_TRANSCRIPTION = config["ENABLE_TRANSCRIPTION"] if "ENABLE_FOREGROUND" in config.keys(): self.ENABLE_FOREGROUND = config["ENABLE_FOREGROUND"] - if "AUTH_KEYS" in config.keys(): - self.AUTH_KEYS = config["AUTH_KEYS"] - if "MESSAGE_FORMAT" in config.keys(): - self.MESSAGE_FORMAT = config["MESSAGE_FORMAT"] - if "FONT_FAMILY" in config.keys(): - self.FONT_FAMILY = config["FONT_FAMILY"] - if "ENABLE_VOICE2CHAT" in config.keys(): - self.ENABLE_VOICE2CHAT = config["ENABLE_VOICE2CHAT"] - if "CHOICE_MIC_DEVICE" in config.keys(): - self.CHOICE_MIC_DEVICE = config["CHOICE_MIC_DEVICE"] - if "MIC_THRESHOLD" in config.keys(): - self.MIC_THRESHOLD = config["MIC_THRESHOLD"] - if "INPUT_VOICE_LANGUAGE" in config.keys(): - self.INPUT_VOICE_LANGUAGE = config["INPUT_VOICE_LANGUAGE"] + + # tab ui if "TRANSPARENCY" in config.keys(): self.TRANSPARENCY = config["TRANSPARENCY"] if "APPEARANCE_THEME" in config.keys(): self.APPEARANCE_THEME = config["APPEARANCE_THEME"] if "UI_SCALING" in config.keys(): self.UI_SCALING = config["UI_SCALING"] + if "FONT_FAMILY" in config.keys(): + self.FONT_FAMILY = config["FONT_FAMILY"] + + # translation + if "CHOICE_TRANSLATOR" in config.keys(): + self.CHOICE_TRANSLATOR = config["CHOICE_TRANSLATOR"] + if "INPUT_SOURCE_LANG" in config.keys(): + self.INPUT_SOURCE_LANG = config["INPUT_SOURCE_LANG"] + if "INPUT_TARGET_LANG" in config.keys(): + self.INPUT_TARGET_LANG = config["INPUT_TARGET_LANG"] + if "OUTPUT_SOURCE_LANG" in config.keys(): + self.OUTPUT_SOURCE_LANG = config["OUTPUT_SOURCE_LANG"] + if "OUTPUT_TARGET_LANG" in config.keys(): + self.OUTPUT_TARGET_LANG = config["OUTPUT_TARGET_LANG"] + + # Transcription + if "CHOICE_MIC_DEVICE" in config.keys(): + self.CHOICE_MIC_DEVICE = config["CHOICE_MIC_DEVICE"] + if "INPUT_MIC_VOICE_LANGUAGE" in config.keys(): + self.INPUT_MIC_VOICE_LANGUAGE = config["INPUT_MIC_VOICE_LANGUAGE"] + if "ENABLE_MIC_IS_DYNAMIC" in config.keys(): + self.ENABLE_MIC_IS_DYNAMIC = config["ENABLE_MIC_IS_DYNAMIC"] + if "MIC_THRESHOLD" in config.keys(): + self.MIC_THRESHOLD = config["MIC_THRESHOLD"] + if "CHOICE_SPEAKER_DEVICE" in config.keys(): + self.CHOICE_SPEAKER_DEVICE = config["CHOICE_SPEAKER_DEVICE"] + if "INPUT_SPEAKER_VOICE_LANGUAGE" in config.keys(): + self.INPUT_SPEAKER_VOICE_LANGUAGE = config["INPUT_SPEAKER_VOICE_LANGUAGE"] + if "ENABLE_SPEAKER_IS_DYNAMIC" in config.keys(): + self.ENABLE_SPEAKER_IS_DYNAMIC = config["ENABLE_SPEAKER_IS_DYNAMIC"] + if "SPEAKER_THRESHOLD" in config.keys(): + self.SPEAKER_THRESHOLD = config["SPEAKER_THRESHOLD"] + + # Parameter + if "OSC_IP_ADDRESS" in config.keys(): + self.OSC_IP_ADDRESS = config["OSC_IP_ADDRESS"] + if "OSC_PORT" in config.keys(): + self.OSC_PORT = config["OSC_PORT"] + if "AUTH_KEYS" in config.keys(): + self.AUTH_KEYS = config["AUTH_KEYS"] + if "MESSAGE_FORMAT" in config.keys(): + self.MESSAGE_FORMAT = config["MESSAGE_FORMAT"] with open(self.PATH_CONFIG, 'w') as fp: config = { - "OSC_IP_ADDRESS": self.OSC_IP_ADDRESS, - "OSC_PORT": self.OSC_PORT, "ENABLE_TRANSLATION": self.ENABLE_TRANSLATION, - "CHOICE_TRANSLATOR": self.CHOICE_TRANSLATOR, - "SOURCE_LANG": self.SOURCE_LANG, - "TARGET_LANG": self.TARGET_LANG, + "ENABLE_TRANSCRIPTION": self.ENABLE_TRANSCRIPTION, "ENABLE_FOREGROUND": self.ENABLE_FOREGROUND, - "AUTH_KEYS": self.AUTH_KEYS, - "MESSAGE_FORMAT": self.MESSAGE_FORMAT, - "FONT_FAMILY": self.FONT_FAMILY, - "ENABLE_VOICE2CHAT": self.ENABLE_VOICE2CHAT, - "CHOICE_MIC_DEVICE": self.CHOICE_MIC_DEVICE, - "INPUT_VOICE_LANGUAGE": self.INPUT_VOICE_LANGUAGE, "TRANSPARENCY": self.TRANSPARENCY, "APPEARANCE_THEME": self.APPEARANCE_THEME, "UI_SCALING": self.UI_SCALING, + "FONT_FAMILY": self.FONT_FAMILY, + "CHOICE_TRANSLATOR": self.CHOICE_TRANSLATOR, + "INPUT_SOURCE_LANG": self.INPUT_SOURCE_LANG, + "INPUT_TARGET_LANG": self.INPUT_TARGET_LANG, + "OUTPUT_SOURCE_LANG": self.OUTPUT_SOURCE_LANG, + "OUTPUT_TARGET_LANG": self.OUTPUT_TARGET_LANG, + "CHOICE_MIC_DEVICE": self.CHOICE_MIC_DEVICE, + "INPUT_MIC_VOICE_LANGUAGE": self.INPUT_MIC_VOICE_LANGUAGE, + "ENABLE_MIC_IS_DYNAMIC": self.ENABLE_MIC_IS_DYNAMIC, + "MIC_THRESHOLD": self.MIC_THRESHOLD, + "CHOICE_SPEAKER_DEVICE": self.CHOICE_SPEAKER_DEVICE, + "INPUT_SPEAKER_VOICE_LANGUAGE": self.INPUT_SPEAKER_VOICE_LANGUAGE, + "ENABLE_SPEAKER_IS_DYNAMIC": self.ENABLE_SPEAKER_IS_DYNAMIC, + "SPEAKER_THRESHOLD": self.SPEAKER_THRESHOLD, + "OSC_IP_ADDRESS": self.OSC_IP_ADDRESS, + "OSC_PORT": self.OSC_PORT, + "AUTH_KEYS": self.AUTH_KEYS, + "MESSAGE_FORMAT": self.MESSAGE_FORMAT, } json.dump(config, fp, indent=4) @@ -1045,7 +1087,7 @@ class App(customtkinter.CTk): self.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") self.textbox_message_log.configure(state='disabled') - ## set voice2chat: + ## set transcription instance self.vr = VoiceRecognizer() self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else list(self.vr.input_device_dict.keys())[0] @@ -1079,6 +1121,8 @@ class App(customtkinter.CTk): # start threading th = threading.Thread(target = self.voice_input) th.start() + self.ENABLE_TRANSCRIPTION = True + save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) def voice_input(self): mic_status = self.vr.set_mic(self.CHOICE_MIC_DEVICE) @@ -1086,13 +1130,13 @@ class App(customtkinter.CTk): if mic_status: # start voice_input while self.checkbox_transcription.get() is True: - message = self.vr.listen_voice(language=self.INPUT_VOICE_LANGUAGE) + message = self.vr.listen_voice(language=self.INPUT_MIC_VOICE_LANGUAGE) if len(message) > 0: # translate if self.checkbox_translation.get() is False: chat_message = f"{message}" - elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.SOURCE_LANG == "None") or (self.TARGET_LANG == "None"): + elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("0.0", f"Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') @@ -1100,8 +1144,8 @@ class App(customtkinter.CTk): else: result = self.translator.translate( translator_name=self.CHOICE_TRANSLATOR, - source_language=self.SOURCE_LANG, - target_language=self.TARGET_LANG, + source_language=self.INPUT_SOURCE_LANG, + target_language=self.INPUT_TARGET_LANG, message=message ) chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) @@ -1140,7 +1184,7 @@ class App(customtkinter.CTk): # translate if self.checkbox_translation.get() is False: chat_message = f"{message}" - elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.SOURCE_LANG == "None") or (self.TARGET_LANG == "None"): + elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("0.0", f"Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') @@ -1148,8 +1192,8 @@ class App(customtkinter.CTk): else: result = self.translator.translate( translator_name=self.CHOICE_TRANSLATOR, - source_language=self.SOURCE_LANG, - target_language=self.TARGET_LANG, + source_language=self.INPUT_SOURCE_LANG, + target_language=self.INPUT_TARGET_LANG, message=message ) chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) From 1ba2bcc9e1975c17b2a63ed48635f0afada132d1 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 05:48:43 +0900 Subject: [PATCH 08/35] update textbox message --- VRCT.py | 144 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 61 deletions(-) diff --git a/VRCT.py b/VRCT.py index 728a4a9f..23ffaba6 100644 --- a/VRCT.py +++ b/VRCT.py @@ -246,7 +246,7 @@ https://twitter.com/misya_ai 再配布とかはやめてね """ - self.textbox_information.insert("0.0", textbox_information_message) + self.textbox_information.insert("end", textbox_information_message) self.textbox_information.configure(state='disabled') class ToplevelWindowConfig(customtkinter.CTkToplevel): @@ -764,7 +764,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def optionmenu_translation_translator_callback(self, choice): if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") self.parent.textbox_message_log.configure(state='disabled') else: self.optionmenu_translation_input_source_language.configure( @@ -834,7 +834,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): save_json(self.parent.PATH_CONFIG, "AUTH_KEYS", self.parent.AUTH_KEYS) else: self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") self.parent.textbox_message_log.configure(state='disabled') def update_message_format(self): @@ -1060,37 +1060,44 @@ class App(customtkinter.CTk): self.entry_message_box.grid(row=1, column=1, columnspan=2, padx=(10, 10), pady=(5, 10), sticky="nsew") # set default values - ## set checkbox enable translation - if self.ENABLE_TRANSLATION: - self.checkbox_translation.select() - else: - self.checkbox_translation.deselect() - - ## set set checkbox enable foreground - if self.ENABLE_FOREGROUND: - self.checkbox_foreground.select() - self.attributes("-topmost", True) - else: - self.checkbox_foreground.deselect() - self.attributes("-topmost", False) - - ## 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 translator instance self.translator = Translator() if self.translator.authentication(self.CHOICE_TRANSLATOR, self.AUTH_KEYS[self.CHOICE_TRANSLATOR]) is False: # error update Auth key self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("0.0", f"Auth Keyを設定してないか間違っています\n") + self.textbox_message_log.insert("end", f"[ERROR] Auth Keyを設定してないか間違っています\n") self.textbox_message_log.configure(state='disabled') ## set transcription instance self.vr = VoiceRecognizer() self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else list(self.vr.input_device_dict.keys())[0] + ## set checkbox enable translation + if self.ENABLE_TRANSLATION: + self.checkbox_translation.select() + else: + self.checkbox_translation.deselect() + self.checkbox_translation_callback() + + ## set checkbox enable transcription + if self.ENABLE_TRANSCRIPTION: + self.checkbox_transcription.select() + else: + self.checkbox_transcription.deselect() + self.checkbox_transcription_callback() + + ## set set checkbox enable foreground + if self.ENABLE_FOREGROUND: + self.checkbox_foreground.select() + else: + self.checkbox_foreground.deselect() + self.checkbox_foreground_callback() + + ## 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", self.TRANSPARENCY/100) @@ -1114,55 +1121,70 @@ class App(customtkinter.CTk): def checkbox_translation_callback(self): self.ENABLE_TRANSLATION = self.checkbox_translation.get() + if self.ENABLE_TRANSLATION: + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[INFO] start translation\n") + self.textbox_message_log.configure(state='disabled') + else: + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[INFO] stop translation\n") + self.textbox_message_log.configure(state='disabled') save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) def checkbox_transcription_callback(self): - if self.checkbox_transcription.get() is True: + self.ENABLE_TRANSCRIPTION = self.checkbox_transcription.get() + if self.ENABLE_TRANSCRIPTION is True: # start threading th = threading.Thread(target = self.voice_input) th.start() - self.ENABLE_TRANSCRIPTION = True - save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) + save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) def voice_input(self): - mic_status = self.vr.set_mic(self.CHOICE_MIC_DEVICE) + self.vr.set_mic(self.CHOICE_MIC_DEVICE) self.vr.init_mic(threshold=self.MIC_THRESHOLD, is_dynamic=self.ENABLE_MIC_IS_DYNAMIC) - if mic_status: - # start voice_input - while self.checkbox_transcription.get() is True: - message = self.vr.listen_voice(language=self.INPUT_MIC_VOICE_LANGUAGE) - if len(message) > 0: - # translate - if self.checkbox_translation.get() is False: - chat_message = f"{message}" - elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("0.0", f"Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_log.configure(state='disabled') - chat_message = f"{message}" - else: - result = self.translator.translate( - translator_name=self.CHOICE_TRANSLATOR, - source_language=self.INPUT_SOURCE_LANG, - target_language=self.INPUT_TARGET_LANG, - message=message - ) - chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + # start voice_input + if self.checkbox_transcription.get() is True: + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[INFO] start transcription\n") + self.textbox_message_log.configure(state='disabled') - # send OSC message - message = osc_message_builder.OscMessageBuilder(address="/chatbox/input") - message.add_arg(f"{chat_message}") - message.add_arg(True) - message.add_arg(True) - message = message.build() - client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) - client.send(message) - - # update textbox message log + while self.checkbox_transcription.get() is True: + message = self.vr.listen_voice(language=self.INPUT_MIC_VOICE_LANGUAGE) + if len(message) > 0: + # translate + if self.checkbox_translation.get() is False: + chat_message = f"{message}" + elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("0.0", f"{chat_message}\n") + self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') + chat_message = f"{message}" + else: + result = self.translator.translate( + translator_name=self.CHOICE_TRANSLATOR, + source_language=self.INPUT_SOURCE_LANG, + target_language=self.INPUT_TARGET_LANG, + message=message + ) + chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + + # send OSC message + message = osc_message_builder.OscMessageBuilder(address="/chatbox/input") + message.add_arg(f"{chat_message}") + message.add_arg(True) + message.add_arg(True) + message = message.build() + client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) + client.send(message) + + # update textbox message log + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[VOICE] {chat_message}\n") + self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[INFO] stop transcription\n") + self.textbox_message_log.configure(state='disabled') def checkbox_foreground_callback(self): value = self.checkbox_foreground.get() @@ -1186,7 +1208,7 @@ class App(customtkinter.CTk): chat_message = f"{message}" elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("0.0", f"Auth Keyもしくは言語の設定が間違っています\n") + self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') chat_message = f"{message}" else: @@ -1209,7 +1231,7 @@ class App(customtkinter.CTk): # update textbox message log self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("0.0", f"{chat_message}\n") + self.textbox_message_log.insert("end", f"[CHAT] {chat_message}\n") self.textbox_message_log.configure(state='disabled') # delete message in entry message box From 69409834784dc38f1c711bff6f8cd4381420618d Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 06:01:23 +0900 Subject: [PATCH 09/35] add osc send typing --- VRCT.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/VRCT.py b/VRCT.py index 23ffaba6..0fbc7479 100644 --- a/VRCT.py +++ b/VRCT.py @@ -1187,14 +1187,11 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='disabled') def checkbox_foreground_callback(self): - value = self.checkbox_foreground.get() - - if value: + self.ENABLE_FOREGROUND = self.checkbox_foreground.get() + if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) else: self.attributes("-topmost", False) - - self.ENABLE_FOREGROUND = value save_json(self.PATH_CONFIG, "ENABLE_FOREGROUND", self.ENABLE_FOREGROUND) def entry_message_box_press_key_enter(self, event): @@ -1238,10 +1235,22 @@ class App(customtkinter.CTk): self.entry_message_box.delete(0, customtkinter.END) def entry_message_box_press_key_any(self, event): + # send OSC typing + typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") + typing.add_arg(True) + typing = typing.build() + client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) + client.send(typing) if self.ENABLE_FOREGROUND: self.attributes("-topmost", False) def entry_message_box_leave(self, event): + # send OSC typing + typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") + typing.add_arg(False) + typing = typing.build() + client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) + client.send(typing) if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) From dfd41fe7874a57434f83f757f40be9984370800f Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 06:47:06 +0900 Subject: [PATCH 10/35] add auto scroll textbox --- VRCT.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/VRCT.py b/VRCT.py index 0fbc7479..091c0ab3 100644 --- a/VRCT.py +++ b/VRCT.py @@ -766,6 +766,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.textbox_message_log.configure(state='normal') self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") self.parent.textbox_message_log.configure(state='disabled') + self.parent.textbox_message_log.see("end") else: self.optionmenu_translation_input_source_language.configure( values=self.parent.translator.languages[choice], @@ -792,12 +793,10 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def optionmenu_input_mic_device_callback(self, choice): self.parent.CHOICE_MIC_DEVICE = choice save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) - self.parent.vr.set_mic(choice) def optionmenu_input_mic_voice_language_callback(self, choice): self.parent.INPUT_MIC_VOICE_LANGUAGE = choice save_json(self.parent.PATH_CONFIG, "INPUT_MIC_VOICE_LANGUAGE", self.parent.INPUT_MIC_VOICE_LANGUAGE) - self.parent.vr.set_mic(choice) def checkbox_input_mic_is_dynamic_callback(self): value = self.checkbox_input_mic_is_dynamic.get() @@ -828,6 +827,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.textbox_message_log.configure(state='normal') self.parent.textbox_message_log.delete("0.0", "end") self.parent.textbox_message_log.configure(state='disabled') + self.parent.textbox_message_log.see("end") if self.parent.translator.authentication(self.parent.CHOICE_TRANSLATOR, self.parent.AUTH_KEYS[self.parent.CHOICE_TRANSLATOR]) is True: self.parent.AUTH_KEYS["DeepL(auth)"] = value @@ -836,6 +836,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.textbox_message_log.configure(state='normal') self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") self.parent.textbox_message_log.configure(state='disabled') + self.parent.textbox_message_log.see("end") def update_message_format(self): value = self.entry_message_format.get() @@ -1067,6 +1068,7 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[ERROR] Auth Keyを設定してないか間違っています\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") ## set transcription instance self.vr = VoiceRecognizer() @@ -1075,9 +1077,9 @@ class App(customtkinter.CTk): ## set checkbox enable translation if self.ENABLE_TRANSLATION: self.checkbox_translation.select() + self.checkbox_translation_callback() else: self.checkbox_translation.deselect() - self.checkbox_translation_callback() ## set checkbox enable transcription if self.ENABLE_TRANSCRIPTION: @@ -1121,14 +1123,13 @@ class App(customtkinter.CTk): def checkbox_translation_callback(self): self.ENABLE_TRANSLATION = self.checkbox_translation.get() + self.textbox_message_log.configure(state='normal') if self.ENABLE_TRANSLATION: - self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[INFO] start translation\n") - self.textbox_message_log.configure(state='disabled') else: - self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[INFO] stop translation\n") - self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) def checkbox_transcription_callback(self): @@ -1148,6 +1149,7 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[INFO] start transcription\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") while self.checkbox_transcription.get() is True: message = self.vr.listen_voice(language=self.INPUT_MIC_VOICE_LANGUAGE) @@ -1159,6 +1161,7 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") chat_message = f"{message}" else: result = self.translator.translate( @@ -1182,9 +1185,11 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[VOICE] {chat_message}\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[INFO] stop transcription\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") def checkbox_foreground_callback(self): self.ENABLE_FOREGROUND = self.checkbox_foreground.get() @@ -1195,6 +1200,13 @@ class App(customtkinter.CTk): save_json(self.PATH_CONFIG, "ENABLE_FOREGROUND", self.ENABLE_FOREGROUND) def entry_message_box_press_key_enter(self, event): + # send OSC typing + typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") + typing.add_arg(False) + typing = typing.build() + client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) + client.send(typing) + if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) @@ -1207,6 +1219,7 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") chat_message = f"{message}" else: result = self.translator.translate( @@ -1230,9 +1243,10 @@ class App(customtkinter.CTk): self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[CHAT] {chat_message}\n") self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") # delete message in entry message box - self.entry_message_box.delete(0, customtkinter.END) + # self.entry_message_box.delete(0, customtkinter.END) def entry_message_box_press_key_any(self, event): # send OSC typing From eb7faea978176d35023c8881b9afd3ef426521bc Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 10:04:49 +0900 Subject: [PATCH 11/35] add message tab ui --- VRCT.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/VRCT.py b/VRCT.py index 091c0ab3..658b1a10 100644 --- a/VRCT.py +++ b/VRCT.py @@ -980,7 +980,7 @@ class App(customtkinter.CTk): self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico")) self.title("VRCT") self.geometry(f"{400}x{140}") - self.minsize(400, 110) + self.minsize(400, 140) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) @@ -1044,14 +1044,34 @@ class App(customtkinter.CTk): self.button_config.grid(row=5, column=1, padx=(5, 10), pady=(5, 5), sticky="wse") self.config_window = None + # add tabview textbox + self.tabview_logs = customtkinter.CTkTabview(master=self) + self.tabview_logs.add("send") + self.tabview_logs.add("receive") + self.tabview_logs.grid(row=0, column=1, padx=5, pady=0, sticky="nsew") + self.tabview_logs._segmented_button.grid(sticky="W") + self.tabview_logs.tab("send").grid_rowconfigure(0, weight=1) + self.tabview_logs.tab("send").grid_columnconfigure(0, weight=1) + self.tabview_logs.tab("receive").grid_rowconfigure(0, weight=1) + self.tabview_logs.tab("receive").grid_columnconfigure(0, weight=1) + self.tabview_logs.configure(state='disabled') + # add textbox message log self.textbox_message_log = customtkinter.CTkTextbox( - self, + self.tabview_logs.tab("send"), font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.textbox_message_log.grid(row=0, column=1, padx=(10, 10), pady=(10, 5), sticky="nsew") + 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 log + self.textbox_message_receive_log = customtkinter.CTkTextbox( + self.tabview_logs.tab("receive"), + font=customtkinter.CTkFont(family=self.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 entry message box self.entry_message_box = customtkinter.CTkEntry( self, From 1e6c5ad1bc95927072a959aae7fbf0b99799b023 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 17:45:22 +0900 Subject: [PATCH 12/35] add ui font change --- VRCT.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/VRCT.py b/VRCT.py index 658b1a10..aa52f8f8 100644 --- a/VRCT.py +++ b/VRCT.py @@ -273,6 +273,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.tabview_config.tab("Transcription").grid_columnconfigure(1, weight=1) self.tabview_config.tab("Parameter").grid_columnconfigure(1, weight=1) self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY)) + self.tabview_config._segmented_button.grid(sticky="W") # tab UI ## slider transparency @@ -748,9 +749,11 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): # main window self.parent.checkbox_translation.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.checkbox_transcription.configure(font=customtkinter.CTkFont(family=choice)) self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.tabview_logs._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) # window information try: From 5c822de80b6b57d9130505d68f817bbebeabf9e3 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Sun, 11 Jun 2023 17:59:48 +0900 Subject: [PATCH 13/35] add unuse items font change --- VRCT.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/VRCT.py b/VRCT.py index aa52f8f8..bb096440 100644 --- a/VRCT.py +++ b/VRCT.py @@ -718,10 +718,11 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.optionmenu_translation_input_source_language.configure(font=customtkinter.CTkFont(family=choice)) self.label_translation_input_arrow.configure(font=customtkinter.CTkFont(family=choice)) self.optionmenu_translation_input_target_language.configure(font=customtkinter.CTkFont(family=choice)) - # self.label_translation_output_language.configure(font=customtkinter.CTkFont(family=choice)) - # self.optionmenu_translation_output_source_language.configure(font=customtkinter.CTkFont(family=choice)) - # self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) - # self.optionmenu_translation_output_target_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_output_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_output_source_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_output_target_language.configure(font=customtkinter.CTkFont(family=choice)) # tab Transcription self.label_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) @@ -730,12 +731,12 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.optionmenu_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) self.label_input_mic_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) self.label_input_mic_threshold.configure(font=customtkinter.CTkFont(family=choice)) - # self.label_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) - # self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) - # self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - # self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - # self.label_input_speaker_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) - # self.label_input_speaker_threshold.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_threshold.configure(font=customtkinter.CTkFont(family=choice)) # tab Parameter self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) From a0004f007052f799b2ea5c7dec49e6f305d2d051 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Mon, 12 Jun 2023 12:13:35 +0900 Subject: [PATCH 14/35] update gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ea9ad5fb..39debb4c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ VRCT.onefile-build/ VRCT.exe VRCT.spec deepl-translate/ -translators/ \ No newline at end of file +translators/ +test/ \ No newline at end of file From 63ed08798694c7f57f4e01bdb4731940f0d9402b Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Mon, 12 Jun 2023 12:49:37 +0900 Subject: [PATCH 15/35] make modules --- VRCT.py | 897 +----------------------------------------- osc_tools.py | 21 + transcription.py | 70 ++++ translation.py | 74 ++++ utils.py | 8 + window_config.py | 604 ++++++++++++++++++++++++++++ window_information.py | 93 +++++ 7 files changed, 888 insertions(+), 879 deletions(-) create mode 100644 osc_tools.py create mode 100644 transcription.py create mode 100644 translation.py create mode 100644 utils.py create mode 100644 window_config.py create mode 100644 window_information.py diff --git a/VRCT.py b/VRCT.py index bb096440..5e74690b 100644 --- a/VRCT.py +++ b/VRCT.py @@ -1,852 +1,15 @@ import os import json import threading -import deepl -import deepl_translate -import translators as ts -from pythonosc import osc_message_builder -from pythonosc import udp_client -import tkinter as tk import customtkinter from PIL import Image -import pyaudio -import speech_recognition as sr -def save_json(path, key, value): - with open(path, "r") as fp: - json_data = json.load(fp) - json_data[key] = value - with open(path, "w") as fp: - json.dump(json_data, fp, indent=4) - -# Translator -class Translator(): - def __init__(self): - self.translator_status = { - "DeepL(web)": False, - "DeepL(auth)": False, - "Google(web)": False, - "Bing(web)": False, - } - self.languages = {} - self.languages["DeepL(web)"] = [ - "JA","EN","BG","ZH","CS","DA","NL","ET","FI","FR","DE","EL","HU","IT", - "LV","LT","PL","PT","RO","RU","SK","SL","ES","SV", - ] - self.languages["DeepL(auth)"] = [ - "JA","EN-US","EN-GB","BG","CS","DA","DE","EL","ES","ET","FI","FR","HU", - "ID","IT","KO","LT","LV","NB","NL","PL","PT","PT-BR","PT-PT","RO","RU", - "SK","SL","SV","TR","UK","ZH", - ] - self.languages["Google(web)"] = [ - "ja","en","zh","ar","ru","fr","de","es","pt","it","ko","el","nl","hi", - "tr","ms","th","vi","id","he","pl","mn","cs","hu","et","bg","da","fi", - "ro","sv","sl","fa","bs","sr","tl","ht","ca","hr","lv","lt","ur","uk", - "cy","sw","sm","sk","af","no","bn","mg","mt","gu","ta","te","pa","am", - "az","be","ceb","eo","eu","ga" - ] - self.languages["Bing(web)"] = [ - "ja","en","zh","ar","ru","fr","de","es","pt","it","ko","el","nl","hi", - "tr","ms","th","vi","id","he","pl","cs","hu","et","bg","da","fi","ro", - "sv","sl","fa","bs","sr","fj","tl","ht","ca","hr","lv","lt","ur","uk", - "cy","ty","to","sw","sm","sk","af","no","bn","mg","mt","otq","tlh","gu", - "ta","te","pa","ga" - ] - self.deepl_client = None - - def authentication(self, translator_name, authkey=None): - result = False - try: - if translator_name == "DeepL(web)": - self.translator_status["DeepL(web)"] = True - result = True - elif translator_name == "DeepL(auth)": - self.deepl_client = deepl.Translator(authkey) - self.deepl_client.translate_text(" ", target_lang="EN-US") - self.translator_status["DeepL(auth)"] = True - result = True - elif translator_name == "Google(web)": - self.translator_status["Google(web)"] = True - result = True - elif translator_name == "Bing(web)": - self.translator_status["Bing(web)"] = True - result = True - except: - pass - return result - - def translate(self, translator_name, source_language, target_language, message): - result = False - try: - if translator_name == "DeepL(web)": - result = deepl_translate.translate(source_language=source_language, target_language=target_language, text=message) - elif translator_name == "DeepL(auth)": - result = self.deepl_client.translate_text(message, source_lang=source_language, target_lang=target_language).text - elif translator_name == "Google(web)": - result = ts.translate_text(query_text=message, translator="google", from_language=source_language, to_language=target_language) - elif translator_name == "Bing(web)": - result = ts.translate_text(query_text=message, translator="bing", from_language=source_language, to_language=target_language) - except: - pass - return result - -# VoiceRecognizer -class VoiceRecognizer(): - def __init__(self): - self.input_device_dict = self.search_input_device() - self.r = sr.Recognizer() - self.mic = None - self.languages = [ - "ja-JP","en-US","en-GB","af-ZA","ar-DZ","ar-BH","ar-EG","ar-IL","ar-IQ","ar-JO","ar-KW","ar-LB","ar-MA", - "ar-OM","ar-PS","ar-QA","ar-SA","ar-TN","ar-AE","eu-ES","bg-BG","ca-ES","cmn-Hans-CN","cmn-Hans-HK", - "cmn-Hant-TW","yue-Hant-HK","hr_HR","cs-CZ","da-DK","en-AU","en-CA","en-IN","en-IE","en-NZ","en-PH", - "en-ZA","fa-IR","fr-FR","fil-PH","gl-ES","de-DE","el-GR","fi-FI","he-IL","hi-IN","hu-HU","id-ID","is-IS", - "it-IT","it-CH","ko-KR","lt-LT","ms-MY","nl-NL","nb-NO","pl-PL","pt-BR","pt-PT","ro-RO","ru-RU","sr-RS", - "sk-SK","sl-SI","es-AR","es-BO","es-CL","es-CO","es-CR","es-DO","es-EC","es-SV","es-GT","es-HN","es-MX", - "es-NI","es-PA","es-PY","es-PE","es-PR","es-ES","es-UY","es-US","es-VE","sv-SE","th-TH","tr-TR","uk-UA", - "vi-VN","zu-ZA" - ] - - def search_input_device(self): - pa = pyaudio.PyAudio() - input_device_dict = {} - - mic_cnt = 1 - for i in range(pa.get_device_count()): - device = pa.get_device_info_by_index(i) - try: - device["name"] = device["name"].encode('shift_jis').decode('utf-8') - except: - device["name"] = device["name"].encode('utf-8').decode('utf-8') - if device["maxInputChannels"] > 0: - input_device_dict[f'No.{mic_cnt}:{device["name"]}'] = device["index"] - mic_cnt += 1 - pa.terminate() - return input_device_dict - - def set_mic(self, device_name, threshold=50, is_dynamic=False): - if device_name in [v for v in self.input_device_dict.keys()]: - index = self.input_device_dict[device_name] - self.mic = sr.Microphone(device_index=index) - self.r.energy_threshold = threshold - if is_dynamic: - with self.mic as source: - self.r.adjust_for_ambient_noise(source, 3.0) - return True - else: - return False - - def init_mic(self, threshold=50, is_dynamic=False): - if isinstance(self.mic, sr.Microphone): - self.r.energy_threshold = threshold - if is_dynamic: - with self.mic as source: - self.r.adjust_for_ambient_noise(source, 3.0) - return True - else: - return False - - def listen_voice(self, language): - if self.mic != None: - with self.mic as source: - audio = self.r.listen(source) - try: - text = self.r.recognize_google(audio, language=language) - return text - except: - return "" - else: - return False - -class ToplevelWindowInformation(customtkinter.CTkToplevel): - def __init__(self, parent, *args, **kwargs): - super().__init__(parent, *args, **kwargs) - self.parent = parent - self.grid_columnconfigure(0, weight=1) - self.grid_rowconfigure(0, weight=1) - # self.geometry(f"{500}x{300}") - self.minsize(500, 300) - - self.after(200, lambda: self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico"))) - self.title("Information") - # create textbox information - self.textbox_information = customtkinter.CTkTextbox( - self, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.textbox_information.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="nsew") - textbox_information_message = """VRCT(v0.4b) - -# 概要 -VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツールになります。 -翻訳エンジンを使用してメッセージとその翻訳部分を同時に送信することができます。 -(翻訳エンジンはDeepL,Google,Bingに対応) - -# 使用方法 - 初期設定時 - 0. VRChatのOSCを有効にする(重要) - - (任意) - 1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する - 2. ギアアイコンのボタンでconfigウィンドウを開く - 3. ParameterタブのDeepL Auth Keyに認証キーを記載し、フロッピーアイコンのボタンを押す - 4. configウィンドウを閉じる - - 通常使用時 - 1. メッセージボックスにメッセージを記入 - 2. Enterキーを押し、メッセージを送信する - -# その他の設定 - translation チェックボックス: 翻訳の有効無効 - foreground チェックボックス: 最前面表示の有効無効 - - configウィンドウ - UIタブ - Select translator: 翻訳エンジンの変更 - Select Language: 翻訳する言語[source, target]を選択 - Transparency: ウィンドウの透過度の調整 - Appearance Theme: ウィンドウテーマを選択 - UI Scaling: UIサイズを調整 - Font Family: 表示フォントを選択 - Parameterタブ - OSC IP address: 変更不要 - OSC port: 変更不要 - DeepL Auth key: DeepLの認証キーの設定 - Message Format: 送信するメッセージのデコレーションの設定 - [message]がメッセージボックスに記入したメッセージに置換される - [translation]が翻訳されたメッセージに置換される - 初期フォーマット:"[message]([translation])" - - 設定の初期化 - config.jsonを削除 - -# お問い合わせ -要望などはTwitterまで -https://twitter.com/misya_ai - -# アップデート履歴 -[2023-05-29: v0.1b] v0.1b リリース -[2023-05-30: v0.2b] -- configボタンをギアアイコンに変更 -- 詳細情報のボタンを追加 -- 翻訳機能有効無効のチェックボックスを追加 -- 最前面表示の有効無効のチェックボックスを追加 -- いくつかのバグを修正 -[2023-06-03: v0.3b] -- 全体的にUIを刷新 -- 透過機能を追加 -- テーマのLight/Dark/Systemのモードの変更機能を追加 -- UIのスケール変更機能を追加 -- フォントの変更機能を追加 -[2023-06-06: v0.4b] -- 翻訳エンジンを追加 -- 入力と出力の翻訳言語を選択できるように変更 - -# 注意事項 -再配布とかはやめてね -""" - - self.textbox_information.insert("end", textbox_information_message) - self.textbox_information.configure(state='disabled') - -class ToplevelWindowConfig(customtkinter.CTkToplevel): - def __init__(self, parent, *args, **kwargs): - super().__init__(parent, *args, **kwargs) - self.parent = parent - # self.geometry(f"{350}x{270}") - # self.resizable(False, False) - self.grid_columnconfigure(0, weight=1) - self.grid_rowconfigure(0, weight=1) - - self.after(200, lambda: self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico"))) - self.title("Config") - - # tabwiew config - self.tabview_config = customtkinter.CTkTabview(self) - self.tabview_config.grid(row=0, column=0, padx=5, pady=5, sticky="nsew") - self.tabview_config.add("UI") - self.tabview_config.add("Translation") - self.tabview_config.add("Transcription") - self.tabview_config.add("Parameter") - self.tabview_config.tab("UI").grid_columnconfigure(1, weight=1) - self.tabview_config.tab("Translation").grid_columnconfigure([1,2,3], weight=1) - self.tabview_config.tab("Transcription").grid_columnconfigure(1, weight=1) - self.tabview_config.tab("Parameter").grid_columnconfigure(1, weight=1) - self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY)) - self.tabview_config._segmented_button.grid(sticky="W") - - # tab UI - ## slider transparency - self.label_transparency = customtkinter.CTkLabel( - self.tabview_config.tab("UI"), - text="Transparency:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_transparency.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.slider_transparency = customtkinter.CTkSlider( - self.tabview_config.tab("UI"), - from_=50, - to=100, - command=self.slider_transparency_callback, - variable=tk.DoubleVar(value=self.parent.TRANSPARENCY), - ) - self.slider_transparency.grid(row=0, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") - - ## optionmenu theme - self.label_appearance_theme = customtkinter.CTkLabel( - self.tabview_config.tab("UI"), - text="Appearance Theme:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_appearance_theme.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_appearance_theme = customtkinter.CTkOptionMenu( - self.tabview_config.tab("UI"), - values=["Light", "Dark", "System"], - command=self.optionmenu_theme_callback, - variable=customtkinter.StringVar(value=self.parent.APPEARANCE_THEME) - ) - self.optionmenu_appearance_theme.grid(row=1, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") - - ## optionmenu UI scaling - self.label_ui_scaling = customtkinter.CTkLabel( - self.tabview_config.tab("UI"), - text="UI Scaling:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_ui_scaling.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_ui_scaling = customtkinter.CTkOptionMenu( - self.tabview_config.tab("UI"), - values=["80%", "90%", "100%", "110%", "120%"], - command=self.optionmenu_ui_scaling_callback, - variable=customtkinter.StringVar(value=self.parent.UI_SCALING) - ) - self.optionmenu_ui_scaling.grid(row=2, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") - - ## optionmenu font family - self.label_font_family = customtkinter.CTkLabel( - self.tabview_config.tab("UI"), - text="Font Family:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_font_family.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - font_families = list(tk.font.families()) - self.optionmenu_font_family = customtkinter.CTkOptionMenu( - self.tabview_config.tab("UI"), - values=font_families, - command=self.optionmenu_font_family_callback, - variable=customtkinter.StringVar(value=self.parent.FONT_FAMILY) - ) - self.optionmenu_font_family.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") - - # tab Translation - ## optionmenu translation translator - self.label_translation_translator = customtkinter.CTkLabel( - self.tabview_config.tab("Translation"), - text="Select Translator:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_translation_translator.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_translation_translator = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Translation"), - values=list(self.parent.translator.translator_status.keys()), - command=self.optionmenu_translation_translator_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.CHOICE_TRANSLATOR) - ) - self.optionmenu_translation_translator.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - - ## optionmenu translation input language - self.label_translation_input_language = customtkinter.CTkLabel( - self.tabview_config.tab("Translation"), - text="Input Language:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_translation_input_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - - ## select translation input source language - self.optionmenu_translation_input_source_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Translation"), - command=self.optionmenu_translation_input_source_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.INPUT_SOURCE_LANG), - ) - self.optionmenu_translation_input_source_language.grid(row=1, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## label translation input arrow - self.label_translation_input_arrow = customtkinter.CTkLabel( - self.tabview_config.tab("Translation"), - text="-->", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_translation_input_arrow.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## select translation input target language - self.optionmenu_translation_input_target_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Translation"), - command=self.optionmenu_translation_input_target_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.INPUT_TARGET_LANG), - ) - self.optionmenu_translation_input_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## optionmenu translation output language - self.label_translation_output_language = customtkinter.CTkLabel( - self.tabview_config.tab("Translation"), - text="Output Language:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) - ) - self.label_translation_output_language.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - - ## select translation output source language - self.optionmenu_translation_output_source_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Translation"), - # command=self.optionmenu_translation_output_source_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.OUTPUT_SOURCE_LANG), - state="disabled", - ) - self.optionmenu_translation_output_source_language.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## label translation output arrow - self.label_translation_output_arrow = customtkinter.CTkLabel( - self.tabview_config.tab("Translation"), - text="-->", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_translation_output_arrow.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## select translation output target language - self.optionmenu_translation_output_target_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Translation"), - # command=self.optionmenu_translation_output_target_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], - variable=customtkinter.StringVar(value=self.parent.OUTPUT_TARGET_LANG), - state="disabled", - ) - self.optionmenu_translation_output_target_language.grid(row=2, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") - - # tab Transcription - ## optionmenu input mic device - self.label_input_mic_device = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Mic Device:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_input_mic_device.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_input_mic_device = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Transcription"), - values=list(self.parent.vr.input_device_dict.keys()), - command=self.optionmenu_input_mic_device_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) - ) - self.optionmenu_input_mic_device.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - - ## optionmenu input mic voice language - self.label_input_mic_voice_language = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Mic Voice Language:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_input_mic_voice_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_input_mic_voice_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Transcription"), - values=list(self.parent.vr.languages), - command=self.optionmenu_input_mic_voice_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.INPUT_MIC_VOICE_LANGUAGE) - ) - self.optionmenu_input_mic_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - - ## checkbox input mic in dynamic - self.label_input_mic_is_dynamic = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Mic IsDynamic:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_input_mic_is_dynamic.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.checkbox_input_mic_is_dynamic = customtkinter.CTkCheckBox( - self.tabview_config.tab("Transcription"), - text="", - onvalue=True, - offvalue=False, - command=self.checkbox_input_mic_is_dynamic_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.checkbox_input_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - if self.parent.ENABLE_MIC_IS_DYNAMIC is True: - self.checkbox_input_mic_is_dynamic.select() - else: - self.checkbox_input_mic_is_dynamic.deselect() - - ## slider input mic threshold - self.label_input_mic_threshold = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Mic Threshold:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_input_mic_threshold.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.slider_input_mic_threshold = customtkinter.CTkSlider( - self.tabview_config.tab("Transcription"), - from_=0, - to=300, - command=self.slider_input_mic_threshold_callback, - variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), - ) - self.slider_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") - - ## optionmenu input speaker device - self.label_input_speaker_device = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Speaker Device:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) - ) - self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Transcription"), - values=list(self.parent.vr.input_device_dict.keys()), - # command=self.optionmenu_input_speaker_device_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), - state="disabled" - ) - self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - - ## optionmenu input speaker voice language - self.label_input_speaker_voice_language = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Speaker Voice Language:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) - ) - self.label_input_speaker_voice_language.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.optionmenu_input_speaker_voice_language = customtkinter.CTkOptionMenu( - self.tabview_config.tab("Transcription"), - values=list(self.parent.vr.languages), - # command=self.optionmenu_input_speaker_voice_language_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - variable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_VOICE_LANGUAGE), - state="disabled" - ) - self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - - ## checkbox input speaker in dynamic - self.label_input_speaker_is_dynamic = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Speaker IsDynamic:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) - ) - self.label_input_speaker_is_dynamic.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.checkbox_input_speaker_is_dynamic = customtkinter.CTkCheckBox( - self.tabview_config.tab("Transcription"), - text="", - onvalue=True, - offvalue=False, - # command=self.checkbox_input_speaker_is_dynamic_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - state="disabled" - ) - self.checkbox_input_speaker_is_dynamic.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - if self.parent.ENABLE_SPEAKER_IS_DYNAMIC is True: - self.checkbox_input_speaker_is_dynamic.select() - else: - self.checkbox_input_speaker_is_dynamic.deselect() - - ## slider input speaker threshold - self.label_input_speaker_threshold = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Speaker Threshold:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) - ) - self.label_input_speaker_threshold.grid(row=7, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.slider_input_speaker_threshold = customtkinter.CTkSlider( - self.tabview_config.tab("Transcription"), - from_=0, - to=300, - # command=self.slider_input_speaker_threshold_callback, - variable=tk.DoubleVar(value=self.parent.SPEAKER_THRESHOLD), - state="disabled" - ) - self.slider_input_speaker_threshold.grid(row=7, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") - - # tab Parameter - ## entry ip address - self.label_ip_address = customtkinter.CTkLabel( - self.tabview_config.tab("Parameter"), - text="OSC IP address:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_ip_address.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.entry_ip_address = customtkinter.CTkEntry( - self.tabview_config.tab("Parameter"), - textvariable=customtkinter.StringVar(value=self.parent.OSC_IP_ADDRESS), - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.entry_ip_address.grid(row=0, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_ip_address = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_ip_address, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_ip_address.grid(row=0, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## entry port - self.label_port = customtkinter.CTkLabel( - self.tabview_config.tab("Parameter"), - text="OSC Port:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_port.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.entry_port = customtkinter.CTkEntry( - self.tabview_config.tab("Parameter"), - textvariable=customtkinter.StringVar(value=self.parent.OSC_PORT), - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.entry_port.grid(row=1, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_port = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_port, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_port.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## entry authkey - self.label_authkey = customtkinter.CTkLabel( - self.tabview_config.tab("Parameter"), - text="DeepL Auth Key:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_authkey.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.entry_authkey = customtkinter.CTkEntry( - self.tabview_config.tab("Parameter"), - textvariable=customtkinter.StringVar(value=self.parent.AUTH_KEYS["DeepL(auth)"]), - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.entry_authkey.grid(row=2, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_authkey = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_authkey, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_authkey.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - ## entry message format - self.label_message_format = customtkinter.CTkLabel( - self.tabview_config.tab("Parameter"), - text="Message Format:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_message_format.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.entry_message_format = customtkinter.CTkEntry( - self.tabview_config.tab("Parameter"), - textvariable=customtkinter.StringVar(value=self.parent.MESSAGE_FORMAT), - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.entry_message_format.grid(row=3, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_message_format = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_message_format, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_message_format.grid(row=3, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") - - def slider_transparency_callback(self, value): - self.parent.wm_attributes("-alpha", value/100) - self.parent.TRANSPARENCY = value - save_json(self.parent.PATH_CONFIG, "TRANSPARENCY", self.parent.TRANSPARENCY) - - def optionmenu_theme_callback(self, choice): - customtkinter.set_appearance_mode(choice) - self.parent.APPEARANCE_THEME = choice - save_json(self.parent.PATH_CONFIG, "APPEARANCE_THEME", self.parent.APPEARANCE_THEME) - - def optionmenu_ui_scaling_callback(self, choice): - new_scaling_float = int(choice.replace("%", "")) / 100 - customtkinter.set_widget_scaling(new_scaling_float) - self.parent.UI_SCALING = choice - save_json(self.parent.PATH_CONFIG, "UI_SCALING", self.parent.UI_SCALING) - - def optionmenu_font_family_callback(self, choice): - # tab menu - self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) - - # tab UI - self.label_transparency.configure(font=customtkinter.CTkFont(family=choice)) - self.label_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) - self.label_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) - self.label_font_family.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_font_family.configure(font=customtkinter.CTkFont(family=choice)) - - # tab Translation - self.label_translation_translator.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_translation_translator.configure(font=customtkinter.CTkFont(family=choice)) - self.label_translation_input_language.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_translation_input_source_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_translation_input_arrow.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_translation_input_target_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_translation_output_language.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_translation_output_source_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) - self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_translation_output_target_language.configure(font=customtkinter.CTkFont(family=choice)) - - # tab Transcription - self.label_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_mic_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_mic_threshold.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_threshold.configure(font=customtkinter.CTkFont(family=choice)) - - # tab Parameter - self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_ip_address.configure(font=customtkinter.CTkFont(family=choice)) - self.label_port.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_port.configure(font=customtkinter.CTkFont(family=choice)) - self.label_authkey.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_authkey.configure(font=customtkinter.CTkFont(family=choice)) - self.label_message_format.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_message_format.configure(font=customtkinter.CTkFont(family=choice)) - - # main window - self.parent.checkbox_translation.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.checkbox_transcription.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.tabview_logs._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) - - # window information - try: - self.parent.information_window.textbox_information.configure(font=customtkinter.CTkFont(family=choice)) - except: - pass - - self.parent.FONT_FAMILY = choice - save_json(self.parent.PATH_CONFIG, "FONT_FAMILY", self.parent.FONT_FAMILY) - - def optionmenu_translation_translator_callback(self, choice): - if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_log.configure(state='disabled') - self.parent.textbox_message_log.see("end") - else: - self.optionmenu_translation_input_source_language.configure( - values=self.parent.translator.languages[choice], - variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][0])) - self.optionmenu_translation_input_target_language.configure( - values=self.parent.translator.languages[choice], - variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) - - self.parent.CHOICE_TRANSLATOR = choice - self.parent.INPUT_SOURCE_LANG = self.parent.translator.languages[choice][0] - self.parent.INPUT_TARGET_LANG = self.parent.translator.languages[choice][1] - save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR) - save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) - save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) - - def optionmenu_translation_input_source_language_callback(self, choice): - self.parent.INPUT_SOURCE_LANG = choice - save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) - - def optionmenu_translation_input_target_language_callback(self, choice): - self.parent.INPUT_TARGET_LANG = choice - save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) - - def optionmenu_input_mic_device_callback(self, choice): - self.parent.CHOICE_MIC_DEVICE = choice - save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) - - def optionmenu_input_mic_voice_language_callback(self, choice): - self.parent.INPUT_MIC_VOICE_LANGUAGE = choice - save_json(self.parent.PATH_CONFIG, "INPUT_MIC_VOICE_LANGUAGE", self.parent.INPUT_MIC_VOICE_LANGUAGE) - - def checkbox_input_mic_is_dynamic_callback(self): - value = self.checkbox_input_mic_is_dynamic.get() - self.parent.ENABLE_MIC_IS_DYNAMIC = value - save_json(self.parent.PATH_CONFIG, "ENABLE_MIC_IS_DYNAMIC", self.parent.ENABLE_MIC_IS_DYNAMIC) - self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) - - def slider_input_mic_threshold_callback(self, value): - self.parent.MIC_THRESHOLD = value - save_json(self.parent.PATH_CONFIG, "MIC_THRESHOLD", self.parent.MIC_THRESHOLD) - self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) - - def update_ip_address(self): - value = self.entry_ip_address.get() - if len(value) > 0: - self.parent.OSC_IP_ADDRESS = value - save_json(self.parent.PATH_CONFIG, "OSC_IP_ADDRESS", self.parent.OSC_IP_ADDRESS) - - def update_port(self): - value = self.entry_port.get() - if len(value) > 0: - self.parent.OSC_PORT = value - save_json(self.parent.PATH_CONFIG, "OSC_PORT", self.parent.OSC_PORT) - - def update_authkey(self): - value = self.entry_authkey.get() - if len(value) > 0: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.delete("0.0", "end") - self.parent.textbox_message_log.configure(state='disabled') - self.parent.textbox_message_log.see("end") - - if self.parent.translator.authentication(self.parent.CHOICE_TRANSLATOR, self.parent.AUTH_KEYS[self.parent.CHOICE_TRANSLATOR]) is True: - self.parent.AUTH_KEYS["DeepL(auth)"] = value - save_json(self.parent.PATH_CONFIG, "AUTH_KEYS", self.parent.AUTH_KEYS) - else: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_log.configure(state='disabled') - self.parent.textbox_message_log.see("end") - - def update_message_format(self): - value = self.entry_message_format.get() - if len(value) > 0: - self.parent.MESSAGE_FORMAT = value - save_json(self.parent.PATH_CONFIG, "MESSAGE_FORMAT", self.parent.MESSAGE_FORMAT) +import utils +import translation +import transcription +import osc_tools +import window_config +import window_information class App(customtkinter.CTk): def __init__(self, *args, **kwargs): @@ -1086,7 +249,7 @@ class App(customtkinter.CTk): # set default values ## set translator instance - self.translator = Translator() + self.translator = translation.Translator() if self.translator.authentication(self.CHOICE_TRANSLATOR, self.AUTH_KEYS[self.CHOICE_TRANSLATOR]) is False: # error update Auth key self.textbox_message_log.configure(state='normal') @@ -1095,7 +258,7 @@ class App(customtkinter.CTk): self.textbox_message_log.see("end") ## set transcription instance - self.vr = VoiceRecognizer() + self.vr = transcription.VoiceRecognizer() self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else list(self.vr.input_device_dict.keys())[0] ## set checkbox enable translation @@ -1137,12 +300,12 @@ class App(customtkinter.CTk): def button_config_callback(self): if self.config_window is None or not self.config_window.winfo_exists(): - self.config_window = ToplevelWindowConfig(self) + self.config_window = window_config.ToplevelWindowConfig(self) self.config_window.focus() def button_information_callback(self): if self.information_window is None or not self.information_window.winfo_exists(): - self.information_window = ToplevelWindowInformation(self) + self.information_window = window_information.ToplevelWindowInformation(self) self.information_window.focus() def checkbox_translation_callback(self): @@ -1154,7 +317,7 @@ class App(customtkinter.CTk): self.textbox_message_log.insert("end", f"[INFO] stop translation\n") self.textbox_message_log.configure(state='disabled') self.textbox_message_log.see("end") - save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) + utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) def checkbox_transcription_callback(self): self.ENABLE_TRANSCRIPTION = self.checkbox_transcription.get() @@ -1162,7 +325,7 @@ class App(customtkinter.CTk): # start threading th = threading.Thread(target = self.voice_input) th.start() - save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) + utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) def voice_input(self): self.vr.set_mic(self.CHOICE_MIC_DEVICE) @@ -1197,13 +360,7 @@ class App(customtkinter.CTk): chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - message = osc_message_builder.OscMessageBuilder(address="/chatbox/input") - message.add_arg(f"{chat_message}") - message.add_arg(True) - message.add_arg(True) - message = message.build() - client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) - client.send(message) + osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log self.textbox_message_log.configure(state='normal') @@ -1221,15 +378,11 @@ class App(customtkinter.CTk): self.attributes("-topmost", True) else: self.attributes("-topmost", False) - save_json(self.PATH_CONFIG, "ENABLE_FOREGROUND", self.ENABLE_FOREGROUND) + utils.save_json(self.PATH_CONFIG, "ENABLE_FOREGROUND", self.ENABLE_FOREGROUND) def entry_message_box_press_key_enter(self, event): # send OSC typing - typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") - typing.add_arg(False) - typing = typing.build() - client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) - client.send(typing) + osc_tools.send_typing(False, self.OSC_IP_ADDRESS, self.OSC_PORT) if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) @@ -1255,13 +408,7 @@ class App(customtkinter.CTk): chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - message = osc_message_builder.OscMessageBuilder(address="/chatbox/input") - message.add_arg(f"{chat_message}") - message.add_arg(True) - message.add_arg(True) - message = message.build() - client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) - client.send(message) + osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log self.textbox_message_log.configure(state='normal') @@ -1274,21 +421,13 @@ class App(customtkinter.CTk): def entry_message_box_press_key_any(self, event): # send OSC typing - typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") - typing.add_arg(True) - typing = typing.build() - client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) - client.send(typing) + osc_tools.send_typing(True, self.OSC_IP_ADDRESS, self.OSC_PORT) if self.ENABLE_FOREGROUND: self.attributes("-topmost", False) def entry_message_box_leave(self, event): # send OSC typing - typing = osc_message_builder.OscMessageBuilder(address="/chatbox/typing") - typing.add_arg(False) - typing = typing.build() - client = udp_client.SimpleUDPClient(self.OSC_IP_ADDRESS, self.OSC_PORT) - client.send(typing) + osc_tools.send_typing(False, self.OSC_IP_ADDRESS, self.OSC_PORT) if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) diff --git a/osc_tools.py b/osc_tools.py new file mode 100644 index 00000000..dacda522 --- /dev/null +++ b/osc_tools.py @@ -0,0 +1,21 @@ +from pythonosc import osc_message_builder +from pythonosc import udp_client + +# send OSC message typing +def send_typing(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() + client = udp_client.SimpleUDPClient(ip_address, port) + client.send(b_typing) + +# send OSC message +def send_message(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}") + msg.add_arg(True) + msg.add_arg(True) + b_msg = msg.build() + client = udp_client.SimpleUDPClient(ip_address, port) + client.send(b_msg) \ No newline at end of file diff --git a/transcription.py b/transcription.py new file mode 100644 index 00000000..7b0eee17 --- /dev/null +++ b/transcription.py @@ -0,0 +1,70 @@ +import pyaudio +import speech_recognition as sr + +# VoiceRecognizer +class VoiceRecognizer(): + def __init__(self): + self.input_device_dict = self.search_input_device() + self.r = sr.Recognizer() + self.mic = None + self.languages = [ + "ja-JP","en-US","en-GB","af-ZA","ar-DZ","ar-BH","ar-EG","ar-IL","ar-IQ","ar-JO","ar-KW","ar-LB","ar-MA", + "ar-OM","ar-PS","ar-QA","ar-SA","ar-TN","ar-AE","eu-ES","bg-BG","ca-ES","cmn-Hans-CN","cmn-Hans-HK", + "cmn-Hant-TW","yue-Hant-HK","hr_HR","cs-CZ","da-DK","en-AU","en-CA","en-IN","en-IE","en-NZ","en-PH", + "en-ZA","fa-IR","fr-FR","fil-PH","gl-ES","de-DE","el-GR","fi-FI","he-IL","hi-IN","hu-HU","id-ID","is-IS", + "it-IT","it-CH","ko-KR","lt-LT","ms-MY","nl-NL","nb-NO","pl-PL","pt-BR","pt-PT","ro-RO","ru-RU","sr-RS", + "sk-SK","sl-SI","es-AR","es-BO","es-CL","es-CO","es-CR","es-DO","es-EC","es-SV","es-GT","es-HN","es-MX", + "es-NI","es-PA","es-PY","es-PE","es-PR","es-ES","es-UY","es-US","es-VE","sv-SE","th-TH","tr-TR","uk-UA", + "vi-VN","zu-ZA" + ] + + def search_input_device(self): + pa = pyaudio.PyAudio() + input_device_dict = {} + + mic_cnt = 1 + for i in range(pa.get_device_count()): + device = pa.get_device_info_by_index(i) + try: + device["name"] = device["name"].encode('shift_jis').decode('utf-8') + except: + device["name"] = device["name"].encode('utf-8').decode('utf-8') + if device["maxInputChannels"] > 0: + input_device_dict[f'No.{mic_cnt}:{device["name"]}'] = device["index"] + mic_cnt += 1 + pa.terminate() + return input_device_dict + + def set_mic(self, device_name, threshold=50, is_dynamic=False): + if device_name in [v for v in self.input_device_dict.keys()]: + index = self.input_device_dict[device_name] + self.mic = sr.Microphone(device_index=index) + self.r.energy_threshold = threshold + if is_dynamic: + with self.mic as source: + self.r.adjust_for_ambient_noise(source, 3.0) + return True + else: + return False + + def init_mic(self, threshold=50, is_dynamic=False): + if isinstance(self.mic, sr.Microphone): + self.r.energy_threshold = threshold + if is_dynamic: + with self.mic as source: + self.r.adjust_for_ambient_noise(source, 3.0) + return True + else: + return False + + def listen_voice(self, language): + if self.mic != None: + with self.mic as source: + audio = self.r.listen(source) + try: + text = self.r.recognize_google(audio, language=language) + return text + except: + return "" + else: + return False \ No newline at end of file diff --git a/translation.py b/translation.py new file mode 100644 index 00000000..cbb96f4f --- /dev/null +++ b/translation.py @@ -0,0 +1,74 @@ +import deepl +import deepl_translate +import translators as ts + +# Translator +class Translator(): + def __init__(self): + self.translator_status = { + "DeepL(web)": False, + "DeepL(auth)": False, + "Google(web)": False, + "Bing(web)": False, + } + self.languages = {} + self.languages["DeepL(web)"] = [ + "JA","EN","BG","ZH","CS","DA","NL","ET","FI","FR","DE","EL","HU","IT", + "LV","LT","PL","PT","RO","RU","SK","SL","ES","SV", + ] + self.languages["DeepL(auth)"] = [ + "JA","EN-US","EN-GB","BG","CS","DA","DE","EL","ES","ET","FI","FR","HU", + "ID","IT","KO","LT","LV","NB","NL","PL","PT","PT-BR","PT-PT","RO","RU", + "SK","SL","SV","TR","UK","ZH", + ] + self.languages["Google(web)"] = [ + "ja","en","zh","ar","ru","fr","de","es","pt","it","ko","el","nl","hi", + "tr","ms","th","vi","id","he","pl","mn","cs","hu","et","bg","da","fi", + "ro","sv","sl","fa","bs","sr","tl","ht","ca","hr","lv","lt","ur","uk", + "cy","sw","sm","sk","af","no","bn","mg","mt","gu","ta","te","pa","am", + "az","be","ceb","eo","eu","ga" + ] + self.languages["Bing(web)"] = [ + "ja","en","zh","ar","ru","fr","de","es","pt","it","ko","el","nl","hi", + "tr","ms","th","vi","id","he","pl","cs","hu","et","bg","da","fi","ro", + "sv","sl","fa","bs","sr","fj","tl","ht","ca","hr","lv","lt","ur","uk", + "cy","ty","to","sw","sm","sk","af","no","bn","mg","mt","otq","tlh","gu", + "ta","te","pa","ga" + ] + self.deepl_client = None + + def authentication(self, translator_name, authkey=None): + result = False + try: + if translator_name == "DeepL(web)": + self.translator_status["DeepL(web)"] = True + result = True + elif translator_name == "DeepL(auth)": + self.deepl_client = deepl.Translator(authkey) + self.deepl_client.translate_text(" ", target_lang="EN-US") + self.translator_status["DeepL(auth)"] = True + result = True + elif translator_name == "Google(web)": + self.translator_status["Google(web)"] = True + result = True + elif translator_name == "Bing(web)": + self.translator_status["Bing(web)"] = True + result = True + except: + pass + return result + + def translate(self, translator_name, source_language, target_language, message): + result = False + try: + if translator_name == "DeepL(web)": + result = deepl_translate.translate(source_language=source_language, target_language=target_language, text=message) + elif translator_name == "DeepL(auth)": + result = self.deepl_client.translate_text(message, source_lang=source_language, target_lang=target_language).text + elif translator_name == "Google(web)": + result = ts.translate_text(query_text=message, translator="google", from_language=source_language, to_language=target_language) + elif translator_name == "Bing(web)": + result = ts.translate_text(query_text=message, translator="bing", from_language=source_language, to_language=target_language) + except: + pass + return result \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 00000000..f1937616 --- /dev/null +++ b/utils.py @@ -0,0 +1,8 @@ +import json + +def save_json(path, key, value): + with open(path, "r") as fp: + json_data = json.load(fp) + json_data[key] = value + with open(path, "w") as fp: + json.dump(json_data, fp, indent=4) \ No newline at end of file diff --git a/window_config.py b/window_config.py new file mode 100644 index 00000000..e95b01b4 --- /dev/null +++ b/window_config.py @@ -0,0 +1,604 @@ +import os +import tkinter as tk +import customtkinter +from PIL import Image +import utils + +class ToplevelWindowConfig(customtkinter.CTkToplevel): + def __init__(self, parent, *args, **kwargs): + super().__init__(parent, *args, **kwargs) + self.parent = parent + # self.geometry(f"{350}x{270}") + # self.resizable(False, False) + self.grid_columnconfigure(0, weight=1) + self.grid_rowconfigure(0, weight=1) + + self.after(200, lambda: self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico"))) + self.title("Config") + + # tabwiew config + self.tabview_config = customtkinter.CTkTabview(self) + self.tabview_config.grid(row=0, column=0, padx=5, pady=5, sticky="nsew") + self.tabview_config.add("UI") + self.tabview_config.add("Translation") + self.tabview_config.add("Transcription") + self.tabview_config.add("Parameter") + self.tabview_config.tab("UI").grid_columnconfigure(1, weight=1) + self.tabview_config.tab("Translation").grid_columnconfigure([1,2,3], weight=1) + self.tabview_config.tab("Transcription").grid_columnconfigure(1, weight=1) + self.tabview_config.tab("Parameter").grid_columnconfigure(1, weight=1) + self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY)) + self.tabview_config._segmented_button.grid(sticky="W") + + # tab UI + ## slider transparency + self.label_transparency = customtkinter.CTkLabel( + self.tabview_config.tab("UI"), + text="Transparency:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_transparency.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.slider_transparency = customtkinter.CTkSlider( + self.tabview_config.tab("UI"), + from_=50, + to=100, + command=self.slider_transparency_callback, + variable=tk.DoubleVar(value=self.parent.TRANSPARENCY), + ) + self.slider_transparency.grid(row=0, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") + + ## optionmenu theme + self.label_appearance_theme = customtkinter.CTkLabel( + self.tabview_config.tab("UI"), + text="Appearance Theme:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_appearance_theme.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_appearance_theme = customtkinter.CTkOptionMenu( + self.tabview_config.tab("UI"), + values=["Light", "Dark", "System"], + command=self.optionmenu_theme_callback, + variable=customtkinter.StringVar(value=self.parent.APPEARANCE_THEME) + ) + self.optionmenu_appearance_theme.grid(row=1, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + + ## optionmenu UI scaling + self.label_ui_scaling = customtkinter.CTkLabel( + self.tabview_config.tab("UI"), + text="UI Scaling:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_ui_scaling.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_ui_scaling = customtkinter.CTkOptionMenu( + self.tabview_config.tab("UI"), + values=["80%", "90%", "100%", "110%", "120%"], + command=self.optionmenu_ui_scaling_callback, + variable=customtkinter.StringVar(value=self.parent.UI_SCALING) + ) + self.optionmenu_ui_scaling.grid(row=2, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + + ## optionmenu font family + self.label_font_family = customtkinter.CTkLabel( + self.tabview_config.tab("UI"), + text="Font Family:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_font_family.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + font_families = list(tk.font.families()) + self.optionmenu_font_family = customtkinter.CTkOptionMenu( + self.tabview_config.tab("UI"), + values=font_families, + command=self.optionmenu_font_family_callback, + variable=customtkinter.StringVar(value=self.parent.FONT_FAMILY) + ) + self.optionmenu_font_family.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + + # tab Translation + ## optionmenu translation translator + self.label_translation_translator = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="Select Translator:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_translator.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_translation_translator = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + values=list(self.parent.translator.translator_status.keys()), + command=self.optionmenu_translation_translator_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_TRANSLATOR) + ) + self.optionmenu_translation_translator.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## optionmenu translation input language + self.label_translation_input_language = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="Input Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_input_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + + ## select translation input source language + self.optionmenu_translation_input_source_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + command=self.optionmenu_translation_input_source_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.INPUT_SOURCE_LANG), + ) + self.optionmenu_translation_input_source_language.grid(row=1, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## label translation input arrow + self.label_translation_input_arrow = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="-->", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_input_arrow.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## select translation input target language + self.optionmenu_translation_input_target_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + command=self.optionmenu_translation_input_target_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.INPUT_TARGET_LANG), + ) + self.optionmenu_translation_input_target_language.grid(row=1, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## optionmenu translation output language + self.label_translation_output_language = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="Output Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_translation_output_language.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + + ## select translation output source language + self.optionmenu_translation_output_source_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + # command=self.optionmenu_translation_output_source_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.OUTPUT_SOURCE_LANG), + state="disabled", + ) + self.optionmenu_translation_output_source_language.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## label translation output arrow + self.label_translation_output_arrow = customtkinter.CTkLabel( + self.tabview_config.tab("Translation"), + text="-->", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_translation_output_arrow.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## select translation output target language + self.optionmenu_translation_output_target_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Translation"), + # command=self.optionmenu_translation_output_target_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], + variable=customtkinter.StringVar(value=self.parent.OUTPUT_TARGET_LANG), + state="disabled", + ) + self.optionmenu_translation_output_target_language.grid(row=2, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") + + # tab Transcription + ## optionmenu input mic device + self.label_input_mic_device = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Mic Device:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_mic_device.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_mic_device = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.input_device_dict.keys()), + command=self.optionmenu_input_mic_device_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) + ) + self.optionmenu_input_mic_device.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## optionmenu input mic voice language + self.label_input_mic_voice_language = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Mic Voice Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_mic_voice_language.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_mic_voice_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.languages), + command=self.optionmenu_input_mic_voice_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.INPUT_MIC_VOICE_LANGUAGE) + ) + self.optionmenu_input_mic_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## checkbox input mic in dynamic + self.label_input_mic_is_dynamic = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Mic IsDynamic:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_mic_is_dynamic.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.checkbox_input_mic_is_dynamic = customtkinter.CTkCheckBox( + self.tabview_config.tab("Transcription"), + text="", + onvalue=True, + offvalue=False, + command=self.checkbox_input_mic_is_dynamic_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.checkbox_input_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + if self.parent.ENABLE_MIC_IS_DYNAMIC is True: + self.checkbox_input_mic_is_dynamic.select() + else: + self.checkbox_input_mic_is_dynamic.deselect() + + ## slider input mic threshold + self.label_input_mic_threshold = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Mic Threshold:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_mic_threshold.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.slider_input_mic_threshold = customtkinter.CTkSlider( + self.tabview_config.tab("Transcription"), + from_=0, + to=300, + command=self.slider_input_mic_threshold_callback, + variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), + ) + self.slider_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + + ## optionmenu input speaker device + self.label_input_speaker_device = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker Device:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.input_device_dict.keys()), + # command=self.optionmenu_input_speaker_device_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), + state="disabled" + ) + self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## optionmenu input speaker voice language + self.label_input_speaker_voice_language = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker Voice Language:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_voice_language.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.optionmenu_input_speaker_voice_language = customtkinter.CTkOptionMenu( + self.tabview_config.tab("Transcription"), + values=list(self.parent.vr.languages), + # command=self.optionmenu_input_speaker_voice_language_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + variable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_VOICE_LANGUAGE), + state="disabled" + ) + self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + + ## checkbox input speaker in dynamic + self.label_input_speaker_is_dynamic = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker IsDynamic:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_is_dynamic.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.checkbox_input_speaker_is_dynamic = customtkinter.CTkCheckBox( + self.tabview_config.tab("Transcription"), + text="", + onvalue=True, + offvalue=False, + # command=self.checkbox_input_speaker_is_dynamic_callback, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), + state="disabled" + ) + self.checkbox_input_speaker_is_dynamic.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + if self.parent.ENABLE_SPEAKER_IS_DYNAMIC is True: + self.checkbox_input_speaker_is_dynamic.select() + else: + self.checkbox_input_speaker_is_dynamic.deselect() + + ## slider input speaker threshold + self.label_input_speaker_threshold = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker Threshold:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + ) + self.label_input_speaker_threshold.grid(row=7, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.slider_input_speaker_threshold = customtkinter.CTkSlider( + self.tabview_config.tab("Transcription"), + from_=0, + to=300, + # command=self.slider_input_speaker_threshold_callback, + variable=tk.DoubleVar(value=self.parent.SPEAKER_THRESHOLD), + state="disabled" + ) + self.slider_input_speaker_threshold.grid(row=7, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + + # tab Parameter + ## entry ip address + self.label_ip_address = customtkinter.CTkLabel( + self.tabview_config.tab("Parameter"), + text="OSC IP address:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_ip_address.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_ip_address = customtkinter.CTkEntry( + self.tabview_config.tab("Parameter"), + textvariable=customtkinter.StringVar(value=self.parent.OSC_IP_ADDRESS), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.entry_ip_address.grid(row=0, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") + self.button_ip_address = customtkinter.CTkButton( + self.tabview_config.tab("Parameter"), + text="", + width=1, + command=self.update_ip_address, + image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) + ) + self.button_ip_address.grid(row=0, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## entry port + self.label_port = customtkinter.CTkLabel( + self.tabview_config.tab("Parameter"), + text="OSC Port:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_port.grid(row=1, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_port = customtkinter.CTkEntry( + self.tabview_config.tab("Parameter"), + textvariable=customtkinter.StringVar(value=self.parent.OSC_PORT), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.entry_port.grid(row=1, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") + self.button_port = customtkinter.CTkButton( + self.tabview_config.tab("Parameter"), + text="", + width=1, + command=self.update_port, + image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) + ) + self.button_port.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## entry authkey + self.label_authkey = customtkinter.CTkLabel( + self.tabview_config.tab("Parameter"), + text="DeepL Auth Key:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_authkey.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_authkey = customtkinter.CTkEntry( + self.tabview_config.tab("Parameter"), + textvariable=customtkinter.StringVar(value=self.parent.AUTH_KEYS["DeepL(auth)"]), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.entry_authkey.grid(row=2, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") + self.button_authkey = customtkinter.CTkButton( + self.tabview_config.tab("Parameter"), + text="", + width=1, + command=self.update_authkey, + image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) + ) + self.button_authkey.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + ## entry message format + self.label_message_format = customtkinter.CTkLabel( + self.tabview_config.tab("Parameter"), + text="Message Format:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_message_format.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_message_format = customtkinter.CTkEntry( + self.tabview_config.tab("Parameter"), + textvariable=customtkinter.StringVar(value=self.parent.MESSAGE_FORMAT), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.entry_message_format.grid(row=3, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") + self.button_message_format = customtkinter.CTkButton( + self.tabview_config.tab("Parameter"), + text="", + width=1, + command=self.update_message_format, + image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) + ) + self.button_message_format.grid(row=3, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + + def slider_transparency_callback(self, value): + self.parent.wm_attributes("-alpha", value/100) + self.parent.TRANSPARENCY = value + utils.save_json(self.parent.PATH_CONFIG, "TRANSPARENCY", self.parent.TRANSPARENCY) + + def optionmenu_theme_callback(self, choice): + customtkinter.set_appearance_mode(choice) + self.parent.APPEARANCE_THEME = choice + utils.save_json(self.parent.PATH_CONFIG, "APPEARANCE_THEME", self.parent.APPEARANCE_THEME) + + def optionmenu_ui_scaling_callback(self, choice): + new_scaling_float = int(choice.replace("%", "")) / 100 + customtkinter.set_widget_scaling(new_scaling_float) + self.parent.UI_SCALING = choice + utils.save_json(self.parent.PATH_CONFIG, "UI_SCALING", self.parent.UI_SCALING) + + def optionmenu_font_family_callback(self, choice): + # tab menu + self.tabview_config._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) + + # tab UI + self.label_transparency.configure(font=customtkinter.CTkFont(family=choice)) + self.label_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_appearance_theme.configure(font=customtkinter.CTkFont(family=choice)) + self.label_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_ui_scaling.configure(font=customtkinter.CTkFont(family=choice)) + self.label_font_family.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_font_family.configure(font=customtkinter.CTkFont(family=choice)) + + # tab Translation + self.label_translation_translator.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_translator.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_input_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_input_source_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_input_arrow.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_input_target_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_output_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_output_source_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) + self.label_translation_output_arrow.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_translation_output_target_language.configure(font=customtkinter.CTkFont(family=choice)) + + # tab Transcription + self.label_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_mic_device.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_mic_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_mic_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_mic_threshold.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_threshold.configure(font=customtkinter.CTkFont(family=choice)) + + # tab Parameter + self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_ip_address.configure(font=customtkinter.CTkFont(family=choice)) + self.label_port.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_port.configure(font=customtkinter.CTkFont(family=choice)) + self.label_authkey.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_authkey.configure(font=customtkinter.CTkFont(family=choice)) + self.label_message_format.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_message_format.configure(font=customtkinter.CTkFont(family=choice)) + + # main window + self.parent.checkbox_translation.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.checkbox_transcription.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.tabview_logs._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) + + # window information + try: + self.parent.information_window.textbox_information.configure(font=customtkinter.CTkFont(family=choice)) + except: + pass + + self.parent.FONT_FAMILY = choice + utils.save_json(self.parent.PATH_CONFIG, "FONT_FAMILY", self.parent.FONT_FAMILY) + + def optionmenu_translation_translator_callback(self, choice): + if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: + self.parent.textbox_message_log.configure(state='normal') + self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_log.configure(state='disabled') + self.parent.textbox_message_log.see("end") + else: + self.optionmenu_translation_input_source_language.configure( + values=self.parent.translator.languages[choice], + variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][0])) + self.optionmenu_translation_input_target_language.configure( + values=self.parent.translator.languages[choice], + variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) + + self.parent.CHOICE_TRANSLATOR = choice + self.parent.INPUT_SOURCE_LANG = self.parent.translator.languages[choice][0] + self.parent.INPUT_TARGET_LANG = self.parent.translator.languages[choice][1] + utils.save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR) + utils.save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) + utils.save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) + + def optionmenu_translation_input_source_language_callback(self, choice): + self.parent.INPUT_SOURCE_LANG = choice + utils.save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) + + def optionmenu_translation_input_target_language_callback(self, choice): + self.parent.INPUT_TARGET_LANG = choice + utils.save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) + + def optionmenu_input_mic_device_callback(self, choice): + self.parent.CHOICE_MIC_DEVICE = choice + utils.save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) + + def optionmenu_input_mic_voice_language_callback(self, choice): + self.parent.INPUT_MIC_VOICE_LANGUAGE = choice + utils.save_json(self.parent.PATH_CONFIG, "INPUT_MIC_VOICE_LANGUAGE", self.parent.INPUT_MIC_VOICE_LANGUAGE) + + def checkbox_input_mic_is_dynamic_callback(self): + value = self.checkbox_input_mic_is_dynamic.get() + self.parent.ENABLE_MIC_IS_DYNAMIC = value + utils.save_json(self.parent.PATH_CONFIG, "ENABLE_MIC_IS_DYNAMIC", self.parent.ENABLE_MIC_IS_DYNAMIC) + self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + + def slider_input_mic_threshold_callback(self, value): + self.parent.MIC_THRESHOLD = value + utils.save_json(self.parent.PATH_CONFIG, "MIC_THRESHOLD", self.parent.MIC_THRESHOLD) + self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + + def update_ip_address(self): + value = self.entry_ip_address.get() + if len(value) > 0: + self.parent.OSC_IP_ADDRESS = value + utils.save_json(self.parent.PATH_CONFIG, "OSC_IP_ADDRESS", self.parent.OSC_IP_ADDRESS) + + def update_port(self): + value = self.entry_port.get() + if len(value) > 0: + self.parent.OSC_PORT = value + utils.save_json(self.parent.PATH_CONFIG, "OSC_PORT", self.parent.OSC_PORT) + + def update_authkey(self): + value = self.entry_authkey.get() + if len(value) > 0: + self.parent.textbox_message_log.configure(state='normal') + self.parent.textbox_message_log.delete("0.0", "end") + self.parent.textbox_message_log.configure(state='disabled') + self.parent.textbox_message_log.see("end") + + if self.parent.translator.authentication(self.parent.CHOICE_TRANSLATOR, self.parent.AUTH_KEYS[self.parent.CHOICE_TRANSLATOR]) is True: + self.parent.AUTH_KEYS["DeepL(auth)"] = value + utils.save_json(self.parent.PATH_CONFIG, "AUTH_KEYS", self.parent.AUTH_KEYS) + else: + self.parent.textbox_message_log.configure(state='normal') + self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_log.configure(state='disabled') + self.parent.textbox_message_log.see("end") + + def update_message_format(self): + value = self.entry_message_format.get() + if len(value) > 0: + self.parent.MESSAGE_FORMAT = value + utils.save_json(self.parent.PATH_CONFIG, "MESSAGE_FORMAT", self.parent.MESSAGE_FORMAT) \ No newline at end of file diff --git a/window_information.py b/window_information.py new file mode 100644 index 00000000..48e55ed4 --- /dev/null +++ b/window_information.py @@ -0,0 +1,93 @@ +import os +import customtkinter + +class ToplevelWindowInformation(customtkinter.CTkToplevel): + def __init__(self, parent, *args, **kwargs): + super().__init__(parent, *args, **kwargs) + self.parent = parent + self.grid_columnconfigure(0, weight=1) + self.grid_rowconfigure(0, weight=1) + # self.geometry(f"{500}x{300}") + self.minsize(500, 300) + + self.after(200, lambda: self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico"))) + self.title("Information") + # create textbox information + self.textbox_information = customtkinter.CTkTextbox( + self, + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.textbox_information.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="nsew") + textbox_information_message = """VRCT(v0.4b) + +# 概要 +VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツールになります。 +翻訳エンジンを使用してメッセージとその翻訳部分を同時に送信することができます。 +(翻訳エンジンはDeepL,Google,Bingに対応) + +# 使用方法 + 初期設定時 + 0. VRChatのOSCを有効にする(重要) + + (任意) + 1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する + 2. ギアアイコンのボタンでconfigウィンドウを開く + 3. ParameterタブのDeepL Auth Keyに認証キーを記載し、フロッピーアイコンのボタンを押す + 4. configウィンドウを閉じる + + 通常使用時 + 1. メッセージボックスにメッセージを記入 + 2. Enterキーを押し、メッセージを送信する + +# その他の設定 + translation チェックボックス: 翻訳の有効無効 + foreground チェックボックス: 最前面表示の有効無効 + + configウィンドウ + UIタブ + Select translator: 翻訳エンジンの変更 + Select Language: 翻訳する言語[source, target]を選択 + Transparency: ウィンドウの透過度の調整 + Appearance Theme: ウィンドウテーマを選択 + UI Scaling: UIサイズを調整 + Font Family: 表示フォントを選択 + Parameterタブ + OSC IP address: 変更不要 + OSC port: 変更不要 + DeepL Auth key: DeepLの認証キーの設定 + Message Format: 送信するメッセージのデコレーションの設定 + [message]がメッセージボックスに記入したメッセージに置換される + [translation]が翻訳されたメッセージに置換される + 初期フォーマット:"[message]([translation])" + + 設定の初期化 + config.jsonを削除 + +# お問い合わせ +要望などはTwitterまで +https://twitter.com/misya_ai + +# アップデート履歴 +[2023-05-29: v0.1b] v0.1b リリース +[2023-05-30: v0.2b] +- configボタンをギアアイコンに変更 +- 詳細情報のボタンを追加 +- 翻訳機能有効無効のチェックボックスを追加 +- 最前面表示の有効無効のチェックボックスを追加 +- いくつかのバグを修正 +[2023-06-03: v0.3b] +- 全体的にUIを刷新 +- 透過機能を追加 +- テーマのLight/Dark/Systemのモードの変更機能を追加 +- UIのスケール変更機能を追加 +- フォントの変更機能を追加 +[2023-06-06: v0.4b] +- 翻訳エンジンを追加 +- 入力と出力の翻訳言語を選択できるように変更 + +# 注意事項 +再配布とかはやめてね +""" + + self.textbox_information.insert("end", textbox_information_message) + self.textbox_information.configure(state='disabled') \ No newline at end of file From 073603ed91f84a1231807b91a53776e94e79b6b3 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 13 Jun 2023 06:25:41 +0900 Subject: [PATCH 16/35] pyaudio -> sounddevice --- VRCT.py | 3 ++- transcription.py | 47 +++++++++++++++++++++++++++++------------------ window_config.py | 4 ++-- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/VRCT.py b/VRCT.py index 5e74690b..2fbe8467 100644 --- a/VRCT.py +++ b/VRCT.py @@ -259,7 +259,8 @@ class App(customtkinter.CTk): ## set transcription instance self.vr = transcription.VoiceRecognizer() - self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else list(self.vr.input_device_dict.keys())[0] + self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else self.vr.search_default_device_index()[0]["name"] + self.CHOICE_SPEAKER_DEVICE = self.CHOICE_SPEAKER_DEVICE if self.CHOICE_SPEAKER_DEVICE is not None else self.vr.search_default_device_index()[1]["name"] ## set checkbox enable translation if self.ENABLE_TRANSLATION: diff --git a/transcription.py b/transcription.py index 7b0eee17..ceddfb5c 100644 --- a/transcription.py +++ b/transcription.py @@ -1,10 +1,9 @@ -import pyaudio +import sounddevice as sd import speech_recognition as sr # VoiceRecognizer class VoiceRecognizer(): def __init__(self): - self.input_device_dict = self.search_input_device() self.r = sr.Recognizer() self.mic = None self.languages = [ @@ -19,25 +18,37 @@ class VoiceRecognizer(): ] def search_input_device(self): - pa = pyaudio.PyAudio() - input_device_dict = {} + device_list = sd.query_devices() + input_device_list = [] - mic_cnt = 1 - for i in range(pa.get_device_count()): - device = pa.get_device_info_by_index(i) - try: - device["name"] = device["name"].encode('shift_jis').decode('utf-8') - except: - device["name"] = device["name"].encode('utf-8').decode('utf-8') - if device["maxInputChannels"] > 0: - input_device_dict[f'No.{mic_cnt}:{device["name"]}'] = device["index"] - mic_cnt += 1 - pa.terminate() - return input_device_dict + for device in device_list: + if device["max_input_channels"] > 0: + input_device_list.append({"name": device["name"], "index": device["index"]}) + + return input_device_list + + def search_output_device(self): + device_list = sd.query_devices() + output_device_list = [] + + for device in device_list: + if device["max_output_channels"] > 0: + output_device_list.append({"name": device["name"], "index": device["index"]}) + + return output_device_list + + def search_default_device_index(self): + device_list = sd.query_devices() + default_device_list = [] + for i in sd.default.device: + default_device_list.append({"name": device_list[i]["name"], "index": device_list[i]["index"]}) + return default_device_list def set_mic(self, device_name, threshold=50, is_dynamic=False): - if device_name in [v for v in self.input_device_dict.keys()]: - index = self.input_device_dict[device_name] + input_device_list = self.search_input_device() + if device_name in [input_device["name"] for input_device in input_device_list]: + index = [device["index"] for device in input_device_list if device["name"] == device_name][0] + self.mic = sr.Microphone(device_index=index) self.r.energy_threshold = threshold if is_dynamic: diff --git a/window_config.py b/window_config.py index e95b01b4..a5ef6daf 100644 --- a/window_config.py +++ b/window_config.py @@ -204,7 +204,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.label_input_mic_device.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_input_mic_device = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), - values=list(self.parent.vr.input_device_dict.keys()), + values=[device["name"] for device in self.parent.vr.search_input_device()], command=self.optionmenu_input_mic_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) @@ -277,7 +277,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), - values=list(self.parent.vr.input_device_dict.keys()), + values=[device["name"] for device in self.parent.vr.search_output_device()], # command=self.optionmenu_input_speaker_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), From 61f769ef0651777e9c5f48f3d8c23199f35f93ff Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 13 Jun 2023 13:51:31 +0900 Subject: [PATCH 17/35] update transcription mic/spk --- VRCT.py | 90 +++++++++++++++++++++++++---------- transcription.py | 121 ++++++++++++++++++++++++++++++++++++++++------- window_config.py | 2 +- 3 files changed, 171 insertions(+), 42 deletions(-) diff --git a/VRCT.py b/VRCT.py index 2fbe8467..a6a36757 100644 --- a/VRCT.py +++ b/VRCT.py @@ -259,8 +259,8 @@ class App(customtkinter.CTk): ## set transcription instance self.vr = transcription.VoiceRecognizer() - self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else self.vr.search_default_device_index()[0]["name"] - self.CHOICE_SPEAKER_DEVICE = self.CHOICE_SPEAKER_DEVICE if self.CHOICE_SPEAKER_DEVICE is not None else self.vr.search_default_device_index()[1]["name"] + self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else self.vr.search_default_device()[0] + self.CHOICE_SPEAKER_DEVICE = self.CHOICE_SPEAKER_DEVICE if self.CHOICE_SPEAKER_DEVICE is not None else self.vr.search_default_device()[1] ## set checkbox enable translation if self.ENABLE_TRANSLATION: @@ -324,33 +324,44 @@ class App(customtkinter.CTk): self.ENABLE_TRANSCRIPTION = self.checkbox_transcription.get() if self.ENABLE_TRANSCRIPTION is True: # start threading - th = threading.Thread(target = self.voice_input) - th.start() + self.vr.set_mic(self.CHOICE_MIC_DEVICE) + self.vr.init_mic(threshold=self.MIC_THRESHOLD, is_dynamic=self.ENABLE_MIC_IS_DYNAMIC) + th_vr_listen_mic = threading.Thread(target = self.vr_listen_mic) + th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) + th_vr_listen_mic.start() + th_vr_recognize_mic.start() + + self.vr.set_spk(self.CHOICE_SPEAKER_DEVICE) + self.vr.init_spk() + th_vr_listen_spk = threading.Thread(target = self.vr_listen_spk) + th_vr_recognize_spk = threading.Thread(target = self.vr_recognize_spk) + th_vr_listen_spk.start() + th_vr_recognize_spk.start() + utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) - def voice_input(self): - self.vr.set_mic(self.CHOICE_MIC_DEVICE) - self.vr.init_mic(threshold=self.MIC_THRESHOLD, is_dynamic=self.ENABLE_MIC_IS_DYNAMIC) + def vr_listen_mic(self): + while self.checkbox_transcription.get() is True: + self.vr.listen_mic() - # start voice_input - if self.checkbox_transcription.get() is True: - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[INFO] start transcription\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + def vr_recognize_mic(self): + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[INFO] start transcription\n") + self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") while self.checkbox_transcription.get() is True: - message = self.vr.listen_voice(language=self.INPUT_MIC_VOICE_LANGUAGE) + message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) if len(message) > 0: # translate if self.checkbox_translation.get() is False: - chat_message = f"{message}" - elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): + voice_message = f"{message}" + elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: self.textbox_message_log.configure(state='normal') self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_log.configure(state='disabled') self.textbox_message_log.see("end") - chat_message = f"{message}" + voice_message = f"{message}" else: result = self.translator.translate( translator_name=self.CHOICE_TRANSLATOR, @@ -358,20 +369,51 @@ class App(customtkinter.CTk): target_language=self.INPUT_TARGET_LANG, message=message ) - chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[VOICE] {chat_message}\n") + self.textbox_message_log.insert("end", f"[VOICE] {voice_message}\n") + self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") + + def vr_listen_spk(self): + while self.checkbox_transcription.get() is True: + self.vr.listen_spk() + + def vr_recognize_spk(self): + while self.checkbox_transcription.get() is True: + message = self.vr.recognize_spk(language=self.INPUT_SPEAKER_VOICE_LANGUAGE) + if len(message) > 0: + # translate + if self.checkbox_translation.get() is False: + voice_message = f"{message}" + elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") + self.textbox_message_log.configure(state='disabled') + self.textbox_message_log.see("end") + voice_message = f"{message}" + else: + result = self.translator.translate( + translator_name=self.CHOICE_TRANSLATOR, + source_language=self.INPUT_SOURCE_LANG, + target_language=self.INPUT_TARGET_LANG, + message=message + ) + voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + + # send OSC message + osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + + # update textbox message log + self.textbox_message_log.configure(state='normal') + self.textbox_message_log.insert("end", f"[VOICE] {voice_message}\n") self.textbox_message_log.configure(state='disabled') self.textbox_message_log.see("end") - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[INFO] stop transcription\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") def checkbox_foreground_callback(self): self.ENABLE_FOREGROUND = self.checkbox_foreground.get() diff --git a/transcription.py b/transcription.py index ceddfb5c..ba358d08 100644 --- a/transcription.py +++ b/transcription.py @@ -1,3 +1,8 @@ +import io +import queue +import numpy as np +import soundcard as sc +import soundfile as sf import sounddevice as sd import speech_recognition as sr @@ -5,7 +10,6 @@ import speech_recognition as sr class VoiceRecognizer(): def __init__(self): self.r = sr.Recognizer() - self.mic = None self.languages = [ "ja-JP","en-US","en-GB","af-ZA","ar-DZ","ar-BH","ar-EG","ar-IL","ar-IQ","ar-JO","ar-KW","ar-LB","ar-MA", "ar-OM","ar-PS","ar-QA","ar-SA","ar-TN","ar-AE","eu-ES","bg-BG","ca-ES","cmn-Hans-CN","cmn-Hans-HK", @@ -16,6 +20,18 @@ class VoiceRecognizer(): "es-NI","es-PA","es-PY","es-PE","es-PR","es-ES","es-UY","es-US","es-VE","sv-SE","th-TH","tr-TR","uk-UA", "vi-VN","zu-ZA" ] + self.mic = None + self.enable_mic_recognize = False + self.queue_mic = queue.Queue() + + self.spk_device_name = None + self.spk_sample_rate = 16000 + self.spk_interval = 3 + self.spk_buffer_size = 4096 + self.spk_language = "en-US" + self.spk_audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) + self.n = 0 + self.queue_spk = queue.Queue() def search_input_device(self): device_list = sd.query_devices() @@ -28,21 +44,20 @@ class VoiceRecognizer(): return input_device_list def search_output_device(self): - device_list = sd.query_devices() + device_list = sc.all_speakers() output_device_list = [] for device in device_list: - if device["max_output_channels"] > 0: - output_device_list.append({"name": device["name"], "index": device["index"]}) + output_device_list.append(str(device.name)) return output_device_list - def search_default_device_index(self): + def search_default_device(self): device_list = sd.query_devices() - default_device_list = [] - for i in sd.default.device: - default_device_list.append({"name": device_list[i]["name"], "index": device_list[i]["index"]}) - return default_device_list + mic_index = sd.default.device[0] + name_mic = device_list[mic_index]["name"] + name_spk = str(sc.default_speaker().name) + return name_mic, name_spk def set_mic(self, device_name, threshold=50, is_dynamic=False): input_device_list = self.search_input_device() @@ -68,14 +83,86 @@ class VoiceRecognizer(): else: return False - def listen_voice(self, language): + def listen_mic(self): if self.mic != None: with self.mic as source: audio = self.r.listen(source) - try: - text = self.r.recognize_google(audio, language=language) - return text - except: - return "" - else: - return False \ No newline at end of file + self.queue_mic.put(audio) + + def recognize_mic(self, language): + try: + audio = self.queue_mic.get() + text = self.r.recognize_google(audio, language=language) + except: + text = "" + return text + + def set_spk(self, device_name=str(sc.default_speaker().name), sample_rate=16000, interval=3, buffer_size=4096, language="en-US"): + self.spk_device_name = device_name + self.spk_sample_rate = sample_rate + self.spk_interval = interval + self.spk_buffer_size = buffer_size + self.spk_language = language + + def init_spk(self): + self.spk_audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) + self.n = 0 + + def listen_spk(self): + audio = self.spk_audio + n = self.n + with sc.get_microphone(id=self.spk_device_name, include_loopback=True).recorder(samplerate=self.spk_sample_rate, channels=1) as source: + while n < self.spk_sample_rate * self.spk_interval: + data = source.record(self.spk_buffer_size) + audio[n:n+len(data)] = data.reshape(-1) + n += len(data) + m = n * 4 // 5 + vol = np.convolve(audio[m:n] ** 2, np.ones(100) / 100, 'same') + m += vol.argmin() + audio_prev = audio.copy() + self.queue_spk.put(audio[:m]) + audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) + audio[:n-m] = audio_prev[m:n] + n = n-m + self.spk_audio = audio + self.n = n + + def recognize_spk(self): + try: + audio = self.queue_spk.get() + with io.BytesIO() as memory_file: + sf.write(file=memory_file, data=audio, format="WAV", samplerate=self.spk_sample_rate) + memory_file.seek(0) + with sr.AudioFile(memory_file) as source: + audio = self.r.record(source) + text = self.r.recognize_google(audio, language=self.spk_language) + except Exception as e: + text = "" + return text + +if __name__ == "__main__": + import time + import threading + + vr = VoiceRecognizer() + mic_name, spk_name = vr.search_default_device() + vr.spk_enable_recognize = True + vr.set_spk(language="ja-JP") + vr.init_spk() + + def vr_listen_spk(): + while True: + vr.listen_spk() + + def vr_recognize_spk(): + while True: + text = vr.recognize_spk() + print(text) + + th_vr_listen_spk = threading.Thread(target=vr_listen_spk) + th_vr_recognize_spk = threading.Thread(target=vr_recognize_spk) + th_vr_listen_spk.start() + th_vr_recognize_spk.start() + + while True: + time.sleep(60) \ No newline at end of file diff --git a/window_config.py b/window_config.py index a5ef6daf..6930db1a 100644 --- a/window_config.py +++ b/window_config.py @@ -277,7 +277,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), - values=[device["name"] for device in self.parent.vr.search_output_device()], + values=self.parent.vr.search_output_device(), # command=self.optionmenu_input_speaker_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), From dbc322ac15052a93e37efa80f397335c6a86ac3e Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 13 Jun 2023 18:04:29 +0900 Subject: [PATCH 18/35] update transcription UI --- VRCT.py | 159 +++++++++++++++++++++++++++-------------------- transcription.py | 60 +++++++----------- window_config.py | 132 ++++++++++++++++++++++----------------- 3 files changed, 189 insertions(+), 162 deletions(-) diff --git a/VRCT.py b/VRCT.py index a6a36757..016053ed 100644 --- a/VRCT.py +++ b/VRCT.py @@ -35,12 +35,14 @@ class App(customtkinter.CTk): ## Transcription self.CHOICE_MIC_DEVICE = None self.INPUT_MIC_VOICE_LANGUAGE = "ja-JP" - self.ENABLE_MIC_IS_DYNAMIC = False - self.MIC_THRESHOLD = 300 + self.INPUT_MIC_IS_DYNAMIC = False + self.INPUT_MIC_THRESHOLD = 300 self.CHOICE_SPEAKER_DEVICE = None self.INPUT_SPEAKER_VOICE_LANGUAGE = "ja-JP" - self.ENABLE_SPEAKER_IS_DYNAMIC = False - self.SPEAKER_THRESHOLD = 300 + self.INPUT_SPEAKER_SAMPLING_RATE = 16000 + self.INPUT_SPEAKER_INTERVAL = 3 + self.INPUT_SPEAKER_BUFFER_SIZE = 4096 + ## Parameter self.OSC_IP_ADDRESS = "127.0.0.1" self.OSC_PORT = 9000 @@ -91,18 +93,20 @@ class App(customtkinter.CTk): self.CHOICE_MIC_DEVICE = config["CHOICE_MIC_DEVICE"] if "INPUT_MIC_VOICE_LANGUAGE" in config.keys(): self.INPUT_MIC_VOICE_LANGUAGE = config["INPUT_MIC_VOICE_LANGUAGE"] - if "ENABLE_MIC_IS_DYNAMIC" in config.keys(): - self.ENABLE_MIC_IS_DYNAMIC = config["ENABLE_MIC_IS_DYNAMIC"] - if "MIC_THRESHOLD" in config.keys(): - self.MIC_THRESHOLD = config["MIC_THRESHOLD"] + if "INPUT_MIC_IS_DYNAMIC" in config.keys(): + self.INPUT_MIC_IS_DYNAMIC = config["INPUT_MIC_IS_DYNAMIC"] + if "INPUT_MIC_THRESHOLD" in config.keys(): + self.INPUT_MIC_THRESHOLD = config["INPUT_MIC_THRESHOLD"] if "CHOICE_SPEAKER_DEVICE" in config.keys(): self.CHOICE_SPEAKER_DEVICE = config["CHOICE_SPEAKER_DEVICE"] if "INPUT_SPEAKER_VOICE_LANGUAGE" in config.keys(): self.INPUT_SPEAKER_VOICE_LANGUAGE = config["INPUT_SPEAKER_VOICE_LANGUAGE"] - if "ENABLE_SPEAKER_IS_DYNAMIC" in config.keys(): - self.ENABLE_SPEAKER_IS_DYNAMIC = config["ENABLE_SPEAKER_IS_DYNAMIC"] - if "SPEAKER_THRESHOLD" in config.keys(): - self.SPEAKER_THRESHOLD = config["SPEAKER_THRESHOLD"] + if "INPUT_SPEAKER_SAMPLING_RATE" in config.keys(): + self.INPUT_SPEAKER_SAMPLING_RATE = config["INPUT_SPEAKER_SAMPLING_RATE"] + if "INPUT_SPEAKER_INTERVAL" in config.keys(): + self.INPUT_SPEAKER_INTERVAL = config["INPUT_SPEAKER_INTERVAL"] + if "INPUT_SPEAKER_BUFFER_SIZE" in config.keys(): + self.INPUT_SPEAKER_BUFFER_SIZE = config["INPUT_SPEAKER_BUFFER_SIZE"] # Parameter if "OSC_IP_ADDRESS" in config.keys(): @@ -130,12 +134,13 @@ class App(customtkinter.CTk): "OUTPUT_TARGET_LANG": self.OUTPUT_TARGET_LANG, "CHOICE_MIC_DEVICE": self.CHOICE_MIC_DEVICE, "INPUT_MIC_VOICE_LANGUAGE": self.INPUT_MIC_VOICE_LANGUAGE, - "ENABLE_MIC_IS_DYNAMIC": self.ENABLE_MIC_IS_DYNAMIC, - "MIC_THRESHOLD": self.MIC_THRESHOLD, + "INPUT_MIC_IS_DYNAMIC": self.INPUT_MIC_IS_DYNAMIC, + "INPUT_MIC_THRESHOLD": self.INPUT_MIC_THRESHOLD, "CHOICE_SPEAKER_DEVICE": self.CHOICE_SPEAKER_DEVICE, "INPUT_SPEAKER_VOICE_LANGUAGE": self.INPUT_SPEAKER_VOICE_LANGUAGE, - "ENABLE_SPEAKER_IS_DYNAMIC": self.ENABLE_SPEAKER_IS_DYNAMIC, - "SPEAKER_THRESHOLD": self.SPEAKER_THRESHOLD, + "INPUT_SPEAKER_SAMPLING_RATE": self.INPUT_SPEAKER_SAMPLING_RATE, + "INPUT_SPEAKER_INTERVAL": self.INPUT_SPEAKER_INTERVAL, + "INPUT_SPEAKER_BUFFER_SIZE": self.INPUT_SPEAKER_BUFFER_SIZE, "OSC_IP_ADDRESS": self.OSC_IP_ADDRESS, "OSC_PORT": self.OSC_PORT, "AUTH_KEYS": self.AUTH_KEYS, @@ -215,29 +220,40 @@ class App(customtkinter.CTk): self.tabview_logs = customtkinter.CTkTabview(master=self) self.tabview_logs.add("send") self.tabview_logs.add("receive") + self.tabview_logs.add("system") self.tabview_logs.grid(row=0, column=1, padx=5, pady=0, sticky="nsew") self.tabview_logs._segmented_button.grid(sticky="W") self.tabview_logs.tab("send").grid_rowconfigure(0, weight=1) self.tabview_logs.tab("send").grid_columnconfigure(0, weight=1) self.tabview_logs.tab("receive").grid_rowconfigure(0, weight=1) self.tabview_logs.tab("receive").grid_columnconfigure(0, weight=1) - self.tabview_logs.configure(state='disabled') + self.tabview_logs.tab("system").grid_rowconfigure(0, weight=1) + self.tabview_logs.tab("system").grid_columnconfigure(0, weight=1) + # self.tabview_logs.configure(state='disabled') - # add textbox message log - self.textbox_message_log = customtkinter.CTkTextbox( + # add textbox message send log + self.textbox_message_send_log = customtkinter.CTkTextbox( self.tabview_logs.tab("send"), font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.textbox_message_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_log.configure(state='disabled') + 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 log + # add textbox message receive log self.textbox_message_receive_log = customtkinter.CTkTextbox( self.tabview_logs.tab("receive"), font=customtkinter.CTkFont(family=self.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') + # self.textbox_message_receive_log.configure(state='disabled') + + # add textbox message system log + self.textbox_message_system_log = customtkinter.CTkTextbox( + self.tabview_logs.tab("system"), + font=customtkinter.CTkFont(family=self.FONT_FAMILY) + ) + self.textbox_message_system_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") + # self.textbox_message_system_log.configure(state='disabled') # add entry message box self.entry_message_box = customtkinter.CTkEntry( @@ -252,10 +268,10 @@ class App(customtkinter.CTk): self.translator = translation.Translator() if self.translator.authentication(self.CHOICE_TRANSLATOR, self.AUTH_KEYS[self.CHOICE_TRANSLATOR]) is False: # error update Auth key - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[ERROR] Auth Keyを設定してないか間違っています\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_system_log.configure(state='normal') + self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyを設定してないか間違っています\n") + self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.see("end") ## set transcription instance self.vr = transcription.VoiceRecognizer() @@ -301,7 +317,10 @@ class App(customtkinter.CTk): def button_config_callback(self): if self.config_window is None or not self.config_window.winfo_exists(): - self.config_window = window_config.ToplevelWindowConfig(self) + try: + self.config_window = window_config.ToplevelWindowConfig(self) + except Exception as e: + print(e) self.config_window.focus() def button_information_callback(self): @@ -311,30 +330,32 @@ class App(customtkinter.CTk): def checkbox_translation_callback(self): self.ENABLE_TRANSLATION = self.checkbox_translation.get() - self.textbox_message_log.configure(state='normal') + self.textbox_message_system_log.configure(state='normal') if self.ENABLE_TRANSLATION: - self.textbox_message_log.insert("end", f"[INFO] start translation\n") + self.textbox_message_system_log.insert("end", f"[INFO] start translation\n") else: - self.textbox_message_log.insert("end", f"[INFO] stop translation\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_system_log.insert("end", f"[INFO] stop translation\n") + self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.see("end") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) def checkbox_transcription_callback(self): self.ENABLE_TRANSCRIPTION = self.checkbox_transcription.get() if self.ENABLE_TRANSCRIPTION is True: # start threading - self.vr.set_mic(self.CHOICE_MIC_DEVICE) - self.vr.init_mic(threshold=self.MIC_THRESHOLD, is_dynamic=self.ENABLE_MIC_IS_DYNAMIC) - th_vr_listen_mic = threading.Thread(target = self.vr_listen_mic) - th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) - th_vr_listen_mic.start() - th_vr_recognize_mic.start() + self.vr.set_mic(self.CHOICE_MIC_DEVICE, threshold=self.INPUT_MIC_THRESHOLD, is_dynamic=self.INPUT_MIC_IS_DYNAMIC) + self.vr.init_mic() self.vr.set_spk(self.CHOICE_SPEAKER_DEVICE) self.vr.init_spk() + + th_vr_listen_mic = threading.Thread(target = self.vr_listen_mic) + th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) th_vr_listen_spk = threading.Thread(target = self.vr_listen_spk) th_vr_recognize_spk = threading.Thread(target = self.vr_recognize_spk) + + th_vr_listen_mic.start() + th_vr_recognize_mic.start() th_vr_listen_spk.start() th_vr_recognize_spk.start() @@ -345,10 +366,10 @@ class App(customtkinter.CTk): self.vr.listen_mic() def vr_recognize_mic(self): - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[INFO] start transcription\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_system_log.configure(state='normal') + self.textbox_message_system_log.insert("end", f"[INFO] start transcription\n") + self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.see("end") while self.checkbox_transcription.get() is True: message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) @@ -357,10 +378,10 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: voice_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_system_log.configure(state='normal') + self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") + self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.see("end") voice_message = f"{message}" else: result = self.translator.translate( @@ -375,10 +396,10 @@ class App(customtkinter.CTk): osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[VOICE] {voice_message}\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_send_log.configure(state='normal') + self.textbox_message_send_log.insert("end", f"[VOICE] {voice_message}\n") + self.textbox_message_send_log.configure(state='disabled') + self.textbox_message_send_log.see("end") def vr_listen_spk(self): while self.checkbox_transcription.get() is True: @@ -392,10 +413,10 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: voice_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_system_log.configure(state='normal') + self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") + self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.see("end") voice_message = f"{message}" else: result = self.translator.translate( @@ -409,11 +430,11 @@ class App(customtkinter.CTk): # send OSC message osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) - # update textbox message log - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[VOICE] {voice_message}\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + # update textbox message receive log + self.textbox_message_receive_log.configure(state='normal') + self.textbox_message_receive_log.insert("end", f"[VOICE] {voice_message}\n") + self.textbox_message_receive_log.configure(state='disabled') + self.textbox_message_receive_log.see("end") def checkbox_foreground_callback(self): self.ENABLE_FOREGROUND = self.checkbox_foreground.get() @@ -436,10 +457,10 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: chat_message = f"{message}" elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_system_log.configure(state='normal') + self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") + self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.see("end") chat_message = f"{message}" else: result = self.translator.translate( @@ -451,13 +472,13 @@ class App(customtkinter.CTk): chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + # osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - self.textbox_message_log.configure(state='normal') - self.textbox_message_log.insert("end", f"[CHAT] {chat_message}\n") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_log.see("end") + self.textbox_message_receive_log.configure(state='normal') + self.textbox_message_receive_log.insert("end", f"[CHAT] {chat_message}\n") + self.textbox_message_receive_log.configure(state='disabled') + self.textbox_message_receive_log.see("end") # delete message in entry message box # self.entry_message_box.delete(0, customtkinter.END) diff --git a/transcription.py b/transcription.py index ba358d08..07c8f9ce 100644 --- a/transcription.py +++ b/transcription.py @@ -20,18 +20,18 @@ class VoiceRecognizer(): "es-NI","es-PA","es-PY","es-PE","es-PR","es-ES","es-UY","es-US","es-VE","sv-SE","th-TH","tr-TR","uk-UA", "vi-VN","zu-ZA" ] - self.mic = None - self.enable_mic_recognize = False - self.queue_mic = queue.Queue() + self.mic_device_name = None + self.mic_threshold = 50 + self.mic_is_dynamic = False + self.mic_queue = queue.Queue() self.spk_device_name = None self.spk_sample_rate = 16000 self.spk_interval = 3 self.spk_buffer_size = 4096 - self.spk_language = "en-US" self.spk_audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) self.n = 0 - self.queue_spk = queue.Queue() + self.spk_queue = queue.Queue() def search_input_device(self): device_list = sd.query_devices() @@ -61,48 +61,34 @@ class VoiceRecognizer(): def set_mic(self, device_name, threshold=50, is_dynamic=False): input_device_list = self.search_input_device() - if device_name in [input_device["name"] for input_device in input_device_list]: - index = [device["index"] for device in input_device_list if device["name"] == device_name][0] + self.mic_device_name = [device["index"] for device in input_device_list if device["name"] == device_name][0] + self.mic_threshold = threshold + self.mic_is_dynamic = is_dynamic - self.mic = sr.Microphone(device_index=index) - self.r.energy_threshold = threshold - if is_dynamic: - with self.mic as source: - self.r.adjust_for_ambient_noise(source, 3.0) - return True - else: - return False - - def init_mic(self, threshold=50, is_dynamic=False): - if isinstance(self.mic, sr.Microphone): - self.r.energy_threshold = threshold - if is_dynamic: - with self.mic as source: - self.r.adjust_for_ambient_noise(source, 3.0) - return True - else: - return False + def init_mic(self): + self.r.energy_threshold = self.mic_threshold + if self.mic_is_dynamic: + with self.mic as source: + self.r.adjust_for_ambient_noise(source, 3.0) def listen_mic(self): - if self.mic != None: - with self.mic as source: - audio = self.r.listen(source) - self.queue_mic.put(audio) + with sr.Microphone(device_index=self.mic_device_name) as source: + audio = self.r.listen(source) + self.mic_queue.put(audio) def recognize_mic(self, language): try: - audio = self.queue_mic.get() + audio = self.mic_queue.get() text = self.r.recognize_google(audio, language=language) except: text = "" return text - def set_spk(self, device_name=str(sc.default_speaker().name), sample_rate=16000, interval=3, buffer_size=4096, language="en-US"): + def set_spk(self, device_name=str(sc.default_speaker().name), sample_rate=16000, interval=3, buffer_size=4096): self.spk_device_name = device_name self.spk_sample_rate = sample_rate self.spk_interval = interval self.spk_buffer_size = buffer_size - self.spk_language = language def init_spk(self): self.spk_audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) @@ -120,23 +106,23 @@ class VoiceRecognizer(): vol = np.convolve(audio[m:n] ** 2, np.ones(100) / 100, 'same') m += vol.argmin() audio_prev = audio.copy() - self.queue_spk.put(audio[:m]) + self.spk_queue.put(audio[:m]) audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) audio[:n-m] = audio_prev[m:n] n = n-m self.spk_audio = audio self.n = n - def recognize_spk(self): + def recognize_spk(self, language): try: - audio = self.queue_spk.get() + audio = self.spk_queue.get() with io.BytesIO() as memory_file: sf.write(file=memory_file, data=audio, format="WAV", samplerate=self.spk_sample_rate) memory_file.seek(0) with sr.AudioFile(memory_file) as source: audio = self.r.record(source) - text = self.r.recognize_google(audio, language=self.spk_language) - except Exception as e: + text = self.r.recognize_google(audio, language=language) + except: text = "" return text diff --git a/window_config.py b/window_config.py index 6930db1a..db17e496 100644 --- a/window_config.py +++ b/window_config.py @@ -245,7 +245,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.checkbox_input_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - if self.parent.ENABLE_MIC_IS_DYNAMIC is True: + if self.parent.INPUT_MIC_IS_DYNAMIC is True: self.checkbox_input_mic_is_dynamic.select() else: self.checkbox_input_mic_is_dynamic.deselect() @@ -263,7 +263,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): from_=0, to=300, command=self.slider_input_mic_threshold_callback, - variable=tk.DoubleVar(value=self.parent.MIC_THRESHOLD), + variable=tk.DoubleVar(value=self.parent.INPUT_MIC_THRESHOLD), ) self.slider_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") @@ -272,16 +272,15 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.tabview_config.tab("Transcription"), text="Input Speaker Device:", fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), values=self.parent.vr.search_output_device(), - # command=self.optionmenu_input_speaker_device_callback, + command=self.optionmenu_input_speaker_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), - state="disabled" ) self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") @@ -290,59 +289,65 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.tabview_config.tab("Transcription"), text="Input Speaker Voice Language:", fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.label_input_speaker_voice_language.grid(row=5, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_input_speaker_voice_language = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), values=list(self.parent.vr.languages), - # command=self.optionmenu_input_speaker_voice_language_callback, + command=self.optionmenu_input_speaker_voice_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_VOICE_LANGUAGE), - state="disabled" ) self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - ## checkbox input speaker in dynamic - self.label_input_speaker_is_dynamic = customtkinter.CTkLabel( + ## entry input speaker sampling rate + self.label_input_speaker_sampling_rate = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), - text="Input Speaker IsDynamic:", + text="Input Speaker SamplingRate:", fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_input_speaker_is_dynamic.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.checkbox_input_speaker_is_dynamic = customtkinter.CTkCheckBox( + self.label_input_speaker_sampling_rate.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_input_speaker_sampling_rate = customtkinter.CTkEntry( self.tabview_config.tab("Transcription"), - text="", - onvalue=True, - offvalue=False, - # command=self.checkbox_input_speaker_is_dynamic_callback, - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), - state="disabled" + textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_SAMPLING_RATE), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.checkbox_input_speaker_is_dynamic.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") - if self.parent.ENABLE_SPEAKER_IS_DYNAMIC is True: - self.checkbox_input_speaker_is_dynamic.select() - else: - self.checkbox_input_speaker_is_dynamic.deselect() + self.entry_input_speaker_sampling_rate.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_sampling_rate.bind("", self.entry_input_speaker_sampling_rate_callback) - ## slider input speaker threshold - self.label_input_speaker_threshold = customtkinter.CTkLabel( + ## entry input speaker interval + self.label_input_speaker_interval = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), - text="Input Speaker Threshold:", + text="Input Speaker Interval:", fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_input_speaker_threshold.grid(row=7, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.slider_input_speaker_threshold = customtkinter.CTkSlider( + self.label_input_speaker_interval.grid(row=7, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_input_speaker_interval = customtkinter.CTkEntry( self.tabview_config.tab("Transcription"), - from_=0, - to=300, - # command=self.slider_input_speaker_threshold_callback, - variable=tk.DoubleVar(value=self.parent.SPEAKER_THRESHOLD), - state="disabled" + textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_INTERVAL), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.slider_input_speaker_threshold.grid(row=7, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + self.entry_input_speaker_interval.grid(row=7, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_interval.bind("", self.entry_input_speaker_interval_callback) + + ## entry input speaker buffer size + self.label_input_speaker_buffer_size = customtkinter.CTkLabel( + self.tabview_config.tab("Transcription"), + text="Input Speaker BufferSize:", + fg_color="transparent", + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.label_input_speaker_buffer_size.grid(row=8, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.entry_input_speaker_buffer_size = customtkinter.CTkEntry( + self.tabview_config.tab("Transcription"), + textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_BUFFER_SIZE), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) + ) + self.entry_input_speaker_buffer_size.grid(row=8, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_buffer_size.bind("", self.entry_input_speaker_buffer_size_callback) # tab Parameter ## entry ip address @@ -522,10 +527,10 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def optionmenu_translation_translator_callback(self, choice): if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_log.configure(state='disabled') - self.parent.textbox_message_log.see("end") + self.parent.textbox_message_system_log.configure(state='normal') + self.parent.textbox_message_system_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_system_log.configure(state='disabled') + self.parent.textbox_message_system_log.see("end") else: self.optionmenu_translation_input_source_language.configure( values=self.parent.translator.languages[choice], @@ -559,14 +564,34 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def checkbox_input_mic_is_dynamic_callback(self): value = self.checkbox_input_mic_is_dynamic.get() - self.parent.ENABLE_MIC_IS_DYNAMIC = value - utils.save_json(self.parent.PATH_CONFIG, "ENABLE_MIC_IS_DYNAMIC", self.parent.ENABLE_MIC_IS_DYNAMIC) - self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + self.parent.INPUT_MIC_IS_DYNAMIC = value + utils.save_json(self.parent.PATH_CONFIG, "INPUT_MIC_IS_DYNAMIC", self.parent.INPUT_MIC_IS_DYNAMIC) + self.parent.vr.set_mic(self.parent.CHOICE_MIC_DEVICE, threshold=self.parent.INPUT_MIC_THRESHOLD, is_dynamic=self.parent.INPUT_MIC_IS_DYNAMIC) def slider_input_mic_threshold_callback(self, value): - self.parent.MIC_THRESHOLD = value - utils.save_json(self.parent.PATH_CONFIG, "MIC_THRESHOLD", self.parent.MIC_THRESHOLD) - self.parent.vr.init_mic(threshold=self.parent.MIC_THRESHOLD, is_dynamic=self.parent.ENABLE_MIC_IS_DYNAMIC) + self.parent.INPUT_MIC_THRESHOLD = value + utils.save_json(self.parent.PATH_CONFIG, "INPUT_MIC_THRESHOLD", self.parent.INPUT_MIC_THRESHOLD) + self.parent.vr.set_mic(self.parent.CHOICE_MIC_DEVICE, threshold=self.parent.INPUT_MIC_THRESHOLD, is_dynamic=self.parent.INPUT_MIC_IS_DYNAMIC) + + def optionmenu_input_speaker_device_callback(self, choice): + self.parent.CHOICE_SPEAKER_DEVICE = choice + utils.save_json(self.parent.PATH_CONFIG, "CHOICE_SPEAKER_DEVICE", self.parent.CHOICE_SPEAKER_DEVICE) + + def optionmenu_input_speaker_voice_language_callback(self, choice): + self.parent.INPUT_SPEAKER_VOICE_LANGUAGE = choice + utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_VOICE_LANGUAGE", self.parent.INPUT_SPEAKER_VOICE_LANGUAGE) + + def entry_input_speaker_sampling_rate_callback(self, event): + self.parent.INPUT_SPEAKER_SAMPLING_RATE = int(self.entry_input_speaker_sampling_rate.get()) + utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_SAMPLING_RATE", self.parent.INPUT_SPEAKER_SAMPLING_RATE) + + def entry_input_speaker_interval_callback(self, event): + self.parent.INPUT_SPEAKER_INTERVAL = int(self.entry_input_speaker_interval.get()) + utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_INTERVAL", self.parent.INPUT_SPEAKER_INTERVAL) + + def entry_input_speaker_buffer_size_callback(self, event): + self.parent.INPUT_SPEAKER_BUFFER_SIZE = int(self.entry_input_speaker_buffer_size.get()) + utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_BUFFER_SIZE", self.parent.INPUT_SPEAKER_BUFFER_SIZE) def update_ip_address(self): value = self.entry_ip_address.get() @@ -583,19 +608,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def update_authkey(self): value = self.entry_authkey.get() if len(value) > 0: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.delete("0.0", "end") - self.parent.textbox_message_log.configure(state='disabled') - self.parent.textbox_message_log.see("end") - if self.parent.translator.authentication(self.parent.CHOICE_TRANSLATOR, self.parent.AUTH_KEYS[self.parent.CHOICE_TRANSLATOR]) is True: self.parent.AUTH_KEYS["DeepL(auth)"] = value utils.save_json(self.parent.PATH_CONFIG, "AUTH_KEYS", self.parent.AUTH_KEYS) else: - self.parent.textbox_message_log.configure(state='normal') - self.parent.textbox_message_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_log.configure(state='disabled') - self.parent.textbox_message_log.see("end") + self.parent.textbox_message_system_log.configure(state='normal') + self.parent.textbox_message_system_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") + self.parent.textbox_message_system_log.configure(state='disabled') + self.parent.textbox_message_system_log.see("end") def update_message_format(self): value = self.entry_message_format.get() From 115d3a75c6d837f1ae77c5f5e31e1230ed9168cc Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 13 Jun 2023 18:39:18 +0900 Subject: [PATCH 19/35] add output language optionmenu --- VRCT.py | 14 ++++++------- window_config.py | 54 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/VRCT.py b/VRCT.py index 016053ed..94c38452 100644 --- a/VRCT.py +++ b/VRCT.py @@ -30,15 +30,15 @@ class App(customtkinter.CTk): self.CHOICE_TRANSLATOR = "DeepL(web)" self.INPUT_SOURCE_LANG = "JA" self.INPUT_TARGET_LANG = "EN" - self.OUTPUT_SOURCE_LANG = "JA" - self.OUTPUT_TARGET_LANG = "EN" + self.OUTPUT_SOURCE_LANG = "EN" + self.OUTPUT_TARGET_LANG = "JA" ## Transcription self.CHOICE_MIC_DEVICE = None self.INPUT_MIC_VOICE_LANGUAGE = "ja-JP" self.INPUT_MIC_IS_DYNAMIC = False self.INPUT_MIC_THRESHOLD = 300 self.CHOICE_SPEAKER_DEVICE = None - self.INPUT_SPEAKER_VOICE_LANGUAGE = "ja-JP" + self.INPUT_SPEAKER_VOICE_LANGUAGE = "en-US" self.INPUT_SPEAKER_SAMPLING_RATE = 16000 self.INPUT_SPEAKER_INTERVAL = 3 self.INPUT_SPEAKER_BUFFER_SIZE = 4096 @@ -421,14 +421,14 @@ class App(customtkinter.CTk): else: result = self.translator.translate( translator_name=self.CHOICE_TRANSLATOR, - source_language=self.INPUT_SOURCE_LANG, - target_language=self.INPUT_TARGET_LANG, + source_language=self.OUTPUT_SOURCE_LANG, + target_language=self.OUTPUT_TARGET_LANG, message=message ) voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + # osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message receive log self.textbox_message_receive_log.configure(state='normal') @@ -472,7 +472,7 @@ class App(customtkinter.CTk): chat_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) # send OSC message - # osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log self.textbox_message_receive_log.configure(state='normal') diff --git a/window_config.py b/window_config.py index db17e496..eb451b97 100644 --- a/window_config.py +++ b/window_config.py @@ -158,18 +158,17 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.tabview_config.tab("Translation"), text="Output Language:", fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY, overstrike=True) + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.label_translation_output_language.grid(row=2, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") ## select translation output source language self.optionmenu_translation_output_source_language = customtkinter.CTkOptionMenu( self.tabview_config.tab("Translation"), - # command=self.optionmenu_translation_output_source_language_callback, + command=self.optionmenu_translation_output_source_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], variable=customtkinter.StringVar(value=self.parent.OUTPUT_SOURCE_LANG), - state="disabled", ) self.optionmenu_translation_output_source_language.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") @@ -185,11 +184,10 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ## select translation output target language self.optionmenu_translation_output_target_language = customtkinter.CTkOptionMenu( self.tabview_config.tab("Translation"), - # command=self.optionmenu_translation_output_target_language_callback, + command=self.optionmenu_translation_output_target_language_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), values=self.parent.translator.languages[self.parent.CHOICE_TRANSLATOR], variable=customtkinter.StringVar(value=self.parent.OUTPUT_TARGET_LANG), - state="disabled", ) self.optionmenu_translation_output_target_language.grid(row=2, column=3, columnspan=1, padx=5, pady=5, sticky="nsew") @@ -250,7 +248,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): else: self.checkbox_input_mic_is_dynamic.deselect() - ## slider input mic threshold + ## entry input mic threshold self.label_input_mic_threshold = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), text="Input Mic Threshold:", @@ -258,14 +256,13 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.label_input_mic_threshold.grid(row=3, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.slider_input_mic_threshold = customtkinter.CTkSlider( + self.entry_input_mic_threshold = customtkinter.CTkEntry( self.tabview_config.tab("Transcription"), - from_=0, - to=300, - command=self.slider_input_mic_threshold_callback, - variable=tk.DoubleVar(value=self.parent.INPUT_MIC_THRESHOLD), + textvariable=customtkinter.StringVar(value=self.parent.INPUT_MIC_THRESHOLD), + font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.slider_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + self.entry_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + self.entry_input_mic_threshold.bind("", self.entry_input_mic_threshold_callback) ## optionmenu input speaker device self.label_input_speaker_device = customtkinter.CTkLabel( @@ -495,8 +492,13 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_is_dynamic.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_threshold.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_sampling_rate.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_input_speaker_sampling_rate.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_interval.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_input_speaker_interval.configure(font=customtkinter.CTkFont(family=choice)) + self.label_input_speaker_buffer_size.configure(font=customtkinter.CTkFont(family=choice)) + self.entry_input_speaker_buffer_size.configure(font=customtkinter.CTkFont(family=choice)) + # tab Parameter self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) @@ -538,13 +540,23 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.optionmenu_translation_input_target_language.configure( values=self.parent.translator.languages[choice], variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) + self.optionmenu_translation_output_source_language.configure( + values=self.parent.translator.languages[choice], + variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][1])) + self.optionmenu_translation_output_target_language.configure( + values=self.parent.translator.languages[choice], + variable=customtkinter.StringVar(value=self.parent.translator.languages[choice][0])) self.parent.CHOICE_TRANSLATOR = choice self.parent.INPUT_SOURCE_LANG = self.parent.translator.languages[choice][0] self.parent.INPUT_TARGET_LANG = self.parent.translator.languages[choice][1] + self.parent.OUTPUT_SOURCE_LANG = self.parent.translator.languages[choice][1] + self.parent.OUTPUT_TARGET_LANG = self.parent.translator.languages[choice][0] utils.save_json(self.parent.PATH_CONFIG, "CHOICE_TRANSLATOR", self.parent.CHOICE_TRANSLATOR) utils.save_json(self.parent.PATH_CONFIG, "INPUT_SOURCE_LANG", self.parent.INPUT_SOURCE_LANG) utils.save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) + utils.save_json(self.parent.PATH_CONFIG, "OUTPUT_SOURCE_LANG", self.parent.OUTPUT_SOURCE_LANG) + utils.save_json(self.parent.PATH_CONFIG, "OUTPUT_TARGET_LANG", self.parent.OUTPUT_TARGET_LANG) def optionmenu_translation_input_source_language_callback(self, choice): self.parent.INPUT_SOURCE_LANG = choice @@ -554,6 +566,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.INPUT_TARGET_LANG = choice utils.save_json(self.parent.PATH_CONFIG, "INPUT_TARGET_LANG", self.parent.INPUT_TARGET_LANG) + def optionmenu_translation_output_source_language_callback(self, choice): + self.parent.OUTPUT_SOURCE_LANG = choice + utils.save_json(self.parent.PATH_CONFIG, "OUTPUT_SOURCE_LANG", self.parent.OUTPUT_SOURCE_LANG) + + def optionmenu_translation_output_target_language_callback(self, choice): + self.parent.OUTPUT_TARGET_LANG = choice + utils.save_json(self.parent.PATH_CONFIG, "OUTPUT_TARGET_LANG", self.parent.OUTPUT_TARGET_LANG) + def optionmenu_input_mic_device_callback(self, choice): self.parent.CHOICE_MIC_DEVICE = choice utils.save_json(self.parent.PATH_CONFIG, "CHOICE_MIC_DEVICE", self.parent.CHOICE_MIC_DEVICE) @@ -566,12 +586,10 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): value = self.checkbox_input_mic_is_dynamic.get() self.parent.INPUT_MIC_IS_DYNAMIC = value utils.save_json(self.parent.PATH_CONFIG, "INPUT_MIC_IS_DYNAMIC", self.parent.INPUT_MIC_IS_DYNAMIC) - self.parent.vr.set_mic(self.parent.CHOICE_MIC_DEVICE, threshold=self.parent.INPUT_MIC_THRESHOLD, is_dynamic=self.parent.INPUT_MIC_IS_DYNAMIC) - def slider_input_mic_threshold_callback(self, value): - self.parent.INPUT_MIC_THRESHOLD = value + def entry_input_mic_threshold_callback(self, event): + self.parent.INPUT_MIC_THRESHOLD = int(self.entry_input_mic_threshold.get()) utils.save_json(self.parent.PATH_CONFIG, "INPUT_MIC_THRESHOLD", self.parent.INPUT_MIC_THRESHOLD) - self.parent.vr.set_mic(self.parent.CHOICE_MIC_DEVICE, threshold=self.parent.INPUT_MIC_THRESHOLD, is_dynamic=self.parent.INPUT_MIC_IS_DYNAMIC) def optionmenu_input_speaker_device_callback(self, choice): self.parent.CHOICE_SPEAKER_DEVICE = choice From 96472dfc81d55c475207518ca39d5b2f18e7635d Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 13 Jun 2023 19:17:30 +0900 Subject: [PATCH 20/35] add translation send/receive checkbox --- VRCT.py | 100 +++++++++++++++++++++++++++++------------------ window_config.py | 3 +- 2 files changed, 65 insertions(+), 38 deletions(-) diff --git a/VRCT.py b/VRCT.py index 94c38452..e3b12206 100644 --- a/VRCT.py +++ b/VRCT.py @@ -19,7 +19,8 @@ class App(customtkinter.CTk): self.PATH_CONFIG = "./config.json" ## main window self.ENABLE_TRANSLATION = False - self.ENABLE_TRANSCRIPTION = False + self.ENABLE_TRANSCRIPTION_SEND = False + self.ENABLE_TRANSCRIPTION_RECEIVE = False self.ENABLE_FOREGROUND = False ## UI self.TRANSPARENCY = 100 @@ -61,8 +62,10 @@ class App(customtkinter.CTk): # main window if "ENABLE_TRANSLATION" in config.keys(): self.ENABLE_TRANSLATION = config["ENABLE_TRANSLATION"] - if "ENABLE_TRANSCRIPTION" in config.keys(): - self.ENABLE_TRANSCRIPTION = config["ENABLE_TRANSCRIPTION"] + if "ENABLE_TRANSCRIPTION_SEND" in config.keys(): + self.ENABLE_TRANSCRIPTION_SEND = config["ENABLE_TRANSCRIPTION_SEND"] + if "ENABLE_TRANSCRIPTION_RECEIVE" in config.keys(): + self.ENABLE_TRANSCRIPTION_RECEIVE = config["ENABLE_TRANSCRIPTION_RECEIVE"] if "ENABLE_FOREGROUND" in config.keys(): self.ENABLE_FOREGROUND = config["ENABLE_FOREGROUND"] @@ -121,7 +124,8 @@ class App(customtkinter.CTk): with open(self.PATH_CONFIG, 'w') as fp: config = { "ENABLE_TRANSLATION": self.ENABLE_TRANSLATION, - "ENABLE_TRANSCRIPTION": self.ENABLE_TRANSCRIPTION, + "ENABLE_TRANSCRIPTION_SEND": self.ENABLE_TRANSCRIPTION_SEND, + "ENABLE_TRANSCRIPTION_RECEIVE": self.ENABLE_TRANSCRIPTION_RECEIVE, "ENABLE_FOREGROUND": self.ENABLE_FOREGROUND, "TRANSPARENCY": self.TRANSPARENCY, "APPEARANCE_THEME": self.APPEARANCE_THEME, @@ -172,16 +176,27 @@ class App(customtkinter.CTk): ) self.checkbox_translation.grid(row=0, column=0, columnspan=2 ,padx=10, pady=(5, 5), sticky="we") - # add checkbox transcription - self.checkbox_transcription = customtkinter.CTkCheckBox( + # add checkbox transcription send + self.checkbox_transcription_send = customtkinter.CTkCheckBox( self.sidebar_frame, - text="Transcription", + text="TranscriptionSend", onvalue=True, offvalue=False, - command=self.checkbox_transcription_callback, + command=self.checkbox_transcription_send_callback, font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.checkbox_transcription.grid(row=1, 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") + + # add checkbox transcription receive + self.checkbox_transcription_receive = customtkinter.CTkCheckBox( + self.sidebar_frame, + text="TranscriptionReceive", + onvalue=True, + offvalue=False, + command=self.checkbox_transcription_receive_callback, + font=customtkinter.CTkFont(family=self.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 = customtkinter.CTkCheckBox( @@ -192,7 +207,7 @@ class App(customtkinter.CTk): command=self.checkbox_foreground_callback, font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.checkbox_foreground.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") # add button information self.button_information = customtkinter.CTkButton( @@ -245,7 +260,7 @@ class App(customtkinter.CTk): font=customtkinter.CTkFont(family=self.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') + self.textbox_message_receive_log.configure(state='disabled') # add textbox message system log self.textbox_message_system_log = customtkinter.CTkTextbox( @@ -253,7 +268,7 @@ class App(customtkinter.CTk): font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) self.textbox_message_system_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - # self.textbox_message_system_log.configure(state='disabled') + self.textbox_message_system_log.configure(state='disabled') # add entry message box self.entry_message_box = customtkinter.CTkEntry( @@ -285,12 +300,19 @@ class App(customtkinter.CTk): else: self.checkbox_translation.deselect() - ## set checkbox enable transcription - if self.ENABLE_TRANSCRIPTION: - self.checkbox_transcription.select() + ## set checkbox enable transcription send + if self.ENABLE_TRANSCRIPTION_SEND: + self.checkbox_transcription_send.select() else: - self.checkbox_transcription.deselect() - self.checkbox_transcription_callback() + self.checkbox_transcription_send.deselect() + self.checkbox_transcription_send_callback() + + ## set checkbox enable transcription receive + if self.ENABLE_TRANSCRIPTION_RECEIVE: + self.checkbox_transcription_receive.select() + else: + self.checkbox_transcription_receive.deselect() + self.checkbox_transcription_receive_callback() ## set set checkbox enable foreground if self.ENABLE_FOREGROUND: @@ -317,10 +339,7 @@ class App(customtkinter.CTk): def button_config_callback(self): if self.config_window is None or not self.config_window.winfo_exists(): - try: - self.config_window = window_config.ToplevelWindowConfig(self) - except Exception as e: - print(e) + self.config_window = window_config.ToplevelWindowConfig(self) self.config_window.focus() def button_information_callback(self): @@ -339,30 +358,37 @@ class App(customtkinter.CTk): self.textbox_message_system_log.see("end") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) - def checkbox_transcription_callback(self): - self.ENABLE_TRANSCRIPTION = self.checkbox_transcription.get() - if self.ENABLE_TRANSCRIPTION is True: + def checkbox_transcription_send_callback(self): + self.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() + if self.ENABLE_TRANSCRIPTION_SEND is True: # start threading self.vr.set_mic(self.CHOICE_MIC_DEVICE, threshold=self.INPUT_MIC_THRESHOLD, is_dynamic=self.INPUT_MIC_IS_DYNAMIC) self.vr.init_mic() - - self.vr.set_spk(self.CHOICE_SPEAKER_DEVICE) - self.vr.init_spk() - th_vr_listen_mic = threading.Thread(target = self.vr_listen_mic) th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) - th_vr_listen_spk = threading.Thread(target = self.vr_listen_spk) - th_vr_recognize_spk = threading.Thread(target = self.vr_recognize_spk) - th_vr_listen_mic.start() th_vr_recognize_mic.start() + utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_SEND", self.ENABLE_TRANSCRIPTION_SEND) + + def checkbox_transcription_receive_callback(self): + self.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get() + if self.ENABLE_TRANSCRIPTION_RECEIVE is True: + # start threading + self.vr.set_spk( + self.CHOICE_SPEAKER_DEVICE, + # int(self.INPUT_SPEAKER_SAMPLING_RATE), + # int(self.INPUT_SPEAKER_INTERVAL), + # int(self.INPUT_SPEAKER_BUFFER_SIZE), + ) + self.vr.init_spk() + th_vr_listen_spk = threading.Thread(target = self.vr_listen_spk) + th_vr_recognize_spk = threading.Thread(target = self.vr_recognize_spk) th_vr_listen_spk.start() th_vr_recognize_spk.start() - - utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION", self.ENABLE_TRANSCRIPTION) + utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_RECEIVE", self.ENABLE_TRANSCRIPTION_RECEIVE) def vr_listen_mic(self): - while self.checkbox_transcription.get() is True: + while self.checkbox_transcription_send.get() is True: self.vr.listen_mic() def vr_recognize_mic(self): @@ -371,7 +397,7 @@ class App(customtkinter.CTk): self.textbox_message_system_log.configure(state='disabled') self.textbox_message_system_log.see("end") - while self.checkbox_transcription.get() is True: + while self.checkbox_transcription_send.get() is True: message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) if len(message) > 0: # translate @@ -402,11 +428,11 @@ class App(customtkinter.CTk): self.textbox_message_send_log.see("end") def vr_listen_spk(self): - while self.checkbox_transcription.get() is True: + while self.checkbox_transcription_receive.get() is True: self.vr.listen_spk() def vr_recognize_spk(self): - while self.checkbox_transcription.get() is True: + while self.checkbox_transcription_receive.get() is True: message = self.vr.recognize_spk(language=self.INPUT_SPEAKER_VOICE_LANGUAGE) if len(message) > 0: # translate diff --git a/window_config.py b/window_config.py index eb451b97..2ccc623d 100644 --- a/window_config.py +++ b/window_config.py @@ -512,7 +512,8 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): # main window self.parent.checkbox_translation.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.checkbox_transcription.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.checkbox_transcription_send.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.checkbox_transcription_receive.configure(font=customtkinter.CTkFont(family=choice)) self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) From 0f4b63e67b312c783f091fc7dfd59da9653eaf71 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Wed, 14 Jun 2023 09:03:22 +0900 Subject: [PATCH 21/35] update func change font --- window_config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/window_config.py b/window_config.py index 2ccc623d..5606183c 100644 --- a/window_config.py +++ b/window_config.py @@ -515,7 +515,9 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.checkbox_transcription_send.configure(font=customtkinter.CTkFont(family=choice)) self.parent.checkbox_transcription_receive.configure(font=customtkinter.CTkFont(family=choice)) self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) - self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.textbox_message_send_log.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.textbox_message_receive_log.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.textbox_message_system_log.configure(font=customtkinter.CTkFont(family=choice)) self.parent.entry_message_box.configure(font=customtkinter.CTkFont(family=choice)) self.parent.tabview_logs._segmented_button.configure(font=customtkinter.CTkFont(family=choice)) From 35cba754ccb84e049e4f5fdb2aaccb9d37ee08ec Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Wed, 14 Jun 2023 22:37:43 +0900 Subject: [PATCH 22/35] bugfix --- VRCT.py | 28 ++++++++++++++++------------ window_config.py | 1 - 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/VRCT.py b/VRCT.py index e3b12206..de0c0c81 100644 --- a/VRCT.py +++ b/VRCT.py @@ -155,8 +155,8 @@ class App(customtkinter.CTk): # init main window self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico")) self.title("VRCT") - self.geometry(f"{400}x{140}") - self.minsize(400, 140) + self.geometry(f"{400}x{170}") + self.minsize(400, 170) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) @@ -362,7 +362,11 @@ class App(customtkinter.CTk): self.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() if self.ENABLE_TRANSCRIPTION_SEND is True: # start threading - self.vr.set_mic(self.CHOICE_MIC_DEVICE, threshold=self.INPUT_MIC_THRESHOLD, is_dynamic=self.INPUT_MIC_IS_DYNAMIC) + self.vr.set_mic( + device_name=self.CHOICE_MIC_DEVICE, + threshold=int(self.INPUT_MIC_THRESHOLD), + is_dynamic=self.INPUT_MIC_IS_DYNAMIC, + ) self.vr.init_mic() th_vr_listen_mic = threading.Thread(target = self.vr_listen_mic) th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) @@ -375,10 +379,10 @@ class App(customtkinter.CTk): if self.ENABLE_TRANSCRIPTION_RECEIVE is True: # start threading self.vr.set_spk( - self.CHOICE_SPEAKER_DEVICE, - # int(self.INPUT_SPEAKER_SAMPLING_RATE), - # int(self.INPUT_SPEAKER_INTERVAL), - # int(self.INPUT_SPEAKER_BUFFER_SIZE), + device_name=self.CHOICE_SPEAKER_DEVICE, + sample_rate=int(self.INPUT_SPEAKER_SAMPLING_RATE), + interval=int(self.INPUT_SPEAKER_INTERVAL), + buffer_size=int(self.INPUT_SPEAKER_BUFFER_SIZE), ) self.vr.init_spk() th_vr_listen_spk = threading.Thread(target = self.vr_listen_spk) @@ -482,7 +486,7 @@ class App(customtkinter.CTk): # translate if self.checkbox_translation.get() is False: chat_message = f"{message}" - elif (self.translator.translator_status[self.CHOICE_TRANSLATOR] is False) or (self.INPUT_SOURCE_LANG == "None") or (self.INPUT_TARGET_LANG == "None"): + elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: self.textbox_message_system_log.configure(state='normal') self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") self.textbox_message_system_log.configure(state='disabled') @@ -501,10 +505,10 @@ class App(customtkinter.CTk): osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - self.textbox_message_receive_log.configure(state='normal') - self.textbox_message_receive_log.insert("end", f"[CHAT] {chat_message}\n") - self.textbox_message_receive_log.configure(state='disabled') - self.textbox_message_receive_log.see("end") + self.textbox_message_send_log.configure(state='normal') + self.textbox_message_send_log.insert("end", f"[CHAT] {chat_message}\n") + self.textbox_message_send_log.configure(state='disabled') + self.textbox_message_send_log.see("end") # delete message in entry message box # self.entry_message_box.delete(0, customtkinter.END) diff --git a/window_config.py b/window_config.py index 5606183c..c1cf3fd4 100644 --- a/window_config.py +++ b/window_config.py @@ -499,7 +499,6 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.label_input_speaker_buffer_size.configure(font=customtkinter.CTkFont(family=choice)) self.entry_input_speaker_buffer_size.configure(font=customtkinter.CTkFont(family=choice)) - # tab Parameter self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) self.entry_ip_address.configure(font=customtkinter.CTkFont(family=choice)) From cb5b4f4e499ded53bcd890f327c248ebf59cc065 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 15 Jun 2023 01:03:36 +0900 Subject: [PATCH 23/35] update textbox print message --- VRCT.py | 72 ++++++++++++++++++++++-------------------------- utils.py | 11 +++++++- window_config.py | 10 ++----- 3 files changed, 45 insertions(+), 48 deletions(-) diff --git a/VRCT.py b/VRCT.py index de0c0c81..b2975b76 100644 --- a/VRCT.py +++ b/VRCT.py @@ -244,7 +244,6 @@ class App(customtkinter.CTk): self.tabview_logs.tab("receive").grid_columnconfigure(0, weight=1) self.tabview_logs.tab("system").grid_rowconfigure(0, weight=1) self.tabview_logs.tab("system").grid_columnconfigure(0, weight=1) - # self.tabview_logs.configure(state='disabled') # add textbox message send log self.textbox_message_send_log = customtkinter.CTkTextbox( @@ -283,10 +282,7 @@ class App(customtkinter.CTk): self.translator = translation.Translator() if self.translator.authentication(self.CHOICE_TRANSLATOR, self.AUTH_KEYS[self.CHOICE_TRANSLATOR]) is False: # error update Auth key - self.textbox_message_system_log.configure(state='normal') - self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyを設定してないか間違っています\n") - self.textbox_message_system_log.configure(state='disabled') - self.textbox_message_system_log.see("end") + utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") ## set transcription instance self.vr = transcription.VoiceRecognizer() @@ -307,6 +303,9 @@ class App(customtkinter.CTk): self.checkbox_transcription_send.deselect() self.checkbox_transcription_send_callback() + ## init threads send + self.threads_send = [] + ## set checkbox enable transcription receive if self.ENABLE_TRANSCRIPTION_RECEIVE: self.checkbox_transcription_receive.select() @@ -314,6 +313,9 @@ class App(customtkinter.CTk): self.checkbox_transcription_receive.deselect() self.checkbox_transcription_receive_callback() + ## init threads receive + self.threads_receive = [] + ## set set checkbox enable foreground if self.ENABLE_FOREGROUND: self.checkbox_foreground.select() @@ -337,6 +339,9 @@ class App(customtkinter.CTk): customtkinter.set_appearance_mode(self.APPEARANCE_THEME) customtkinter.set_default_color_theme("blue") + # delete window + self.protocol("WM_DELETE_WINDOW", self.delete_window) + def button_config_callback(self): if self.config_window is None or not self.config_window.winfo_exists(): self.config_window = window_config.ToplevelWindowConfig(self) @@ -349,13 +354,10 @@ class App(customtkinter.CTk): def checkbox_translation_callback(self): self.ENABLE_TRANSLATION = self.checkbox_translation.get() - self.textbox_message_system_log.configure(state='normal') if self.ENABLE_TRANSLATION: - self.textbox_message_system_log.insert("end", f"[INFO] start translation\n") + utils.print_textbox(self.textbox_message_system_log, "[info] Start translation") else: - self.textbox_message_system_log.insert("end", f"[INFO] stop translation\n") - self.textbox_message_system_log.configure(state='disabled') - self.textbox_message_system_log.see("end") + utils.print_textbox(self.textbox_message_system_log, "[info] Stop translation") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) def checkbox_transcription_send_callback(self): @@ -372,6 +374,8 @@ class App(customtkinter.CTk): th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) th_vr_listen_mic.start() th_vr_recognize_mic.start() + self.threads_send.append(th_vr_listen_mic) + self.threads_send.append(th_vr_recognize_mic) utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_SEND", self.ENABLE_TRANSCRIPTION_SEND) def checkbox_transcription_receive_callback(self): @@ -389,6 +393,8 @@ class App(customtkinter.CTk): th_vr_recognize_spk = threading.Thread(target = self.vr_recognize_spk) th_vr_listen_spk.start() th_vr_recognize_spk.start() + self.threads_receive.append(th_vr_listen_spk) + self.threads_receive.append(th_vr_recognize_spk) utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_RECEIVE", self.ENABLE_TRANSCRIPTION_RECEIVE) def vr_listen_mic(self): @@ -396,11 +402,7 @@ class App(customtkinter.CTk): self.vr.listen_mic() def vr_recognize_mic(self): - self.textbox_message_system_log.configure(state='normal') - self.textbox_message_system_log.insert("end", f"[INFO] start transcription\n") - self.textbox_message_system_log.configure(state='disabled') - self.textbox_message_system_log.see("end") - + utils.print_textbox(self.textbox_message_system_log, "[info] Start sending transcription from your voice") while self.checkbox_transcription_send.get() is True: message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) if len(message) > 0: @@ -408,10 +410,7 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: voice_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - self.textbox_message_system_log.configure(state='normal') - self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_system_log.configure(state='disabled') - self.textbox_message_system_log.see("end") + utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") voice_message = f"{message}" else: result = self.translator.translate( @@ -426,16 +425,17 @@ class App(customtkinter.CTk): osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - self.textbox_message_send_log.configure(state='normal') - self.textbox_message_send_log.insert("end", f"[VOICE] {voice_message}\n") - self.textbox_message_send_log.configure(state='disabled') - self.textbox_message_send_log.see("end") + utils.print_textbox(self.textbox_message_send_log, f"[voice] {voice_message}") + utils.print_textbox(self.textbox_message_system_log, "[info] Stop sending transcription from your voice") + for t in self.threads_send: + t.join() def vr_listen_spk(self): while self.checkbox_transcription_receive.get() is True: self.vr.listen_spk() def vr_recognize_spk(self): + utils.print_textbox(self.textbox_message_system_log, "[info] Start transcription of speaker's voice") while self.checkbox_transcription_receive.get() is True: message = self.vr.recognize_spk(language=self.INPUT_SPEAKER_VOICE_LANGUAGE) if len(message) > 0: @@ -443,10 +443,7 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: voice_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - self.textbox_message_system_log.configure(state='normal') - self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_system_log.configure(state='disabled') - self.textbox_message_system_log.see("end") + utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") voice_message = f"{message}" else: result = self.translator.translate( @@ -461,10 +458,10 @@ class App(customtkinter.CTk): # osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message receive log - self.textbox_message_receive_log.configure(state='normal') - self.textbox_message_receive_log.insert("end", f"[VOICE] {voice_message}\n") - self.textbox_message_receive_log.configure(state='disabled') - self.textbox_message_receive_log.see("end") + utils.print_textbox(self.textbox_message_receive_log, f"[voice] {voice_message}") + utils.print_textbox(self.textbox_message_system_log, "[info] Stop transcription of speaker's voice") + for t in self.threads_receive: + t.join() def checkbox_foreground_callback(self): self.ENABLE_FOREGROUND = self.checkbox_foreground.get() @@ -487,10 +484,7 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: chat_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - self.textbox_message_system_log.configure(state='normal') - self.textbox_message_system_log.insert("end", f"[ERROR] Auth Keyもしくは言語の設定が間違っています\n") - self.textbox_message_system_log.configure(state='disabled') - self.textbox_message_system_log.see("end") + utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") chat_message = f"{message}" else: result = self.translator.translate( @@ -505,10 +499,7 @@ class App(customtkinter.CTk): osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - self.textbox_message_send_log.configure(state='normal') - self.textbox_message_send_log.insert("end", f"[CHAT] {chat_message}\n") - self.textbox_message_send_log.configure(state='disabled') - self.textbox_message_send_log.see("end") + utils.print_textbox(self.textbox_message_send_log, f"[chat] {chat_message}") # delete message in entry message box # self.entry_message_box.delete(0, customtkinter.END) @@ -525,6 +516,9 @@ class App(customtkinter.CTk): if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) + def delete_window(self): + self.destroy() + if __name__ == "__main__": app = App() app.mainloop() \ No newline at end of file diff --git a/utils.py b/utils.py index f1937616..cb107d32 100644 --- a/utils.py +++ b/utils.py @@ -1,8 +1,17 @@ import json +import datetime def save_json(path, key, value): with open(path, "r") as fp: json_data = json.load(fp) json_data[key] = value with open(path, "w") as fp: - json.dump(json_data, fp, indent=4) \ No newline at end of file + json.dump(json_data, fp, indent=4) + +def print_textbox(textbox, message): + now = datetime.datetime.now() + now = now.strftime('%H:%M:%S') + textbox.configure(state='normal') + textbox.insert("end", f"[{now}]{message}\n") + textbox.configure(state='disabled') + textbox.see("end") \ No newline at end of file diff --git a/window_config.py b/window_config.py index c1cf3fd4..03d222eb 100644 --- a/window_config.py +++ b/window_config.py @@ -531,10 +531,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def optionmenu_translation_translator_callback(self, choice): if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: - self.parent.textbox_message_system_log.configure(state='normal') - self.parent.textbox_message_system_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_system_log.configure(state='disabled') - self.parent.textbox_message_system_log.see("end") + utils.print_textbox(self.parent.textbox_message_system_log, f"[error] Auth Key or language setting is incorrect") else: self.optionmenu_translation_input_source_language.configure( values=self.parent.translator.languages[choice], @@ -632,10 +629,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.AUTH_KEYS["DeepL(auth)"] = value utils.save_json(self.parent.PATH_CONFIG, "AUTH_KEYS", self.parent.AUTH_KEYS) else: - self.parent.textbox_message_system_log.configure(state='normal') - self.parent.textbox_message_system_log.insert("end", f"[ERROR]Auth Keyを設定してないか間違っています\n") - self.parent.textbox_message_system_log.configure(state='disabled') - self.parent.textbox_message_system_log.see("end") + utils.print_textbox(self.parent.textbox_message_system_log, f"[error] Auth Key or language setting is incorrect") def update_message_format(self): value = self.entry_message_format.get() From edefa119e97385a6abcd735acb3311ab3ab4dbc0 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 15 Jun 2023 03:18:05 +0900 Subject: [PATCH 24/35] bugfix Thread close process --- VRCT.py | 156 +++++++++++++++++++++++++++---------------------------- utils.py | 18 ++++++- 2 files changed, 94 insertions(+), 80 deletions(-) diff --git a/VRCT.py b/VRCT.py index b2975b76..501ebe3b 100644 --- a/VRCT.py +++ b/VRCT.py @@ -297,31 +297,29 @@ class App(customtkinter.CTk): self.checkbox_translation.deselect() ## set checkbox enable transcription send + self.th_vr_listen_mic = None + self.th_vr_recognize_mic = None if self.ENABLE_TRANSCRIPTION_SEND: self.checkbox_transcription_send.select() + self.checkbox_transcription_send_callback() else: self.checkbox_transcription_send.deselect() - self.checkbox_transcription_send_callback() - - ## init threads send - self.threads_send = [] ## set checkbox enable transcription receive + self.th_vr_listen_spk = None + self.th_vr_recognize_spk = None if self.ENABLE_TRANSCRIPTION_RECEIVE: self.checkbox_transcription_receive.select() + self.checkbox_transcription_receive_callback() else: self.checkbox_transcription_receive.deselect() - self.checkbox_transcription_receive_callback() - - ## init threads receive - self.threads_receive = [] ## set set checkbox enable foreground if self.ENABLE_FOREGROUND: self.checkbox_foreground.select() + self.checkbox_foreground_callback() else: self.checkbox_foreground.deselect() - self.checkbox_foreground_callback() ## set bind entry message box self.entry_message_box.bind("", self.entry_message_box_press_key_enter) @@ -363,6 +361,7 @@ class App(customtkinter.CTk): def checkbox_transcription_send_callback(self): self.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() if self.ENABLE_TRANSCRIPTION_SEND is True: + utils.print_textbox(self.textbox_message_system_log, "[info] Start sending transcription from your voice") # start threading self.vr.set_mic( device_name=self.CHOICE_MIC_DEVICE, @@ -370,17 +369,23 @@ class App(customtkinter.CTk): is_dynamic=self.INPUT_MIC_IS_DYNAMIC, ) self.vr.init_mic() - th_vr_listen_mic = threading.Thread(target = self.vr_listen_mic) - th_vr_recognize_mic = threading.Thread(target = self.vr_recognize_mic) - th_vr_listen_mic.start() - th_vr_recognize_mic.start() - self.threads_send.append(th_vr_listen_mic) - self.threads_send.append(th_vr_recognize_mic) + self.th_vr_listen_mic = utils.thread_fnc(self.vr_listen_mic) + self.th_vr_recognize_mic = utils.thread_fnc(self.vr_recognize_mic) + self.th_vr_listen_mic.start() + self.th_vr_recognize_mic.start() + else: + if isinstance(self.th_vr_listen_mic, utils.thread_fnc): + self.th_vr_listen_mic.stop() + if isinstance(self.th_vr_recognize_mic, utils.thread_fnc): + self.th_vr_recognize_mic.stop() + + utils.print_textbox(self.textbox_message_system_log, "[info] Stop sending transcription from your voice") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_SEND", self.ENABLE_TRANSCRIPTION_SEND) def checkbox_transcription_receive_callback(self): self.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get() if self.ENABLE_TRANSCRIPTION_RECEIVE is True: + utils.print_textbox(self.textbox_message_system_log, "[info] Start transcription of speaker's voice") # start threading self.vr.set_spk( device_name=self.CHOICE_SPEAKER_DEVICE, @@ -389,79 +394,68 @@ class App(customtkinter.CTk): buffer_size=int(self.INPUT_SPEAKER_BUFFER_SIZE), ) self.vr.init_spk() - th_vr_listen_spk = threading.Thread(target = self.vr_listen_spk) - th_vr_recognize_spk = threading.Thread(target = self.vr_recognize_spk) - th_vr_listen_spk.start() - th_vr_recognize_spk.start() - self.threads_receive.append(th_vr_listen_spk) - self.threads_receive.append(th_vr_recognize_spk) + self.th_vr_listen_spk = utils.thread_fnc(self.vr_listen_spk) + self.th_vr_recognize_spk = utils.thread_fnc(self.vr_recognize_spk) + self.th_vr_listen_spk.start() + self.th_vr_recognize_spk.start() + else: + if isinstance(self.th_vr_listen_spk, utils.thread_fnc): + self.th_vr_listen_spk.stop() + if isinstance(self.th_vr_recognize_spk, utils.thread_fnc): + self.th_vr_recognize_spk.stop() + + utils.print_textbox(self.textbox_message_system_log, "[info] Stop transcription of speaker's voice") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_RECEIVE", self.ENABLE_TRANSCRIPTION_RECEIVE) def vr_listen_mic(self): - while self.checkbox_transcription_send.get() is True: - self.vr.listen_mic() + self.vr.listen_mic() def vr_recognize_mic(self): - utils.print_textbox(self.textbox_message_system_log, "[info] Start sending transcription from your voice") - while self.checkbox_transcription_send.get() is True: - message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) - if len(message) > 0: - # translate - if self.checkbox_translation.get() is False: - voice_message = f"{message}" - elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") - voice_message = f"{message}" - else: - result = self.translator.translate( - translator_name=self.CHOICE_TRANSLATOR, - source_language=self.INPUT_SOURCE_LANG, - target_language=self.INPUT_TARGET_LANG, - message=message - ) - voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) - - # send OSC message - osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) - - # update textbox message log - utils.print_textbox(self.textbox_message_send_log, f"[voice] {voice_message}") - utils.print_textbox(self.textbox_message_system_log, "[info] Stop sending transcription from your voice") - for t in self.threads_send: - t.join() + message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) + if len(message) > 0: + # translate + if self.checkbox_translation.get() is False: + voice_message = f"{message}" + elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: + utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") + voice_message = f"{message}" + else: + result = self.translator.translate( + translator_name=self.CHOICE_TRANSLATOR, + source_language=self.INPUT_SOURCE_LANG, + target_language=self.INPUT_TARGET_LANG, + message=message + ) + voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + # send OSC message + osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + # update textbox message log + utils.print_textbox(self.textbox_message_send_log, f"[voice] {voice_message}") def vr_listen_spk(self): - while self.checkbox_transcription_receive.get() is True: - self.vr.listen_spk() + self.vr.listen_spk() def vr_recognize_spk(self): - utils.print_textbox(self.textbox_message_system_log, "[info] Start transcription of speaker's voice") - while self.checkbox_transcription_receive.get() is True: - message = self.vr.recognize_spk(language=self.INPUT_SPEAKER_VOICE_LANGUAGE) - if len(message) > 0: - # translate - if self.checkbox_translation.get() is False: - voice_message = f"{message}" - elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") - voice_message = f"{message}" - else: - result = self.translator.translate( - translator_name=self.CHOICE_TRANSLATOR, - source_language=self.OUTPUT_SOURCE_LANG, - target_language=self.OUTPUT_TARGET_LANG, - message=message - ) - voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) - - # send OSC message - # osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) - - # update textbox message receive log - utils.print_textbox(self.textbox_message_receive_log, f"[voice] {voice_message}") - utils.print_textbox(self.textbox_message_system_log, "[info] Stop transcription of speaker's voice") - for t in self.threads_receive: - t.join() + message = self.vr.recognize_spk(language=self.INPUT_SPEAKER_VOICE_LANGUAGE) + if len(message) > 0: + # translate + if self.checkbox_translation.get() is False: + voice_message = f"{message}" + elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: + utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") + voice_message = f"{message}" + else: + result = self.translator.translate( + translator_name=self.CHOICE_TRANSLATOR, + source_language=self.OUTPUT_SOURCE_LANG, + target_language=self.OUTPUT_TARGET_LANG, + message=message + ) + voice_message = self.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", result) + # send OSC message + # osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) + # update textbox message receive log + utils.print_textbox(self.textbox_message_receive_log, f"[voice] {voice_message}") def checkbox_foreground_callback(self): self.ENABLE_FOREGROUND = self.checkbox_foreground.get() @@ -517,6 +511,10 @@ class App(customtkinter.CTk): self.attributes("-topmost", True) def delete_window(self): + thread_list = threading.enumerate() + thread_list.remove(threading.main_thread()) + for thread in thread_list: + thread.stop() self.destroy() if __name__ == "__main__": diff --git a/utils.py b/utils.py index cb107d32..132dd03a 100644 --- a/utils.py +++ b/utils.py @@ -1,5 +1,6 @@ import json import datetime +import threading def save_json(path, key, value): with open(path, "r") as fp: @@ -14,4 +15,19 @@ def print_textbox(textbox, message): textbox.configure(state='normal') textbox.insert("end", f"[{now}]{message}\n") textbox.configure(state='disabled') - textbox.see("end") \ No newline at end of file + textbox.see("end") + +class thread_fnc(threading.Thread): + def __init__(self, fnc, *args, **kwargs): + super(thread_fnc, self).__init__(*args, **kwargs) + self.fnc = fnc + self._stop = threading.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() \ No newline at end of file From edb20b4da76b18693493a437aa360fc99e777729 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 15 Jun 2023 10:27:54 +0900 Subject: [PATCH 25/35] update tab UI --- VRCT.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/VRCT.py b/VRCT.py index 501ebe3b..f90199fc 100644 --- a/VRCT.py +++ b/VRCT.py @@ -152,11 +152,15 @@ class App(customtkinter.CTk): } json.dump(config, fp, indent=4) + ## set UI theme + customtkinter.set_appearance_mode(self.APPEARANCE_THEME) + customtkinter.set_default_color_theme("blue") + # init main window self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico")) self.title("VRCT") - self.geometry(f"{400}x{170}") - self.minsize(400, 170) + self.geometry(f"{400}x{175}") + self.minsize(400, 175) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) @@ -168,7 +172,7 @@ class App(customtkinter.CTk): # add checkbox translation self.checkbox_translation = customtkinter.CTkCheckBox( self.sidebar_frame, - text="Translation", + text="translation", onvalue=True, offvalue=False, command=self.checkbox_translation_callback, @@ -179,7 +183,7 @@ class App(customtkinter.CTk): # add checkbox transcription send self.checkbox_transcription_send = customtkinter.CTkCheckBox( self.sidebar_frame, - text="TranscriptionSend", + text="voice2chatbox", onvalue=True, offvalue=False, command=self.checkbox_transcription_send_callback, @@ -190,7 +194,7 @@ class App(customtkinter.CTk): # add checkbox transcription receive self.checkbox_transcription_receive = customtkinter.CTkCheckBox( self.sidebar_frame, - text="TranscriptionReceive", + text="speaker2log", onvalue=True, offvalue=False, command=self.checkbox_transcription_receive_callback, @@ -201,7 +205,7 @@ class App(customtkinter.CTk): # add checkbox foreground self.checkbox_foreground = customtkinter.CTkCheckBox( self.sidebar_frame, - text="Foreground", + text="foreground", onvalue=True, offvalue=False, command=self.checkbox_foreground_callback, @@ -236,7 +240,7 @@ class App(customtkinter.CTk): self.tabview_logs.add("send") self.tabview_logs.add("receive") self.tabview_logs.add("system") - self.tabview_logs.grid(row=0, column=1, padx=5, pady=0, sticky="nsew") + self.tabview_logs.grid(row=0, column=1, padx=0, pady=0, sticky="nsew") self.tabview_logs._segmented_button.grid(sticky="W") self.tabview_logs.tab("send").grid_rowconfigure(0, weight=1) self.tabview_logs.tab("send").grid_columnconfigure(0, weight=1) @@ -244,6 +248,7 @@ class App(customtkinter.CTk): self.tabview_logs.tab("receive").grid_columnconfigure(0, weight=1) self.tabview_logs.tab("system").grid_rowconfigure(0, weight=1) self.tabview_logs.tab("system").grid_columnconfigure(0, weight=1) + self.tabview_logs.configure(fg_color="transparent") # add textbox message send log self.textbox_message_send_log = customtkinter.CTkTextbox( @@ -275,7 +280,7 @@ class App(customtkinter.CTk): placeholder_text="message", font=customtkinter.CTkFont(family=self.FONT_FAMILY) ) - self.entry_message_box.grid(row=1, column=1, columnspan=2, padx=(10, 10), pady=(5, 10), sticky="nsew") + self.entry_message_box.grid(row=1, column=1, columnspan=2, padx=5, pady=(5, 10), sticky="nsew") # set default values ## set translator instance @@ -333,10 +338,6 @@ class App(customtkinter.CTk): new_scaling_float = int(self.UI_SCALING.replace("%", "")) / 100 customtkinter.set_widget_scaling(new_scaling_float) - ## set UI theme - customtkinter.set_appearance_mode(self.APPEARANCE_THEME) - customtkinter.set_default_color_theme("blue") - # delete window self.protocol("WM_DELETE_WINDOW", self.delete_window) From 3f59e80ea1a8363fb88da912165cb98a05bf700e Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 15 Jun 2023 15:26:59 +0900 Subject: [PATCH 26/35] update log text color --- VRCT.py | 54 ++++++++++++++++++++++++++++++++++++------------ utils.py | 13 ++++++++++-- window_config.py | 11 +++++++--- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/VRCT.py b/VRCT.py index f90199fc..b6918330 100644 --- a/VRCT.py +++ b/VRCT.py @@ -237,11 +237,14 @@ class App(customtkinter.CTk): # add tabview textbox self.tabview_logs = customtkinter.CTkTabview(master=self) + self.tabview_logs.add("log") self.tabview_logs.add("send") self.tabview_logs.add("receive") self.tabview_logs.add("system") self.tabview_logs.grid(row=0, column=1, padx=0, pady=0, sticky="nsew") self.tabview_logs._segmented_button.grid(sticky="W") + self.tabview_logs.tab("log").grid_rowconfigure(0, weight=1) + self.tabview_logs.tab("log").grid_columnconfigure(0, weight=1) self.tabview_logs.tab("send").grid_rowconfigure(0, weight=1) self.tabview_logs.tab("send").grid_columnconfigure(0, weight=1) self.tabview_logs.tab("receive").grid_rowconfigure(0, weight=1) @@ -250,6 +253,14 @@ class App(customtkinter.CTk): self.tabview_logs.tab("system").grid_columnconfigure(0, weight=1) self.tabview_logs.configure(fg_color="transparent") + # add textbox message log + self.textbox_message_log = customtkinter.CTkTextbox( + self.tabview_logs.tab("log"), + font=customtkinter.CTkFont(family=self.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 = customtkinter.CTkTextbox( self.tabview_logs.tab("send"), @@ -287,7 +298,8 @@ class App(customtkinter.CTk): self.translator = translation.Translator() if self.translator.authentication(self.CHOICE_TRANSLATOR, self.AUTH_KEYS[self.CHOICE_TRANSLATOR]) is False: # error update Auth key - utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") + utils.print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + utils.print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") ## set transcription instance self.vr = transcription.VoiceRecognizer() @@ -354,15 +366,18 @@ class App(customtkinter.CTk): def checkbox_translation_callback(self): self.ENABLE_TRANSLATION = self.checkbox_translation.get() if self.ENABLE_TRANSLATION: - utils.print_textbox(self.textbox_message_system_log, "[info] Start translation") + utils.print_textbox(self.textbox_message_log, "Start translation", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Start translation", "INFO") else: - utils.print_textbox(self.textbox_message_system_log, "[info] Stop translation") + utils.print_textbox(self.textbox_message_log, "Stop translation", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Stop translation", "INFO") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSLATION", self.ENABLE_TRANSLATION) def checkbox_transcription_send_callback(self): self.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() if self.ENABLE_TRANSCRIPTION_SEND is True: - utils.print_textbox(self.textbox_message_system_log, "[info] Start sending transcription from your voice") + utils.print_textbox(self.textbox_message_log, "Start voice2chatbox", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO") # start threading self.vr.set_mic( device_name=self.CHOICE_MIC_DEVICE, @@ -380,13 +395,15 @@ class App(customtkinter.CTk): if isinstance(self.th_vr_recognize_mic, utils.thread_fnc): self.th_vr_recognize_mic.stop() - utils.print_textbox(self.textbox_message_system_log, "[info] Stop sending transcription from your voice") + utils.print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_SEND", self.ENABLE_TRANSCRIPTION_SEND) def checkbox_transcription_receive_callback(self): self.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get() if self.ENABLE_TRANSCRIPTION_RECEIVE is True: - utils.print_textbox(self.textbox_message_system_log, "[info] Start transcription of speaker's voice") + utils.print_textbox(self.textbox_message_log, "Start speaker2log", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO") # start threading self.vr.set_spk( device_name=self.CHOICE_SPEAKER_DEVICE, @@ -405,7 +422,8 @@ class App(customtkinter.CTk): if isinstance(self.th_vr_recognize_spk, utils.thread_fnc): self.th_vr_recognize_spk.stop() - utils.print_textbox(self.textbox_message_system_log, "[info] Stop transcription of speaker's voice") + utils.print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") utils.save_json(self.PATH_CONFIG, "ENABLE_TRANSCRIPTION_RECEIVE", self.ENABLE_TRANSCRIPTION_RECEIVE) def vr_listen_mic(self): @@ -418,7 +436,8 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: voice_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") + utils.print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + utils.print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") voice_message = f"{message}" else: result = self.translator.translate( @@ -431,7 +450,8 @@ class App(customtkinter.CTk): # send OSC message osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - utils.print_textbox(self.textbox_message_send_log, f"[voice] {voice_message}") + utils.print_textbox(self.textbox_message_log, f"{voice_message}", "SEND") + utils.print_textbox(self.textbox_message_send_log, f"{voice_message}", "SEND") def vr_listen_spk(self): self.vr.listen_spk() @@ -443,7 +463,8 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: voice_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") + utils.print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + utils.print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") voice_message = f"{message}" else: result = self.translator.translate( @@ -456,14 +477,19 @@ class App(customtkinter.CTk): # send OSC message # osc_tools.send_message(voice_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message receive log - utils.print_textbox(self.textbox_message_receive_log, f"[voice] {voice_message}") + utils.print_textbox(self.textbox_message_log, f"{voice_message}", "RECEIVE") + utils.print_textbox(self.textbox_message_receive_log, f"{voice_message}", "RECEIVE") def checkbox_foreground_callback(self): self.ENABLE_FOREGROUND = self.checkbox_foreground.get() if self.ENABLE_FOREGROUND: self.attributes("-topmost", True) + utils.print_textbox(self.textbox_message_log, "Start foreground", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") else: self.attributes("-topmost", False) + utils.print_textbox(self.textbox_message_log, "Stop foreground", "INFO") + utils.print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") utils.save_json(self.PATH_CONFIG, "ENABLE_FOREGROUND", self.ENABLE_FOREGROUND) def entry_message_box_press_key_enter(self, event): @@ -479,7 +505,8 @@ class App(customtkinter.CTk): if self.checkbox_translation.get() is False: chat_message = f"{message}" elif self.translator.translator_status[self.CHOICE_TRANSLATOR] is False: - utils.print_textbox(self.textbox_message_system_log, "[error] Auth Key or language setting is incorrect") + utils.print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + utils.print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") chat_message = f"{message}" else: result = self.translator.translate( @@ -494,7 +521,8 @@ class App(customtkinter.CTk): osc_tools.send_message(chat_message, self.OSC_IP_ADDRESS, self.OSC_PORT) # update textbox message log - utils.print_textbox(self.textbox_message_send_log, f"[chat] {chat_message}") + utils.print_textbox(self.textbox_message_log, f"{chat_message}", "SEND") + utils.print_textbox(self.textbox_message_send_log, f"{chat_message}", "SEND") # delete message in entry message box # self.entry_message_box.delete(0, customtkinter.END) diff --git a/utils.py b/utils.py index 132dd03a..2b93ac12 100644 --- a/utils.py +++ b/utils.py @@ -1,6 +1,7 @@ import json import datetime import threading +import tkinter as tk def save_json(path, key, value): with open(path, "r") as fp: @@ -9,11 +10,19 @@ def save_json(path, key, value): with open(path, "w") as fp: json.dump(json_data, fp, indent=4) -def print_textbox(textbox, message): +def print_textbox(textbox, message, tags=None): now = datetime.datetime.now() now = now.strftime('%H:%M:%S') + + textbox.tag_config("ERROR", foreground="#FF0000") + textbox.tag_config("INFO", foreground="#1BFF00") + textbox.tag_config("SEND", foreground="#0378e2") + textbox.tag_config("RECEIVE", foreground="#ffa500") + textbox.configure(state='normal') - textbox.insert("end", f"[{now}]{message}\n") + textbox.insert("end", f"[{now}][") + textbox.insert("end", f"{tags}", tags) + textbox.insert("end", f"]{message}\n") textbox.configure(state='disabled') textbox.see("end") diff --git a/window_config.py b/window_config.py index 03d222eb..31011d12 100644 --- a/window_config.py +++ b/window_config.py @@ -514,6 +514,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.checkbox_transcription_send.configure(font=customtkinter.CTkFont(family=choice)) self.parent.checkbox_transcription_receive.configure(font=customtkinter.CTkFont(family=choice)) self.parent.checkbox_foreground.configure(font=customtkinter.CTkFont(family=choice)) + self.parent.textbox_message_log.configure(font=customtkinter.CTkFont(family=choice)) self.parent.textbox_message_send_log.configure(font=customtkinter.CTkFont(family=choice)) self.parent.textbox_message_receive_log.configure(font=customtkinter.CTkFont(family=choice)) self.parent.textbox_message_system_log.configure(font=customtkinter.CTkFont(family=choice)) @@ -531,7 +532,8 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def optionmenu_translation_translator_callback(self, choice): if self.parent.translator.authentication(choice, self.parent.AUTH_KEYS[choice]) is False: - utils.print_textbox(self.parent.textbox_message_system_log, f"[error] Auth Key or language setting is incorrect") + utils.print_textbox(self.parent.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + utils.print_textbox(self.parent.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") else: self.optionmenu_translation_input_source_language.configure( values=self.parent.translator.languages[choice], @@ -625,11 +627,14 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): def update_authkey(self): value = self.entry_authkey.get() if len(value) > 0: - if self.parent.translator.authentication(self.parent.CHOICE_TRANSLATOR, self.parent.AUTH_KEYS[self.parent.CHOICE_TRANSLATOR]) is True: + if self.parent.translator.authentication("DeepL(auth)", self.parent.AUTH_KEYS["DeepL(auth)"]) is True: self.parent.AUTH_KEYS["DeepL(auth)"] = value utils.save_json(self.parent.PATH_CONFIG, "AUTH_KEYS", self.parent.AUTH_KEYS) + utils.print_textbox(self.parent.textbox_message_log, "Auth key update completed", "INFO") + utils.print_textbox(self.parent.textbox_message_system_log, "Auth key update completed", "INFO") else: - utils.print_textbox(self.parent.textbox_message_system_log, f"[error] Auth Key or language setting is incorrect") + utils.print_textbox(self.parent.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") + utils.print_textbox(self.parent.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") def update_message_format(self): value = self.entry_message_format.get() From 71d6d0097153a560315103dfecf98f2cd036ffe1 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 15 Jun 2023 16:29:58 +0900 Subject: [PATCH 27/35] update Parameter config UI --- window_config.py | 82 +++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 57 deletions(-) diff --git a/window_config.py b/window_config.py index 31011d12..3496d091 100644 --- a/window_config.py +++ b/window_config.py @@ -46,7 +46,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.slider_transparency_callback, variable=tk.DoubleVar(value=self.parent.TRANSPARENCY), ) - self.slider_transparency.grid(row=0, column=1, columnspan=3, padx=5, pady=10, sticky="nsew") + self.slider_transparency.grid(row=0, column=1, columnspan=1, padx=5, pady=10, sticky="nsew") ## optionmenu theme self.label_appearance_theme = customtkinter.CTkLabel( @@ -62,7 +62,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_theme_callback, variable=customtkinter.StringVar(value=self.parent.APPEARANCE_THEME) ) - self.optionmenu_appearance_theme.grid(row=1, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_appearance_theme.grid(row=1, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") ## optionmenu UI scaling self.label_ui_scaling = customtkinter.CTkLabel( @@ -78,7 +78,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_ui_scaling_callback, variable=customtkinter.StringVar(value=self.parent.UI_SCALING) ) - self.optionmenu_ui_scaling.grid(row=2, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_ui_scaling.grid(row=2, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") ## optionmenu font family self.label_font_family = customtkinter.CTkLabel( @@ -95,7 +95,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.optionmenu_font_family_callback, variable=customtkinter.StringVar(value=self.parent.FONT_FAMILY) ) - self.optionmenu_font_family.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky="nsew") + self.optionmenu_font_family.grid(row=3, column=1, columnspan=1, padx=5, pady=5, sticky="nsew") # tab Translation ## optionmenu translation translator @@ -207,7 +207,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_MIC_DEVICE) ) - self.optionmenu_input_mic_device.grid(row=0, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.optionmenu_input_mic_device.grid(row=0, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") ## optionmenu input mic voice language self.label_input_mic_voice_language = customtkinter.CTkLabel( @@ -224,7 +224,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.INPUT_MIC_VOICE_LANGUAGE) ) - self.optionmenu_input_mic_voice_language.grid(row=1, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.optionmenu_input_mic_voice_language.grid(row=1, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") ## checkbox input mic in dynamic self.label_input_mic_is_dynamic = customtkinter.CTkLabel( @@ -242,7 +242,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): command=self.checkbox_input_mic_is_dynamic_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.checkbox_input_mic_is_dynamic.grid(row=2, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.checkbox_input_mic_is_dynamic.grid(row=2, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") if self.parent.INPUT_MIC_IS_DYNAMIC is True: self.checkbox_input_mic_is_dynamic.select() else: @@ -261,7 +261,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): textvariable=customtkinter.StringVar(value=self.parent.INPUT_MIC_THRESHOLD), font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.entry_input_mic_threshold.grid(row=3, column=1, columnspan=3 ,padx=5, pady=10, sticky="nsew") + self.entry_input_mic_threshold.grid(row=3, column=1, columnspan=1 ,padx=5, pady=10, sticky="nsew") self.entry_input_mic_threshold.bind("", self.entry_input_mic_threshold_callback) ## optionmenu input speaker device @@ -279,7 +279,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), ) - self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.optionmenu_input_speaker_device.grid(row=4, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") ## optionmenu input speaker voice language self.label_input_speaker_voice_language = customtkinter.CTkLabel( @@ -296,7 +296,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_VOICE_LANGUAGE), ) - self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") ## entry input speaker sampling rate self.label_input_speaker_sampling_rate = customtkinter.CTkLabel( @@ -311,7 +311,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_SAMPLING_RATE), font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.entry_input_speaker_sampling_rate.grid(row=6, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_sampling_rate.grid(row=6, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") self.entry_input_speaker_sampling_rate.bind("", self.entry_input_speaker_sampling_rate_callback) ## entry input speaker interval @@ -327,7 +327,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_INTERVAL), font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.entry_input_speaker_interval.grid(row=7, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_interval.grid(row=7, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") self.entry_input_speaker_interval.bind("", self.entry_input_speaker_interval_callback) ## entry input speaker buffer size @@ -343,7 +343,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_BUFFER_SIZE), font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.entry_input_speaker_buffer_size.grid(row=8, column=1, columnspan=3 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_buffer_size.grid(row=8, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") self.entry_input_speaker_buffer_size.bind("", self.entry_input_speaker_buffer_size_callback) # tab Parameter @@ -361,14 +361,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.entry_ip_address.grid(row=0, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_ip_address = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_ip_address, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_ip_address.grid(row=0, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + self.entry_ip_address.bind("", self.entry_ip_address_callback) ## entry port self.label_port = customtkinter.CTkLabel( @@ -384,14 +377,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.entry_port.grid(row=1, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_port = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_port, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_port.grid(row=1, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + self.entry_port.bind("", self.entry_port_callback) ## entry authkey self.label_authkey = customtkinter.CTkLabel( @@ -407,14 +393,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.entry_authkey.grid(row=2, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_authkey = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_authkey, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_authkey.grid(row=2, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + self.entry_authkey.bind("", self.entry_authkey_callback) ## entry message format self.label_message_format = customtkinter.CTkLabel( @@ -430,14 +409,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.entry_message_format.grid(row=3, column=1, columnspan=1, padx=1, pady=5, sticky="nsew") - self.button_message_format = customtkinter.CTkButton( - self.tabview_config.tab("Parameter"), - text="", - width=1, - command=self.update_message_format, - image=customtkinter.CTkImage(Image.open(os.path.join(os.path.dirname(__file__), "img", "save-icon.png"))) - ) - self.button_message_format.grid(row=3, column=2, columnspan=1, padx=5, pady=5, sticky="nsew") + self.entry_message_format.bind("", self.entry_message_format_callback) def slider_transparency_callback(self, value): self.parent.wm_attributes("-alpha", value/100) @@ -612,19 +584,15 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.INPUT_SPEAKER_BUFFER_SIZE = int(self.entry_input_speaker_buffer_size.get()) utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_BUFFER_SIZE", self.parent.INPUT_SPEAKER_BUFFER_SIZE) - def update_ip_address(self): - value = self.entry_ip_address.get() - if len(value) > 0: - self.parent.OSC_IP_ADDRESS = value - utils.save_json(self.parent.PATH_CONFIG, "OSC_IP_ADDRESS", self.parent.OSC_IP_ADDRESS) + def entry_ip_address_callback(self, event): + self.parent.OSC_IP_ADDRESS = self.entry_ip_address.get() + utils.save_json(self.parent.PATH_CONFIG, "OSC_IP_ADDRESS", self.parent.OSC_IP_ADDRESS) - def update_port(self): - value = self.entry_port.get() - if len(value) > 0: - self.parent.OSC_PORT = value - utils.save_json(self.parent.PATH_CONFIG, "OSC_PORT", self.parent.OSC_PORT) + def entry_port_callback(self, event): + self.parent.OSC_PORT = self.entry_port.get() + utils.save_json(self.parent.PATH_CONFIG, "OSC_PORT", self.parent.OSC_PORT) - def update_authkey(self): + def entry_authkey_callback(self, event): value = self.entry_authkey.get() if len(value) > 0: if self.parent.translator.authentication("DeepL(auth)", self.parent.AUTH_KEYS["DeepL(auth)"]) is True: @@ -636,7 +604,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): utils.print_textbox(self.parent.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") utils.print_textbox(self.parent.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") - def update_message_format(self): + def entry_message_format_callback(self, event): value = self.entry_message_format.get() if len(value) > 0: self.parent.MESSAGE_FORMAT = value From c495321021f7b5f6fe1658b9740e17d0675c9d57 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Thu, 15 Jun 2023 18:05:54 +0900 Subject: [PATCH 28/35] update information --- window_config.py | 4 ++-- window_information.py | 32 +++++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/window_config.py b/window_config.py index 3496d091..97cbe9d2 100644 --- a/window_config.py +++ b/window_config.py @@ -118,7 +118,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ## optionmenu translation input language self.label_translation_input_language = customtkinter.CTkLabel( self.tabview_config.tab("Translation"), - text="Input Language:", + text="Send Language:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) @@ -156,7 +156,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ## optionmenu translation output language self.label_translation_output_language = customtkinter.CTkLabel( self.tabview_config.tab("Translation"), - text="Output Language:", + text="Receive Language:", fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) diff --git a/window_information.py b/window_information.py index 48e55ed4..b2e5f2ec 100644 --- a/window_information.py +++ b/window_information.py @@ -18,7 +18,7 @@ class ToplevelWindowInformation(customtkinter.CTkToplevel): font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) self.textbox_information.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="nsew") - textbox_information_message = """VRCT(v0.4b) + textbox_information_message = """VRCT(v1.0) # 概要 VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツールになります。 @@ -41,16 +41,40 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ # その他の設定 translation チェックボックス: 翻訳の有効無効 + voice2chatbox チェックボックス : マイクの音声を文字起こししてチャットボックスに送信する + speaker2log チェックボックス : スピーカーの音声から文字起こししてログに表示する foreground チェックボックス: 最前面表示の有効無効 + テキストボックス + logタブ + すべてのログを表示 + sendタブ + 送信したメッセージを表示 + receiveタブ + 受信したメッセージを表示 + systemタブ + 機能についてのメッセージを表示 + configウィンドウ UIタブ - Select translator: 翻訳エンジンの変更 - Select Language: 翻訳する言語[source, target]を選択 Transparency: ウィンドウの透過度の調整 Appearance Theme: ウィンドウテーマを選択 UI Scaling: UIサイズを調整 Font Family: 表示フォントを選択 + Translationタブ + Select Translator: 翻訳エンジンの変更 + Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択 + Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択 + Transcriptionタブ + Input Mic Device: 音声を入力するマイクを選択 + Input Mic Voice Language: 入力する音声の言語 + Input Mic IsDynamic: マイクの自動調整 + Input Mic Threshold: 音声取得のしきい値 + Input Speaker Device: 音声を受信するスピーカーを選択 + Input Speaker Voice Language: 受信する音声の言語 + Input Speaker SamplingRate: 受信する音声の調整 + Input Speaker Interval: 受信する音声の調整 + Input Speaker BufferSize: 受信する音声の調整 Parameterタブ OSC IP address: 変更不要 OSC port: 変更不要 @@ -84,6 +108,8 @@ https://twitter.com/misya_ai [2023-06-06: v0.4b] - 翻訳エンジンを追加 - 入力と出力の翻訳言語を選択できるように変更 +[2023-06-15: v1.0] +- 文字起こし機能を追加 # 注意事項 再配布とかはやめてね From 2009b613ec3d080776d7826501493285617f5c66 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Fri, 16 Jun 2023 21:49:55 +0900 Subject: [PATCH 29/35] remove import package --- utils.py | 1 - window_config.py | 1 - 2 files changed, 2 deletions(-) diff --git a/utils.py b/utils.py index 2b93ac12..22234748 100644 --- a/utils.py +++ b/utils.py @@ -1,7 +1,6 @@ import json import datetime import threading -import tkinter as tk def save_json(path, key, value): with open(path, "r") as fp: diff --git a/window_config.py b/window_config.py index 97cbe9d2..e2c2ebbb 100644 --- a/window_config.py +++ b/window_config.py @@ -1,7 +1,6 @@ import os import tkinter as tk import customtkinter -from PIL import Image import utils class ToplevelWindowConfig(customtkinter.CTkToplevel): From 92e6ed92059b6dc48944fe1ee6cc9b264d57c655 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 20 Jun 2023 09:01:31 +0900 Subject: [PATCH 30/35] update spk process --- VRCT.py | 50 ++++++++------ transcription.py | 171 +++++++++++++++++++++++++++-------------------- window_config.py | 2 +- 3 files changed, 131 insertions(+), 92 deletions(-) diff --git a/VRCT.py b/VRCT.py index b6918330..aa591c87 100644 --- a/VRCT.py +++ b/VRCT.py @@ -1,6 +1,7 @@ import os import json -import threading +import queue +import time import customtkinter from PIL import Image @@ -41,7 +42,7 @@ class App(customtkinter.CTk): self.CHOICE_SPEAKER_DEVICE = None self.INPUT_SPEAKER_VOICE_LANGUAGE = "en-US" self.INPUT_SPEAKER_SAMPLING_RATE = 16000 - self.INPUT_SPEAKER_INTERVAL = 3 + self.INPUT_SPEAKER_INTERVAL = 4 self.INPUT_SPEAKER_BUFFER_SIZE = 4096 ## Parameter @@ -302,7 +303,9 @@ class App(customtkinter.CTk): utils.print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") ## set transcription instance - self.vr = transcription.VoiceRecognizer() + self.mic_queue = queue.Queue() + self.spk_queue = queue.Queue() + self.vr = transcription.VoiceRecognizer(self.mic_queue, self.spk_queue) self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else self.vr.search_default_device()[0] self.CHOICE_SPEAKER_DEVICE = self.CHOICE_SPEAKER_DEVICE if self.CHOICE_SPEAKER_DEVICE is not None else self.vr.search_default_device()[1] @@ -383,6 +386,7 @@ class App(customtkinter.CTk): device_name=self.CHOICE_MIC_DEVICE, threshold=int(self.INPUT_MIC_THRESHOLD), is_dynamic=self.INPUT_MIC_IS_DYNAMIC, + language=self.INPUT_MIC_VOICE_LANGUAGE, ) self.vr.init_mic() self.th_vr_listen_mic = utils.thread_fnc(self.vr_listen_mic) @@ -404,21 +408,18 @@ class App(customtkinter.CTk): if self.ENABLE_TRANSCRIPTION_RECEIVE is True: utils.print_textbox(self.textbox_message_log, "Start speaker2log", "INFO") utils.print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO") - # start threading + self.vr.set_spk( device_name=self.CHOICE_SPEAKER_DEVICE, - sample_rate=int(self.INPUT_SPEAKER_SAMPLING_RATE), interval=int(self.INPUT_SPEAKER_INTERVAL), - buffer_size=int(self.INPUT_SPEAKER_BUFFER_SIZE), + language=self.INPUT_SPEAKER_VOICE_LANGUAGE, ) - self.vr.init_spk() - self.th_vr_listen_spk = utils.thread_fnc(self.vr_listen_spk) + self.vr.start_spk_recording() self.th_vr_recognize_spk = utils.thread_fnc(self.vr_recognize_spk) - self.th_vr_listen_spk.start() self.th_vr_recognize_spk.start() else: - if isinstance(self.th_vr_listen_spk, utils.thread_fnc): - self.th_vr_listen_spk.stop() + if self.vr.spk_stream is not None: + self.vr.close_spk_stream() if isinstance(self.th_vr_recognize_spk, utils.thread_fnc): self.th_vr_recognize_spk.stop() @@ -430,7 +431,7 @@ class App(customtkinter.CTk): self.vr.listen_mic() def vr_recognize_mic(self): - message = self.vr.recognize_mic(language=self.INPUT_MIC_VOICE_LANGUAGE) + message = self.vr.recognize_mic() if len(message) > 0: # translate if self.checkbox_translation.get() is False: @@ -457,7 +458,7 @@ class App(customtkinter.CTk): self.vr.listen_spk() def vr_recognize_spk(self): - message = self.vr.recognize_spk(language=self.INPUT_SPEAKER_VOICE_LANGUAGE) + message = self.vr.recognize_spk() if len(message) > 0: # translate if self.checkbox_translation.get() is False: @@ -540,12 +541,23 @@ class App(customtkinter.CTk): self.attributes("-topmost", True) def delete_window(self): - thread_list = threading.enumerate() - thread_list.remove(threading.main_thread()) - for thread in thread_list: - thread.stop() + if isinstance(self.th_vr_listen_mic, utils.thread_fnc): + while not self.th_vr_listen_mic.stopped(): + self.th_vr_listen_mic.stop() + if isinstance(self.th_vr_recognize_mic, utils.thread_fnc): + while not self.th_vr_recognize_mic.stopped(): + self.th_vr_recognize_mic.stop() + if self.vr.spk_stream is not None: + self.vr.close_spk_stream() + if isinstance(self.th_vr_recognize_spk, utils.thread_fnc): + while not self.th_vr_recognize_spk.stopped(): + self.th_vr_recognize_spk.stop() self.destroy() + if __name__ == "__main__": - app = App() - app.mainloop() \ No newline at end of file + try: + app = App() + app.mainloop() + except Exception as e: + print(e) \ No newline at end of file diff --git a/transcription.py b/transcription.py index 07c8f9ce..991126a5 100644 --- a/transcription.py +++ b/transcription.py @@ -5,11 +5,14 @@ import soundcard as sc import soundfile as sf import sounddevice as sd import speech_recognition as sr +import pyaudiowpatch as pyaudio # VoiceRecognizer class VoiceRecognizer(): - def __init__(self): + def __init__(self, mic_queue, spk_queue): self.r = sr.Recognizer() + self.p = pyaudio.PyAudio() + self.languages = [ "ja-JP","en-US","en-GB","af-ZA","ar-DZ","ar-BH","ar-EG","ar-IL","ar-IQ","ar-JO","ar-KW","ar-LB","ar-MA", "ar-OM","ar-PS","ar-QA","ar-SA","ar-TN","ar-AE","eu-ES","bg-BG","ca-ES","cmn-Hans-CN","cmn-Hans-HK", @@ -23,47 +26,55 @@ class VoiceRecognizer(): self.mic_device_name = None self.mic_threshold = 50 self.mic_is_dynamic = False - self.mic_queue = queue.Queue() + self.mic_language = "ja-JP" + self.mic_queue = mic_queue - self.spk_device_name = None - self.spk_sample_rate = 16000 + self.spk_device = None self.spk_interval = 3 - self.spk_buffer_size = 4096 - self.spk_audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) - self.n = 0 - self.spk_queue = queue.Queue() + self.spk_language = "ja-JP" + self.spk_stream = None + self.spk_queue = spk_queue def search_input_device(self): + devices = [] device_list = sd.query_devices() - input_device_list = [] - for device in device_list: if device["max_input_channels"] > 0: - input_device_list.append({"name": device["name"], "index": device["index"]}) - - return input_device_list + devices.append(device) + return devices def search_output_device(self): - device_list = sc.all_speakers() - output_device_list = [] - - for device in device_list: - output_device_list.append(str(device.name)) - - return output_device_list + devices =[] + with pyaudio.PyAudio() as p: + wasapi_info = p.get_host_api_info_by_type(pyaudio.paWASAPI) + for host_index in range(0, p.get_host_api_count()): + for device_index in range(0, p. get_host_api_info_by_index(host_index)['deviceCount']): + device = p.get_device_info_by_host_api_device_index(host_index, device_index) + if device["hostApi"] == wasapi_info["index"] and device["isLoopbackDevice"] is True: + devices.append(device) + return devices def search_default_device(self): device_list = sd.query_devices() mic_index = sd.default.device[0] name_mic = device_list[mic_index]["name"] - name_spk = str(sc.default_speaker().name) + with pyaudio.PyAudio() as p: + wasapi_info = p.get_host_api_info_by_type(pyaudio.paWASAPI) + default_speakers = p.get_device_info_by_index(wasapi_info["defaultOutputDevice"]) + + if not default_speakers["isLoopbackDevice"]: + for loopback in p.get_loopback_device_info_generator(): + if default_speakers["name"] in loopback["name"]: + name_spk = loopback["name"] + break return name_mic, name_spk - def set_mic(self, device_name, threshold=50, is_dynamic=False): + def set_mic(self, device_name, threshold=50, is_dynamic=False, language="ja-JP"): input_device_list = self.search_input_device() self.mic_device_name = [device["index"] for device in input_device_list if device["name"] == device_name][0] self.mic_threshold = threshold self.mic_is_dynamic = is_dynamic + self.mic_language = language def init_mic(self): self.r.energy_threshold = self.mic_threshold @@ -76,79 +87,95 @@ class VoiceRecognizer(): audio = self.r.listen(source) self.mic_queue.put(audio) - def recognize_mic(self, language): + def recognize_mic(self): try: audio = self.mic_queue.get() - text = self.r.recognize_google(audio, language=language) + text = self.r.recognize_google(audio, language=self.mic_language) except: text = "" return text - def set_spk(self, device_name=str(sc.default_speaker().name), sample_rate=16000, interval=3, buffer_size=4096): - self.spk_device_name = device_name - self.spk_sample_rate = sample_rate + def set_spk(self, device_name, interval, language): + output_device_list = self.search_output_device() + self.spk_device = [device for device in output_device_list if device["name"] == device_name][0] self.spk_interval = interval - self.spk_buffer_size = buffer_size + self.spk_language = language - def init_spk(self): - self.spk_audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) - self.n = 0 + def spk_record_callback(self, in_data, frame_count, time_info, status): + self.spk_queue.put(in_data) + return (in_data, pyaudio.paContinue) - def listen_spk(self): - audio = self.spk_audio - n = self.n - with sc.get_microphone(id=self.spk_device_name, include_loopback=True).recorder(samplerate=self.spk_sample_rate, channels=1) as source: - while n < self.spk_sample_rate * self.spk_interval: - data = source.record(self.spk_buffer_size) - audio[n:n+len(data)] = data.reshape(-1) - n += len(data) - m = n * 4 // 5 - vol = np.convolve(audio[m:n] ** 2, np.ones(100) / 100, 'same') - m += vol.argmin() - audio_prev = audio.copy() - self.spk_queue.put(audio[:m]) - audio = np.empty(self.spk_sample_rate * self.spk_interval + self.spk_buffer_size, dtype=np.float32) - audio[:n-m] = audio_prev[m:n] - n = n-m - self.spk_audio = audio - self.n = n + def start_spk_recording(self): + self.close_spk_stream() + self.spk_stream = self.p.open(format=pyaudio.paInt16, + channels=self.spk_device["maxInputChannels"], + rate=int(self.spk_device["defaultSampleRate"]), + frames_per_buffer=int(self.spk_device["defaultSampleRate"])*self.spk_interval, + input=True, + input_device_index=self.spk_device["index"], + stream_callback=self.spk_record_callback + ) - def recognize_spk(self, language): + def stop_spk_stream(self): + self.spk_stream.stop_stream() + + def start_spk_stream(self): + self.spk_stream.start_stream() + + def close_spk_stream(self): + if self.spk_stream is not None: + self.spk_stream.stop_stream() + self.spk_stream.close() + self.spk_stream = None + + def recognize_spk(self): try: - audio = self.spk_queue.get() - with io.BytesIO() as memory_file: - sf.write(file=memory_file, data=audio, format="WAV", samplerate=self.spk_sample_rate) - memory_file.seek(0) - with sr.AudioFile(memory_file) as source: - audio = self.r.record(source) - text = self.r.recognize_google(audio, language=language) + in_data = self.spk_queue.get() + audio_data = sr.AudioData(in_data, int(self.spk_device["defaultSampleRate"]), self.spk_interval) + text = self.r.recognize_google(audio_data, language=self.spk_language) except: text = "" return text if __name__ == "__main__": - import time import threading - vr = VoiceRecognizer() - mic_name, spk_name = vr.search_default_device() - vr.spk_enable_recognize = True - vr.set_spk(language="ja-JP") - vr.init_spk() + mic_queue = queue.Queue() + spk_queue = queue.Queue() + vr = VoiceRecognizer(mic_queue, spk_queue) - def vr_listen_spk(): + mic_name, spk_name = vr.search_default_device() + print("mic_name", mic_name) + print("spk_name", spk_name) + + ############################################################### + vr.set_mic(device_name=mic_name, threshold=300, is_dynamic=False, language="ja-JP") + vr.init_mic() + + def vr_listen_mic(): while True: - vr.listen_spk() + vr.listen_mic() + + def vr_recognize_mic(): + while True: + text = vr.recognize_mic() + if len(text) > 0: + print(text) + th_vr_listen_mic = threading.Thread(target=vr_listen_mic) + th_vr_listen_mic.start() + th_vr_recognize_mic = threading.Thread(target=vr_recognize_mic) + th_vr_recognize_mic.start() + ############################################################### + + ############################################################### + vr.set_spk(device_name=spk_name, interval=4, language="ja-JP") + vr.start_spk_recording() def vr_recognize_spk(): while True: text = vr.recognize_spk() - print(text) - - th_vr_listen_spk = threading.Thread(target=vr_listen_spk) + if len(text) > 0: + print(text) th_vr_recognize_spk = threading.Thread(target=vr_recognize_spk) - th_vr_listen_spk.start() th_vr_recognize_spk.start() - - while True: - time.sleep(60) \ No newline at end of file + ############################################################### \ No newline at end of file diff --git a/window_config.py b/window_config.py index e2c2ebbb..5efa71fb 100644 --- a/window_config.py +++ b/window_config.py @@ -273,7 +273,7 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.label_input_speaker_device.grid(row=4, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.optionmenu_input_speaker_device = customtkinter.CTkOptionMenu( self.tabview_config.tab("Transcription"), - values=self.parent.vr.search_output_device(), + values=[device["name"] for device in self.parent.vr.search_output_device()], command=self.optionmenu_input_speaker_device_callback, font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY), variable=customtkinter.StringVar(value=self.parent.CHOICE_SPEAKER_DEVICE), From 3e246b7aa6c1fce01bcb81d9c03908cc64e39f87 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 20 Jun 2023 10:41:32 +0900 Subject: [PATCH 31/35] update transcription add daemon=True --- VRCT.py | 18 ++++-------------- transcription.py | 10 +++------- utils.py | 4 ++-- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/VRCT.py b/VRCT.py index aa591c87..11983318 100644 --- a/VRCT.py +++ b/VRCT.py @@ -1,9 +1,9 @@ import os import json import queue -import time import customtkinter from PIL import Image +import pyaudiowpatch as pyaudio import utils import translation @@ -305,7 +305,8 @@ class App(customtkinter.CTk): ## set transcription instance self.mic_queue = queue.Queue() self.spk_queue = queue.Queue() - self.vr = transcription.VoiceRecognizer(self.mic_queue, self.spk_queue) + self.p = pyaudio.PyAudio() + self.vr = transcription.VoiceRecognizer(self.p, self.mic_queue, self.spk_queue) self.CHOICE_MIC_DEVICE = self.CHOICE_MIC_DEVICE if self.CHOICE_MIC_DEVICE is not None else self.vr.search_default_device()[0] self.CHOICE_SPEAKER_DEVICE = self.CHOICE_SPEAKER_DEVICE if self.CHOICE_SPEAKER_DEVICE is not None else self.vr.search_default_device()[1] @@ -541,20 +542,9 @@ class App(customtkinter.CTk): self.attributes("-topmost", True) def delete_window(self): - if isinstance(self.th_vr_listen_mic, utils.thread_fnc): - while not self.th_vr_listen_mic.stopped(): - self.th_vr_listen_mic.stop() - if isinstance(self.th_vr_recognize_mic, utils.thread_fnc): - while not self.th_vr_recognize_mic.stopped(): - self.th_vr_recognize_mic.stop() - if self.vr.spk_stream is not None: - self.vr.close_spk_stream() - if isinstance(self.th_vr_recognize_spk, utils.thread_fnc): - while not self.th_vr_recognize_spk.stopped(): - self.th_vr_recognize_spk.stop() + self.quit() self.destroy() - if __name__ == "__main__": try: app = App() diff --git a/transcription.py b/transcription.py index 991126a5..9a746d79 100644 --- a/transcription.py +++ b/transcription.py @@ -1,17 +1,12 @@ -import io -import queue -import numpy as np -import soundcard as sc -import soundfile as sf import sounddevice as sd import speech_recognition as sr import pyaudiowpatch as pyaudio # VoiceRecognizer class VoiceRecognizer(): - def __init__(self, mic_queue, spk_queue): + def __init__(self, p_audio, mic_queue, spk_queue): self.r = sr.Recognizer() - self.p = pyaudio.PyAudio() + self.p = p_audio self.languages = [ "ja-JP","en-US","en-GB","af-ZA","ar-DZ","ar-BH","ar-EG","ar-IL","ar-IQ","ar-JO","ar-KW","ar-LB","ar-MA", @@ -138,6 +133,7 @@ class VoiceRecognizer(): return text if __name__ == "__main__": + import queue import threading mic_queue = queue.Queue() diff --git a/utils.py b/utils.py index 22234748..234bacf7 100644 --- a/utils.py +++ b/utils.py @@ -26,8 +26,8 @@ def print_textbox(textbox, message, tags=None): textbox.see("end") class thread_fnc(threading.Thread): - def __init__(self, fnc, *args, **kwargs): - super(thread_fnc, self).__init__(*args, **kwargs) + def __init__(self, fnc, daemon=True, *args, **kwargs): + super(thread_fnc, self).__init__(daemon=daemon, *args, **kwargs) self.fnc = fnc self._stop = threading.Event() def stop(self): From ab1c9f52549c4d1ed7d0a3b8aea82af4fe5098fd Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 20 Jun 2023 10:46:09 +0900 Subject: [PATCH 32/35] remove Parameters INPUT_SPEAKER_SAMPLING_RATE/INPUT_SPEAKER_BUFFER_SIZE --- VRCT.py | 8 -------- window_config.py | 48 ++---------------------------------------------- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/VRCT.py b/VRCT.py index 11983318..b319e009 100644 --- a/VRCT.py +++ b/VRCT.py @@ -41,9 +41,7 @@ class App(customtkinter.CTk): self.INPUT_MIC_THRESHOLD = 300 self.CHOICE_SPEAKER_DEVICE = None self.INPUT_SPEAKER_VOICE_LANGUAGE = "en-US" - self.INPUT_SPEAKER_SAMPLING_RATE = 16000 self.INPUT_SPEAKER_INTERVAL = 4 - self.INPUT_SPEAKER_BUFFER_SIZE = 4096 ## Parameter self.OSC_IP_ADDRESS = "127.0.0.1" @@ -105,12 +103,8 @@ class App(customtkinter.CTk): self.CHOICE_SPEAKER_DEVICE = config["CHOICE_SPEAKER_DEVICE"] if "INPUT_SPEAKER_VOICE_LANGUAGE" in config.keys(): self.INPUT_SPEAKER_VOICE_LANGUAGE = config["INPUT_SPEAKER_VOICE_LANGUAGE"] - if "INPUT_SPEAKER_SAMPLING_RATE" in config.keys(): - self.INPUT_SPEAKER_SAMPLING_RATE = config["INPUT_SPEAKER_SAMPLING_RATE"] if "INPUT_SPEAKER_INTERVAL" in config.keys(): self.INPUT_SPEAKER_INTERVAL = config["INPUT_SPEAKER_INTERVAL"] - if "INPUT_SPEAKER_BUFFER_SIZE" in config.keys(): - self.INPUT_SPEAKER_BUFFER_SIZE = config["INPUT_SPEAKER_BUFFER_SIZE"] # Parameter if "OSC_IP_ADDRESS" in config.keys(): @@ -143,9 +137,7 @@ class App(customtkinter.CTk): "INPUT_MIC_THRESHOLD": self.INPUT_MIC_THRESHOLD, "CHOICE_SPEAKER_DEVICE": self.CHOICE_SPEAKER_DEVICE, "INPUT_SPEAKER_VOICE_LANGUAGE": self.INPUT_SPEAKER_VOICE_LANGUAGE, - "INPUT_SPEAKER_SAMPLING_RATE": self.INPUT_SPEAKER_SAMPLING_RATE, "INPUT_SPEAKER_INTERVAL": self.INPUT_SPEAKER_INTERVAL, - "INPUT_SPEAKER_BUFFER_SIZE": self.INPUT_SPEAKER_BUFFER_SIZE, "OSC_IP_ADDRESS": self.OSC_IP_ADDRESS, "OSC_PORT": self.OSC_PORT, "AUTH_KEYS": self.AUTH_KEYS, diff --git a/window_config.py b/window_config.py index 5efa71fb..f3b75268 100644 --- a/window_config.py +++ b/window_config.py @@ -297,22 +297,6 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): ) self.optionmenu_input_speaker_voice_language.grid(row=5, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") - ## entry input speaker sampling rate - self.label_input_speaker_sampling_rate = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Speaker SamplingRate:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_input_speaker_sampling_rate.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.entry_input_speaker_sampling_rate = customtkinter.CTkEntry( - self.tabview_config.tab("Transcription"), - textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_SAMPLING_RATE), - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.entry_input_speaker_sampling_rate.grid(row=6, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") - self.entry_input_speaker_sampling_rate.bind("", self.entry_input_speaker_sampling_rate_callback) - ## entry input speaker interval self.label_input_speaker_interval = customtkinter.CTkLabel( self.tabview_config.tab("Transcription"), @@ -320,31 +304,15 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): fg_color="transparent", font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.label_input_speaker_interval.grid(row=7, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") + self.label_input_speaker_interval.grid(row=6, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") self.entry_input_speaker_interval = customtkinter.CTkEntry( self.tabview_config.tab("Transcription"), textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_INTERVAL), font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) ) - self.entry_input_speaker_interval.grid(row=7, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") + self.entry_input_speaker_interval.grid(row=6, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") self.entry_input_speaker_interval.bind("", self.entry_input_speaker_interval_callback) - ## entry input speaker buffer size - self.label_input_speaker_buffer_size = customtkinter.CTkLabel( - self.tabview_config.tab("Transcription"), - text="Input Speaker BufferSize:", - fg_color="transparent", - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.label_input_speaker_buffer_size.grid(row=8, column=0, columnspan=1, padx=5, pady=5, sticky="nsw") - self.entry_input_speaker_buffer_size = customtkinter.CTkEntry( - self.tabview_config.tab("Transcription"), - textvariable=customtkinter.StringVar(value=self.parent.INPUT_SPEAKER_BUFFER_SIZE), - font=customtkinter.CTkFont(family=self.parent.FONT_FAMILY) - ) - self.entry_input_speaker_buffer_size.grid(row=8, column=1, columnspan=1 ,padx=5, pady=5, sticky="nsew") - self.entry_input_speaker_buffer_size.bind("", self.entry_input_speaker_buffer_size_callback) - # tab Parameter ## entry ip address self.label_ip_address = customtkinter.CTkLabel( @@ -463,12 +431,8 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.optionmenu_input_speaker_device.configure(font=customtkinter.CTkFont(family=choice)) self.label_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) self.optionmenu_input_speaker_voice_language.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_sampling_rate.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_input_speaker_sampling_rate.configure(font=customtkinter.CTkFont(family=choice)) self.label_input_speaker_interval.configure(font=customtkinter.CTkFont(family=choice)) self.entry_input_speaker_interval.configure(font=customtkinter.CTkFont(family=choice)) - self.label_input_speaker_buffer_size.configure(font=customtkinter.CTkFont(family=choice)) - self.entry_input_speaker_buffer_size.configure(font=customtkinter.CTkFont(family=choice)) # tab Parameter self.label_ip_address.configure(font=customtkinter.CTkFont(family=choice)) @@ -571,18 +535,10 @@ class ToplevelWindowConfig(customtkinter.CTkToplevel): self.parent.INPUT_SPEAKER_VOICE_LANGUAGE = choice utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_VOICE_LANGUAGE", self.parent.INPUT_SPEAKER_VOICE_LANGUAGE) - def entry_input_speaker_sampling_rate_callback(self, event): - self.parent.INPUT_SPEAKER_SAMPLING_RATE = int(self.entry_input_speaker_sampling_rate.get()) - utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_SAMPLING_RATE", self.parent.INPUT_SPEAKER_SAMPLING_RATE) - def entry_input_speaker_interval_callback(self, event): self.parent.INPUT_SPEAKER_INTERVAL = int(self.entry_input_speaker_interval.get()) utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_INTERVAL", self.parent.INPUT_SPEAKER_INTERVAL) - def entry_input_speaker_buffer_size_callback(self, event): - self.parent.INPUT_SPEAKER_BUFFER_SIZE = int(self.entry_input_speaker_buffer_size.get()) - utils.save_json(self.parent.PATH_CONFIG, "INPUT_SPEAKER_BUFFER_SIZE", self.parent.INPUT_SPEAKER_BUFFER_SIZE) - def entry_ip_address_callback(self, event): self.parent.OSC_IP_ADDRESS = self.entry_ip_address.get() utils.save_json(self.parent.PATH_CONFIG, "OSC_IP_ADDRESS", self.parent.OSC_IP_ADDRESS) From 2c1d75c55f98cfc06422b10037f77574eb881416 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 20 Jun 2023 10:56:42 +0900 Subject: [PATCH 33/35] add save error log --- VRCT.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VRCT.py b/VRCT.py index b319e009..c138dcde 100644 --- a/VRCT.py +++ b/VRCT.py @@ -542,4 +542,5 @@ if __name__ == "__main__": app = App() app.mainloop() except Exception as e: - print(e) \ No newline at end of file + with open("./error.log", "r") as fp: + fp.write(f"{e}") \ No newline at end of file From c99f49ca7b711bebf224581932c3821a15ce24f2 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 20 Jun 2023 10:59:51 +0900 Subject: [PATCH 34/35] update information --- window_information.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/window_information.py b/window_information.py index b2e5f2ec..2b7056e9 100644 --- a/window_information.py +++ b/window_information.py @@ -72,9 +72,7 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ Input Mic Threshold: 音声取得のしきい値 Input Speaker Device: 音声を受信するスピーカーを選択 Input Speaker Voice Language: 受信する音声の言語 - Input Speaker SamplingRate: 受信する音声の調整 Input Speaker Interval: 受信する音声の調整 - Input Speaker BufferSize: 受信する音声の調整 Parameterタブ OSC IP address: 変更不要 OSC port: 変更不要 @@ -108,8 +106,9 @@ https://twitter.com/misya_ai [2023-06-06: v0.4b] - 翻訳エンジンを追加 - 入力と出力の翻訳言語を選択できるように変更 -[2023-06-15: v1.0] -- 文字起こし機能を追加 +[2023-06-20: v1.0] +- マイクからの音声の文字起こし機能を追加 +- スピーカーからの音声の文字起こし機能を追加 # 注意事項 再配布とかはやめてね From 19ae8e05b11944435370234287841b331e005817 Mon Sep 17 00:00:00 2001 From: misyaguziya Date: Tue, 20 Jun 2023 11:11:29 +0900 Subject: [PATCH 35/35] update readme --- REDME.txt | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/REDME.txt b/REDME.txt index 50abae82..c13a7629 100644 --- a/REDME.txt +++ b/REDME.txt @@ -11,7 +11,7 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ   0. VRChatのOSCを有効にする(重要)   (任意) - 1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する +  1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する   2. ギアアイコンのボタンでconfigウィンドウを開く   3. ParameterタブのDeepL Auth Keyに認証キーを記載し、フロッピーアイコンのボタンを押す   4. configウィンドウを閉じる @@ -22,16 +22,34 @@ VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツ  その他の設定   - translation チェックボックス: 翻訳の有効無効 +  - voice2chatbox チェックボックス : マイクの音声を文字起こししてチャットボックスに送信する +  - speaker2log チェックボックス : スピーカーの音声から文字起こししてログに表示する   - foreground チェックボックス: 最前面表示の有効無効 -  - Configウィンドウ -   - GUIタブ -    - Select translator: 翻訳エンジンの変更 -    - Select Language: 翻訳する言語[source, target]を選択 +   - テキストボックス +    - logタブ: すべてのログを表示 +    - sendタブ: 送信したメッセージを表示 +    - receiveタブ: 受信したメッセージを表示 +    - systemタブ: 機能についてのメッセージを表示 + +  - configウィンドウ +   - UIタブ     - Transparency: ウィンドウの透過度の調整     - Appearance Theme: ウィンドウテーマを選択     - UI Scaling: UIサイズを調整     - Font Family: 表示フォントを選択 +   - Translationタブ +    - Select Translator: 翻訳エンジンの変更 +    - Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択 +    - Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択 +   - Transcriptionタブ +    - Input Mic Device: 音声を入力するマイクを選択 +    - Input Mic Voice Language: 入力する音声の言語 +    - Input Mic IsDynamic: マイクの自動調整 +    - Input Mic Threshold: 音声取得のしきい値 +    - Input Speaker Device: 音声を受信するスピーカーを選択 +    - Input Speaker Voice Language: 受信する音声の言語 +    - Input Speaker Interval: 受信する音声の調整   - Parameterタブ     - OSC IP address: 変更不要     - OSC port: 変更不要 @@ -64,4 +82,10 @@ https://twitter.com/misya_ai - フォントの変更機能を追加 [2023-06-06: v0.4b] - 翻訳エンジンを追加 -- 入力と出力の翻訳言語を選択できるように変更 \ No newline at end of file +- 入力と出力の翻訳言語を選択できるように変更 +[2023-06-20: v1.0] +- マイクからの音声の文字起こし機能を追加 +- スピーカーからの音声の文字起こし機能を追加 + +# 注意事項 +再配布とかはやめてね \ No newline at end of file