【免费下载链接】WhisperSubTranslate
A free, local desktop app to extract subtitles (SRT) from video and translate them into any language — unlimited use, no signup, no cloud.
WhisperSubTranslate 是一款免费、纯本地运行的桌面字幕提取与翻译工具:拖入视频,用 whisper.cpp 生成 SRT 字幕,再离线或在线翻译成任意语言。本文以它的源码为样本,拆解 Electron 四层目录结构(main / preload / renderer / shared)与基于 contextBridge 的沙箱化 IPC 通道设计,帮你快速看懂一个生产级桌面应用的安全边界是怎么划出来的。
一、四层目录总览:一张表看懂 src/ 结构
整个应用代码集中在src/下,按 Electron 进程模型划分为职责清晰的四层:
| 层级 | 目录 | 职责 |
|---|---|---|
| 主进程 | src/main/ | 窗口管理、系统权限、字幕提取、模型下载、安全策略 |
| 预加载桥 | src/preload/ | 用contextBridge暴露最小化 API,隔离渲染进程 |
| 渲染进程 | src/renderer/ | 纯 UI 逻辑,按功能拆分模块,不接触 Node.js |
| 共享常量 | src/shared/ | 定义 IPC 通道名,主进程与预加载脚本共用 |
这种划分遵循 Electron 官方推荐的安全模型:渲染进程默认拿不到任何 Node 能力,所有系统操作必须"过桥"。下面逐层拆解。
二、主进程(src/main):业务核心与第一道安全防线
入口文件 src/main/index.js 做了三件事:
- 初始化全局服务:按需加载 services/transcription.js(字幕提取核心)与 services/error-logger.js(统一错误日志,超过 2MB 自动裁剪到最近 1000 行);
- 按域注册 IPC 处理器:
registerTranscriptionHandlers、registerTranslationHandlers等,分别位于 src/main/ipc/ 下的 transcription、translation、models、files、history、settings 六个文件,每个文件只管一个业务域; - 生命周期兜底:监听
uncaughtException、render-process-gone等事件,渲染进程崩溃时自动重载并写入日志。
窗口配置是安全实践的关键,见 src/main/window.js:
webPreferences: { nodeIntegration: false, // 渲染进程禁用 Node contextIsolation: true, // 启用上下文隔离 preload: path.join(SOURCE_ROOT, 'src', 'preload', 'index.js'), webSecurity: true, }主进程还叠加了三层防线:
- CSP 响应头:在
window.js中通过webRequest.onHeadersReceived注入严格的 Content-Security-Policy,禁止内联脚本与外部资源(仅允许 Google Fonts); - 导航拦截:
will-navigate与setWindowOpenHandler双重拦截,只有白名单 HTTPS 域名才能打开,其余一律阻止; - 崩溃自愈:渲染进程 30 秒内崩溃超过 3 次即停止自动恢复并弹窗提示,避免无限重启。
外部 URL 白名单:一行代码看懂策略
src/main/ipc/files.js 定义了isAllowedExternalUrl:只放行https:协议 + 固定主机名单(如模型托管站、文档站),并对github.com路径做格式校验防止路径穿越。渲染进程想打开任何外部链接,都必须先过这道关卡。
三、Preload 桥(src/preload):沙箱化 IPC 通道的核心
src/preload/index.js 是理解本项目安全架构的最佳切入点。它通过contextBridge.exposeInMainWorld('electronAPI', {...})向页面只暴露一个window.electronAPI对象,规则非常克制:
规则 1:只暴露方法,不暴露 ipcRenderer 本身。渲染进程无法自己发明通道名,只能调用预定义好的 30 多个具名方法,例如extractSubtitles(data)、downloadModel(modelName)。
规则 2:请求/响应用invoke,事件流用"订阅 + 退订"。以进度事件为例(见 src/preload/index.js):
onProgressUpdate: (callback) => { const handler = (_event, data) => callback(data); ipcRenderer.on('progress-update', handler); return () => ipcRenderer.removeListener('progress-update', handler); }注意回调被包了一层,事件对象event永远不会泄漏到渲染进程,且返回值是一个可注销订阅的函数——这从源头规避了内存泄漏,也是官方文档推荐的标准写法。
规则 3:文件路径安全处理。getFilePathFromFile优先使用webUtils.getPathForFile(Electron 推荐方式),失败再降级,体现了"官方 API 优先 + 兜底降级"的防御式编码。
四、Shared 层(src/shared):通道名的单一事实来源
如果主进程写ipcMain.handle('extract-subtitles', ...)、预加载写ipcRenderer.invoke('extract-subtitles'),字符串一旦拼错就是静默失败。WhisperSubTranslate 的做法是把全部通道名集中到 src/shared/ipc-channels.js:
module.exports = Object.freeze({ EXTRACT_SUBTITLES: 'extract-subtitles', TRANSLATE_SUBTITLE: 'translate-subtitle', PROGRESS_UPDATE: 'progress-update', // ... 共 40 个通道 });Object.freeze保证常量不可被运行时篡改。主进程侧(src/main/ipc/transcription.js)与预加载侧都引用同一份常量,IDE 跳转即可在"发起方—处理方"之间往返,这是多人维护 IPC 代码最实用的小技巧。
五、渲染进程(src/renderer):纯前端,按功能切分
src/renderer/index.js 只负责引导启动:加载历史、检查模型状态、恢复设置等十余步,每步都独立 try/catch,单点失败不影响整体。真正的 UI 逻辑按功能拆在 src/renderer/features/:
queue.js/processing.js— 多文件队列与处理状态机(含"会话 epoch"机制,丢弃中止后的过期事件)models.js/providers.js— 模型管理与翻译供应商配置history.js/logs.js/settings.js/progress.js— 历史、日志、设置与进度条
渲染进程内没有任何require('fs')之类的 Node 调用——它想读写磁盘,唯一路径是调用window.electronAPI,这正是沙箱化 IPC 的价值:权限收敛在一个 200 行的文件里,攻击面一目了然。
六、进阶安全细节:值得抄进你项目的 5 个实践
- 原子写文件:字幕先写入
.wst-extract-临时目录,成功后再原子替换目标文件(src/main/services/file-safety.js),进程崩溃也不会留下半成品 SRT; - 路径输入校验:
isSafeLocalPath限制长度 < 4096 且禁止空字符,防注入(src/main/ipc/files.js); - API Key 安全存储:走 Electron
safeStorage(Windows DPAPI / macOS Keychain / Linux keyring),无密钥环时显式降级并标记insecure告警; - 错误日志脱敏:error-logger.js 只导出错误类别(如
disk-space),绝不外传字幕正文与凭据; - 本地翻译引擎完全离线:src/main/services/local-translator.js 基于 node-llama-cpp 加载 Hy-MT2 模型,视频与文本无需出网。
七、如何高效阅读这份源码:推荐顺序
- src/shared/ipc-channels.js — 10 秒读完全部通道,建立全局地图;
- src/preload/index.js — 看每个 API 的入参出参,等于拿到一份"接口文档";
- src/main/window.js — 对照学习 CSP、导航拦截、崩溃恢复三件套;
- 挑一个感兴趣的通道(如
translate-subtitle),从 preload 跳到 src/main/ipc/translation.js 再跳到 services,走通一条完整链路; - 结合 docs/README.zh.md 与 CONTRIBUTING.md 了解构建与贡献流程。
小结:WhisperSubTranslate 用"main 持权、preload 架桥、renderer 无根、shared 定约"的四层结构,把 Electron 的安全模型落到了每一行代码里。对想构建本地 AI 桌面工具的朋友来说,这套可直接复用的骨架——尤其是通道常量集中管理、订阅退订模式和 URL 白名单——值得写进你的第一版设计文档。
【免费下载链接】WhisperSubTranslate
A free, local desktop app to extract subtitles (SRT) from video and translate them into any language — unlimited use, no signup, no cloud.
相关推荐
Feather 免越狱侧载指南:用开发者证书在 iPhone 上签名安装第三方应用
Feather 免越狱侧载指南:用开发者证书在 iPhone 上签名安装第三方应用 Feather 是一个运行在 iOS / iPadOS 设备上的应用管理器与
移动开发原生移动桌面应用Free Claude Code:用 61 家免费服务商驱动 11 个 AI 编程代理
Free Claude Code:用 61 家免费服务商驱动 11 个 AI 编程代理 Free Claude Code 是一款开源本地代理工具,把 Claud
后端API网关LLM 网关人工智能GetStoreApp核心功能解析:离线部署Microsoft Store应用的5大优势
GetStoreApp核心功能解析:离线部署Microsoft Store应用的5大优势 GetStoreApp是一款专为Windows用户设计的离线下载工具,
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考