Rescript 开源视频剪辑工具开发者指南:Electron 本地打包与 GitHub Actions 发布完整教程

原创2026-10-23 18:26:29381 阅读

Rescript 开源视频剪辑工具开发者指南:Electron 本地打包与 GitHub Actions 发布完整教程

Rescript 是一款完全离线运行的转写式(transcript-based)音视频剪辑开源工具——把视频丢进去,本地 Whisper 模型逐字转写,删掉文字对应的片段即被剪掉。它同时提供浏览器网页版和基于 Electron 的桌面应用,桌面版通过 GitHub Actions 实现三平台自动构建、签名、发布与自动更新。本文带你从源码跑起来,一路到本地打包出可安装的安装包,并拆解整套 CI 发布流程。

Rescript 转写式视频剪辑工具桌面端编辑器界面,包含文字转写、视频预览与时间线

一、30 秒看懂项目结构

Rescript 前端基于 Next.js + React + TypeScript,桌面端由 electron/ 目录提供外壳。核心目录如下:

目录 / 文件 作用
app/、components/ Next.js 页面与 UI 组件(编辑器主体)
electron/main.ts Electron 主进程:窗口、app:// 协议、菜单
electron/media.ts 桌面端媒体引擎:主进程中运行原生 ffmpeg 完成导出
electron/updater.ts 自动更新:读取 GitHub Release 的 latest-*.yml 清单
scripts/build-electron.mjs 用 esbuild 打包 Electron 主进程/preload
scripts/fetch-ffmpeg.mjs 下载并校验各平台原生 ffmpeg 二进制
scripts/after-pack.cjs 打包钩子:校验 ffmpeg 已进入安装包
.github/workflows/release.yml 发布工作流(tag 触发,三平台矩阵)
.github/workflows/ci.yml 日常 CI:lint、类型检查、测试、构建

📖 完整的发布文档见 RELEASING.md,是理解本文最权威的参考。

二、本地一键启动:Web 版与桌面开发模式

克隆仓库并安装依赖(postinstall 会自动应用补丁并拷贝 WASM 资产):

git clone https://gitcode.com/gh_mirrors/resc/rescript
cd rescript
npm install

两条最常用的启动命令(定义在 package.json 的 scripts 中):

  • npm run dev —— 启动 Next.js 开发服务器(http://localhost:3000),体验网页版编辑器
  • npm run electron:dev —— 同时拉起 Next.js 开发服与 Electron 窗口

第二条命令的巧妙之处在于 scripts/electron-dev.mjs:它会先轮询 http://localhost:3000 直到有响应,再启动 Electron,避免窗口抢跑开发服务器导致的白屏竞态。

开发期自动更新是禁用的,仅当 app.isPackaged 为 true(即打包后的应用)才会检查更新,见 electron/updater.ts。

Rescript 编辑器界面:转写文字、说话人分组、Cut/Correct 操作与时间线波形

三、Electron 桌面端架构:为什么安装包里没有 node_modules

理解桌面端的关键是明白渲染层装的是什么。npm run dist 会先执行 export:desktop(STATIC_EXPORT=1 NEXT_PUBLIC_ELECTRON=1 next build),产出一份 Next.js 静态导出目录 out/;再由 esbuild 把 Electron 主进程和 preload 各自压成单个 JS 文件(scripts/build-electron.mjs)。

于是安装包的内容非常"干净":

  1. 渲染层 = 静态 out/(Next.js、transformers.js、ffmpeg.wasm 全部已内联其中)
  2. 主进程 = electron-dist/main.js + preload.js 两个打包文件,不携带任何 node_modules
  3. 原生 ffmpeg = 通过 build.extraResources 塞进 resources/ffmpeg/ 的静态二进制

主进程通过自定义 app:// 特权协议加载静态导出(electron/main.ts),并自行注入 COOP/COEP 响应头——因为 GitHub Pages 给不了这些跨源隔离头,而 SharedArrayBuffer 是 ffmpeg.wasm 多线程的硬性前提。

为什么桌面端要用原生 ffmpeg? 浏览器版 ffmpeg.wasm 的堆上限是 2 GiB,整个渲染结果都驻留内存,长视频和 4K 导出必然失败。桌面端改为在主进程直接跑静态 ffmpeg,源文件从磁盘读、结果写临时文件,内存不再是瓶颈(electron/media.ts)。

四、本地打包:一条命令产出三平台安装包

在干净的工作区执行:

npm run dist    # 未签名的桌面安装包,输出到 dist/

这一条命令实际串联了三步(见 package.json):

  1. export:desktop —— Next.js 静态导出到 out/
  2. build:electron + fetch:ffmpeg —— 打包主进程、下载 ffmpeg
  3. electron-builder —— 按 build 配置 产出各平台安装包

其中 fetch:ffmpeg 值得单独看:它下载固定版本的 ffmpeg-static(b6.1.1)对应各架构的二进制,并逐一核对 SHA-256 摘要,落到 build/ffmpeg/<os>-<arch>/ 目录。而 scripts/after-pack.cjs 是打包流水线上的"保险丝"——如果 ffmpeg 没被正确拷入安装包,它会直接让构建失败,而不是让用户静默降级到 wasm 引擎再撞内存墙。

各平台产物目标在 package.json 的 build 段里一目了然:macOS 出 DMG/ZIP(x64 + arm64,含签名与公证配置)、Windows 出 NSIS 安装器、Linux 出 AppImage 与 deb。

Rescript 转写式剪辑界面:删除文字即剪掉片段,支持说话人区分与实时预览

五、GitHub Actions 发布流程拆解

5.1 触发方式:推送 v*.*.* tag

发布工作流 .github/workflows/release.yml 只被语义化版本 tag 触发,使用矩阵在 macOS / Ubuntu / Windows 三台独立 runner 上并行构建(fail-fast: false,一个平台失败不拖累其他平台)。

每个平台的步骤基本一致:

  1. npm ci + 类型检查(web 与 electron 两套 tsconfig 都查)
  2. macOS 额外解码 App Store Connect API key,用于公证
  3. 执行 npm run release = npm run dist + electron-builder --publish always,把安装包和 latest-*.yml 更新清单一并上传为 draft Release
  4. Ubuntu 节点顺带上传 Sentry source maps(continue-on-error: true,绝不阻塞发布)

5.2 最后一步:draft 变 published 的"闸门"

publish job 依赖全部三个平台 job 成功才运行(release.yml):

  • 解析上一个 tag,对两 tag 之间的 diff 用 AI 生成 Release Notes(npm run notes:preview 可在本地预览)
  • 执行 gh release edit --draft=false --latest,把 draft 翻转为正式发布

这个设计的意义:自动更新只拉取 published 的 Release,所以任何一次构建残缺(比如 Windows 挂了),用户都绝不会收到只有两个平台的"半套"更新。

5.3 配套 CI:每次 push 到 main 的质量闸门

.github/workflows/ci.yml 在每次 push / PR 时跑 lint、web 与 electron 双套类型检查、i18n 与时间线导出测试、真实 ffmpeg 渲染测试(复用与桌面应用相同的静态 ffmpeg 构建),最后完整构建 Next.js 与 Electron 主进程——发布流程里的所有构建步骤,在 CI 里都已经被"预演"过。

六、打一个新版本:发布者的日常操作流

维护者发版只需三步,全部有现成脚本(package.json):

npm run cut:patch    # 或 cut:minor / cut:major

它封装了 npm version <type> && git push --follow-tags:递增 package.json 的版本号 → 提交 Release vX.Y.Z → 打同名 tag → 推送。tag 一到远端,第五节描述的发布流水线自动接管,剩下的就是看 Actions 日志。

⚠️ 注意:npm version 拒绝在工作区有未提交改动时运行,发版前请先 commit。另外 macOS 签名需要仓库配好 CSC_LINK、APPLE_API_KEY 等 Secrets(完整清单见 RELEASING.md 的表格)。

七、常见问题速查

现象 原因与对策
构建失败提示 native ffmpeg missing 先跑 npm run fetch:ffmpeg,after-pack 钩子在拦截缺件的安装包
打包后桌面应用回退到 wasm 引擎 检查 resources/ffmpeg/ 是否存在;可用 RESCRIPT_MEDIA_ENGINE=wasm 强制 wasm 排查
Windows-on-ARM 上应用无法启动 需 arm64 构建:x64 版在 WOA 模拟下 V8 拿不到 SSE4.1,Wasm SIMD 无法启用(见 RELEASING.md)
本地 electron:dev 白屏 多为开发服务器未就绪,确认 ELECTRON_START_URL 指向且 3000 端口已响应

小结

Rescript 的桌面端工程化值得借鉴:静态导出 + esbuild 让安装包摆脱 node_modules 依赖;after-pack 钩子把"静默降级"变成"响亮失败";draft → published 的两段式发布确保自动更新永不推送残缺版本。从 npm run electron:dev 到 npm run cut:patch,你只需要记住这两条命令,中间的全部复杂性都已经被脚本和 CI 收编了。

登录后查看全文
rescript