diff --git a/README.md b/README.md deleted file mode 100644 index 13c563a6..00000000 --- a/README.md +++ /dev/null @@ -1,116 +0,0 @@ -
- - - - - VRCT Logo - - -
-
- -[![GitHub release](https://img.shields.io/github/v/release/misyaguziya/VRCT.svg)](https://github.com/misyaguziya/VRCT/releases) -[![Downloads](https://img.shields.io/github/downloads/misyaguziya/VRCT/total)](https://github.com/misyaguziya/VRCT/releases) -[![Licence](https://img.shields.io/github/license/misyaguziya/VRCT)](https://github.com/misyaguziya/VRCT/blob/master/LICENSE) -[![Booth](https://img.shields.io/badge/Store-Booth.pm-red)](https://misyaguziya.booth.pm/items/5155325) -[![Github Sponsors](https://img.shields.io/badge/GitHub%20Sponsors-30363D?&logo=GitHub-Sponsors&logoColor=EA4AAA)](https://github.com/sponsors/misyaguziya) - -

-Become a VRCT Supporter on: -

- - - - - - PIXIV FANBOX - -   - - - - - - Patreon - -   - - - - Ko-fi - -   - -
- - - - - Supporter Section Border - - -
-
- -| **English** | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [繁體中文](./README.zh-Hant.md) | - -

-VRCT is software that supports VRChat conversations with translation and transcription. -

- -![](docs/main_window.png) - -
- -# Download & Install -Download from anywhere you like. -- [Github.com](https://github.com/misyaguziya/VRCT/releases/) -- [BOOTH.pm](https://misyaguziya.booth.pm/items/5155325) - -Just download and run the exe. - -# What is VRCT? -VRCT is software that supports conversations between people who speak different languages by providing chat or voice translation. -These features are designed for use within VRChat. -*Although not supported, it is also used for other purposes such as watching movies. - -VRCT supports your conversations with -- 💬 **Send chat to VRChat** -- 🌐 **Translation** -- 🎙 **Transcription of audio from microphone** -- 🔈 **Transcription of audio from Speaker** - -# Documents -Initial setup, basic functions, and other features are also described. -- [Documents Link](https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246?pvs=4) - -# How to Use (YouTube) -
- -[![](https://img.youtube.com/vi/rUTad037n8Q/0.jpg)](https://www.youtube.com/watch?v=rUTad037n8Q) - -
- -# If you want to run it in python -1. Install the following version of python. - `python version 3.11.5` -2. Install package and run main.py. - ```bash - ./install.bat - python main.py - ``` - -## Author -- [みしゃ(misyaguzi)](https://github.com/misyaguziya) (Main Development) -- [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI multilingual support) -- [レラ](https://github.com/soumt-r) (Technical Support) -- [どね](https://twitter.com/done_vrc) (Logo Design) - -## Thanks to our contributors - - - - ---- - -VRCT is not endorsed by VRChat and does not reflect the views or opinions of VRChat or anyone officially involved in producing or managing VRChat properties. VRChat and all associated properties are trademarks or registered trademarks of VRChat Inc. VRChat © VRChat Inc. \ No newline at end of file diff --git a/README.md b/README.md new file mode 120000 index 00000000..ab3e36da --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +docs/readmes/README.en.md \ No newline at end of file diff --git a/docs/kofi_logo.png b/docs/img/kofi_logo.png similarity index 100% rename from docs/kofi_logo.png rename to docs/img/kofi_logo.png diff --git a/docs/main_window.png b/docs/img/main_window.png similarity index 100% rename from docs/main_window.png rename to docs/img/main_window.png diff --git a/docs/patreon_logo_black.png b/docs/img/patreon_logo_black.png similarity index 100% rename from docs/patreon_logo_black.png rename to docs/img/patreon_logo_black.png diff --git a/docs/patreon_logo_white.png b/docs/img/patreon_logo_white.png similarity index 100% rename from docs/patreon_logo_white.png rename to docs/img/patreon_logo_white.png diff --git a/docs/pixiv_fanbox_black.png b/docs/img/pixiv_fanbox_black.png similarity index 100% rename from docs/pixiv_fanbox_black.png rename to docs/img/pixiv_fanbox_black.png diff --git a/docs/pixiv_fanbox_white.png b/docs/img/pixiv_fanbox_white.png similarity index 100% rename from docs/pixiv_fanbox_white.png rename to docs/img/pixiv_fanbox_white.png diff --git a/docs/supporter_section_border_d.png b/docs/img/supporter_section_border_d.png similarity index 100% rename from docs/supporter_section_border_d.png rename to docs/img/supporter_section_border_d.png diff --git a/docs/supporter_section_border_l.png b/docs/img/supporter_section_border_l.png similarity index 100% rename from docs/supporter_section_border_l.png rename to docs/img/supporter_section_border_l.png diff --git a/docs/vrct_logo.png b/docs/img/vrct_logo.png similarity index 100% rename from docs/vrct_logo.png rename to docs/img/vrct_logo.png diff --git a/docs/vrct_logo_black.png b/docs/img/vrct_logo_black.png similarity index 100% rename from docs/vrct_logo_black.png rename to docs/img/vrct_logo_black.png diff --git a/docs/vrct_logo_white.png b/docs/img/vrct_logo_white.png similarity index 100% rename from docs/vrct_logo_white.png rename to docs/img/vrct_logo_white.png diff --git a/docs/readmes/README.en.md b/docs/readmes/README.en.md new file mode 100644 index 00000000..f3f35a16 --- /dev/null +++ b/docs/readmes/README.en.md @@ -0,0 +1,107 @@ +
+ + + + + VRCT Logo + + +
+
+ +[![GitHub release](https://img.shields.io/github/v/release/misyaguziya/VRCT.svg)](https://github.com/misyaguziya/VRCT/releases) +[![Downloads](https://img.shields.io/github/downloads/misyaguziya/VRCT/total)](https://github.com/misyaguziya/VRCT/releases) +[![Licence](https://img.shields.io/github/license/misyaguziya/VRCT)](https://github.com/misyaguziya/VRCT/blob/master/LICENSE) +[![Booth](https://img.shields.io/badge/Store-Booth.pm-red)](https://misyaguziya.booth.pm/items/5155325) +[![Github Sponsors](https://img.shields.io/badge/GitHub%20Sponsors-30363D?&logo=GitHub-Sponsors&logoColor=EA4AAA)](https://github.com/sponsors/misyaguziya) + +

+Become a VRCT Supporter on: +

+ + + + + + PIXIV FANBOX + +   + + + + + + Patreon + +   + + + + Ko-fi + +   + +
+ + + + + Supporter Section Border + + +
+
+ +| **English** | [日本語](/docs/readmes/README.ja.md) | [한국어](/docs/readmes/README.ko.md) | [繁體中文](/docs/readmes/README.zh-Hant.md) | + +

+VRCT is software that supports VRChat conversations with translation and transcription. +

+ +![](/docs/img/main_window.png) + +
+ +# Download & Install +Download from anywhere you like. +- [Github.com](https://github.com/misyaguziya/VRCT/releases/) +- [BOOTH.pm](https://misyaguziya.booth.pm/items/5155325) + +Just download and run the exe. + +# What is VRCT? +VRCT is software that supports conversations between people who speak different languages by providing chat or voice translation. +These features are designed for use within VRChat. +*Although not supported, it is also used for other purposes such as watching movies. + +VRCT supports your conversations with +- 💬 **Send chat to VRChat** +- 🌐 **Translation** +- 🎙 **Transcription of audio from microphone** +- 🔈 **Transcription of audio from Speaker** + +# Documents +Initial setup, basic functions, and other features are also described. +- [Documents Link](https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246?pvs=4) + +# How to Use (YouTube) +
+ +[![](https://img.youtube.com/vi/rUTad037n8Q/0.jpg)](https://www.youtube.com/watch?v=rUTad037n8Q) + +
+ +## Author +- [みしゃ(misyaguzi)](https://github.com/misyaguziya) (Main Development) +- [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI multilingual support) +- [レラ](https://github.com/soumt-r) (Technical Support) +- [どね](https://twitter.com/done_vrc) (Logo Design) + +## Thanks to our contributors + + + + +--- + +VRCT is not endorsed by VRChat and does not reflect the views or opinions of VRChat or anyone officially involved in producing or managing VRChat properties. VRChat and all associated properties are trademarks or registered trademarks of VRChat Inc. VRChat © VRChat Inc. \ No newline at end of file diff --git a/README.ja.md b/docs/readmes/README.ja.md similarity index 67% rename from README.ja.md rename to docs/readmes/README.ja.md index 1d7a8c2a..86efe858 100644 --- a/README.ja.md +++ b/docs/readmes/README.ja.md @@ -1,9 +1,9 @@
- - - VRCT Logo + + + VRCT Logo
@@ -21,44 +21,44 @@ Become a VRCT Supporter on: - - - PIXIV FANBOX + + + PIXIV FANBOX    - - - Patreon + + + Patreon    - Ko-fi + Ko-fi   
- - - Supporter Section Border + + + Supporter Section Border

-| [English](./README.md) | **日本語** | [한국어](./README.ko.md) | [繁體中文](./README.zh-Hant.md) | +| [English](/docs/readmes/README.en.md) | **日本語** | [한국어](/docs/readmes/README.ko.md) | [繁體中文](/docs/readmes/README.zh-Hant.md) |

VRCTは翻訳や文字起こしでVRChatの会話をサポートするソフトウェアです。

-![](docs/main_window.png) +![](/docs/img/main_window.png)
@@ -91,15 +91,6 @@ VRCTはあなたの会話を以下でサポートをします。
-# pythonで実行したい場合 -1. 以下のバージョンのpythonをインストールしてください。 - `python version 3.11.5` -2. packageのインストールとmain.pyを起動してください。 - ```bash - ./install.bat - python main.py - ``` - ## Author - [みしゃ(misyaguzi)](https://github.com/misyaguziya) (メイン開発) - [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI多言語対応) diff --git a/README.ko.md b/docs/readmes/README.ko.md similarity index 67% rename from README.ko.md rename to docs/readmes/README.ko.md index cffa325c..d09e9d36 100644 --- a/README.ko.md +++ b/docs/readmes/README.ko.md @@ -1,9 +1,9 @@
- - - VRCT Logo + + + VRCT Logo
@@ -21,44 +21,44 @@ Become a VRCT Supporter on: - - - PIXIV FANBOX + + + PIXIV FANBOX    - - - Patreon + + + Patreon    - Ko-fi + Ko-fi   
- - - Supporter Section Border + + + Supporter Section Border

-| [English](./README.md) | [日本語](./README.ja.md) | **한국어** | [繁體中文](./README.zh-Hant.md) | +| [English](/docs/readmes/README.en.md) | [日本語](/docs/readmes/README.ja.md) | **한국어** | [繁體中文](/docs/readmes/README.zh-Hant.md) |

VRCT는 음성인식 및 번역 기능을 통해 VRChat의 대화를 지원하는 소프트웨어입니다.

-![](docs/main_window.png) +![](/docs/img/main_window.png)
@@ -91,15 +91,6 @@ VRCT는 다음과 같이 당신의 대화를 도와드려요.
-# python으로 실행하고 싶은 경우 -1. 다음 버전의 python을 설치합니다. - `python version 3.11.5` -2. 패키지를 설치하고 main.py를 실행합니다. - ```bash - ./install.bat - python main.py - ``` - ## Author - [みしゃ(misyaguzi)](https://github.com/misyaguziya) (주요 개발) - [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI 다국어 지원) diff --git a/README.zh-Hant.md b/docs/readmes/README.zh-Hant.md similarity index 64% rename from README.zh-Hant.md rename to docs/readmes/README.zh-Hant.md index ea79a1b1..05a8fece 100644 --- a/README.zh-Hant.md +++ b/docs/readmes/README.zh-Hant.md @@ -1,9 +1,9 @@
- - - VRCT Logo + + + VRCT Logo
@@ -21,44 +21,44 @@ Become a VRCT Supporter on: - - - PIXIV FANBOX + + + PIXIV FANBOX    - - - Patreon + + + Patreon    - Ko-fi + Ko-fi   
- - - Supporter Section Border + + + Supporter Section Border

-| [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) | **繁體中文** |

VRCT 是一個支援 VRChat 對話翻譯和紀錄的軟體。

-![](docs/main_window.png) +![](/docs/img/main_window.png)
@@ -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}/> + +
+ ); +}; \ 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";