-| [English](./README.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | **繁體中文** |
+| [English](/docs/readmes/README.en.md) | [日本語](/docs/readmes/README.ja.md) | [한국어](/docs/readmes/README.ko.md) | **繁體中文** |
@@ -90,15 +90,6 @@ VRCT 可以:
-# 原始碼啟動
-1. 安裝此版本的 Python。
- `python version 3.11.5`
-2. 安裝 package 並啟動 main.py。
- ```bash
- ./install.bat
- python main.py
- ```
-
## 作者
- [みしゃ(misyaguzi)](https://github.com/misyaguziya) (主要開發)
- [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI 多語系支援)
diff --git a/locales/en.yml b/locales/en.yml
index 7c677718..a52ac107 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -8,13 +8,13 @@ common:
common_error:
no_device_mic: "No mic device detected."
- no_device_speaker: "No Speaker device detected."
+ no_device_speaker: "No speaker device detected."
threshold_invalid_value: "You can set it with a value between {{min}} to {{max}}."
failed_download_weight_ctranslate2: "CTranslate2 weight download error."
failed_download_weight_whisper: "Whisper weight download error."
- translation_limit: "Translation engine limit error."
+ translation_limit: "Translation engine limit reached or temporarily restricted."
deepl_auth_key_invalid_length: "DeepL auth key length is not correct."
- deepl_auth_key_failed_authentication: "Auth Key is incorrect or Usage limit reached."
+ deepl_auth_key_failed_authentication: "Auth key is incorrect or API usage limit reached."
invalid_value_mic_record_timeout: "It cannot be greater than '{{mic_phrase_timeout_label}}' with a value of 0 or more."
invalid_value_mic_phrase_timeout: "It cannot be set lower than '{{mic_record_timeout_label}}' with a value of 0 or more."
@@ -28,18 +28,18 @@ main_page:
translation: "Translation"
transcription_send: "Voice2Chatbox"
transcription_receive: "Speaker2Log"
- foreground: "Foreground"
+ foreground: "Set To Stay On Top"
language_settings: "Language Settings"
your_language: "Your Language"
- translate_each_other_label: "Translate Each Other"
- swap_button_label: "Swap Languages"
+ translate_each_other_label: "Translate Both Languages"
+ swap_button_label: "Switch Languages"
target_language: "Target Language"
translator: "Translator"
translator_label_default: "Default"
translator_selector:
- is_selected_same_language: "Since the same language is selected for both '{{your_language}}' and '{{target_language}}', only '{{ctranslate2}}' is available."
+ is_selected_same_language: "You are selecting the same language for '{{your_language}}' and '{{target_language}}' so only '{{ctranslate2}}' is available."
message_log:
all: "All"
@@ -48,7 +48,7 @@ main_page:
system: "System"
show_resend_button: "Show Resend Button"
- resend_button_on_hover_desc: "Press and hold to send"
+ resend_button_on_hover_desc: "Press And Hold To Send"
state_text_enabled: "Enabled"
state_text_disabled: "Disabled"
@@ -57,28 +57,28 @@ main_page:
title_your_language: "Select Your Language"
title_target_language: "Select Target Language"
- update_available: "New version is here!"
+ update_available: "New version is ready!"
updating: "Now updating..."
update_modal:
cpu_desc: "Use CPU only as the compute device."
cuda_desc: "Selectable between CPU and NVIDIA GPUs as compute devices."
- cuda_compare_cpu_desc: "With GPU selection, processing is faster compared to a CPU."
+ cuda_compare_cpu_desc: "GPUs offer faster processing than CPUs."
cuda_disk_space_desc: "Requires approximately {{size}} of disk space."
close_modal: "Close"
download_latest_and_restart: "The latest version will be downloaded,\nand the app will automatically restart."
is_latest_version_already: "Already using the latest version"
- is_current_compute_device: "Currently using this version"
+ is_current_compute_device: "The version currently in use"
config_page:
- version: "version {{version}}"
+ version: "Version {{version}}"
model_download_button_label: "Download"
side_menu_labels:
device: "Device"
appearance: "Appearance"
translation: "Translation"
transcription: "Transcription"
- others: "Others"
+ others: "Other"
hotkeys: "Hotkeys"
advanced_settings: "Advanced Settings"
@@ -90,17 +90,17 @@ config_page:
mic_host_device:
label: "Mic Device"
mic_dynamic_energy_threshold:
- label_for_automatic: "Mic Energy Threshold (Current Setting: Automatic)"
- desc_for_automatic: "Automatically determine microphone input sensitivity."
- label_for_manual: "Mic Energy Threshold (Current Setting: Manual)"
- desc_for_manual: "Manually determine the microphone input sensitivity using the slider. Press the microphone icon to input your voice and adjust the sensitivity while monitoring the volume."
+ label_for_automatic: "Mic Sensitivity Settings (Current Setting: Automatic)"
+ desc_for_automatic: "Automatically control mic input sensitivity."
+ label_for_manual: "Mic Sensitivity Settings (Current Setting: Manual)"
+ desc_for_manual: "Input sensitivity can be manually adjusted using the slider. Click the mic icon to test your voice input and adjust the level while monitoring the volume."
speaker_device:
label: "Speaker Device"
speaker_dynamic_energy_threshold:
- label_for_automatic: "Speaker Energy Threshold (Current Setting: Automatic)"
- desc_for_automatic: "Automatically determine speaker input sensitivity."
- label_for_manual: "Speaker Energy Threshold (Current Setting: Manual)"
- desc_for_manual: "Manually determine the speaker input sensitivity using the slider. Press the headphones icon to listen to the audio and adjust the sensitivity while monitoring the volume."
+ label_for_automatic: "Speaker Input Sensitivity Adjustment (Current Setting: Automatic)"
+ desc_for_automatic: "Automatically control speaker input sensitivity."
+ label_for_manual: "Speaker Input Sensitivity Adjustment (Current Setting: Manual)"
+ desc_for_manual: "Input sensitivity can be manually adjusted using the slider. Click the headphone icon to listen to the audio and adjust the level while checking the volume."
appearance:
transparency:
@@ -110,12 +110,12 @@ config_page:
label: "UI Size"
textbox_ui_size:
label: "Message Logs Font Size"
- desc: "You can adjust the font size used in the logs relative to the UI size."
+ desc: "You can adjust the log font size by changing the scaling factor relative to the UI size."
send_message_button_type:
label: "Send Message Button"
- hide: "Hide (Use enter key to send)"
+ hide: "Hide (Use Enter key to send)"
show: "Show"
- show_and_disable_enter_key: "Show and disable to send when pressed enter key"
+ show_and_disable_enter_key: "Show and disable sending using the Enter key."
font_family:
label: "Font Family"
ui_language:
@@ -124,14 +124,14 @@ config_page:
translation:
ctranslate2_weight_type:
label: "{{ctranslate2}} Model"
- desc: "You can choose the translation model to use for the internal translation engine."
- small: "Basic model ({{capacity}})"
- large: "High accuracy model ({{capacity}})"
+ desc: "You can choose the translation model when using the {{ctranslate2}} translation engine."
+ small: "Basic Model ({{capacity}})"
+ large: "High Accuracy Model ({{capacity}})"
ctranslate2_compute_device:
- label: "{{ctranslate2}} Compute Device"
+ label: "Processing device for AI translation {{ctranslate2}}"
deepl_auth_key:
label: "DeepL Auth Key"
- desc: "Please select {{translator}} on the main screen with DeepL_API when using. ※Some languages may not be supported."
+ desc: "When using it, please change {{translator}} on the main screen to DeepL_API. ※Some languages may not be supported."
open_auth_key_webpage: "Open DeepL Account Webpage"
save: "Save"
edit: "Edit"
@@ -143,7 +143,7 @@ config_page:
section_label_transcription_engines: "Transcription Engines"
mic_record_timeout:
label: "Mic Record Timeout"
- desc: "Detects silence and, when the specified number of seconds has passed, considers the mic input to have ended. (Second(s))"
+ desc: "Detects silence and, when the specified number of seconds passes, the system considers the voice input to have ended. (Second(s))"
mic_phrase_timeout:
label: "Mic Phrase Timeout"
desc: "Transcription processing is performed at intervals of the specified number of seconds."
@@ -152,9 +152,9 @@ config_page:
desc: "It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs and send to VRChat."
mic_word_filter:
label: "Mic Word Filter"
- desc: "If a registered word is detected, the text will not be sent. To add multiple words at once, separate them with a ',' (comma).\n*Duplicate words will not be registered."
+ desc: "If a registered word is detected, the message will not be sent. To add multiple words at once, separate them with ',' (comma).\n*Duplicate words will not be registered."
add_button_label: "Add"
- count_desc: "Current registered word count: {{count}}"
+ count_desc: "Words Currently Registered: {{count}}"
speaker_record_timeout:
label: "Speaker Record Timeout"
desc: "Detects silence and, when the specified number of seconds has passed, considers the speaker input to have ended. (Second(s))"
@@ -165,20 +165,20 @@ config_page:
label: "Speaker Max Words"
desc: "It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs."
select_transcription_engine:
- label: "Transcription Engine"
+ label: "Transcription Engine Used For Speech Recognition"
whisper_weight_type:
label: "Whisper Model"
- desc: "Larger models tend to have higher accuracy, but they also consume more CPU or GPU resources.\nEspecially for models larger than medium, it may be difficult or even impossible to use them depending on the performance of your CPU/GPU."
+ desc: "Larger models have higher accuracy, but they also consume more CPU or GPU resources.\nEspecially for models larger than medium, it may be difficult or even impossible to use them depending on the performance of your CPU/GPU."
model_template: "{{model_name}} model ({{capacity}})"
recommended_model_template: "{{model_name}} model ({{capacity}}) (Recommended)"
whisper_compute_device:
- label: "Whisper Compute Device"
+ label: "Processing Device Used For Whisper"
vr:
single_line: "Single line"
- multi_lines: "Multi lines"
+ multi_lines: "Multiple Lines"
overlay_enable: "Enable"
- restore_default_settings: "Restore Default Settings"
+ restore_default_settings: "Reset to Default Settings"
position: "Position"
rotation: "Rotation"
x_position: "X-axis (left-right)"
@@ -188,46 +188,46 @@ config_page:
y_rotation: "Y-axis rotation"
z_rotation: "Z-axis rotation"
sample_text_button:
- start: "Send sample texts\nto Overlay"
+ start: "Send Sample Texts\nTo Overlay"
stop: "Stop Sending"
- sample_text: "Sample text."
+ sample_text: "Sample Text."
opacity: "Opacity"
ui_scaling: "UI Scaling"
- display_duration: "Display duration"
- fadeout_duration: "Fadeout duration"
+ display_duration: "Display Duration"
+ fadeout_duration: "Fadeout Duration"
common_settings: "Common Settings"
tracker: "Tracker"
hmd: "HMD"
- left_hand: "Left hand"
- right_hand: "Right hand"
+ left_hand: "Left Hand"
+ right_hand: "Right Hand"
overlay_show_only_translated_messages:
label: "Show Only Translated Messages"
others:
section_label_sounds: "Sounds"
auto_clear_the_message_box:
- label: "Auto Clear The Message Box"
+ label: "Auto Clear Message box"
send_only_translated_messages:
label: "Send Only Translated Messages"
auto_export_message_logs:
- label: "Auto Export Message Logs"
- desc: "Automatically export the conversation messages as a text file."
+ label: "Auto Save Message Logs"
+ desc: "Automatically saves the conversation messages as text files."
vrc_mic_mute_sync:
label: "VRC Mic Mute Sync"
- desc: "VRCT will not send the message to VRChat while VRChat's mic is muted.\n*There is a bit latency and Push-To-Talk is not supported."
+ desc: "Messages will not be sent to VRCT while VRChat's mic is muted.\n*There may be a slight delay. Push-To-Talk is not supported."
send_message_to_vrc:
label: "Send Message To VRChat"
- desc: "There is a way to use it without sending messages to VRChat, but it is not supported. Enable this feature when you intend to send a message to VRChat."
+ desc: "This feature is not supported, but there is a way to use it without sending messages to VRChat. Make sure to enable this feature when you wish to send messages to VRChat."
notification_vrc_sfx:
label: "Enable Notification Sound When Sending Chat"
- desc: "Disabling this feature will send chats quietly without playing a notification sound that others can hear."
+ desc: "When this feature is disabled, messages will be sent silently without playing the chatbox notification sound that others can hear."
send_received_message_to_vrc:
label: "Send Received Message To VRChat"
- desc: "Send the message you received from the speaker's sound to VRChat's chatbox."
+ desc: "Send the message you received from the speaker's voice to VRChat's chatbox."
hotkeys:
toggle_vrct_visibility:
- label: "Toggle VRCT Visibility"
+ label: "Toggle VRCT visibility"
toggle_translation:
label: "Toggle {{translation}}"
toggle_transcription_send:
@@ -243,4 +243,4 @@ config_page:
open_config_filepath:
label: "Open Config File"
switch_compute_device:
- label: "Switch VRCT to CPU/GPU Version"
\ No newline at end of file
+ label: "Switch VRCT To CPU/GPU Version"
\ No newline at end of file
diff --git a/src-python/config.py b/src-python/config.py
index 8038b047..879b90e5 100644
--- a/src-python/config.py
+++ b/src-python/config.py
@@ -956,7 +956,7 @@ class Config:
def init_config(self):
# Read Only
- self._VERSION = "3.0.4"
+ self._VERSION = "3.0.5"
if getattr(sys, 'frozen', False):
self._PATH_LOCAL = os_path.dirname(sys.executable)
else:
diff --git a/src-python/controller.py b/src-python/controller.py
index faa659b2..c0f5dabc 100644
--- a/src-python/controller.py
+++ b/src-python/controller.py
@@ -6,7 +6,7 @@ import re
from device_manager import device_manager
from config import config
from model import model
-from utils import removeLog, printLog, errorLogging, isConnectedNetwork
+from utils import removeLog, printLog, errorLogging, isConnectedNetwork, isValidIpAddress
class Controller:
def __init__(self) -> None:
@@ -150,7 +150,7 @@ class Controller:
400,
self.run_mapping["error_device"],
{
- "message":"No Speaker device detected",
+ "message":"No speaker device detected",
"data": None
},
)
@@ -1094,9 +1094,29 @@ class Controller:
@staticmethod
def setOscIpAddress(data, *args, **kwargs) -> dict:
- config.OSC_IP_ADDRESS = data
- model.setOscIpAddress(config.OSC_IP_ADDRESS)
- return {"status":200, "result":config.OSC_IP_ADDRESS}
+ if isValidIpAddress(data) is False:
+ response = {
+ "status":400,
+ "result":{
+ "message":"Invalid IP address",
+ "data": config.OSC_IP_ADDRESS
+ }
+ }
+ else:
+ try:
+ model.setOscIpAddress(data)
+ config.OSC_IP_ADDRESS = data
+ response = {"status":200, "result":config.OSC_IP_ADDRESS}
+ except Exception:
+ model.setOscIpAddress(config.OSC_IP_ADDRESS)
+ response = {
+ "status":400,
+ "result":{
+ "message":"Cannot set IP address",
+ "data": config.OSC_IP_ADDRESS
+ }
+ }
+ return response
@staticmethod
def getOscPort(*args, **kwargs) -> dict:
diff --git a/src-python/model.py b/src-python/model.py
index afe0d565..8f62aa5e 100644
--- a/src-python/model.py
+++ b/src-python/model.py
@@ -400,83 +400,83 @@ class Model:
mic_device_list = device_manager.getMicDevices().get(mic_host_name, [{"name": "NoDevice"}])
selected_mic_device = [device for device in mic_device_list if device["name"] == mic_device_name]
- if len(selected_mic_device) == 0:
- return False
+ if len(selected_mic_device) == 0 or mic_device_name == "NoDevice":
+ fnc({"text": False, "language": None})
+ else:
+ self.mic_audio_queue = Queue()
+ # self.mic_energy_queue = Queue()
- self.mic_audio_queue = Queue()
- # self.mic_energy_queue = Queue()
+ mic_device = selected_mic_device[0]
+ record_timeout = config.MIC_RECORD_TIMEOUT
+ phrase_timeout = config.MIC_PHRASE_TIMEOUT
+ if record_timeout > phrase_timeout:
+ record_timeout = phrase_timeout
- mic_device = selected_mic_device[0]
- record_timeout = config.MIC_RECORD_TIMEOUT
- phrase_timeout = config.MIC_PHRASE_TIMEOUT
- if record_timeout > phrase_timeout:
- record_timeout = phrase_timeout
+ self.mic_audio_recorder = SelectedMicEnergyAndAudioRecorder(
+ device=mic_device,
+ energy_threshold=config.MIC_THRESHOLD,
+ dynamic_energy_threshold=config.MIC_AUTOMATIC_THRESHOLD,
+ phrase_time_limit=record_timeout,
+ )
+ # self.mic_audio_recorder.recordIntoQueue(self.mic_audio_queue, mic_energy_queue)
+ self.mic_audio_recorder.recordIntoQueue(self.mic_audio_queue, None)
+ self.mic_transcriber = AudioTranscriber(
+ speaker=False,
+ source=self.mic_audio_recorder.source,
+ phrase_timeout=phrase_timeout,
+ max_phrases=config.MIC_MAX_PHRASES,
+ transcription_engine=config.SELECTED_TRANSCRIPTION_ENGINE,
+ root=config.PATH_LOCAL,
+ whisper_weight_type=config.WHISPER_WEIGHT_TYPE,
+ device=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device"],
+ device_index=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device_index"],
+ )
+ def sendMicTranscript():
+ try:
+ selected_your_languages = config.SELECTED_YOUR_LANGUAGES[config.SELECTED_TAB_NO]
+ languages = [data["language"] for data in selected_your_languages.values() if data["enable"] is True]
+ countries = [data["country"] for data in selected_your_languages.values() if data["enable"] is True]
+ if isinstance(self.mic_transcriber, AudioTranscriber) is True:
+ res = self.mic_transcriber.transcribeAudioQueue(
+ self.mic_audio_queue,
+ languages,
+ countries,
+ config.MIC_AVG_LOGPROB,
+ config.MIC_NO_SPEECH_PROB
+ )
+ if res:
+ result = self.mic_transcriber.getTranscript()
+ fnc(result)
+ except Exception:
+ errorLogging()
- self.mic_audio_recorder = SelectedMicEnergyAndAudioRecorder(
- device=mic_device,
- energy_threshold=config.MIC_THRESHOLD,
- dynamic_energy_threshold=config.MIC_AUTOMATIC_THRESHOLD,
- phrase_time_limit=record_timeout,
- )
- # self.mic_audio_recorder.recordIntoQueue(self.mic_audio_queue, mic_energy_queue)
- self.mic_audio_recorder.recordIntoQueue(self.mic_audio_queue, None)
- self.mic_transcriber = AudioTranscriber(
- speaker=False,
- source=self.mic_audio_recorder.source,
- phrase_timeout=phrase_timeout,
- max_phrases=config.MIC_MAX_PHRASES,
- transcription_engine=config.SELECTED_TRANSCRIPTION_ENGINE,
- root=config.PATH_LOCAL,
- whisper_weight_type=config.WHISPER_WEIGHT_TYPE,
- device=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device"],
- device_index=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device_index"],
- )
- def sendMicTranscript():
- try:
- selected_your_languages = config.SELECTED_YOUR_LANGUAGES[config.SELECTED_TAB_NO]
- languages = [data["language"] for data in selected_your_languages.values() if data["enable"] is True]
- countries = [data["country"] for data in selected_your_languages.values() if data["enable"] is True]
- if isinstance(self.mic_transcriber, AudioTranscriber) is True:
- res = self.mic_transcriber.transcribeAudioQueue(
- self.mic_audio_queue,
- languages,
- countries,
- config.MIC_AVG_LOGPROB,
- config.MIC_NO_SPEECH_PROB
- )
- if res:
- result = self.mic_transcriber.getTranscript()
- fnc(result)
- except Exception:
- errorLogging()
+ def endMicTranscript():
+ while not self.mic_audio_queue.empty():
+ self.mic_audio_queue.get()
+ # while not self.mic_energy_queue.empty():
+ # self.mic_energy_queue.get()
+ self.mic_transcriber = None
+ gc.collect()
- def endMicTranscript():
- while not self.mic_audio_queue.empty():
- self.mic_audio_queue.get()
- # while not self.mic_energy_queue.empty():
- # self.mic_energy_queue.get()
- self.mic_transcriber = None
- gc.collect()
+ # def sendMicEnergy():
+ # if mic_energy_queue.empty() is False:
+ # energy = mic_energy_queue.get()
+ # # print("mic energy:", energy)
+ # try:
+ # fnc(energy)
+ # except Exception:
+ # pass
+ # sleep(0.01)
- # def sendMicEnergy():
- # if mic_energy_queue.empty() is False:
- # energy = mic_energy_queue.get()
- # # print("mic energy:", energy)
- # try:
- # fnc(energy)
- # except Exception:
- # pass
- # sleep(0.01)
+ self.mic_print_transcript = threadFnc(sendMicTranscript, end_fnc=endMicTranscript)
+ self.mic_print_transcript.daemon = True
+ self.mic_print_transcript.start()
- self.mic_print_transcript = threadFnc(sendMicTranscript, end_fnc=endMicTranscript)
- self.mic_print_transcript.daemon = True
- self.mic_print_transcript.start()
+ # self.mic_get_energy = threadFnc(sendMicEnergy)
+ # self.mic_get_energy.daemon = True
+ # self.mic_get_energy.start()
- # self.mic_get_energy = threadFnc(sendMicEnergy)
- # self.mic_get_energy.daemon = True
- # self.mic_get_energy.start()
-
- self.changeMicTranscriptStatus()
+ self.changeMicTranscriptStatus()
def resumeMicTranscript(self):
# キューをクリア
@@ -535,25 +535,25 @@ class Model:
mic_device_list = device_manager.getMicDevices().get(mic_host_name, [{"name": "NoDevice"}])
selected_mic_device = [device for device in mic_device_list if device["name"] == mic_device_name]
- if len(selected_mic_device) == 0:
- return False
+ if len(selected_mic_device) == 0 or mic_device_name == "NoDevice":
+ self.check_mic_energy_fnc(False)
+ else:
+ def sendMicEnergy():
+ if mic_energy_queue.empty() is False:
+ energy = mic_energy_queue.get()
+ try:
+ self.check_mic_energy_fnc(energy)
+ except Exception:
+ errorLogging()
+ sleep(0.01)
- def sendMicEnergy():
- if mic_energy_queue.empty() is False:
- energy = mic_energy_queue.get()
- try:
- self.check_mic_energy_fnc(energy)
- except Exception:
- errorLogging()
- sleep(0.01)
-
- mic_energy_queue = Queue()
- mic_device = selected_mic_device[0]
- self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device)
- self.mic_energy_recorder.recordIntoQueue(mic_energy_queue)
- self.mic_energy_plot_progressbar = threadFnc(sendMicEnergy)
- self.mic_energy_plot_progressbar.daemon = True
- self.mic_energy_plot_progressbar.start()
+ mic_energy_queue = Queue()
+ mic_device = selected_mic_device[0]
+ self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device)
+ self.mic_energy_recorder.recordIntoQueue(mic_energy_queue)
+ self.mic_energy_plot_progressbar = threadFnc(sendMicEnergy)
+ self.mic_energy_plot_progressbar.daemon = True
+ self.mic_energy_plot_progressbar.start()
def stopCheckMicEnergy(self):
if isinstance(self.mic_energy_plot_progressbar, threadFnc):
@@ -566,83 +566,85 @@ class Model:
self.mic_energy_recorder = None
def startSpeakerTranscript(self, fnc):
+ speaker_device_name = config.SELECTED_SPEAKER_DEVICE
+
speaker_device_list = device_manager.getSpeakerDevices()
- selected_speaker_device = [device for device in speaker_device_list if device["name"] == config.SELECTED_SPEAKER_DEVICE]
+ selected_speaker_device = [device for device in speaker_device_list if device["name"] == speaker_device_name]
- if len(selected_speaker_device) == 0:
- return False
+ if len(selected_speaker_device) == 0 or speaker_device_name == "NoDevice":
+ fnc({"text": False, "language": None})
+ else:
+ speaker_audio_queue = Queue()
+ # speaker_energy_queue = Queue()
+ speaker_device = selected_speaker_device[0]
+ record_timeout = config.SPEAKER_RECORD_TIMEOUT
+ phrase_timeout = config.SPEAKER_PHRASE_TIMEOUT
+ if record_timeout > phrase_timeout:
+ record_timeout = phrase_timeout
- speaker_audio_queue = Queue()
- # speaker_energy_queue = Queue()
- speaker_device = selected_speaker_device[0]
- record_timeout = config.SPEAKER_RECORD_TIMEOUT
- phrase_timeout = config.SPEAKER_PHRASE_TIMEOUT
- if record_timeout > phrase_timeout:
- record_timeout = phrase_timeout
+ self.speaker_audio_recorder = SelectedSpeakerEnergyAndAudioRecorder(
+ device=speaker_device,
+ energy_threshold=config.SPEAKER_THRESHOLD,
+ dynamic_energy_threshold=config.SPEAKER_AUTOMATIC_THRESHOLD,
+ phrase_time_limit=record_timeout,
+ )
+ # self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue, speaker_energy_queue)
+ self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue, None)
+ self.speaker_transcriber = AudioTranscriber(
+ speaker=True,
+ source=self.speaker_audio_recorder.source,
+ phrase_timeout=phrase_timeout,
+ max_phrases=config.SPEAKER_MAX_PHRASES,
+ transcription_engine=config.SELECTED_TRANSCRIPTION_ENGINE,
+ root=config.PATH_LOCAL,
+ whisper_weight_type=config.WHISPER_WEIGHT_TYPE,
+ device=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device"],
+ device_index=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device_index"],
+ )
+ def sendSpeakerTranscript():
+ try:
+ selected_target_languages = config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]
+ languages = [data["language"] for data in selected_target_languages.values() if data["enable"] is True]
+ countries = [data["country"] for data in selected_target_languages.values() if data["enable"] is True]
+ if isinstance(self.speaker_transcriber, AudioTranscriber) is True:
+ res = self.speaker_transcriber.transcribeAudioQueue(
+ speaker_audio_queue,
+ languages,
+ countries,
+ config.SPEAKER_AVG_LOGPROB,
+ config.SPEAKER_NO_SPEECH_PROB
+ )
+ if res:
+ result = self.speaker_transcriber.getTranscript()
+ fnc(result)
+ except Exception:
+ errorLogging()
- self.speaker_audio_recorder = SelectedSpeakerEnergyAndAudioRecorder(
- device=speaker_device,
- energy_threshold=config.SPEAKER_THRESHOLD,
- dynamic_energy_threshold=config.SPEAKER_AUTOMATIC_THRESHOLD,
- phrase_time_limit=record_timeout,
- )
- # self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue, speaker_energy_queue)
- self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue, None)
- self.speaker_transcriber = AudioTranscriber(
- speaker=True,
- source=self.speaker_audio_recorder.source,
- phrase_timeout=phrase_timeout,
- max_phrases=config.SPEAKER_MAX_PHRASES,
- transcription_engine=config.SELECTED_TRANSCRIPTION_ENGINE,
- root=config.PATH_LOCAL,
- whisper_weight_type=config.WHISPER_WEIGHT_TYPE,
- device=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device"],
- device_index=config.SELECTED_TRANSCRIPTION_COMPUTE_DEVICE["device_index"],
- )
- def sendSpeakerTranscript():
- try:
- selected_target_languages = config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]
- languages = [data["language"] for data in selected_target_languages.values() if data["enable"] is True]
- countries = [data["country"] for data in selected_target_languages.values() if data["enable"] is True]
- if isinstance(self.speaker_transcriber, AudioTranscriber) is True:
- res = self.speaker_transcriber.transcribeAudioQueue(
- speaker_audio_queue,
- languages,
- countries,
- config.SPEAKER_AVG_LOGPROB,
- config.SPEAKER_NO_SPEECH_PROB
- )
- if res:
- result = self.speaker_transcriber.getTranscript()
- fnc(result)
- except Exception:
- errorLogging()
+ def endSpeakerTranscript():
+ while not speaker_audio_queue.empty():
+ speaker_audio_queue.get()
+ # while not speaker_energy_queue.empty():
+ # speaker_energy_queue.get()
+ self.speaker_transcriber = None
+ gc.collect()
- def endSpeakerTranscript():
- while not speaker_audio_queue.empty():
- speaker_audio_queue.get()
- # while not speaker_energy_queue.empty():
- # speaker_energy_queue.get()
- self.speaker_transcriber = None
- gc.collect()
+ # def sendSpeakerEnergy():
+ # if speaker_energy_queue.empty() is False:
+ # energy = speaker_energy_queue.get()
+ # # print("speaker energy:", energy)
+ # try:
+ # fnc(energy)
+ # except Exception:
+ # pass
+ # sleep(0.01)
- # def sendSpeakerEnergy():
- # if speaker_energy_queue.empty() is False:
- # energy = speaker_energy_queue.get()
- # # print("speaker energy:", energy)
- # try:
- # fnc(energy)
- # except Exception:
- # pass
- # sleep(0.01)
+ self.speaker_print_transcript = threadFnc(sendSpeakerTranscript, end_fnc=endSpeakerTranscript)
+ self.speaker_print_transcript.daemon = True
+ self.speaker_print_transcript.start()
- self.speaker_print_transcript = threadFnc(sendSpeakerTranscript, end_fnc=endSpeakerTranscript)
- self.speaker_print_transcript.daemon = True
- self.speaker_print_transcript.start()
-
- # self.speaker_get_energy = threadFnc(sendSpeakerEnergy)
- # self.speaker_get_energy.daemon = True
- # self.speaker_get_energy.start()
+ # self.speaker_get_energy = threadFnc(sendSpeakerEnergy)
+ # self.speaker_get_energy.daemon = True
+ # self.speaker_get_energy.start()
def stopSpeakerTranscript(self):
if isinstance(self.speaker_print_transcript, threadFnc):
@@ -660,28 +662,29 @@ class Model:
if isinstance(fnc, Callable):
self.check_speaker_energy_fnc = fnc
+ speaker_device_name = config.SELECTED_SPEAKER_DEVICE
speaker_device_list = device_manager.getSpeakerDevices()
- selected_speaker_device = [device for device in speaker_device_list if device["name"] == config.SELECTED_SPEAKER_DEVICE]
+ selected_speaker_device = [device for device in speaker_device_list if device["name"] == speaker_device_name]
- if len(selected_speaker_device) == 0:
- return False
+ if len(selected_speaker_device) == 0 or speaker_device_name == "NoDevice":
+ self.check_speaker_energy_fnc(False)
+ else:
+ def sendSpeakerEnergy():
+ if speaker_energy_queue.empty() is False:
+ energy = speaker_energy_queue.get()
+ try:
+ self.check_speaker_energy_fnc(energy)
+ except Exception:
+ errorLogging()
+ sleep(0.01)
- def sendSpeakerEnergy():
- if speaker_energy_queue.empty() is False:
- energy = speaker_energy_queue.get()
- try:
- self.check_speaker_energy_fnc(energy)
- except Exception:
- errorLogging()
- sleep(0.01)
-
- speaker_energy_queue = Queue()
- speaker_device = selected_speaker_device[0]
- self.speaker_energy_recorder = SelectedSpeakerEnergyRecorder(speaker_device)
- self.speaker_energy_recorder.recordIntoQueue(speaker_energy_queue)
- self.speaker_energy_plot_progressbar = threadFnc(sendSpeakerEnergy)
- self.speaker_energy_plot_progressbar.daemon = True
- self.speaker_energy_plot_progressbar.start()
+ speaker_energy_queue = Queue()
+ speaker_device = selected_speaker_device[0]
+ self.speaker_energy_recorder = SelectedSpeakerEnergyRecorder(speaker_device)
+ self.speaker_energy_recorder.recordIntoQueue(speaker_energy_queue)
+ self.speaker_energy_plot_progressbar = threadFnc(sendSpeakerEnergy)
+ self.speaker_energy_plot_progressbar.daemon = True
+ self.speaker_energy_plot_progressbar.start()
def stopCheckSpeakerEnergy(self):
if isinstance(self.speaker_energy_plot_progressbar, threadFnc):
diff --git a/src-python/models/transcription/transcription_whisper.py b/src-python/models/transcription/transcription_whisper.py
index 080054b5..69499260 100644
--- a/src-python/models/transcription/transcription_whisper.py
+++ b/src-python/models/transcription/transcription_whisper.py
@@ -17,6 +17,8 @@ _MODELS = {
"large-v1": "Systran/faster-whisper-large-v1",
"large-v2": "Systran/faster-whisper-large-v2",
"large-v3": "Systran/faster-whisper-large-v3",
+ "large-v3-turbo-int8": "Zoont/faster-whisper-large-v3-turbo-int8-ct2", #794MB
+ "large-v3-turbo": "deepdml/faster-whisper-large-v3-turbo-ct2", #1.58GB
}
_FILENAMES = [
diff --git a/src-python/utils.py b/src-python/utils.py
index e31a1f46..de538dae 100644
--- a/src-python/utils.py
+++ b/src-python/utils.py
@@ -7,14 +7,22 @@ from logging.handlers import RotatingFileHandler
from ctranslate2 import get_supported_compute_types
import requests
+import ipaddress
-def isConnectedNetwork(url="http://www.google.com", timeout=3):
+def isConnectedNetwork(url="http://www.google.com", timeout=3) -> bool:
try:
response = requests.get(url, timeout=timeout)
return response.status_code == 200
except requests.RequestException:
return False
+def isValidIpAddress(ip_address: str) -> bool:
+ try:
+ ipaddress.ip_address(ip_address)
+ return True
+ except ValueError:
+ return False
+
def getBestComputeType(device, device_index) -> str:
compute_types = get_supported_compute_types(device, device_index)
compute_types = set(compute_types)
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index a23b5b08..14b4c7b2 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -1,108 +1,102 @@
{
- "build": {
- "beforeDevCommand": "",
- "beforeBuildCommand": "",
- "devPath": "http://localhost:1420",
- "distDir": "../dist"
- },
- "package": {
- "productName": "VRCT",
- "version": "3.0.0"
- },
- "tauri": {
- "allowlist": {
- "all": false,
- "window": {
- "all": false,
- "setAlwaysOnTop": true,
- "setFocus": true,
- "setDecorations": true,
- "close": true,
- "hide": true,
- "setPosition": true,
- "setSize": true,
- "maximize": true,
- "minimize": true,
- "unmaximize": true,
- "unminimize": true,
- "startDragging": true
- },
- "globalShortcut": {
- "all": true
- },
- "fs": {
- "readDir": true,
- "readFile": true,
- "exists": true,
- "writeFile": true,
- "createDir": true,
- "removeDir": true,
- "scope": ["$RESOURCE/**", "**/src-tauri/target/debug/plugins/**"]
- },
- "http": {
- "request": true,
- "scope": [
- "https://api.github.com/repos/**",
- "https://github.com/**",
- "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/vrct_plugins_list.json",
- "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/dev_vrct_plugins_list.json"
- ]
- },
- "shell": {
- "all": false,
- "open": true,
- "sidecar": true,
- "scope": [
- {
- "name": "bin/VRCT-sidecar", "sidecar": true,"args": true
- }
- ]
- }
-},
-"windows": [
- {
- "title": "VRCT",
- "center": true,
- "width": 450,
- "height": 220,
- "minWidth": 400,
- "minHeight": 200,
- "transparent": true,
- "decorations": false
- }
- ],
- "security": {
- "csp": null
+ "build": {
+ "beforeDevCommand": "",
+ "beforeBuildCommand": "",
+ "devPath": "http://localhost:1420",
+ "distDir": "../dist"
},
- "bundle": {
- "active": true,
- "targets": "nsis",
- "identifier": "com.vrct.dev",
- "publisher": "m's software",
- "copyright": "Copyright m's software",
- "shortDescription": "VRCT",
- "icon": [
- "icons/32x32.png",
- "icons/128x128.png",
- "icons/128x128@2x.png",
- "icons/icon.icns",
- "icons/icon.ico"
- ],
- "externalBin": [
- "bin/VRCT-sidecar"
- ],
- "resources":{
- "bin/_internal": "_internal",
- "plugins": "plugins"
- },
- "windows": {
- "nsis": {
- "template": "nsis/template.nsi",
- "license": "../LICENSE",
- "installMode": "currentUser",
- "displayLanguageSelector": true
+ "package": {
+ "productName": "VRCT",
+ "version": "3.0.0"
+ },
+ "tauri": {
+ "allowlist": {
+ "all": false,
+ "window": {
+ "all": false,
+ "setAlwaysOnTop": true,
+ "setFocus": true,
+ "setDecorations": true,
+ "close": true,
+ "hide": true,
+ "setPosition": true,
+ "setSize": true,
+ "maximize": true,
+ "minimize": true,
+ "unmaximize": true,
+ "unminimize": true,
+ "startDragging": true
+ },
+ "globalShortcut": {
+ "all": true
+ },
+ "fs": {
+ "readDir": true,
+ "readFile": true,
+ "exists": true,
+ "writeFile": true,
+ "createDir": true,
+ "removeDir": true,
+ "scope": ["$RESOURCE/**", "**/src-tauri/target/debug/plugins/**"]
+ },
+ "http": {
+ "request": true,
+ "scope": [
+ "https://api.github.com/repos/**",
+ "https://github.com/**",
+ "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/vrct_plugins_list.json",
+ "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/dev_vrct_plugins_list.json"
+ ]
+ },
+ "shell": {
+ "all": false,
+ "open": true,
+ "sidecar": true,
+ "scope": [
+ { "name": "bin/VRCT-sidecar", "sidecar": true, "args": true }
+ ]
+ }
+ },
+ "windows": [{
+ "title": "VRCT",
+ "center": true,
+ "width": 450,
+ "height": 220,
+ "minWidth": 400,
+ "minHeight": 200,
+ "transparent": true,
+ "decorations": false
+ }],
+ "security": { "csp": null },
+ "bundle": {
+ "active": true,
+ "targets": "nsis",
+ "identifier": "com.vrct.dev",
+ "publisher": "m's software",
+ "copyright": "Copyright m's software",
+ "shortDescription": "VRCT",
+ "icon": [
+ "icons/32x32.png",
+ "icons/128x128.png",
+ "icons/128x128@2x.png",
+ "icons/icon.icns",
+ "icons/icon.ico"
+ ],
+ "externalBin": [
+ "bin/VRCT-sidecar"
+ ],
+ "resources": {
+ "bin/_internal": "_internal",
+ "plugins": "plugins"
+ },
+ "windows": {
+ "nsis": {
+ "template": "nsis/template.nsi",
+ "license": "../LICENSE",
+ "installMode": "currentUser",
+ "displayLanguageSelector": true
+ }
+ }
}
- }
}
- }
}
diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/_atoms/_entry/_Entry.jsx b/src-ui/app/config_page/setting_section/setting_box/_components/_atoms/_entry/_Entry.jsx
index d9b0d4cb..641e7104 100644
--- a/src-ui/app/config_page/setting_section/setting_box/_components/_atoms/_entry/_Entry.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/_components/_atoms/_entry/_Entry.jsx
@@ -24,7 +24,7 @@ const _Entry = forwardRef((props, ref) => {
{
+ const { t } = useTranslation();
+ const onChangeFunction = (e) => {
+ props.onChangeFunction?.(e.target.value);
+ };
+ const saveFunction = () => {
+ props.saveFunction();
+ };
+ const is_disabled = props.state === "pending";
+
+ const save_button_class_names = clsx(styles.save_button, {
+ [styles.is_disabled]: is_disabled
+ });
+
+ return (
+
+ <_Entry width={props.width} onChange={onChangeFunction} ui_variable={props.variable} is_disabled={is_disabled}/>
+
+ {is_disabled
+ ?
+ : {t("config_page.translation.deepl_auth_key.save")}
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/entry_with_save_button/EntryWithSaveButton.module.scss b/src-ui/app/config_page/setting_section/setting_box/_components/entry_with_save_button/EntryWithSaveButton.module.scss
new file mode 100644
index 00000000..deb86f89
--- /dev/null
+++ b/src-ui/app/config_page/setting_section/setting_box/_components/entry_with_save_button/EntryWithSaveButton.module.scss
@@ -0,0 +1,30 @@
+.container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 1rem;
+ flex-shrink: 0;
+}
+
+.save_button {
+ padding: 0.8rem 1.2rem;
+ background-color: var(--primary_600_color);
+ border-radius: 0.4rem;
+ text-align: center;
+ flex-shrink: 0;
+ min-width: 5.4rem;
+ &:hover {
+ background-color: var(--primary_500_color);
+ }
+ &:active {
+ background-color: var(--primary_700_color);
+ }
+ &.is_disabled {
+ pointer-events: none;
+ background-color: var(--primary_800_color);
+ }
+}
+
+.save_button_label {
+ font-size: 1.4rem;
+}
\ No newline at end of file
diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/index.js b/src-ui/app/config_page/setting_section/setting_box/_components/index.js
index 123a1400..178dbcec 100644
--- a/src-ui/app/config_page/setting_section/setting_box/_components/index.js
+++ b/src-ui/app/config_page/setting_section/setting_box/_components/index.js
@@ -3,6 +3,7 @@ export { ComputeDevice } from "./compute_device/ComputeDevice";
export { DeeplAuthKey, OpenWebpage_DeeplAuthKey } from "./deepl_auth_key/DeeplAuthKey";
export { DropdownMenu } from "./dropdown_menu/DropdownMenu";
export { Entry } from "./entry/Entry";
+export { EntryWithSaveButton } from "./entry_with_save_button/EntryWithSaveButton";
export { HotkeysEntry } from "./hotkeys_entry/HotkeysEntry";
export { LabelComponent } from "./label_component/LabelComponent";
export { RadioButton } from "./radio_button/RadioButton";
diff --git a/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx b/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx
index 716a15c9..b25af8b9 100644
--- a/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/_templates/Templates.jsx
@@ -8,6 +8,7 @@ import {
Slider,
SwitchBox,
Entry,
+ EntryWithSaveButton,
HotkeysEntry,
RadioButton,
OpenWebpage_DeeplAuthKey,
@@ -75,6 +76,9 @@ export const SwitchBoxContainer = (props) => (
export const EntryContainer = (props) => (
);
+export const EntryWithSaveButtonContainer = (props) => (
+
+);
export const HotkeysEntryContainer = (props) => (
diff --git a/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.jsx b/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.jsx
index e36a39f5..d64f4e3c 100644
--- a/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.jsx
@@ -10,6 +10,7 @@ import contributor_iya from "@images/about_vrct/contributor_iya.png";
import contributor_rera from "@images/about_vrct/contributor_rera.png";
import contributor_poposuke from "@images/about_vrct/contributor_poposuke.png";
import contributor_kumaguma from "@images/about_vrct/contributor_kumaguma.png";
+import contributor_riku from "@images/about_vrct/contributor_riku.png";
import localization_section_title from "@images/about_vrct/localization_section_title.png";
import localization_1 from "@images/about_vrct/localization_1.png";
@@ -86,6 +87,10 @@ export const AboutVrct = () => {
+
+
+
+
@@ -158,6 +163,7 @@ const about_vrct_links = {
contributors_rera_github: { img: contributors_github_icon, href: "https://github.com/soumt-r" },
contributors_poposuke_x: { img: contributors_x_icon, href: "https://twitter.com/sig_popo" },
contributors_kumaguma_x: { img: contributors_x_icon, href: "https://twitter.com/K_kumaguma_A" },
+ contributors_riku_x: { img: contributors_x_icon, href: "https://twitter.com/Riku7302" },
};
const OpenLinkContainer = ({className, href_id}) => {
diff --git a/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.module.scss b/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.module.scss
index a4d06e2e..f9efc103 100644
--- a/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.module.scss
+++ b/src-ui/app/config_page/setting_section/setting_box/about_vrct/AboutVrct.module.scss
@@ -160,6 +160,9 @@ $sns_left_pos: 0.8rem;
.contributors_kumaguma_x {
@include contributors_sns_styles($bottom_pos, $sns_left_pos);
}
+.contributors_riku_x {
+ @include contributors_sns_styles($bottom_pos, $sns_left_pos);
+}
.localization_section {
display: flex;
diff --git a/src-ui/app/config_page/setting_section/setting_box/advanced_settings/AdvancedSettings.jsx b/src-ui/app/config_page/setting_section/setting_box/advanced_settings/AdvancedSettings.jsx
index 94dcd358..b96c7fa9 100644
--- a/src-ui/app/config_page/setting_section/setting_box/advanced_settings/AdvancedSettings.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/advanced_settings/AdvancedSettings.jsx
@@ -11,6 +11,7 @@ import {
import {
ActionButtonContainer,
EntryContainer,
+ EntryWithSaveButtonContainer,
} from "../_templates/Templates";
@@ -30,54 +31,59 @@ export const AdvancedSettings = () => {
const OscIpAddressContainer = () => {
const { t } = useTranslation();
- const [ui_variable, setUiVariable] = useState("");
const { currentOscIpAddress, setOscIpAddress } = useOscIpAddress();
- const onChangeFunction = (e) => {
- const value = e.currentTarget.value;
- if (value === "") {
- setUiVariable("");
- } else {
- setUiVariable(value);
- setOscIpAddress(value);
- }
+ const [input_value, setInputValue] = useState(currentOscIpAddress.data);
+
+ const onChangeFunction = (value) => {
+ setInputValue(value);
+ };
+
+ const saveFunction = () => {
+ setOscIpAddress(input_value);
};
useEffect(()=> {
- setUiVariable(currentOscIpAddress.data);
+ setInputValue(currentOscIpAddress.data);
}, [currentOscIpAddress]);
return (
-
);
};
const OscPortContainer = () => {
const { t } = useTranslation();
- const [ui_variable, setUiVariable] = useState("");
const { currentOscPort, setOscPort } = useOscPort();
- const onChangeFunction = (e) => {
- const value = e.currentTarget.value;
- if (value === "") {
- setUiVariable("");
- } else {
- setUiVariable(value);
- setOscPort(value);
- }
+ const [input_value, setInputValue] = useState(currentOscPort.data);
+
+ const onChangeFunction = (value) => {
+ value = value.replace(/[^0-9]/g, "");
+ setInputValue(value);
+ };
+
+ const saveFunction = () => {
+ setOscPort(input_value);
};
useEffect(()=> {
- setUiVariable(currentOscPort.data);
+ setInputValue(currentOscPort.data);
}, [currentOscPort]);
return (
-
);
};
diff --git a/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx b/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx
index c7c9368d..d881b330 100644
--- a/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/transcription/Transcription.jsx
@@ -260,6 +260,8 @@ const WhisperWeightType_Box = () => {
{ id: "large-v1", label: t("config_page.transcription.whisper_weight_type.model_template", {model_name: "large-v1", capacity: "2.87GB"}) },
{ id: "large-v2", label: t("config_page.transcription.whisper_weight_type.model_template", {model_name: "large-v2", capacity: "2.87GB"}) },
{ id: "large-v3", label: t("config_page.transcription.whisper_weight_type.model_template", {model_name: "large-v3", capacity: "2.87GB"}) },
+ { id: "large-v3-turbo-int8", label: t("config_page.transcription.whisper_weight_type.model_template", {model_name: "large-v3-turbo-int8", capacity: "794MB"}) },
+ { id: "large-v3-turbo", label: t("config_page.transcription.whisper_weight_type.model_template", {model_name: "large-v3-turbo", capacity: "1.58GB"}) },
];
const whisper_weight_types = updateLabelsById(currentWhisperWeightTypeStatus.data, new_labels);
diff --git a/src-ui/app/config_page/setting_section/setting_box/translation/Translation.jsx b/src-ui/app/config_page/setting_section/setting_box/translation/Translation.jsx
index 63f0630d..5c4dfa51 100644
--- a/src-ui/app/config_page/setting_section/setting_box/translation/Translation.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/translation/Translation.jsx
@@ -62,7 +62,7 @@ const CTranslate2WeightType_Box = () => {
)}
desc={t(
"config_page.translation.ctranslate2_weight_type.desc",
- {translator: t("main_page.translator")}
+ {ctranslate2: "CTranslate2"}
)}
name="ctransalte2_weight_type"
options={c_translate2_weight_types}
diff --git a/src-ui/assets/about_vrct/contributor_riku.png b/src-ui/assets/about_vrct/contributor_riku.png
new file mode 100644
index 00000000..8d5aaf83
Binary files /dev/null and b/src-ui/assets/about_vrct/contributor_riku.png differ
diff --git a/src-ui/assets/about_vrct/localization_1.png b/src-ui/assets/about_vrct/localization_1.png
index 4d7a4633..b798bdbc 100644
Binary files a/src-ui/assets/about_vrct/localization_1.png and b/src-ui/assets/about_vrct/localization_1.png differ
diff --git a/src-ui/logics/_useBackendErrorHandling.js b/src-ui/logics/_useBackendErrorHandling.js
index 446330cc..c9d99e50 100644
--- a/src-ui/logics/_useBackendErrorHandling.js
+++ b/src-ui/logics/_useBackendErrorHandling.js
@@ -14,6 +14,8 @@ import {
useSpeakerMaxWords,
useDeepLAuthKey,
+
+ useOscIpAddress,
} from "@logics_configs";
import { ui_configs } from "../ui_configs";
@@ -29,14 +31,16 @@ export const _useBackendErrorHandling = () => {
const { updateSpeakerPhraseTimeout } = useSpeakerPhraseTimeout();
const { updateSpeakerMaxWords } = useSpeakerMaxWords();
- const { updateDeepLAuthKey } = useDeepLAuthKey();
+ const { updateDeepLAuthKey, saveErrorDeepLAuthKey } = useDeepLAuthKey();
- const errorHandling_Backend = ({message, data, endpoint}) => {
+ const { updateOscIpAddress } = useOscIpAddress();
+
+ const errorHandling_Backend = ({message, data, endpoint, _result}) => {
switch (message) {
case "No mic device detected":
showNotification_Error(t("common_error.no_device_mic"));
break;
- case "No Speaker device detected":
+ case "No speaker device detected":
showNotification_Error(t("common_error.no_device_speaker"));
break;
@@ -47,9 +51,9 @@ export const _useBackendErrorHandling = () => {
break;
case "Speaker energy threshold value is out of range":
showNotification_Error(t("common_error.threshold_invalid_value",
- { min: ui_configs.speaker_threshold_min, max: ui_configs.speaker_threshold_max },
- ));
- break;
+ { min: ui_configs.speaker_threshold_min, max: ui_configs.speaker_threshold_max },
+ ));
+ break;
case "CTranslate2 weight download error":
showNotification_Error(t("common_error.failed_download_weight_ctranslate2"));
@@ -110,10 +114,23 @@ export const _useBackendErrorHandling = () => {
showNotification_Error(t("common_error.invalid_value_speaker_max_phrase"));
break;
- default:
- if (endpoint === "/set/data/deepl_auth_key") updateDeepLAuthKey(data);
+
+ // Advanced Settings, error messages are set by Backend (EN only)
+ case "Invalid IP address":
+ updateOscIpAddress(data);
showNotification_Error(message);
break;
+
+ case "Cannot set IP address":
+ updateOscIpAddress(data);
+ showNotification_Error(message);
+ break;
+
+ default:
+ // determine by endpoint, not message.
+ if (endpoint === "/set/data/deepl_auth_key") saveErrorDeepLAuthKey({message, data, endpoint, _result});
+
+ break;
}
}
diff --git a/src-ui/logics/configs/advanced_settings/useOscPort.js b/src-ui/logics/configs/advanced_settings/useOscPort.js
index 947d613d..d3e28557 100644
--- a/src-ui/logics/configs/advanced_settings/useOscPort.js
+++ b/src-ui/logics/configs/advanced_settings/useOscPort.js
@@ -1,7 +1,9 @@
import { useStore_OscPort } from "@store";
import { useStdoutToPython } from "@logics/useStdoutToPython";
+import { useNotificationStatus } from "@logics_common";
export const useOscPort = () => {
+ const { showNotification_Error } = useNotificationStatus();
const { asyncStdoutToPython } = useStdoutToPython();
const { currentOscPort, updateOscPort, pendingOscPort } = useStore_OscPort();
@@ -15,10 +17,17 @@ export const useOscPort = () => {
asyncStdoutToPython("/set/data/osc_port", osc_port);
};
+ const saveErrorOscPort = ({data, message, _result}) => {
+ updateOscPort(d => d.data);
+ showNotification_Error(_result);
+ };
+
return {
currentOscPort,
getOscPort,
updateOscPort,
setOscPort,
+
+ saveErrorOscPort,
};
};
\ No newline at end of file
diff --git a/src-ui/logics/configs/translation/useDeepLAuthKey.js b/src-ui/logics/configs/translation/useDeepLAuthKey.js
index 3d66dfba..f93fdd4f 100644
--- a/src-ui/logics/configs/translation/useDeepLAuthKey.js
+++ b/src-ui/logics/configs/translation/useDeepLAuthKey.js
@@ -18,22 +18,30 @@ export const useDeepLAuthKey = () => {
pendingDeepLAuthKey();
asyncStdoutToPython("/set/data/deepl_auth_key", selected_deepl_auth_key);
};
- const saveSuccessDeepLAuthKey = (saved_deepl_auth_key) => {
- updateDeepLAuthKey(saved_deepl_auth_key);
- showNotification_Success(t("config_page.translation.deepl_auth_key.auth_key_success"));
- };
const deleteDeepLAuthKey = () => {
pendingDeepLAuthKey();
asyncStdoutToPython("/delete/data/deepl_auth_key");
};
+ const savedDeepLAuthKey = (data) => {
+ updateDeepLAuthKey(data);
+ showNotification_Success(t("config_page.translation.deepl_auth_key.auth_key_success"));
+ };
+
+ const saveErrorDeepLAuthKey = ({data, message}) => {
+ updateDeepLAuthKey(data);
+ showNotification_Error(message);
+ };
+
return {
currentDeepLAuthKey,
getDeepLAuthKey,
updateDeepLAuthKey,
setDeepLAuthKey,
- saveSuccessDeepLAuthKey,
deleteDeepLAuthKey,
+
+ saveErrorDeepLAuthKey,
+ savedDeepLAuthKey,
};
};
\ No newline at end of file
diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js
index b73fe62e..c015d43e 100644
--- a/src-ui/logics/useReceiveRoutes.js
+++ b/src-ui/logics/useReceiveRoutes.js
@@ -148,7 +148,7 @@ export const useReceiveRoutes = () => {
const { updateSpeakerPhraseTimeout } = useSpeakerPhraseTimeout();
const { updateSpeakerMaxWords } = useSpeakerMaxWords();
- const { updateDeepLAuthKey, saveSuccessDeepLAuthKey } = useDeepLAuthKey();
+ const { updateDeepLAuthKey, savedDeepLAuthKey } = useDeepLAuthKey();
const { updateSelectedCTranslate2WeightType } = useSelectedCTranslate2WeightType();
const {
updateDownloadedCTranslate2WeightTypeStatus,
@@ -353,7 +353,7 @@ export const useReceiveRoutes = () => {
// Translation
"/get/data/deepl_auth_key": updateDeepLAuthKey,
- "/set/data/deepl_auth_key": saveSuccessDeepLAuthKey,
+ "/set/data/deepl_auth_key": savedDeepLAuthKey,
"/delete/data/deepl_auth_key": () => updateDeepLAuthKey(""),
"/get/data/ctranslate2_weight_type": updateSelectedCTranslate2WeightType,
@@ -528,6 +528,8 @@ export const useReceiveRoutes = () => {
"/set/data/speaker_record_timeout": errorHandling_Backend,
"/set/data/speaker_phrase_timeout": errorHandling_Backend,
"/set/data/speaker_max_phrases": errorHandling_Backend,
+
+ "/set/data/osc_ip_address": errorHandling_Backend,
};
@@ -566,11 +568,16 @@ export const useReceiveRoutes = () => {
message: parsed_data.result.message,
data: parsed_data.result.data,
endpoint: parsed_data.endpoint,
+ _result: parsed_data.result,
});
} else {
handleInvalidEndpoint(parsed_data);
}
break;
+ case 500:
+ showNotification_Error(
+ `An error occurred. Please restart VRCT or contact the developers. ${JSON.stringify(parsed_data.result)}`, { hide_duration: null });
+ break;
case 348:
// console.log(`from backend: %c ${JSON.stringify(parsed_data)}`, style_348);
diff --git a/src-ui/logics/useStartPython.js b/src-ui/logics/useStartPython.js
index 394e8cd2..7db442b9 100644
--- a/src-ui/logics/useStartPython.js
+++ b/src-ui/logics/useStartPython.js
@@ -1,8 +1,13 @@
import { Command } from "@tauri-apps/api/shell";
import { store } from "@store";
import { useReceiveRoutes } from "./useReceiveRoutes";
+import {
+ useNotificationStatus,
+} from "@logics_common";
+
export const useStartPython = () => {
const { receiveRoutes } = useReceiveRoutes();
+ const { showNotification_Success, showNotification_Error } = useNotificationStatus();
const asyncStartPython = async () => {
const command = Command.sidecar("bin/VRCT-sidecar");
@@ -16,7 +21,11 @@ export const useStartPython = () => {
console.log(error, line);
}
});
- command.stderr.on("data", line => console.error("stderr:", line));
+ command.stderr.on("data", line => {
+ showNotification_Error(
+ `An error occurred. Please restart VRCT or contact the developers. The last line:${JSON.stringify(line)}`, { hide_duration: null });
+ console.error("stderr", line)
+ });
const backend_subprocess = await command.spawn();
store.backend_subprocess = backend_subprocess;
};
diff --git a/src-ui/store.js b/src-ui/store.js
index c181ced5..e648f946 100644
--- a/src-ui/store.js
+++ b/src-ui/store.js
@@ -132,37 +132,38 @@ export const { atomInstance: Atom_NotificationStatus, useHook: useStore_Notifica
}, "NotificationStatus");
// Main Page
-// Functions
+// Common
+export const { atomInstance: Atom_IsMainPageCompactMode, useHook: useStore_IsMainPageCompactMode } = createAtomWithHook(false, "IsMainPageCompactMode");
+
+// Sidebar Section
export const { atomInstance: Atom_TranslationStatus, useHook: useStore_TranslationStatus } = createAtomWithHook(false, "TranslationStatus", {is_state_ok: true});
export const { atomInstance: Atom_TranscriptionSendStatus, useHook: useStore_TranscriptionSendStatus } = createAtomWithHook(false, "TranscriptionSendStatus", {is_state_ok: true});
export const { atomInstance: Atom_TranscriptionReceiveStatus, useHook: useStore_TranscriptionReceiveStatus } = createAtomWithHook(false, "TranscriptionReceiveStatus", {is_state_ok: true});
export const { atomInstance: Atom_ForegroundStatus, useHook: useStore_ForegroundStatus } = createAtomWithHook(false, "ForegroundStatus", {is_state_ok: true});
-export const { atomInstance: Atom_MessageLogs, useHook: useStore_MessageLogs } = createAtomWithHook([], "MessageLogs");
-// export const { atomInstance: Atom_MessageLogs, useHook: useStore_MessageLogs } = createAtomWithHook(generateTestData(20), "MessageLogs"); // For testing
-export const { atomInstance: Atom_MessageInputValue, useHook: useStore_MessageInputValue } = createAtomWithHook("", "MessageInputValue");
-export const { atomInstance: Atom_IsVisibleResendButton, useHook: useStore_IsVisibleResendButton } = createAtomWithHook(false, "IsVisibleResendButton", {is_state_ok: true});
-export const { atomInstance: Atom_IsAppliedInitMessageBoxHeight, useHook: useStore_IsAppliedInitMessageBoxHeight } = createAtomWithHook(false, "IsAppliedInitMessageBoxHeight");
-
-export const { atomInstance: Atom_SelectableLanguageList, useHook: useStore_SelectableLanguageList } = createAtomWithHook([], "SelectableLanguageList");
-
export const { atomInstance: Atom_SelectedPresetTabNumber, useHook: useStore_SelectedPresetTabNumber } = createAtomWithHook("1", "SelectedPresetTabNumber");
export const { atomInstance: Atom_EnableMultiTranslation, useHook: useStore_EnableMultiTranslation } = createAtomWithHook(false, "EnableMultiTranslation");
export const { atomInstance: Atom_SelectedYourLanguages, useHook: useStore_SelectedYourLanguages } = createAtomWithHook({}, "SelectedYourLanguages");
export const { atomInstance: Atom_SelectedTargetLanguages, useHook: useStore_SelectedTargetLanguages } = createAtomWithHook({}, "SelectedTargetLanguages");
-
export const { atomInstance: Atom_TranslationEngines, useHook: useStore_TranslationEngines } = createAtomWithHook(translator_status, "TranslationEngines");
export const { atomInstance: Atom_SelectedTranslationEngines, useHook: useStore_SelectedTranslationEngines } = createAtomWithHook({1:"", 2:"", 3:""}, "SelectedTranslationEngines");
+export const { atomInstance: Atom_IsOpenedTranslatorSelector, useHook: useStore_IsOpenedTranslatorSelector } = createAtomWithHook(false, "IsOpenedTranslatorSelector");
-
-// Designs
-export const { atomInstance: Atom_IsMainPageCompactMode, useHook: useStore_IsMainPageCompactMode } = createAtomWithHook(false, "IsMainPageCompactMode");
-export const { atomInstance: Atom_MessageInputBoxRatio, useHook: useStore_MessageInputBoxRatio } = createAtomWithHook(20, "MessageInputBoxRatio");
+// Language Selector
export const { atomInstance: Atom_IsOpenedLanguageSelector, useHook: useStore_IsOpenedLanguageSelector } = createAtomWithHook(
{ your_language: false, target_language: false, target_key: "1" },
"IsOpenedLanguageSelector"
);
+export const { atomInstance: Atom_SelectableLanguageList, useHook: useStore_SelectableLanguageList } = createAtomWithHook([], "SelectableLanguageList");
+
+// Message Container
+export const { atomInstance: Atom_MessageLogs, useHook: useStore_MessageLogs } = createAtomWithHook([], "MessageLogs");
+// export const { atomInstance: Atom_MessageLogs, useHook: useStore_MessageLogs } = createAtomWithHook(generateTestData(20), "MessageLogs"); // For testing
+export const { atomInstance: Atom_MessageInputBoxRatio, useHook: useStore_MessageInputBoxRatio } = createAtomWithHook(20, "MessageInputBoxRatio");
+export const { atomInstance: Atom_MessageInputValue, useHook: useStore_MessageInputValue } = createAtomWithHook("", "MessageInputValue");
+export const { atomInstance: Atom_IsVisibleResendButton, useHook: useStore_IsVisibleResendButton } = createAtomWithHook(false, "IsVisibleResendButton", {is_state_ok: true});
+
// Config Page
@@ -170,8 +171,6 @@ export const { atomInstance: Atom_IsOpenedLanguageSelector, useHook: useStore_Is
export const { atomInstance: Atom_SoftwareVersion, useHook: useStore_SoftwareVersion } = createAtomWithHook("-", "SoftwareVersion");
export const { atomInstance: Atom_SelectedConfigTabId, useHook: useStore_SelectedConfigTabId } = createAtomWithHook("device", "SelectedConfigTabId");
export const { atomInstance: Atom_SettingBoxScrollPosition, useHook: useStore_SettingBoxScrollPosition } = createAtomWithHook(0, "SettingBoxScrollPosition");
-
-// Designs
export const { atomInstance: Atom_IsOpenedDropdownMenu, useHook: useStore_IsOpenedDropdownMenu } = createAtomWithHook("", "IsOpenedDropdownMenu");
// Device
@@ -292,9 +291,9 @@ export const { atomInstance: Atom_OscPort, useHook: useStore_OscPort } = createA
-export const { atomInstance: Atom_IsOpenedTranslatorSelector, useHook: useStore_IsOpenedTranslatorSelector } = createAtomWithHook(false, "IsOpenedTranslatorSelector");
-
+// Supporters
export const { atomInstance: Atom_SupportersData, useHook: useStore_SupportersData } = createAtomWithHook(null, "SupportersData", {is_state_ok: true});
+// About VRCT
export const { atomInstance: Atom_VrctPosterIndex, useHook: useStore_VrctPosterIndex } = createAtomWithHook(0, "VrctPosterIndex");
export const { atomInstance: Atom_PosterShowcaseWorldPageIndex, useHook: useStore_PosterShowcaseWorldPageIndex } = createAtomWithHook(0, "PosterShowcaseWorldPageIndex");
\ No newline at end of file
diff --git a/src-ui/ui_configs.js b/src-ui/ui_configs.js
index 6b8d0031..d6ef28eb 100644
--- a/src-ui/ui_configs.js
+++ b/src-ui/ui_configs.js
@@ -89,6 +89,8 @@ export const whisper_weight_type_status = [
{ id: "large-v1", label: "large-v1", is_downloaded: false, progress: null },
{ id: "large-v2", label: "large-v2", is_downloaded: false, progress: null },
{ id: "large-v3", label: "large-v3", is_downloaded: false, progress: null },
+ { id: "large-v3-turbo-int8", label: "large-v3-turbo-int8", is_downloaded: false, progress: null },
+ { id: "large-v3-turbo", label: "large-v3-turbo", is_downloaded: false, progress: null },
];
export const supporters_data_url = "https://shiinasakamoto.github.io/vrct_supporters/assets/supporters/data.json";