From 60eed02805cbf8d2882ed5164c502531055ffec6 Mon Sep 17 00:00:00 2001 From: himeditator Date: Thu, 3 Sep 2026 21:49:11 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E9=87=8D=E6=9E=84=EF=BC=9A=E6=8B=86?= =?UTF-8?q?=E5=88=86=20Ollama=20=E4=B8=8E=20OpenAI=20=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 拆分 Ollama、OpenAI 兼容和 Google 翻译服务 - 重命名主进程与字幕引擎通信参数 - 自动迁移旧版翻译配置 - 在日志中隐藏翻译 API Key - 更新多语言文档和命令行示例 --- README.md | 6 +- README_en.md | 6 +- README_ja.md | 6 +- docs/CHANGELOG.md | 7 ++ docs/TODO.md | 4 +- docs/engine-manual/en.md | 17 ++-- docs/engine-manual/ja.md | 6 +- docs/engine-manual/zh.md | 15 ++-- docs/user-manual/en.md | 40 ++++++--- docs/user-manual/zh.md | 42 ++++++--- engine/audio2text/glm.py | 36 +++----- engine/audio2text/sosv.py | 23 +++-- engine/audio2text/vosk.py | 25 +++--- engine/main.py | 80 +++++++++-------- engine/utils/__init__.py | 2 +- engine/utils/translation.py | 87 ++++++++++--------- src/main/types/index.ts | 13 +-- src/main/utils/AllConfig.ts | 41 +++++++-- src/main/utils/CaptionEngine.ts | 36 ++++---- src/main/utils/UtilsFunc.ts | 2 +- src/renderer/src/components/EngineControl.vue | 87 +++++++++++-------- src/renderer/src/i18n/config/engine.ts | 45 ++++++---- src/renderer/src/i18n/lang/en.ts | 13 +-- src/renderer/src/i18n/lang/ja.ts | 13 +-- src/renderer/src/i18n/lang/zh.ts | 13 +-- src/renderer/src/stores/engineControl.ts | 44 +++++----- src/renderer/src/types/index.ts | 13 +-- 27 files changed, 418 insertions(+), 304 deletions(-) diff --git a/README.md b/README.md index f8500a0..ffa87de 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,11 @@ macOS 平台和 Linux 平台获取系统音频输出需要进行额外设置, > 注意:使用参数量过大的模型会导致资源消耗和翻译延迟较大。建议使用参数量小于 1B 的模型,比如: `qwen2.5:0.5b`, `qwen3:0.6b`。 -使用该模型之前你需要确定本机安装了 [Ollama](https://ollama.com/) 软件,并已经下载了需要的大语言模型。只需要将需要调用的大模型名称添加到设置中的 `模型名称` 字段中,并保证 `Base URL` 字段为空。 +使用该模型之前你需要确定本机安装了 [Ollama](https://ollama.com/) 软件,并已经下载了需要的大语言模型。在“翻译服务”中选择 `Ollama 本地模型`,再填写模型名称即可;Ollama 会使用本机默认服务地址。 #### OpenAI 兼容模型 -如果觉得本地 Ollama 模型的翻译效果不佳,或者不想在本地安装 Ollama 模型,那么可以使用云端的 OpenAI 兼容模型。 +如果觉得本地 Ollama 模型的翻译效果不佳,或者不想在本地安装 Ollama 模型,那么可以在“翻译服务”中选择 `OpenAI 兼容模型`,并分别填写模型名称、Base URL 和 API Key。 以下是一些模型提供商的 `Base URL`: - OpenAI: https://api.openai.com/v1 @@ -145,7 +145,7 @@ API KEY 获取相关链接:[快速开始](https://docs.bigmodel.cn/cn/guide/st ```bash python main.py \ -e gummy \ --k sk-******************************** \ +--gummy_api_key sk-******************************** \ -a 0 \ -d 1 \ -s en \ diff --git a/README_en.md b/README_en.md index 7afd984..9fd6a31 100644 --- a/README_en.md +++ b/README_en.md @@ -86,11 +86,11 @@ If you choose a model other than Gummy, you also need to configure your own tran > Note: Using models with too many parameters will lead to high resource consumption and translation delays. It is recommended to use models with less than 1B parameters, such as: `qwen2.5:0.5b`, `qwen3:0.6b`. -Before using this model, you need to confirm that the [Ollama](https://ollama.com/) software is installed on your local machine and that you have downloaded the required large language model. Simply add the name of the large model you want to call to the `Model Name` field in the settings, and ensure that the `Base URL` field is empty. +Before using this model, confirm that [Ollama](https://ollama.com/) is installed locally and that the required model has been downloaded. Select `Ollama Local Model` as the translation service and enter the model name; Ollama uses its default local service address. #### OpenAI Compatible Model -If you feel the translation effect of the local Ollama model is not good enough, or don't want to install the Ollama model locally, then you can use cloud-based OpenAI compatible models. +If the local Ollama model is not suitable, select `OpenAI-compatible Model` as the translation service and enter its model name, Base URL, and API key separately. Here are some model provider `Base URL`s: - OpenAI: https://api.openai.com/v1 @@ -146,7 +146,7 @@ For runtime parameters and detailed usage instructions, please refer to the [Use ```bash python main.py \ -e gummy \ --k sk-******************************** \ +--gummy_api_key sk-******************************** \ -a 0 \ -d 1 \ -s en \ diff --git a/README_ja.md b/README_ja.md index ab398b8..2a900a5 100644 --- a/README_ja.md +++ b/README_ja.md @@ -87,11 +87,11 @@ Gummyモデル以外を選択した場合、独自の翻訳モデルを設定す > 注意:パラメータ数が多すぎるモデルを使用すると、リソース消費と翻訳遅延が大きくなります。1B未満のパラメータ数のモデルを使用することを推奨します。例:`qwen2.5:0.5b`、`qwen3:0.6b`。 -このモデルを使用する前に、ローカルマシンに[Ollama](https://ollama.com/)ソフトウェアがインストールされており、必要な大規模言語モデルをダウンロード済みであることを確認してください。設定で呼び出す必要がある大規模モデル名を「モデル名」フィールドに入力し、「Base URL」フィールドが空であることを確認してください。 +このモデルを使用する前に、ローカルマシンに [Ollama](https://ollama.com/) がインストールされ、必要なモデルがダウンロード済みであることを確認してください。翻訳サービスで「Ollama ローカルモデル」を選択し、モデル名を入力します。Ollama はデフォルトのローカルサービスアドレスを使用します。 #### OpenAI互換モデル -ローカルのOllamaモデルの翻訳効果が良くないと感じる場合や、ローカルにOllamaモデルをインストールしたくない場合は、クラウド上のOpenAI互換モデルを使用できます。 +ローカルの Ollama モデルが適さない場合は、翻訳サービスで「OpenAI 互換モデル」を選択し、モデル名、Base URL、API Key を個別に入力します。 いくつかのモデルプロバイダの「Base URL」: - OpenAI: https://api.openai.com/v1 @@ -147,7 +147,7 @@ SOSVモデルの使用方法はVoskと同じで、ダウンロードアドレス ```bash python main.py \ -e gummy \ --k sk-******************************** \ +--gummy_api_key sk-******************************** \ -a 0 \ -d 1 \ -s en \ diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index c7ab0a9..064c108 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -188,3 +188,10 @@ - 取消字幕窗口的顶置选项,字幕窗口将始终处于顶置状态 - 将字幕窗口顶置选项改为鼠标穿透选项,当图钉图标为实心时,表示启用鼠标穿透 +## 未发布 + +### 优化体验 + +- 将自定义翻译服务拆分为 Ollama 本地模型和 OpenAI API 兼容模型,分别保存两类服务的配置 +- 重命名主进程与字幕引擎之间含义不准确的翻译参数,并为旧版应用配置提供自动迁移 + diff --git a/docs/TODO.md b/docs/TODO.md index 07fd219..572b964 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -27,4 +27,6 @@ ## TODO -暂无 +- [ ] 重构整个项目(优化项目结构、更改不合适的配置属性名称) +- [ ] 添加只显示翻译内容的选项 +- [ ] 优化多行字幕的体验 diff --git a/docs/engine-manual/en.md b/docs/engine-manual/en.md index f03ca46..7d349b2 100644 --- a/docs/engine-manual/en.md +++ b/docs/engine-manual/en.md @@ -144,10 +144,11 @@ Some speech-to-text models do not provide translation. If needed, an additional Example: ```python -from utils import google_translate, ollama_translate +from utils import google_translate, ollama_translate, openai_translate text = "This is a translation test." google_translate("", "en", text, "time_s") ollama_translate("qwen3:0.6b", "en", text, "time_s") +openai_translate("gpt-4.1-mini", "en", text, "time_s", "https://api.openai.com/v1", "") ``` ### Caption Data Transmission @@ -187,10 +188,12 @@ if __name__ == "__main__": # gummy and sosv parser.add_argument('-s', '--source_language', default='auto', help='Source language code') # gummy only - parser.add_argument('-k', '--api_key', default='', help='API KEY for Gummy model') - # vosk and sosv - parser.add_argument('-tm', '--translation_model', default='ollama', help='Model for translation: ollama or google') - parser.add_argument('-omn', '--ollama_name', default='', help='Ollama model name for translation') + parser.add_argument('--gummy_api_key', default='', help='API key for the Gummy caption engine') + # vosk, sosv and glm translation + parser.add_argument('--translation_provider', choices=['ollama', 'openai', 'google'], default='ollama', help='Translation service provider') + parser.add_argument('--translation_model', default='', help='Translation model name') + parser.add_argument('--translation_base_url', default='', help='OpenAI-compatible API base URL') + parser.add_argument('--translation_api_key', default='', help='OpenAI-compatible API key') # vosk only parser.add_argument('-vosk', '--vosk_model', default='', help='The path to the vosk model.') # sosv only @@ -200,7 +203,7 @@ if __name__ == "__main__": For example, for this project's caption engine, if I want to use the Gummy model, specify the original text as Japanese, translate to Chinese, and capture captions from system audio output, with 0.1s audio data segments each time, the command line parameters would be: ```bash -python main.py -e gummy -s ja -t zh -a 0 -c 10 -k +python main.py -e gummy -s ja -t zh -a 0 -c 10 --gummy_api_key ``` ## Additional Notes @@ -228,4 +231,4 @@ After development and testing, the caption engine must be packaged into an execu With a functional caption engine, it can be launched in the caption software window by specifying the engine's path and runtime arguments. -![](../img/02_en.png) \ No newline at end of file +![](../img/02_en.png) diff --git a/docs/engine-manual/ja.md b/docs/engine-manual/ja.md index e69d624..b8752c3 100644 --- a/docs/engine-manual/ja.md +++ b/docs/engine-manual/ja.md @@ -164,7 +164,7 @@ if __name__ == "__main__": # gummy専用 parser.add_argument('-s', '--source_language', default='en', help='ソース言語コード') parser.add_argument('-t', '--target_language', default='zh', help='ターゲット言語コード') - parser.add_argument('-k', '--api_key', default='', help='GummyモデルのAPI KEY') + parser.add_argument('--gummy_api_key', default='', help='GummyモデルのAPI KEY') # vosk専用 parser.add_argument('-m', '--model_path', default='', help='voskモデルのパス') ``` @@ -172,7 +172,7 @@ if __name__ == "__main__": たとえば、このプロジェクトの字幕エンジンでGummyモデルを使用し、原文を日本語、翻訳を中国語に指定し、システムオーディオ出力の字幕を取得し、毎回0.1秒のオーディオデータをキャプチャする場合、コマンドラインパラメータは以下のようになります: ```bash -python main.py -e gummy -s ja -t zh -a 0 -c 10 -k +python main.py -e gummy -s ja -t zh -a 0 -c 10 --gummy_api_key ``` ## その他 @@ -200,4 +200,4 @@ python main.py -e gummy -s ja -t zh -a 0 -c 10 -k 使用可能な字幕エンジンを取得したら、字幕ソフトウェアウィンドウで字幕エンジンのパスと字幕エンジンの実行コマンド(パラメータ)を指定して字幕エンジンを起動できます。 -![](../img/02_ja.png) \ No newline at end of file +![](../img/02_ja.png) diff --git a/docs/engine-manual/zh.md b/docs/engine-manual/zh.md index ceb0a5c..1104a2e 100644 --- a/docs/engine-manual/zh.md +++ b/docs/engine-manual/zh.md @@ -144,10 +144,11 @@ while True: 样例: ```python -from utils import google_translate, ollama_translate +from utils import google_translate, ollama_translate, openai_translate text = "这是一个翻译测试。" google_translate("", "en", text, "time_s") ollama_translate("qwen3:0.6b", "en", text, "time_s") +openai_translate("gpt-4.1-mini", "en", text, "time_s", "https://api.openai.com/v1", "") ``` ### 字幕数据发送 @@ -187,10 +188,12 @@ if __name__ == "__main__": # gummy and sosv parser.add_argument('-s', '--source_language', default='auto', help='Source language code') # gummy only - parser.add_argument('-k', '--api_key', default='', help='API KEY for Gummy model') - # vosk and sosv - parser.add_argument('-tm', '--translation_model', default='ollama', help='Model for translation: ollama or google') - parser.add_argument('-omn', '--ollama_name', default='', help='Ollama model name for translation') + parser.add_argument('--gummy_api_key', default='', help='API key for the Gummy caption engine') + # vosk, sosv and glm translation + parser.add_argument('--translation_provider', choices=['ollama', 'openai', 'google'], default='ollama', help='Translation service provider') + parser.add_argument('--translation_model', default='', help='Translation model name') + parser.add_argument('--translation_base_url', default='', help='OpenAI-compatible API base URL') + parser.add_argument('--translation_api_key', default='', help='OpenAI-compatible API key') # vosk only parser.add_argument('-vosk', '--vosk_model', default='', help='The path to the vosk model.') # sosv only @@ -200,7 +203,7 @@ if __name__ == "__main__": 比如对于本项目的字幕引擎,我想使用 Gummy 模型,指定原文为日语,翻译为中文,获取系统音频输出的字幕,每次截取 0.1s 的音频数据,那么命令行参数如下: ```bash -python main.py -e gummy -s ja -t zh -a 0 -c 10 -k +python main.py -e gummy -s ja -t zh -a 0 -c 10 --gummy_api_key ``` ## 其他 diff --git a/docs/user-manual/en.md b/docs/user-manual/en.md index a88a97b..916ef83 100644 --- a/docs/user-manual/en.md +++ b/docs/user-manual/en.md @@ -212,7 +212,7 @@ The GLM model supports specifying the following languages: English, Chinese, Jap The SOSV model supports specifying the following languages: English, Chinese, Japanese, Korean, and Cantonese. -#### `-k, --api_key` +#### `--gummy_api_key` Specify the Alibaba Cloud API KEY required for the `Gummy` model. @@ -232,34 +232,35 @@ Specifies the model name to be used for the `glm` model. The default value is `g Specifies the API URL required for the `glm` model. The default value is: `https://open.bigmodel.cn/api/paas/v4/audio/transcriptions`. -#### `-tm, --translation_model` +#### `--translation_provider` -Specify the translation method for Vosk and SOSV models. Default is `ollama`. +Specifies the translation service used by the Vosk, SOSV, and GLM caption engines. The default is `ollama`. Supported values are: - `ollama` Use local Ollama model for translation. Users need to install Ollama software and corresponding models +- `openai` Use an OpenAI API-compatible translation service - `google` Use Google Translate API for translation. No additional configuration needed, but requires network access to Google -This only applies to Vosk and SOSV models. +This only applies to caption engines without built-in translation. -#### `-omn, --ollama_name` +#### `--translation_model` -Specifies the name of the translation model to be used, which can be either a local Ollama model or a cloud model compatible with the OpenAI API. If the Base URL field is not filled in, the local Ollama service will be called by default; otherwise, the API service at the specified address will be invoked via the Python OpenAI library. +Specifies the model name used by Ollama or an OpenAI-compatible service. Google Translate does not use this option. If using an Ollama model, it is recommended to use a model with fewer than 1B parameters, such as `qwen2.5:0.5b` or `qwen3:0.6b`. The corresponding model must be downloaded in Ollama for normal use. The default value is empty and applies to models other than Gummy. -#### `-ourl, --ollama_url` +#### `--translation_base_url` -The base request URL for calling the OpenAI API. If left blank, the local Ollama model on the default port will be called. +The base URL of the OpenAI-compatible service, such as `https://api.openai.com/v1`. Used only with `--translation_provider openai`. The default value is empty and applies to models other than Gummy. -#### `-okey, --ollama_api_key` +#### `--translation_api_key` -Specifies the API KEY for calling OpenAI-compatible models. +Specifies the API key for the OpenAI-compatible service. Used only with `--translation_provider openai`. The default value is empty and applies to models other than Gummy. @@ -290,7 +291,7 @@ For example, to use the Gummy model, specify audio type as system audio output, ```bash python main.py \ -e gummy \ --k sk-******************************** \ +--gummy_api_key sk-******************************** \ -a 0 \ -d 1 \ -s en \ @@ -306,6 +307,21 @@ python main.py \ -a 0 \ -d 1 \ -t en \ +--translation_provider ollama \ +--translation_model qwen3:0.6b +``` + +To use an OpenAI-compatible service instead, specify the service type, model, and Base URL explicitly: + +```bash +python main.py \ +-e vosk \ +-vosk D:\Projects\auto-caption\engine\models\vosk-model-small-cn-0.22 \ +-t en \ +--translation_provider openai \ +--translation_model gpt-4.1-mini \ +--translation_base_url https://api.openai.com/v1 \ +--translation_api_key sk-******************************** ``` To specify the SOSV model, audio type as microphone, automatically select source language, and no translation: @@ -330,4 +346,4 @@ First, download the executable file for your platform from [GitHub Releases](htt Then open a terminal in the directory containing the caption engine executable file and execute commands to run the caption engine. -Simply replace `python main.py` in the above commands with the executable file name (for example: `engine-win.exe`). \ No newline at end of file +Simply replace `python main.py` in the above commands with the executable file name (for example: `engine-win.exe`). diff --git a/docs/user-manual/zh.md b/docs/user-manual/zh.md index 3b587e3..b749ab4 100644 --- a/docs/user-manual/zh.md +++ b/docs/user-manual/zh.md @@ -209,7 +209,7 @@ GLM 模型支持指定的语言有:英语、中文、日语、韩语。 SOSV 模型支持指定的语言有:英语、中文、日语、韩语、粤语。 -#### `-k, --api_key` +#### `--gummy_api_key` 指定 `Gummy` 模型需要使用的阿里云 API KEY。 @@ -229,34 +229,35 @@ SOSV 模型支持指定的语言有:英语、中文、日语、韩语、粤语 指定 `glm` 模型需要使用的 API URL,默认值为:`https://open.bigmodel.cn/api/paas/v4/audio/transcriptions`。 -#### `-tm, --translation_model` +#### `--translation_provider` -指定 Vosk 和 SOSV 模型的翻译方式,默认为 `ollama`。 +指定 Vosk、SOSV 和 GLM 字幕引擎使用的翻译服务,默认为 `ollama`。 该项支持的值有: - `ollama` 使用本地 Ollama 模型进行翻译,需要用户安装 Ollama 软件和对应的模型 +- `openai` 使用 OpenAI API 兼容服务进行翻译 - `google` 使用 Google 翻译 API 进行翻译,无需额外配置,但是需要有能访问 Google 的网络 -该项仅适用于 Vosk 和 SOSV 模型。 +该项仅适用于没有内置翻译功能的字幕引擎。 -#### `-omn, --ollama_name` +#### `--translation_model` -指定要使用的翻译模型名称,可以是 Ollama 本地模型,也可以是 OpenAI API 兼容的云端模型。若未填写 Base URL 字段,则默认调用本地 Ollama 服务,否则会通过 Python OpenAI 库调用该地址指向的 API 服务。 +指定 Ollama 或 OpenAI API 兼容服务使用的模型名称。Google 翻译不使用此参数。 如果使用 Ollama 模型,建议使用参数量小于 1B 的模型,比如: `qwen2.5:0.5b`, `qwen3:0.6b`。需要在 Ollama 中下载了对应的模型才能正常使用。 -默认值为空,适用于除了 Gummy 外的其他模型。 +默认值为空。 -#### `-ourl, --ollama_url` +#### `--translation_base_url` -调用 OpenAI API 的基础请求地址,如果不填写则调用本地默认端口的 Ollama 模型。 +OpenAI API 兼容服务的基础请求地址,例如 `https://api.openai.com/v1`。仅当 `--translation_provider openai` 时使用。 默认值为空,适用于除了 Gummy 外的其他模型。 -#### `-okey, --ollama_api_key` +#### `--translation_api_key` -指定调用 OpenAI 兼容模型的 API KEY。 +指定调用 OpenAI API 兼容服务的 API Key。仅当 `--translation_provider openai` 时使用。 默认值为空,适用于除了 Gummy 外的其他模型。 @@ -287,7 +288,7 @@ SOSV 模型支持指定的语言有:英语、中文、日语、韩语、粤语 ```bash python main.py \ -e gummy \ --k sk-******************************** \ +--gummy_api_key sk-******************************** \ -a 0 \ -d 1 \ -s en \ @@ -303,6 +304,21 @@ python main.py \ -a 0 \ -d 1 \ -t en \ +--translation_provider ollama \ +--translation_model qwen3:0.6b +``` + +如果改用 OpenAI API 兼容服务,需要明确指定服务类型、模型和 Base URL: + +```bash +python main.py \ +-e vosk \ +-vosk D:\Projects\auto-caption\engine\models\vosk-model-small-cn-0.22 \ +-t en \ +--translation_provider openai \ +--translation_model gpt-4.1-mini \ +--translation_base_url https://api.openai.com/v1 \ +--translation_api_key sk-******************************** ``` 指定 SOSV 模型,指定音频类型为麦克风,自动选择源语言,不翻译,执行的命令如下: @@ -327,4 +343,4 @@ python main.py \ 然后再字幕引擎可执行文件所在目录打开终端,执行命令进行运行字幕引擎。 -只需要将上述指令中的 `python main.py` 替换为可执行文件名称即可(比如:`engine-win.exe`)。 \ No newline at end of file +只需要将上述指令中的 `python main.py` 替换为可执行文件名称即可(比如:`engine-win.exe`)。 diff --git a/engine/audio2text/glm.py b/engine/audio2text/glm.py index e39021c..b5729a1 100644 --- a/engine/audio2text/glm.py +++ b/engine/audio2text/glm.py @@ -8,7 +8,7 @@ from datetime import datetime from utils import shared_data -from utils import stdout_cmd, stdout_obj, google_translate, ollama_translate +from utils import stdout_cmd, stdout_obj, get_translation_function class GlmRecognizer: """ @@ -20,22 +20,19 @@ class GlmRecognizer: api_key: GLM-ASR API Key source: 源语言 target: 目标语言 - trans_model: 翻译模型名称 - ollama_name: Ollama 模型名称 + translation_provider: 翻译服务 + translation_model: 翻译模型名称 """ - def __init__(self, url: str, model: str, api_key: str, source: str, target: str | None, trans_model: str, ollama_name: str, ollama_url: str = '', ollama_api_key: str = ''): + def __init__(self, url: str, model: str, api_key: str, source: str, target: str | None, translation_provider: str, translation_model: str, translation_base_url: str = '', translation_api_key: str = ''): self.url = url self.model = model self.api_key = api_key self.source = source self.target = target - if trans_model == 'google': - self.trans_func = google_translate - else: - self.trans_func = ollama_translate - self.ollama_name = ollama_name - self.ollama_url = ollama_url - self.ollama_api_key = ollama_api_key + self.translation_function = get_translation_function(translation_provider) + self.translation_model = translation_model + self.translation_base_url = translation_base_url + self.translation_api_key = translation_api_key self.audio_buffer = [] self.is_speech = False @@ -140,18 +137,11 @@ def output_caption(self, text, time_s, index): } if self.target: - if self.trans_func == ollama_translate: - th = threading.Thread( - target=self.trans_func, - args=(self.ollama_name, self.target, caption['text'], time_s, self.ollama_url, self.ollama_api_key), - daemon=True - ) - else: - th = threading.Thread( - target=self.trans_func, - args=(self.ollama_name, self.target, caption['text'], time_s), - daemon=True - ) + th = threading.Thread( + target=self.translation_function, + args=(self.translation_model, self.target, caption['text'], time_s, self.translation_base_url, self.translation_api_key), + daemon=True + ) th.start() stdout_obj(caption) diff --git a/engine/audio2text/sosv.py b/engine/audio2text/sosv.py index 4466fe3..855a05a 100644 --- a/engine/audio2text/sosv.py +++ b/engine/audio2text/sosv.py @@ -14,7 +14,7 @@ from utils import shared_data from utils import stdout_cmd, stdout_obj -from utils import google_translate, ollama_translate +from utils import get_translation_function class SosvRecognizer: @@ -26,10 +26,10 @@ class SosvRecognizer: vad_model: Silero VAD 模型路径 source: 识别源语言(auto, zh, en, ja, ko, yue) target: 翻译目标语言 - trans_model: 翻译模型名称 - ollama_name: Ollama 模型名称 + translation_provider: 翻译服务 + translation_model: 翻译模型名称 """ - def __init__(self, model_path: str, source: str, target: str | None, trans_model: str, ollama_name: str, ollama_url: str = '', ollama_api_key: str = ''): + def __init__(self, model_path: str, source: str, target: str | None, translation_provider: str, translation_model: str, translation_base_url: str = '', translation_api_key: str = ''): if model_path.startswith('"'): model_path = model_path[1:] if model_path.endswith('"'): @@ -40,13 +40,10 @@ def __init__(self, model_path: str, source: str, target: str | None, trans_model self.ext = ".int8" self.source = source self.target = target - if trans_model == 'google': - self.trans_func = google_translate - else: - self.trans_func = ollama_translate - self.ollama_name = ollama_name - self.ollama_url = ollama_url - self.ollama_api_key = ollama_api_key + self.translation_function = get_translation_function(translation_provider) + self.translation_model = translation_model + self.translation_base_url = translation_base_url + self.translation_api_key = translation_api_key self.time_str = '' self.cur_id = 0 self.prev_content = '' @@ -153,8 +150,8 @@ def send_audio_frame(self, data: bytes): stdout_obj(caption) if self.target: th = threading.Thread( - target=self.trans_func, - args=(self.ollama_name, self.target, caption['text'], self.time_str, self.ollama_url, self.ollama_api_key), + target=self.translation_function, + args=(self.translation_model, self.target, caption['text'], self.time_str, self.translation_base_url, self.translation_api_key), daemon=True ) th.start() diff --git a/engine/audio2text/vosk.py b/engine/audio2text/vosk.py index 480d298..751c5ba 100644 --- a/engine/audio2text/vosk.py +++ b/engine/audio2text/vosk.py @@ -5,7 +5,7 @@ from vosk import Model, KaldiRecognizer, SetLogLevel from utils import shared_data -from utils import stdout_cmd, stdout_obj, google_translate, ollama_translate +from utils import stdout_cmd, stdout_obj, get_translation_function class VoskRecognizer: @@ -15,10 +15,10 @@ class VoskRecognizer: 初始化参数: model_path: Vosk 识别模型路径 target: 翻译目标语言 - trans_model: 翻译模型名称 - ollama_name: Ollama 模型名称 + translation_provider: 翻译服务 + translation_model: 翻译模型名称 """ - def __init__(self, model_path: str, target: str | None, trans_model: str, ollama_name: str, ollama_url: str = '', ollama_api_key: str = ''): + def __init__(self, model_path: str, target: str | None, translation_provider: str, translation_model: str, translation_base_url: str = '', translation_api_key: str = ''): SetLogLevel(-1) if model_path.startswith('"'): model_path = model_path[1:] @@ -26,13 +26,10 @@ def __init__(self, model_path: str, target: str | None, trans_model: str, ollama model_path = model_path[:-1] self.model_path = model_path self.target = target - if trans_model == 'google': - self.trans_func = google_translate - else: - self.trans_func = ollama_translate - self.ollama_name = ollama_name - self.ollama_url = ollama_url - self.ollama_api_key = ollama_api_key + self.translation_function = get_translation_function(translation_provider) + self.translation_model = translation_model + self.translation_base_url = translation_base_url + self.translation_api_key = translation_api_key self.time_str = '' self.cur_id = 0 self.prev_content = '' @@ -67,8 +64,8 @@ def send_audio_frame(self, data: bytes): if self.target: th = threading.Thread( - target=self.trans_func, - args=(self.ollama_name, self.target, caption['text'], self.time_str, self.ollama_url, self.ollama_api_key), + target=self.translation_function, + args=(self.translation_model, self.target, caption['text'], self.time_str, self.translation_base_url, self.translation_api_key), daemon=True ) th.start() @@ -95,4 +92,4 @@ def translate(self): def stop(self): """停止 Vosk 引擎""" - stdout_cmd('info', 'Vosk recognizer closed.') \ No newline at end of file + stdout_cmd('info', 'Vosk recognizer closed.') diff --git a/engine/main.py b/engine/main.py index 5cc55d4..384eb9b 100644 --- a/engine/main.py +++ b/engine/main.py @@ -75,25 +75,25 @@ def main_gummy(s: str, t: str, a: int, c: int, k: str, r: bool, rp: str): engine.stop() -def main_vosk(a: int, c: int, vosk: str, t: str, tm: str, omn: str, ourl: str, okey: str, r: bool, rp: str): +def main_vosk(a: int, c: int, vosk: str, t: str, translation_provider: str, translation_model: str, translation_base_url: str, translation_api_key: str, r: bool, rp: str): """ Parameters: a: Audio source: 0 for output, 1 for input c: Chunk number in 1 second vosk: Vosk model path t: Target language - tm: Translation model type, ollama or google - omn: Ollama model name - ourl: Ollama Base URL - okey: Ollama API Key + translation_provider: Translation service: ollama, openai or google + translation_model: Model name used by the translation service + translation_base_url: OpenAI-compatible API base URL + translation_api_key: OpenAI-compatible API key r: Whether to record the audio rp: Path to save the recorded audio """ stream = AudioStream(a, c) if t == 'none': - engine = VoskRecognizer(vosk, None, tm, omn, ourl, okey) + engine = VoskRecognizer(vosk, None, translation_provider, translation_model, translation_base_url, translation_api_key) else: - engine = VoskRecognizer(vosk, t, tm, omn, ourl, okey) + engine = VoskRecognizer(vosk, t, translation_provider, translation_model, translation_base_url, translation_api_key) engine.start() stream_thread = threading.Thread( @@ -109,7 +109,7 @@ def main_vosk(a: int, c: int, vosk: str, t: str, tm: str, omn: str, ourl: str, o engine.stop() -def main_sosv(a: int, c: int, sosv: str, s: str, t: str, tm: str, omn: str, ourl: str, okey: str, r: bool, rp: str): +def main_sosv(a: int, c: int, sosv: str, s: str, t: str, translation_provider: str, translation_model: str, translation_base_url: str, translation_api_key: str, r: bool, rp: str): """ Parameters: a: Audio source: 0 for output, 1 for input @@ -117,18 +117,18 @@ def main_sosv(a: int, c: int, sosv: str, s: str, t: str, tm: str, omn: str, ourl sosv: Sherpa-ONNX SenseVoice model path s: Source language t: Target language - tm: Translation model type, ollama or google - omn: Ollama model name - ourl: Ollama API URL - okey: Ollama API Key + translation_provider: Translation service: ollama, openai or google + translation_model: Model name used by the translation service + translation_base_url: OpenAI-compatible API base URL + translation_api_key: OpenAI-compatible API key r: Whether to record the audio rp: Path to save the recorded audio """ stream = AudioStream(a, c) if t == 'none': - engine = SosvRecognizer(sosv, s, None, tm, omn, ourl, okey) + engine = SosvRecognizer(sosv, s, None, translation_provider, translation_model, translation_base_url, translation_api_key) else: - engine = SosvRecognizer(sosv, s, t, tm, omn, ourl, okey) + engine = SosvRecognizer(sosv, s, t, translation_provider, translation_model, translation_base_url, translation_api_key) engine.start() stream_thread = threading.Thread( @@ -144,7 +144,7 @@ def main_sosv(a: int, c: int, sosv: str, s: str, t: str, tm: str, omn: str, ourl engine.stop() -def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: str, omn: str, ourl: str, okey: str, r: bool, rp: str): +def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, translation_provider: str, translation_model: str, translation_base_url: str, translation_api_key: str, r: bool, rp: str): """ Parameters: a: Audio source @@ -154,18 +154,18 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: key: GLM API Key s: Source language t: Target language - tm: Translation model - omn: Ollama model name - ourl: Ollama API URL - okey: Ollama API Key + translation_provider: Translation service: ollama, openai or google + translation_model: Model name used by the translation service + translation_base_url: OpenAI-compatible API base URL + translation_api_key: OpenAI-compatible API key r: Record rp: Record path """ stream = AudioStream(a, c) if t == 'none': - engine = GlmRecognizer(url, model, key, s, None, tm, omn, ourl, okey) + engine = GlmRecognizer(url, model, key, s, None, translation_provider, translation_model, translation_base_url, translation_api_key) else: - engine = GlmRecognizer(url, model, key, s, t, tm, omn, ourl, okey) + engine = GlmRecognizer(url, model, key, s, t, translation_provider, translation_model, translation_base_url, translation_api_key) engine.start() stream_thread = threading.Thread( @@ -196,12 +196,12 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: # gummy and sosv and glm parser.add_argument('-s', '--source_language', default='auto', help='Source language code') # gummy only - parser.add_argument('-k', '--api_key', default='', help='API KEY for Gummy model') - # vosk and sosv - parser.add_argument('-tm', '--translation_model', default='ollama', help='Model for translation: ollama or google') - parser.add_argument('-omn', '--ollama_name', default='', help='Ollama model name for translation') - parser.add_argument('-ourl', '--ollama_url', default='', help='Ollama API URL') - parser.add_argument('-okey', '--ollama_api_key', default='', help='Ollama API Key') + parser.add_argument('--gummy_api_key', default='', help='API key for the Gummy caption engine') + # vosk, sosv and glm translation + parser.add_argument('--translation_provider', choices=['ollama', 'openai', 'google'], default='ollama', help='Translation service provider') + parser.add_argument('--translation_model', default='', help='Translation model name (for Ollama or OpenAI-compatible services)') + parser.add_argument('--translation_base_url', default='', help='OpenAI-compatible API base URL') + parser.add_argument('--translation_api_key', default='', help='OpenAI-compatible API key') # vosk only parser.add_argument('-vosk', '--vosk_model', default='', help='The path to the vosk model.') # sosv only @@ -213,6 +213,12 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: args = parser.parse_args() + uses_external_translation = args.caption_engine != 'gummy' and args.target_language != 'none' + if uses_external_translation and args.translation_provider in ('ollama', 'openai') and not args.translation_model: + parser.error('--translation_model is required when translation is enabled with Ollama or OpenAI') + if uses_external_translation and args.translation_provider == 'openai' and not args.translation_base_url: + parser.error('--translation_base_url is required when translation is enabled with OpenAI') + if args.port != 0: threading.Thread(target=start_server, args=(args.port,), daemon=True).start() @@ -225,7 +231,7 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: args.target_language, int(args.audio_type), int(args.chunk_rate), - args.api_key, + args.gummy_api_key, bool(int(args.record)), args.record_path ) @@ -235,10 +241,10 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: int(args.chunk_rate), args.vosk_model, args.target_language, + args.translation_provider, args.translation_model, - args.ollama_name, - args.ollama_url, - args.ollama_api_key, + args.translation_base_url, + args.translation_api_key, bool(int(args.record)), args.record_path ) @@ -249,10 +255,10 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: args.sosv_model, args.source_language, args.target_language, + args.translation_provider, args.translation_model, - args.ollama_name, - args.ollama_url, - args.ollama_api_key, + args.translation_base_url, + args.translation_api_key, bool(int(args.record)), args.record_path ) @@ -265,10 +271,10 @@ def main_glm(a: int, c: int, url: str, model: str, key: str, s: str, t: str, tm: args.glm_api_key, args.source_language, args.target_language, + args.translation_provider, args.translation_model, - args.ollama_name, - args.ollama_url, - args.ollama_api_key, + args.translation_base_url, + args.translation_api_key, bool(int(args.record)), args.record_path ) diff --git a/engine/utils/__init__.py b/engine/utils/__init__.py index aaf2b4a..40f6b73 100644 --- a/engine/utils/__init__.py +++ b/engine/utils/__init__.py @@ -3,4 +3,4 @@ from .sysout import change_caption_display from .shared import shared_data from .server import start_server -from .translation import ollama_translate, google_translate \ No newline at end of file +from .translation import get_translation_function, google_translate, ollama_translate, openai_translate diff --git a/engine/utils/translation.py b/engine/utils/translation.py index e935d60..1345a0f 100644 --- a/engine/utils/translation.py +++ b/engine/utils/translation.py @@ -1,4 +1,4 @@ -from ollama import chat, Client +from ollama import chat from ollama import ChatResponse try: from openai import OpenAI @@ -21,43 +21,14 @@ 'zh-cn': 'Chinese' } -def ollama_translate(model: str, target: str, text: str, time_s: str, url: str = '', key: str = ''): - content = "" - try: - if url: - if OpenAI: - client = OpenAI(base_url=url, api_key=key if key else "ollama") - openai_response = client.chat.completions.create( - model=model, - messages=[ - {"role": "system", "content": f"/no_think Translate the following content into {lang_map[target]}, and do not output any additional information."}, - {"role": "user", "content": text} - ] - ) - content = openai_response.choices[0].message.content or "" - else: - client = Client(host=url) - response: ChatResponse = client.chat( - model=model, - messages=[ - {"role": "system", "content": f"/no_think Translate the following content into {lang_map[target]}, and do not output any additional information."}, - {"role": "user", "content": text} - ] - ) - content = response.message.content or "" - else: - response: ChatResponse = chat( - model=model, - messages=[ - {"role": "system", "content": f"/no_think Translate the following content into {lang_map[target]}, and do not output any additional information."}, - {"role": "user", "content": text} - ] - ) - content = response.message.content or "" - except Exception as e: - stdout_cmd("warn", f"Translation failed: {str(e)}") - return +def _translation_messages(target: str, text: str): + return [ + {"role": "system", "content": f"/no_think Translate the following content into {lang_map[target]}, and do not output any additional information."}, + {"role": "user", "content": text} + ] + +def _output_translation(content: str, text: str, time_s: str): if content.startswith(''): index = content.find('') if index != -1: @@ -69,7 +40,37 @@ def ollama_translate(model: str, target: str, text: str, time_s: str, url: str = "translation": content.strip() }) -def google_translate(model: str, target: str, text: str, time_s: str): + +def ollama_translate(model: str, target: str, text: str, time_s: str, base_url: str = '', api_key: str = ''): + content = "" + try: + response: ChatResponse = chat(model=model, messages=_translation_messages(target, text)) + content = response.message.content or "" + except Exception as e: + stdout_cmd("warn", f"Ollama translation failed: {str(e)}") + return + + _output_translation(content, text, time_s) + + +def openai_translate(model: str, target: str, text: str, time_s: str, base_url: str = '', api_key: str = ''): + if OpenAI is None: + stdout_cmd("warn", "OpenAI translation failed: the openai package is not installed") + return + try: + client = OpenAI(base_url=base_url, api_key=api_key or "not-required") + response = client.chat.completions.create( + model=model, + messages=_translation_messages(target, text) + ) + content = response.choices[0].message.content or "" + except Exception as e: + stdout_cmd("warn", f"OpenAI-compatible translation failed: {str(e)}") + return + + _output_translation(content, text, time_s) + +def google_translate(model: str, target: str, text: str, time_s: str, base_url: str = '', api_key: str = ''): translator = Translator() try: res = asyncio.run(translator.translate(text, dest=target)) @@ -79,5 +80,13 @@ def google_translate(model: str, target: str, text: str, time_s: str): "text": text, "translation": res.text }) - except Exception as e: + except Exception: stdout_cmd("warn", f"Google translation request failed, please check your network connection...") + + +def get_translation_function(provider: str): + return { + 'ollama': ollama_translate, + 'openai': openai_translate, + 'google': google_translate + }[provider] diff --git a/src/main/types/index.ts b/src/main/types/index.ts index ce94e4b..349088d 100644 --- a/src/main/types/index.ts +++ b/src/main/types/index.ts @@ -6,15 +6,16 @@ export interface Controls { engineEnabled: boolean, sourceLang: string, targetLang: string, - transModel: string, - ollamaName: string, - ollamaUrl: string, - ollamaApiKey: string, + translationProvider: 'ollama' | 'openai' | 'google', + ollamaModel: string, + openaiModel: string, + openaiBaseUrl: string, + openaiApiKey: string, engine: string, audio: 0 | 1, translation: boolean, recording: boolean, - API_KEY: string, + gummyApiKey: string, voskModelPath: string, sosvModelPath: string, glmUrl: string, @@ -83,4 +84,4 @@ export interface EngineInfo { cpu: number, mem: number, elapsed: number -} \ No newline at end of file +} diff --git a/src/main/utils/AllConfig.ts b/src/main/utils/AllConfig.ts index 9fe82a7..f4f8e93 100644 --- a/src/main/utils/AllConfig.ts +++ b/src/main/utils/AllConfig.ts @@ -44,14 +44,15 @@ const defaultStyles: Styles = { const defaultControls: Controls = { sourceLang: 'en', targetLang: 'zh', - transModel: 'ollama', - ollamaName: 'qwen2.5:0.5b', - ollamaUrl: 'http://localhost:11434', - ollamaApiKey: '', + translationProvider: 'ollama', + ollamaModel: 'qwen2.5:0.5b', + openaiModel: '', + openaiBaseUrl: 'https://api.openai.com/v1', + openaiApiKey: '', engine: 'gummy', audio: 0, engineEnabled: false, - API_KEY: '', + gummyApiKey: '', voskModelPath: '', sosvModelPath: '', glmUrl: 'https://open.bigmodel.cn/api/paas/v4/audio/transcriptions', @@ -145,10 +146,34 @@ class AllConfig { } public setControls(args: Object) { + const legacy = args as Record + const migratedArgs: Record = { ...legacy } + if(!('translationProvider' in legacy) && typeof legacy.transModel === 'string') { + const legacyUrl = typeof legacy.ollamaUrl === 'string' ? legacy.ollamaUrl : '' + const usesOpenAI = Boolean(legacyUrl && !/^https?:\/\/(localhost|127\.0\.0\.1):11434\/?$/i.test(legacyUrl)) + migratedArgs.translationProvider = legacy.transModel === 'ollama' && usesOpenAI + ? 'openai' + : legacy.transModel + } + if(!('ollamaModel' in legacy) && typeof legacy.ollamaName === 'string') { + migratedArgs.ollamaModel = legacy.ollamaName + } + if(!('openaiModel' in legacy) && migratedArgs.translationProvider === 'openai' && typeof legacy.ollamaName === 'string') { + migratedArgs.openaiModel = legacy.ollamaName + } + if(!('openaiBaseUrl' in legacy) && migratedArgs.translationProvider === 'openai' && typeof legacy.ollamaUrl === 'string' && legacy.ollamaUrl) { + migratedArgs.openaiBaseUrl = legacy.ollamaUrl + } + if(!('openaiApiKey' in legacy) && typeof legacy.ollamaApiKey === 'string') { + migratedArgs.openaiApiKey = legacy.ollamaApiKey + } + if(!('gummyApiKey' in legacy) && typeof legacy.API_KEY === 'string') { + migratedArgs.gummyApiKey = legacy.API_KEY + } const engineEnabled = this.controls.engineEnabled for(let key in this.controls){ - if(key in args) { - this.controls[key] = args[key] + if(key in migratedArgs) { + this.controls[key] = migratedArgs[key] } } this.controls.engineEnabled = engineEnabled @@ -157,7 +182,7 @@ class AllConfig { public sendControls(window: BrowserWindow, info = true) { window.webContents.send('control.controls.set', this.controls) - if(info) Log.info(`Send Controls to #${window.id}:`, this.controls) + if(info) Log.info(`Send Controls to #${window.id}:`, passwordMaskingForObject(this.controls)) } public updateCaptionLog(log: CaptionItem) { diff --git a/src/main/utils/CaptionEngine.ts b/src/main/utils/CaptionEngine.ts index d6d5bb5..5487f44 100644 --- a/src/main/utils/CaptionEngine.ts +++ b/src/main/utils/CaptionEngine.ts @@ -19,6 +19,21 @@ export class CaptionEngine { timerID: NodeJS.Timeout | undefined startTimeoutID: NodeJS.Timeout | undefined + private addTranslationArguments() { + const controls = allConfig.controls + this.command.push('--translation_provider', controls.translationProvider) + if(controls.translationProvider === 'ollama') { + this.command.push('--translation_model', controls.ollamaModel) + } + else if(controls.translationProvider === 'openai') { + this.command.push('--translation_model', controls.openaiModel) + this.command.push('--translation_base_url', controls.openaiBaseUrl) + if(controls.openaiApiKey) { + this.command.push('--translation_api_key', controls.openaiApiKey) + } + } + } + private getApp(): boolean { if (allConfig.controls.customized) { Log.info('Using customized caption engine') @@ -29,7 +44,7 @@ export class CaptionEngine { } else { if(allConfig.controls.engine === 'gummy' && - !allConfig.controls.API_KEY && !process.env.DASHSCOPE_API_KEY + !allConfig.controls.gummyApiKey && !process.env.DASHSCOPE_API_KEY ) { controlWindow.sendErrorMessage(i18n('gummy.key.missing')) return false @@ -79,26 +94,20 @@ export class CaptionEngine { if(allConfig.controls.engine === 'gummy') { this.command.push('-e', 'gummy') this.command.push('-s', allConfig.controls.sourceLang) - if(allConfig.controls.API_KEY) { - this.command.push('-k', allConfig.controls.API_KEY) + if(allConfig.controls.gummyApiKey) { + this.command.push('--gummy_api_key', allConfig.controls.gummyApiKey) } } else if(allConfig.controls.engine === 'vosk'){ this.command.push('-e', 'vosk') this.command.push('-vosk', `"${allConfig.controls.voskModelPath}"`) - this.command.push('-tm', allConfig.controls.transModel) - this.command.push('-omn', allConfig.controls.ollamaName) - if(allConfig.controls.ollamaUrl) this.command.push('-ourl', allConfig.controls.ollamaUrl) - if(allConfig.controls.ollamaApiKey) this.command.push('-okey', allConfig.controls.ollamaApiKey) + this.addTranslationArguments() } else if(allConfig.controls.engine === 'sosv'){ this.command.push('-e', 'sosv') this.command.push('-s', allConfig.controls.sourceLang) this.command.push('-sosv', `"${allConfig.controls.sosvModelPath}"`) - this.command.push('-tm', allConfig.controls.transModel) - this.command.push('-omn', allConfig.controls.ollamaName) - if(allConfig.controls.ollamaUrl) this.command.push('-ourl', allConfig.controls.ollamaUrl) - if(allConfig.controls.ollamaApiKey) this.command.push('-okey', allConfig.controls.ollamaApiKey) + this.addTranslationArguments() } else if(allConfig.controls.engine === 'glm'){ this.command.push('-e', 'glm') @@ -108,10 +117,7 @@ export class CaptionEngine { if(allConfig.controls.glmApiKey) { this.command.push('-gkey', allConfig.controls.glmApiKey) } - this.command.push('-tm', allConfig.controls.transModel) - this.command.push('-omn', allConfig.controls.ollamaName) - if(allConfig.controls.ollamaUrl) this.command.push('-ourl', allConfig.controls.ollamaUrl) - if(allConfig.controls.ollamaApiKey) this.command.push('-okey', allConfig.controls.ollamaApiKey) + this.addTranslationArguments() } } Log.info('Engine Path:', this.appPath) diff --git a/src/main/utils/UtilsFunc.ts b/src/main/utils/UtilsFunc.ts index 09cd890..5251862 100644 --- a/src/main/utils/UtilsFunc.ts +++ b/src/main/utils/UtilsFunc.ts @@ -5,7 +5,7 @@ function passwordMasking(pwd: string) { export function passwordMaskingForList(args: string[]) { const maskedArgs = [...args] for(let i = 1; i < maskedArgs.length; i++) { - if(maskedArgs[i-1] === '-k' || maskedArgs[i-1] === '-okey' || maskedArgs[i-1] === '-gkey') { + if(maskedArgs[i-1] === '--gummy_api_key' || maskedArgs[i-1] === '--translation_api_key' || maskedArgs[i-1] === '-gkey') { maskedArgs[i] = passwordMasking(maskedArgs[i]) } } diff --git a/src/renderer/src/components/EngineControl.vue b/src/renderer/src/components/EngineControl.vue index e168d58..d5e6f3c 100644 --- a/src/renderer/src/components/EngineControl.vue +++ b/src/renderer/src/components/EngineControl.vue @@ -30,18 +30,18 @@ :options="tLangList" > -
- {{ $t('engine.transModel') }} +
+ {{ $t('engine.translationProvider') }}
-
+
-
+
+ + + {{ $t('engine.modelName') }} + + +
+