From d354a6fefa57f67215f8d9e38e90add6ff787eeb Mon Sep 17 00:00:00 2001 From: himeditator Date: Thu, 10 Jul 2025 11:22:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(engine):=20=E4=BC=98=E5=8C=96=20Vosk=20?= =?UTF-8?q?=E5=AD=97=E5=B9=95=E5=BC=95=E6=93=8E=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现文件夹选择功能,用于选择 Vosk 模型路径 - 在 EngineControl 组件中添加模型路径选择按钮和相关提示 - 在 EngineStatus 组件中增加对空模型路径的检查和错误提示 --- caption-engine/audioprcs/__init__.py | 2 +- caption-engine/audioprcs/process.py | 2 +- docs/TODO.md | 4 +- docs/api-docs/electron-ipc.md | 13 +++++ src/main/ControlWindow.ts | 11 +++- src/renderer/src/components/EngineControl.vue | 57 ++++++++++++++++++- src/renderer/src/components/EngineStatus.vue | 5 ++ src/renderer/src/i18n/lang/en.ts | 5 ++ src/renderer/src/i18n/lang/ja.ts | 5 ++ src/renderer/src/i18n/lang/zh.ts | 4 ++ src/renderer/src/stores/engineControl.ts | 8 +++ 11 files changed, 109 insertions(+), 7 deletions(-) diff --git a/caption-engine/audioprcs/__init__.py b/caption-engine/audioprcs/__init__.py index b63d8eb..0d542f8 100644 --- a/caption-engine/audioprcs/__init__.py +++ b/caption-engine/audioprcs/__init__.py @@ -1 +1 @@ -from .process import mergeChunkChannels, resampleRawChunk +from .process import mergeChunkChannels, resampleRawChunk, resampleMonoChunk diff --git a/caption-engine/audioprcs/process.py b/caption-engine/audioprcs/process.py index 650081b..9298593 100644 --- a/caption-engine/audioprcs/process.py +++ b/caption-engine/audioprcs/process.py @@ -50,7 +50,7 @@ def resampleRawChunk(chunk, channels, orig_sr, target_sr, mode="sinc_best"): def resampleMonoChunk(chunk, orig_sr, target_sr, mode="sinc_best"): """ - 将当前单通道进行重采样 + 将当前单通道音频块进行重采样 Args: chunk: (bytes)单通道音频数据块 diff --git a/docs/TODO.md b/docs/TODO.md index c6f58c5..563140c 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -9,11 +9,13 @@ - [x] 添加复制字幕到剪贴板功能 *2025/07/08* - [x] 适配 macOS 平台 *2025/07/08* - [x] 添加字幕文字描边 *2025/07/09* +- [x] 添加基于 Vosk 的字幕引擎 *2025/07/09* ## 待完成 +- [ ] 添加 Ollama 模型用于本地字幕引擎的翻译 +- [ ] 更新 README 和用户手册(字幕引擎构建、Vosk 模型获取和使用) - [ ] 添加本地字幕引擎 - - [ ] 添加基于 Vosk 的字幕引擎 - [ ] 验证 / 添加基于 FunASR 的字幕引擎 - [ ] 减小软件不必要的体积 diff --git a/docs/api-docs/electron-ipc.md b/docs/api-docs/electron-ipc.md index 0dd9fc3..2dbc3e9 100644 --- a/docs/api-docs/electron-ipc.md +++ b/docs/api-docs/electron-ipc.md @@ -44,6 +44,19 @@ - 发送:无数据 - 接收:`string` +### `control.folder.select` + +**介绍:** 打开文件夹选择器,并将用户选择的文件夹路径返回给前端 + +**发起方:** 前端控制窗口 + +**接收方:** 后端控制窗口实例 + +**数据类型:** + +- 发送:无数据 +- 接收:`string` + ## 前端 ==> 后端 ### `control.uiLanguage.change` diff --git a/src/main/ControlWindow.ts b/src/main/ControlWindow.ts index 62284f4..0e73586 100644 --- a/src/main/ControlWindow.ts +++ b/src/main/ControlWindow.ts @@ -1,4 +1,4 @@ -import { shell, BrowserWindow, ipcMain, nativeTheme } from 'electron' +import { shell, BrowserWindow, ipcMain, nativeTheme, dialog } from 'electron' import path from 'path' import { is } from '@electron-toolkit/utils' import icon from '../../build/icon.png?asset' @@ -72,6 +72,15 @@ class ControlWindow { return allConfig.uiTheme }) + ipcMain.handle('control.folder.select', async () => { + const result = await dialog.showOpenDialog({ + properties: ['openDirectory'] + }); + + if (result.canceled) return ""; + return result.filePaths[0]; + }) + ipcMain.on('control.uiLanguage.change', (_, args) => { allConfig.uiLanguage = args if(captionWindow.window){ diff --git a/src/renderer/src/components/EngineControl.vue b/src/renderer/src/components/EngineControl.vue index 06b85cf..7cd9907 100644 --- a/src/renderer/src/components/EngineControl.vue +++ b/src/renderer/src/components/EngineControl.vue @@ -51,7 +51,12 @@
- {{ $t('engine.apikey') }} + + + {{ $t('engine.apikey') }} +
- {{ $t('engine.modelPath') }} + + + {{ $t('engine.modelPath') }} + +
@@ -106,7 +121,7 @@ import { storeToRefs } from 'pinia' import { useGeneralSettingStore } from '@renderer/stores/generalSetting' import { useEngineControlStore } from '@renderer/stores/engineControl' import { notification } from 'ant-design-vue' -import { InfoCircleOutlined } from '@ant-design/icons-vue'; +import { FolderOpenOutlined ,InfoCircleOutlined } from '@ant-design/icons-vue'; import { useI18n } from 'vue-i18n' const { t } = useI18n() @@ -168,6 +183,13 @@ function cancelChange(){ currentCustomizedCommand.value = engineControl.customizedCommand } +function selectFolderPath() { + window.electron.ipcRenderer.invoke('control.folder.select').then((folderPath) => { + if(!folderPath) return + currentModelPath.value = folderPath + }) +} + watch(changeSignal, (val) => { if(val == true) { cancelChange(); @@ -190,6 +212,35 @@ watch(currentEngine, (val) => {