Gemini Subtitle Pro - 项目架构文档
📖 项目概述
Gemini Subtitle Pro 是一款 AI 驱动的视频字幕生成、翻译与润色工具。采用 React + Vite + Electron 技术栈构建,支持 Web 端和桌面客户端双端部署。
- 技术栈: React 19, Vite 6, Electron 39, TypeScript
- AI 引擎: Google Gemini (翻译/润色), OpenAI Whisper (语音识别)
DeepWiki项目详细解析:https://deepwiki.com/corvo007/Gemini-Subtitle-Pro
🏗️ 技术栈架构
技术栈分层图
依赖版本概览
| 类别 | 依赖包 | 版本 | 用途 |
|---|---|---|---|
| 核心框架 | React | 19.2 | UI 框架 |
| Vite | 6.2 | 构建工具 | |
| TypeScript | 5.8 | 类型系统 | |
| Electron | 39 | 桌面容器 | |
| AI SDK | @google/genai | Latest | Gemini API |
| openai | Latest | Whisper API | |
| onnxruntime-web | 1.23 | VAD 推理 | |
| 音视频处理 | @ricky0123/vad-web | 0.0.30 | Silero VAD 封装 |
| fluent-ffmpeg | 2.1 | FFmpeg 控制 | |
| 国际化 | i18next | 25.7 | 国际化核心 |
| react-i18next | 16.5 | React 绑定 | |
| 渲染 | assjs | 0.1.4 | ASS 字幕渲染 |
| 样式 | TailwindCSS | 4.1 | 原子化 CSS |
| Lucide React | 0.554 | 图标库 | |
| 工具库 | clsx / tw-merge | Latest | 样式合并 |
📏 代码规范与工程化
路径别名 (Path Aliases)
本项目在 src 和 electron 目录下全面使用路径别名。除同级文件引用外(推荐统一使用别名),禁止使用相对路径(如 ../../)进行跨层级模块引用。
@/*->src/*(核心源代码)@components/*->src/components/*@hooks/*->src/hooks/*@services/*->src/services/*@utils/*->src/utils/*@types/*->src/types/*@lib/*->src/lib/*(新增)@electron/*->electron/*(Electron 主进程代码)
目录组织原则
- 就近原则 (Co-location):仅在特定模块内部使用的工具函数或组件,应放置在该模块的
utils或shared子目录下,而不是提升到全局。- 例如,
src/components/endToEnd/wizard/utils/validation.ts仅服务于向导模块。
- 例如,
- 关注点分离:
src/utils: 全局通用的、纯 JavaScript/UI 辅助函数。src/services/utils: 基础设施、日志、系统级工具。
🧱 应用模块架构
模块依赖关系
📁 目录结构
Gemini-Subtitle-Pro/
├── 📂 src/ # 前端源代码
│ ├── 📄 App.tsx # 应用主入口
│ ├── 📄 index.tsx # React 渲染入口
│ ├── 📄 index.css # 全局样式
│ ├── 📄 i18n.ts # [NEW] 国际化配置入口
│ │
│ ├── 📂 components/ # UI 组件
│ │ ├── 📂 common/ # 通用业务组件 (Header, PageHeader 等)
│ │ ├── 📂 editor/ # 字幕编辑器与视频预览组件
│ │ │ ├── 📄 VideoPlayerPreview.tsx # [NEW] 渐进式视频播放器,支持 ASS 字幕渲染
│ │ │ ├── 📄 RegenerateModal.tsx # [NEW] 批量重新生成模态框
│ │ │ └── 📄 ... # SubtitleRow, Batch 等
│ │ ├── 📂 compression/ # [NEW] 视频压制页面组件
│ │ │ ├── 📄 EncoderSelector.tsx # 编码器选择与配置
│ │ │ └── 📄 ...
│ │ ├── 📂 pages/ # 页面级组件 (HomePage, WorkspacePage 等)
│ │ ├── 📂 ui/ # 基础 UI 组件库 (Modal, Toggle, TextInput...)
│ │ ├── 📂 settings/ # 设置相关组件
│ │ │ ├── 📂 tabs/ # [NEW] 模块化设置面板 (GeneralTab, AboutTab 等)
│ │ │ └── 📄 SettingsModal.tsx # 设置弹窗容器
│ │ ├── 📂 layout/ # 布局容器
│ │ ├── 📂 modals/ # 业务弹窗 (GlossaryConfirmationModal, SpeakerManagerModal 等)
│ │ ├── 📂 endToEnd/ # 端到端向导组件
│ │ └── 📂 ... # 其他按照功能划分的组件目录
│ │
│ ├── 📂 hooks/ # React Hooks
│ │ ├── 📂 useWorkspaceLogic/ # 核心工作区逻辑 (拆分为多模块)
│ │ ├── 📄 useVideoPreview.ts # [NEW] 视频预览与转码状态
│ │ └── ... # 其他功能 Hooks
│ │
│ ├── 📂 locales/ # [NEW] 国际化资源目录
│ │ ├── 📂 zh-CN/ # 简体中文
│ │ ├── 📂 en-US/ # 英语
│ │ └── 📂 ja-JP/ # 日语 (v2.13 新增)
│ │
│ ├── 📂 services/ # 服务层 (纯逻辑)
│ │ ├── 📂 api/ # API 集成 (Gemini Core, OpenAI)
│ │ ├── 📂 generation/ # 生成服务 (核心业务逻辑)
│ │ │ ├── 📂 pipeline/ # 完整流水线 (Orchestrator, ChunkProcessor)
│ │ │ │ ├── 📂 core/ # [NEW] 步骤基类与类型定义
│ │ │ │ └── 📂 steps/ # [NEW] 步骤实现 (Transcription, Refinement, Alignment, Translation, Proofread)
│ │ │ ├── 📂 extractors/ # 信息提取 (Glossary, Speaker)
│ │ │ └── 📂 batch/ # 批量操作 (proofread.ts, regenerate.ts)
│ │ ├── 📂 audio/ # 音频处理 (Segmenter, Sampler)
│ │ ├── 📂 subtitle/ # 字幕解析与生成 (Parser, Generator)
│ │ │ ├── 📄 reconciler.ts # [NEW] 数据协调器 (数据枢纽)
│ │ │ └── 📄 ...
│ │ ├── 📂 alignment/ # [NEW] 对齐服务
│ │ │ ├── 📂 strategies/ # 对齐策略 (CTC)
│ │ │ └── 📄 index.ts # 策略工厂
│ │ ├── 📂 download/ # 下载服务逻辑
│ │ └── 📂 utils/ # 通用服务工具 (Logger, URL 验证)
│ │
│ ├── 📂 config/ # 配置模块
│ │ ├── 📄 index.ts # 配置导出入口
│ │ └── 📄 models.ts # 模型配置 (步骤→模型映射)
│ │
│ ├── 📂 lib/ # 通用库
│ │ ├── 📄 cn.ts # Tailwind 类名合并工具
│ │ └── 📄 text.ts # 文本处理工具
│ │
│ ├── 📂 types/ # [NEW] 集中式类型定义
│ │ ├── 📄 pipeline.ts # Pipeline 共享类型
│ │ ├── 📄 alignment.ts # Alignment 类型
│ │ └── 📄 ...
│ │
│ └── 📂 workers/ # Web Workers
│
├── 📂 electron/ # Electron 桌面端代码
│ ├── 📄 main.ts # 主进程入口
│ ├── 📄 preload.ts # 预加载脚本
│ ├── 📄 logger.ts # 统一日志服务 (支持 JSON 视图)
│ ├── 📂 utils/ # [NEW] 工具模块
│ │ └── 📄 paths.ts # 便携式路径解析
│ └── 📂 services/ # 桌面服务 (Node.js 环境)
│ ├── 📄 localWhisper.ts # 本地 Whisper 调用 (支持 GPU 检测)
│ ├── 📄 videoPreviewTranscoder.ts # 视频预览与缓存
│ ├── 📄 storage.ts # 便携式存储服务
│ └── ... # 其他系统级服务
│
└── 📄 package.json # 项目配置🔄 核心流程图解
1. 完整 Pipeline 并发架构图
下图展示了字幕生成的完整并发架构,包含并行异步任务、Semaphore 控制及任务间依赖关系:
2. 双 Semaphore 并发控制详解
配置说明:
| Semaphore | 用途 | 默认并发数 | 配置项 |
|---|---|---|---|
transcriptionSemaphore | 控制 Whisper API 调用 | 本地: 1, 云端: 5 | whisperConcurrency |
refinementSemaphore | 控制 Gemini Flash API | 5 | concurrencyFlash |
alignmentSemaphore | 控制对齐服务 | 2 | concurrencyAlignment |
| (术语提取内部) | 控制 Gemini Pro API | 2 | concurrencyPro |
3. Chunk 内部 5 阶段流水线
3.5 Pipeline 步骤架构 (v2.13 新增)
v2.13 引入了基于类的步骤架构,将 Chunk 处理逻辑模块化:
步骤说明:
| 步骤 | 文件 | 输入 | 输出 | 用途 |
|---|---|---|---|---|
TranscriptionStep | TranscriptionStep.ts | AudioChunk | SubtitleItem[] | Whisper 语音转文字 |
WaitForDepsStep | WaitForDepsStep.ts | - | Glossary + Speakers | 等待术语表和说话人提取完成 |
RefinementStep | RefinementStep.ts | SubtitleItem[] | SubtitleItem[] | 时间轴校正、术语应用 |
AlignmentStep | AlignmentStep.ts | SubtitleItem[] | SubtitleItem[] | CTC 强制对齐 |
TranslationStep | TranslationStep.ts | SubtitleItem[] | SubtitleItem[] | AI 翻译 |
ProofreadStep | ProofreadStep.ts | SubtitleItem[] | SubtitleItem[] | 批量校对 (可选) |
3.6 批量操作对比 (v2.13 新增)
v2.13 将批量操作拆分为两种独立模式:
| 特性 | Proofread (校对) | Regenerate (重新生成) |
|---|---|---|
| 文件 | batch/proofread.ts | batch/regenerate.ts |
| 用途 | 润色和校对已有翻译 | 完全重新处理选中片段 |
| 流程 | 仅调用 Gemini Pro 校对 | 转录 → 润色 → 对齐 → 翻译 (完整流水线) |
| 输入 | 已有的 SubtitleItem[] | 原始音频 + 时间范围 |
| 保留内容 | 保留原始时间轴 | 全部重新生成 |
| 适用场景 | 改善翻译质量、修正错别字 | 修复转录错误、重新分句、更新术语表后重跑 |
| 用户提示 | 不支持 | 支持转录提示和翻译提示 |
| 模型 | Gemini 3 Pro | Whisper + Gemini Flash |
4. 数据完整性与协调 ("数据枢纽")
系统采用严格的 数据协调策略 (src/services/subtitle/reconciler.ts) 以确保在流水线各个阶段(Refinement, Alignment, Translation)之间,即使片段数量发生变化(如拆分或合并),元数据也能保持一致。
4.1 协调器逻辑 (The Reconciler Logic)
reconcile(prev, curr) 函数充当连接流水线各个阶段的“数据枢纽”。它智能地将 prev(源)的元数据合并到 curr(新生成)的片段中:
- 语义元数据 (Semantic Metadata) (始终继承):
speaker(说话人 ID/名称)comment(用户备注)- 逻辑: 继承自重叠率最高的
prev片段。即使片段被拆分,所有子片段都会继承父片段的说话人信息。
- 内部状态 (Internal State) (条件继承):
alignmentScore(CTC 置信度)lowConfidence(低置信度标记)hasRegressionIssue,hasCorruptedRangeIssue(错误标记)- 逻辑: 仅当检测到 1:1 映射时才严格继承。如果片段被拆分或合并,这些内部标记会被重置,以此避免错误的传播(例如,“完美对齐”的评分不应自动应用于两个新生成的半片段,除非经过重新验证)。
4.2 对齐策略 (CTC)
系统使用 CTC (Connectionist Temporal Classification) 进行高精度对齐:
- 引擎:
ctcAligner.ts调用外部align.exe(MMS-300m 模型)。 - 功能: 基于音频对齐结果更新
startTime和endTime,但绝不拆分或合并片段。 - 元数据: 为片段添加
alignmentScore。低于阈值的评分会触发lowConfidence标记以供用户复查。
5. 术语提取与用户交互流程
6. 说话人识别在 Pipeline 中的位置
Pipeline 依赖总结:
| 阶段 | 依赖项 | 说明 |
|---|---|---|
| Transcription | transcriptionSemaphore | 独立执行,无阻塞依赖 |
| Wait Glossary | glossaryState.get() | 必须等待术语表确认完成 |
| Wait Speakers | speakerProfilePromise | 必须等待说话人识别完成 |
| Refinement | refinementSemaphore + Glossary + Speakers | 合并并使用所有数据 |
| Alignment | alignmentSemaphore | 高精度时间轴对齐 |
| Translation | refinementSemaphore (共享) | 对齐后进行翻译 |
7. 桌面端全流程 (下载-制作-压制)
桌面端独有的完整工作流,打通从素材获取到成品输出:
8. 全自动 End-to-End 模式 (End-to-End Pipeline)
这是 Electron 端独有的核心功能,通过 IPC 通信协调 主进程 (资源调度) 和 渲染进程 (AI 计算),实现“一键熟肉”。
8.1 跨进程交互架构
8.2 数据流向与状态管理
所有中间状态和配置通过 EndToEndWizard 组件管理,数据流转如下:
用户配置 (Configuration)
- 源:
EndToEndWizardUI - 流向: 通过
IPC (start-processing)-> 主进程EndToEndPipeline服务 - 内容: URL, 模型选择, 翻译风格, 压制参数
- 源:
音视频流 (Media Stream)
yt-dlp-> 磁盘临时目录 ->ffmpeg(提取音频) -> 磁盘 WAV- 磁盘 WAV ->
IPC (read-file)-> 渲染进程内存 (ArrayBuffer) -> Web Audio API
字幕数据 (Subtitle Data)
- 渲染进程生成
SubtitleItem[]数组 - 通过
IPC (subtitle-result)回传主进程 - 主进程将对象序列化为 ASS/SRT 格式文本并写入文件
- 渲染进程生成
进度反馈 (Progress Feedback)
- 各阶段 (下载/转写/压制) 均产生进度事件
- 主进程 ->
IPC (progress)-> 渲染进程useEndToEndHook -> UI 进度条
8.3 关键 IPC 通道
| 通道名 (Channel) | 方向 | 载荷 (Payload) | 作用 |
|---|---|---|---|
end-to-end:start | Renderer -> Main | EndToEndConfig | 启动全自动任务 |
end-to-end:generate-subtitles | Main -> Renderer | path, config | 主进程准备好音频,请求前端开始生成 |
end-to-end:subtitle-result | Renderer -> Main | SubtitleItem[] | 前端完成生成,返回结果 |
end-to-end:progress | Main -> Renderer | stage, progress | 实时进度同步 |
🛰️ 媒体播放自定义协议
为了绕过浏览器的安全限制(CSP、沙箱)并支持大文件流式播放,桌面版实现了一个自定义协议:
local-video:// 协议
- 实现位置:
electron/main.ts - 核心权限:
standard,secure,stream,supportFetchAPI,bypassCSP。 - 关键技术:Tailing Reader:支持读取“增长中的文件”(转码进行中)。它使用轮询机制读取 FFmpeg 正在写入磁盘的新数据。
📺 视频预览与缓存策略
系统采用分片 MP4 (fragmented MP4) 转码策略,平衡兼容性与性能,实现边转码边播放的即时视频预览。
架构概览
视频预览系统由三个核心组件组成:
| 组件 | 位置 | 功能 |
|---|---|---|
VideoPlayerPreview | src/components/editor/ | React 视频播放器,支持 ASS 字幕叠加渲染 |
useVideoPreview | src/hooks/ | 转码进度、视频源、播放状态管理 |
videoPreviewTranscoder | electron/services/ | FFmpeg 转码服务,支持 GPU 加速与缓存 |
流程图
核心特性
| 特性 | 说明 |
|---|---|
| 渐进式播放 | 通过 fMP4 + TailingReader 实现转码未完成即可播放 |
| GPU 加速 | 自动检测 NVENC/QSV/VCE 以加快转码 |
| 格式检测 | 对浏览器兼容格式 (mp4, webm, m4v) 跳过转码 |
| 所见即所得字幕 | 使用 assjs 渲染 ASS 字幕,与视频同步 |
| 浮动/停靠模式 | 支持可调整大小的浮动窗口或停靠面板 |
缓存生命周期
- 存储位置:用户数据目录 (
/preview_cache/)。 - 限制:自动执行总大小限制(默认 3GB)。
- 清理:应用启动时自动检测(最旧文件优先),并支持 UI 手动清理。
IPC 通道
| 通道名 (Channel) | 方向 | 载荷 (Payload) | 作用 |
|---|---|---|---|
transcode-for-preview | Renderer → Main | { filePath } | 请求视频转码 |
transcode-start | Main → Renderer | { outputPath, duration } | 转码已开始,开启渐进式播放 |
transcode-progress | Main → Renderer | { percent, transcodedDuration } | 实时进度更新 |
cache:get-size | Renderer → Main | - | 获取预览缓存大小 |
cache:clear | Renderer → Main | - | 清理预览缓存 |
🧩 核心模块说明
1. 生成服务模块 (src/services/generation/) [NEW]
这是重构后的核心业务逻辑模块,将原有的 Gemini API 逻辑按职责拆分:
| 子模块 | 文件/目录 | 功能描述 |
|---|---|---|
pipeline | index.ts | 生成流程总管 (Orchestrator),协调转写、提取、生成全流程 |
pipelineCore.ts | [NEW] 共享上下文与依赖注入 | |
chunkProcessor.ts | 单个 Chunk 的处理逻辑 (转写 -> 术语/说话人等待 -> 翻译) | |
translation.ts | 具体翻译执行逻辑 | |
glossaryHandler.ts | 术语应用逻辑 | |
resultTransformers.ts | 结果转换与后处理逻辑 | |
core/BaseStep.ts | [NEW] 步骤基类,定义统一接口 | |
steps/*.ts | [NEW] 步骤实现 (Transcription, Refinement, Alignment, Translation, Proofread) | |
extractors | glossary.ts | 术语提取器 (Gemini Pro + Search) |
speakerProfile.ts | 说话人档案提取器 | |
batch | proofread.ts | [NEW] 批量校对操作 |
regenerate.ts | [NEW] 批量重新生成操作 (完整流水线重跑) |
2. Gemini API 核心 (src/services/api/gemini/core/)
只保留最基础的 API 交互能力:
| 文件 | 功能描述 |
|---|---|
client.ts | Gemini API 客户端封装,处理 auth、retry 和 quota |
prompts.ts | 基础 Prompt 模板库 |
schemas.ts | 结构化输出的 Schema 定义 |
3. 音频处理模块 (src/services/audio/)
| 文件 | 功能描述 |
|---|---|
segmenter.ts | 智能音频切分器,使用 Silero VAD 模型检测语音活动,按语义边界切分 |
sampler.ts | 音频采样,生成用于 AI 分析的音频样本 |
decoder.ts | 音频解码,支持多种格式 |
processor.ts | 音频预处理,归一化等 |
converter.ts | 音频格式转换 |
ffmpegExtractor.ts | FFmpeg 音频提取 (核心逻辑) |
4. 字幕处理模块 (src/services/subtitle/)
| 文件 | 功能描述 |
|---|---|
parser.ts | 字幕解析器,支持 SRT/ASS/VTT 等格式 |
generator.ts | 字幕导出,生成双语字幕文件 |
time.ts | 时间码处理工具 |
postCheck.ts | 字幕质量后检查 |
timelineValidator.ts | 字幕时间轴逻辑校验 |
reconciler.ts | [NEW] 数据协调器 (元数据合并) |
5. 下载服务模块 (src/services/download/)
| 文件 | 功能描述 |
|---|---|
download.ts | 视频下载逻辑封装 |
utils.ts | 下载相关工具函数 |
6. Electron 桌面端 (electron/)
| 文件 | 功能描述 |
|---|---|
main.ts | Electron 主进程,窗口管理、IPC 通信 |
preload.ts | 预加载脚本,暴露安全的 Node.js API |
logger.ts | 统一日志系统,支持文件轮转、JSON 视图和多级别日志 |
utils/paths.ts | [NEW] 便携式路径解析,支持 exe 同级目录存储 |
services/localWhisper.ts | 本地 Whisper 模型调用 (whisper.cpp),支持 GPU 检测 |
services/ffmpegAudioExtractor.ts | FFmpeg 音频提取,支持视频文件 |
services/ytdlp.ts | 视频下载服务 (YouTube/Bilibili) |
services/videoCompressor.ts | 视频压制服务 (支持 NVENC/QSV/AMF 硬件加速) |
services/videoPreviewTranscoder.ts | 视频预览转码,fMP4 渐进式播放、缓存管理 |
services/endToEndPipeline.ts | 全自动流水线,编排下载-转写-压制全流程 |
services/storage.ts | 便携式存储服务,配置和日志存储在 exe 同级目录 |
7. 国际化模块 (src/locales/, src/i18n.ts) [NEW]
基于 i18next 实现的完整国际化支持,提供中英双语界面:
| 文件/目录 | 功能描述 |
|---|---|
i18n.ts | 国际化配置入口,初始化 i18next 和 React 绑定 |
locales/ | 翻译资源根目录 |
zh-CN/ | 简体中文翻译,包含 14 个命名空间文件 |
en-US/ | 英文翻译,与 zh-CN 结构相同 |
ja-JP/ | 日语翻译,与 zh-CN 结构相同 (v2.13 新增) |
命名空间组织:
| 命名空间 | 内容 |
|---|---|
common | 通用文本 (按钮、标签、错误) |
home | 首页内容 |
workspace | 工作区页面 |
editor | 字幕编辑器 |
settings | 设置弹窗 |
endToEnd | 端到端向导 |
modals | 业务弹窗 |
services | API 服务消息 |
compression | 视频压制页面 |
download | 下载页面 |
progress | 进度指示器 |
ui | UI 组件 |
app | 应用级文本 |
8. 设置模块 (src/components/settings/) [v2.13 重构]
v2.13 将设置面板重构为模块化 tabs 结构:
| 文件/目录 | 功能描述 |
|---|---|
SettingsModal.tsx | 设置弹窗容器,管理 tab 切换 |
tabs/GeneralTab.tsx | 常规设置 (语言、主题等) |
tabs/ServicesTab.tsx | API 服务配置 (Gemini、OpenAI 密钥) |
tabs/EnhanceTab.tsx | 增强功能 (术语提取、说话人识别开关) |
tabs/PerformanceTab.tsx | 性能设置 (并发数、缓存等) |
tabs/DebugTab.tsx | 调试选项 (Mock 模式、日志级别) |
tabs/AboutTab.tsx | [NEW] 关于页面 (版本、Whisper 状态、GPU 检测) |
AlignmentSettings.tsx | 对齐服务配置 |
LocalWhisperSettings.tsx | 本地 Whisper 配置 |
CacheManagement.tsx | 缓存管理 UI |
关于页面 (AboutTab) 功能:
- 显示应用版本和构建信息
- 本地 Whisper 状态检测
- GPU 硬件加速检测 (NVENC/QSV/AMF)
- 日志文件路径和查看入口
- 系统信息概览
🔧 技术特点
并发控制
// 使用 Semaphore 控制并发数
const semaphore = new Semaphore(concurrency);
await mapInParallel(chunks, async (chunk) => {
await semaphore.acquire();
try {
return await processChunk(chunk);
} finally {
semaphore.release();
}
});模型选择策略
模型配置集中在 src/config/models.ts,支持按处理步骤选择不同模型:
| 处理步骤 | 默认模型 | 特点 |
|---|---|---|
refinement | Gemini 2.5 Flash | 时间轴校正 (规避 3.0 时间戳 Bug) |
translation | Gemini 3 Flash Preview | 翻译、Search Grounding |
glossaryExtraction | Gemini 3 Pro Preview | 多模态、术语提取 |
speakerProfile | Gemini 3 Pro Preview | 说话人分析 |
batchProofread | Gemini 3 Pro Preview | 高质量校对、Search Grounding |
注意: v2.13 起,
batchFixTimestamps已被regenerate操作取代。重新生成会重跑完整流水线(转录→润色→对齐→翻译)。
每个步骤可独立配置:
thinkingLevel: 思考深度 (none/low/medium/high)useSearch: 是否启用 Google SearchmaxOutputTokens: 最大输出 Token 数
重试机制
// 自动重试可恢复的错误
async function generateContentWithRetry(
ai: GoogleGenAI,
params: any,
retries = 3,
signal?: AbortSignal,
onUsage?: (usage: TokenUsage) => void,
timeoutMs?: number
);📊 数据流架构
主数据流图
数据类型转换链
状态数据流
🚀 部署架构
📝 开发指南
环境要求
- Node.js 18+
- npm 或 yarn
快速开始
# 安装依赖
yarn install
# Web 开发模式
yarn dev
# Electron 开发模式
yarn electron:dev
# 构建 Electron 应用
yarn electron:build环境变量
GEMINI_API_KEY=your_gemini_key # 必需:翻译和校对
OPENAI_API_KEY=your_openai_key # 可选:在线 Whisper