招商资讯 > 资讯详情

Recordly 开发文档(中文)格式对比

2026-09-20 06:47:54

Recordly 开发文档(中文)格式对比

语言: 简体中文 · 对应版本 Recordly v1.4.0main 分支,HEAD 4992686

Recordly 开发文档(中文)

本文面向要改代码的人,讲清楚三件事:这套东西怎么跑起来、代码分成哪几块、改了之后怎么验证。
面向用户的功能介绍请看 README.zh-CN.md


目录

  1. 技术栈
  2. 环境准备
  3. 快速开始
  4. 目录结构
  5. 构建流水线
  6. 多窗口体系
  7. IPC 架构与安全策略
  8. 原生层
  9. 渲染层:录制端与编辑器
  10. 数据与文件位置
  11. 国际化
  12. 测试
  13. 代码规范
  14. 环境变量与调试开关
  15. 打包与发布
  16. CI 质量门禁
  17. 常见问题
  18. 贡献流程

1. 技术栈

Recordly 是 Electron 桌面应用,不是 Web 应用。这一点决定了后面所有分层:主进程管窗口/文件/原生能力,渲染进程管 UI,preload 做唯一的安全桥。

选型
桌面壳Electron 43.1
构建Vite 5.1 + vite-plugin-electron 0.28
渲染React 18.2 + TypeScript 5.2(strict: true
样式Tailwind CSS 3.4 + Tailwind Animate
基础组件Radix UI 全家桶(shadcn 风格,见 src/components/ui/
图标@phosphor-icons/react / react-icons
动效motion 12
画布 / 合成pixi.js 8.14 + pixi-filters
视频容器 / 解复用mediabunnymp4boxweb-demuxer@fix-webm-duration/fix
转码 / 封装ffmpeg-staticffprobe-static
录制capturekituiohook-napi(全局键鼠钩子)
时间线交互dnd-timelinereact-resizable-panelsreact-rnd
Lint / 格式Biome 2.3(不是 ESLint + Prettier)
测试Vitest 3.2(environment: node
打包electron-builder 26(NSIS / dmg / zip / AppImage)
自动更新electron-updater(GitHub Releases)
许可证AGPL-3.0(见 LICENSE.md

规模参考:src/ + electron/488 个 .ts/.tsx(其中 86 个 .tsx),134 个测试文件


2. 环境准备

通用

  • Node.js 22(CI 固定用 22;本机 22.x 即可)
  • npm(仓库带 package-lock.json,请用 npm cinpm install,不要混用 pnpm/yarn,否则 postinstall 的原生流程可能对不上)
  • git

各平台额外依赖

平台需要装什么用途
WindowsVisual Studio 2022(或 Build Tools),勾选 C++ 工作负载 + CMake编译 WGC 采集、DXGI 回退、光标监控、GPU 导出等 C++ 辅助程序
macOSXcode Command Line Tools(xcode-select --installswiftc 编译 ScreenCaptureKit 辅助程序
Linuxbuild-essential cmake libx11-dev libxt-dev libxtst-dev libxkbfile-dev libxi-dev libxrandr-dev libxinerama-dev编译原生辅助程序 + uiohook-napi 的 X11 依赖
Windows 不装 CMake 也能跑起来。 详见 5.3 字幕运行时

系统版本下限

平台最低版本原因
macOS14.0 (Sonoma)ScreenCaptureKit 系统音频 / 麦克风能力
Windows10 20H1(Build 19041)原生 WGC 采集与最佳光标隐藏行为
Linux任意现代发行版走 Electron 采集 API;系统音频一般要 PipeWire

3. 快速开始

Shellgit clone https://github.com/webadderallorg/Recordly.git recordly
cd recordly
npm install      # 注意:会触发原生编译,首次较慢
npm run dev

npm install 到底做了什么

不要以为它只是拉包。package.json 里的 postinstall 会依次执行两步,任何一步失败都会让 npm install 以退出码 1 结束

  1. npm run rebuild:nativeelectron-rebuild --force --only uiohook-napi
    把全局键鼠钩子模块按 Electron 的 ABI 重编译。跳过这步,运行时 uiohook-napi 会报 ABI 不匹配。
  2. npm run build:platform-native-helpers → 依次构建:
    • build:whisper-runtime(字幕引擎,见下)
    • build:native-helpers(macOS Swift 辅助程序,非 mac 直接跳过)
    • build:windows-capturebuild:windows-gpu-exportbuild:nvidia-cuda-compositorbuild:cursor-monitor(Windows / CUDA)

只想改前端、不想编译原生代码

CI 就是这么干的,本地同样适用:

Shellnpm ci --ignore-scripts            # 跳过 postinstall
node node_modules/ffmpeg-static/install.js
npx electron-builder install-app-deps
npm run dev

代价是没有原生采集后端,会退回浏览器采集 / ffmpeg 路径。

开发模式的一个关键点

npm run dev 跑的是 vite --config vite.config.ts。当 VITE_DEV_SERVER_URL 存在时:

  • electron/appPaths.ts 会把 userData 切到 Recordly-dev,和正式版数据完全隔离;
  • 不申请单实例锁(shouldEnforceSingleInstanceLock = !IS_DEV),方便同时开多个实例调试。

所以你的开发数据在 %APPDATA%\Recordly-dev,删掉它等于恢复出厂设置。


4. 目录结构

JavaScriptRecordly/
├── electron/                  # 主进程(Node 侧)
│   ├── main.ts                # 入口:窗口、菜单、托盘、权限、GPU 开关
│   ├── preload.ts             # contextBridge,暴露 window.electronAPI
│   ├── electron-env.d.ts      # ★ electronAPI 的类型定义(改 API 必须同步这里)
│   ├── windows.ts             # 各类窗口的创建与生命周期
│   ├── appPaths.ts            # userData / recordings 路径(含 dev 隔离)
│   ├── mediaServer.ts         # 本地媒体 HTTP 服务(给 <video> 喂文件)
│   ├── rendererServer.ts      # 打包后渲染资源服务
│   ├── updater.ts             # electron-updater 封装
│   ├── navigationPolicy.ts    # 外链策略
│   ├── permissionPolicy.ts    # 媒体 / 屏幕采集权限策略
│   ├── gpuSwitches.ts         # 平台相关 GPU 命令行开关
│   ├── cursorHider.ts         # 录制时隐藏系统光标
│   ├── ipc/                   # ★ IPC 层
│   │   ├── handlers.ts        # 注册总入口
│   │   ├── constants.ts       # 频道名与常量
│   │   ├── types.ts
│   │   ├── register/          # 按功能拆分的注册模块
│   │   ├── captions/          # whisper 字幕(解析、分段、静音检测)
│   │   ├── cursor/            # 光标遥测
│   │   ├── export/            # 导出流、原生视频导出
│   │   ├── ffmpeg/            # ffmpeg 二进制探测与滤镜
│   │   ├── project/           # 项目文件的原子保存
│   │   ├── recording/         # 录制(windows / mac / ffmpeg 三条实现)
│   │   └── settings/          # 设置持久化
│   └── native/                # ★ 原生源码 + 预编译产物
│       ├── *.swift            # macOS 辅助程序
│       ├── wgc-capture/       # Windows Graphics Capture(C++)
│       ├── windows-capture/   # DXGI 回退(C++)
│       ├── cursor-monitor/    # 光标监控(C++)
│       ├── gpu-export-probe/  # GPU 导出能力探测(C++)
│       ├── nvidia-cuda-compositor/  # CUDA 合成(.cu)
│       └── bin/<平台-架构>/    # 预编译产物,随包发布
├── src/                       # 渲染进程(React)
│   ├── main.tsx / App.tsx     # 按 windowType 分发窗口
│   ├── components/
│   │   ├── launch/            # 录制端:HUD、源选择、倒计时、更新提示
│   │   ├── video-editor/      # 编辑器:时间线、导出、预览、项目、预设
│   │   ├── ui/                # Radix 封装的基础组件
│   │   ├── announcements/     # 公告
│   │   └── countdown/
│   ├── lib/
│   │   ├── exporter/          # ★ 导出引擎(帧渲染、编码、音频、封装)
│   │   ├── announcements.ts / appSettings.ts / wallpapers.ts ...
│   │   └── geometry/
│   ├── contexts/              # I18nContext / ThemeContext / ShortcutsContext
│   ├── hooks/                 # useScreenRecorder、设备枚举、音量表
│   ├── i18n/                  # 10 语言 × 7 命名空间
│   ├── utils/                 # 比例换算、平台判断
│   └── assets/                # 光标素材(macOS / Tahoe / Windows 11 三套)
├── scripts/                   # 构建与发布脚本(.mjs)
├── public/                    # 静态资源:应用图标、壁纸、wasm
├── build/                     # macOS entitlements
├── branding/                  # 品牌源素材
├── docs/                      # 公告说明 + README 用媒体
├── icons/                     # 打包图标(icns / ico / png)
└── .github/workflows/         # CI 与发布流水线

三个入口别搞混:

入口文件说明
主进程electron/main.ts构建后是 dist-electron/main.cjs
preloadelectron/preload.ts构建后同目录
渲染进程index.htmlsrc/main.tsxsrc/App.tsx构建后是 dist/

@ 别名指向 src/,在 vite.config.ts、vitest.config.ts、tsconfig.json 三处都配了,新增构建入口记得同步。


5. 构建流水线

5.1 dev 与 build 的区别

命令实际动作
npm run devvite --config vite.config.tsvite-plugin-electron 顺带编译主进程与 preload 并拉起 Electron
npm run buildbuild:platform-native-helperstscvite buildnormalize:electron-main-cjssmoke:electron-main-cjselectron-builder
npm run build:win / :mac / :linux同上,最后换成 electron-builder --win / --mac / --linux

产物:dist/(渲染)、dist-electron/(主进程 + preload)、release/(安装包,electron-builder 的 directories.output)。

5.2 主进程为什么强制 CJS

vite.config.ts 里有三个不显眼但很关键的设计:

  1. electronMainCjsOutputPlugin 强制 lib.formats = ["cjs"]、入口文件名 .cjs
    原因写在注释里:Vite 的 mergeConfig 会把 lib.formats 和插件的 ESM 默认值拼接在一起,导致输出格式不确定。
  2. inlineDynamicImports: true:主进程打成单文件,避免 Electron 加载动态 chunk 时的路径问题。
  3. electronMainCjsGuardPlugincloseBundle 阶段调用 scripts/smoke-electron-main-cjs.mjs 做冒烟检查,失败就让整个 vite build 抛错
    也就是说构建产物格式一旦退化,构建会立刻中断而不是留到运行时报错。
排查构建问题先看 npm run smoke:electron-main-cjs,它是这套机制的真相来源。

5.3 字幕(whisper)运行时

scripts/build-whisper-runtime.mjs 的逻辑值得单独讲,因为它决定了「Windows 上要不要装 CMake」:

  1. 优先走预编译:Windows x64 会下载 whisper.cpp 官方 whisper-bin-x64.zip(版本 v1.8.4,带 SHA-256 校验),解压后取出 whisper-cli.exe 与相关 DLL,写入 electron/native/bin/win32-x64/
  2. 下载失败才回退源码编译:需要 CMake + VS。Windows 上生成器按 VS 2026 → VS 2022 → VS 2019 顺序自动回退(见 scripts/windows-cmake-generators.mjs)。
  3. 缺 CMake 的失败策略分场合:
    • postinstall / CI=true / WHISPER_RUNTIME_ALLOW_MISSING=1只警告,退出 0;
    • 直接调用 npm run buildbuild:win 等 → 硬报错,避免打出一个静默缺失字幕能力的安装包。
  4. 已 staged 会跳过重复构建,判断依据是同目录下的 whisper-runtime.json 清单(版本 + 架构 + 二进制存在)。

5.4 生产构建的两个坑

  • terser 会删掉 console.log / console.debugdrop_console: truedrop_debugger: true)。
    所以「本地有日志、打包装没有」是预期行为,别为此加 console.error
  • manualChunks 只分了三块react-vendorvideo-processing(mediabunny / mp4box / fix-webm-duration)。往 src/lib/exporter/ 里引重库时注意别把主 chunk 撑爆(chunkSizeWarningLimit 已放宽到 1000 kB)。

5.5 打包配置要点(electron-builder.json5

  • appId: dev.recordly.appasar: true
  • asarUnpackffmpeg-staticffprobe-staticuiohook-napielectron/native/bin/** 必须解包,因为要以真实文件路径去 exec
  • extraResourcespublic/wallpapersassets/wallpapers(壁纸不进 asar)。
  • 剥离!dist/wallpapers/**whisper-bench*whisper-quantize*whisper-server*whisper-vad-speech-segments* 等调试用二进制不进包。
  • macOShardenedRuntime: true + 两个 entitlements 文件;extendInfo 里声明了相机 / 麦克风 / 音频采集用途说明,并注册了 .recordly 文档类型。
  • Windows:NSIS,可选安装目录、建桌面与开始菜单快捷方式。
  • publish:GitHub Releases(webadderall/Recordly,tag 前缀 v),publishAutoUpdate: true

6. 多窗口体系

这是 Recordly 最容易让人迷路的地方:一个渲染入口,多个窗口身份

src/App.tsx 从 URL 查询参数读 windowType,然后分发组件:

windowType组件窗口特点
hud-overlaycomponents/launch/HudWindow无边框透明浮层,主入口(启动即它)。开启 HTML 级鼠标穿透,hudOverlaySetIgnoreMouse(true)
source-selectorcomponents/launch/SourceSelector透明背景;挑选屏幕 / 窗口
countdowncomponents/countdown/CountdownOverlay录制前倒计时浮层
update-toastcomponents/launch/UpdateToastWindow透明、overflow: visible,仅 macOS 使用
editorcomponents/video-editor/EditorWindow主编辑器窗口

主进程侧的窗口创建集中在 electron/windows.tscreateHudOverlayWindow / createSourceSelectorWindow / createEditorWindow / showUpdateToastWindow

判断一个窗口是不是编辑器,用的是 URL 里有没有 windowType=editor

TypeScriptfunction isEditorWindow(window: BrowserWindow) {
  return window.webContents.getURL().includes("windowType=editor");
}

所以改窗口 URL 参数会直接破坏主进程逻辑,别随手改。

平台差异(都是踩过的坑,注释里写得很细)

  • 托盘只在 Linux 启用shouldUseTray())。macOS / Windows 走 Dock / 任务栏。
  • Win32 HUD 的鼠标穿透脆弱:开启穿透(Win11+)后,对透明 HUD 调 show/moveTop/focus永久破坏 setIgnoreMouseEvents 转发,窗口变成彻底点不透。所以托盘唤醒时用 showInactive() + 重新断言鼠标状态。Win10 不支持穿透,HUD 常驻可交互,反而可以正常 show/restore
  • Linux Wayland 焦点问题:合成器忽略 focus()。做法是干脆销毁并重建 HUD 窗口(创建路径能拿到焦点),注释里点名提到了 XDG activation token 的缺失。
  • Linux Wayland 屏幕共享只弹一次 portalsetDisplayMediaRequestHandler 里,若源 id 是哨兵 screen:linux-portal 或为空,跳过 desktopCapturer.getSources(),直接返回合成 id——因为 getSources() 本身就会触发一次 portal。

关闭编辑器的行为

Windows 上关闭编辑器不是关窗口,而是隐藏它并重新显示 HUDcloseEditorWindowToHud),目的是让录制收尾(例如摄像头文件 finalize)继续在渲染进程里跑完,同时应用回到「随时可录」状态。有未保存改动时弹三选一:保存关闭 / 放弃关闭 / 取消。


7. IPC 架构与安全策略

7.1 桥的形态

  • electron/preload.ts 通过 contextBridge 暴露 window.electronAPI
  • 类型定义集中在 electron/electron-env.d.tsinterface Window 里,约 700 行,覆盖录制、导出、项目、字幕、更新、权限等全部能力。
  • 新增或修改 API 必须同步这个 .d.ts,否则渲染进程拿不到类型(并且 Biome 对该文件单独放宽了 noNamespacenoExplicitAny,说明它是有意保持集中的)。

7.2 主进程侧的注册方式

  • 总入口:electron/ipc/handlers.ts(同时负责 cleanupNativeVideoExportSessionscleanupAllExportStreamskillWindowsCaptureProcess 等清理)。
  • 按功能拆到 electron/ipc/register/
    announcementsassetscaptionsexportexportCaptionSidecarspermissionsprojectrecordingsettingssourceMappingsources
  • 频道名用 kebab-case,例如 set-has-unsaved-changeshud-overlay-closerequest-save-before-close
  • 有些频道直接写在 main.ts 里(更新相关的 install-downloaded-updatecheck-for-app-updates 等),因为它们要拿到 mainWindow 这类窗口引用。

加一个 IPC 的标准动作: 在对应 register/*.ts 里注册 → 在 preload.ts 暴露 → 在 electron-env.d.ts 补类型 → 渲染层调用。

7.3 安全策略(三道闸)

  1. 导航策略navigationPolicy.ts):web-contents-created 时统一加固,外链一律 shell.openExternal,不在应用内导航。
  2. 媒体权限策略permissionPolicy.ts + main.ts 里的 setPermissionCheckHandler / setPermissionRequestHandler):
    只有可信采集窗口(即 HUD 主框架)且来源在可信 URL 列表内才放行 media 权限。可信列表 = dist/index.html 的文件 URL + dev server URL + 打包后的本地渲染服务地址。
  3. 设备权限直接全拒setDevicePermissionHandler(() => false) —— Recordly 不使用 WebHID / Web Serial / WebUSB,默认不授予任何设备。

另外 setDisplayMediaRequestHandler 接管了 getDisplayMedia():渲染层调它不会弹系统选择器,而是落到用户预选的源上。这里有个必须遵守的约束(注释明确警告):

回调只能传 { id, name } 的 video 对象。如果图省事把完整的 DesktopCapturerSource(带 thumbnail、appIcon 等)强转过去,会破坏 Electron 内部的光标约束传播,导致渲染层设的 cursor: 'never' 被原生采集管线静默忽略。

8. 原生层

electron/native/ 是「JS 干不了的事」的落点。预编译产物提交在 electron/native/bin/<平台-架构>/ 并随包发布,所以普通开发不需要每次都编原生代码。

macOS(Swift,只在 macOS 上编译)

scripts/build-native-helpers.mjs 在非 macOS 平台直接跳过。用 swiftcarm64-apple-macos14.0x86_64-apple-macos14.0 两个目标各编一份:

源文件产物作用
ScreenCaptureKitRecorder.swiftrecordly-screencapturekit-helperScreenCaptureKit 录制(含系统音频)
ScreenCaptureKitWindowList.swiftrecordly-window-list窗口列表枚举
SystemCursorAssets.swiftrecordly-system-cursors导出系统光标素材(用于编辑器里重绘光标)
NativeCursorMonitor.swiftrecordly-native-cursor-monitor原生光标位置 / 类型采样

swiftc 会直接抛错并提示安装 Xcode Command Line Tools。

Windows(C++ / CMake)

目录产物作用
wgc-capture/wgc-capture.exe当前实际编译的 Windows 采集辅助程序:Windows Graphics Capture + Media Foundation 编码 + WASAPI loopback 系统音频
cursor-monitor/cursor-monitor.exe光标遥测(位置、类型、点击事件)
gpu-export-probe/recordly-gpu-export.exeGPU 导出能力探测
nvidia-cuda-compositor/recordly-nvidia-cuda-compositor.exeCUDA 合成(实验性,需 NVIDIA 显卡 + CUDA 工具链)
windows-capture/含 DXGI 回退实现(dxgi_session.cpp),但当前没有任何构建脚本引用它,属遗留代码。别误以为它在打包里

Windows 生成器自动回退顺序:Visual Studio 18 202617 202216 2019,并会清理 CMakeCache.txtCMakeFiles 后重试。

脚本对已提交的预编译产物也很友好:找得到 CMake 就源码编译,找不到但 bin/ 里已有现成 wgc-capture.exe 就直接复用(并校验清单),两边都不满足才报错退出。

辅助程序清单(helpers-manifest)

scripts/native-helper-manifest.mjs 会为每个原生辅助程序生成 / 校验 helpers-manifest.json:记录源目录与二进制的对应关系。构建时更新,打包冒烟测试时校验。改原生源码后发现产物没更新,先看这个清单的告警。

与主进程的衔接

  • 二进制寻址electron/ipc/paths/binaries.ts(配套测试 binaries.test.ts)。
  • 打包后路径校验npm run smoke:packaged-binaries 会检查打包产物里的原生二进制是否都在位——CI 三个平台都会跑这一步。

9. 渲染层:录制端与编辑器

9.1 录制端(src/components/launch/

HUD 是常驻入口,内部按功能拆开:

  • HudWindow.tsx + LaunchWindow.tsx:主体与外壳
  • popovers/MicPopoverWebcamPopoverSourcePopoverProjectPopoverMorePopoverCountdownPopover,由 LaunchPopoverCoordinator 统一协调(同时只允许一个弹出层)
  • hooks/useLaunchWindowActionsuseLaunchWindowSystemStateuseRecordingTimeruseHudBarDraguseWebcamPreviewOverlayuseLaunchHudInteractionState
  • hudMousePassthrough.ts / hudViewportBounds.ts / floatingWebcamPreview.ts:注意这三个都带独立测试,说明它们是易碎逻辑,改动务必跑测试
  • contexts/HudInteractionContext:HUD 交互态共享

9.2 编辑器(src/components/video-editor/

体量最大的子系统,按职责再分层:

子目录 / 文件职责
layout/外壳:EditorShellEditorHeaderEditorSidebarEditorPreviewPanelEditorTimelinePanel、各类 Dialog 汇总
timeline/时间线子系统,见下
videoPlayback/预览引擎:缩放变换、光标跟随相机、光标渲染、场景动效、播放速率、webcam 同步
export/导出控制器、进度、设置、持久化、冒烟导出自动化
project/项目生命周期、打开/保存动作、快照模型、项目库
state/useProjectStateuseTimelineStateuseEditorUiStateuseAppearanceState
presets/预设与偏好持久化
audio/片段音频、预览同步、波形(含 Web Worker waveform.worker.ts
captions/自动字幕控制器
hooks/区域命令(缩放 / 裁剪 / 注释 / 音频 / 字幕 / 片段)、全局交互、历史记录、时间线投影

这一层的架构约定:纯逻辑抽成同名 .ts 并配 .test.ts,React 组件只做装配。
例如 clipSplit.ts / clipSplit.test.tszoomTransform.ts / zoomTransform.test.tseditorHistory.ts / editorHistory.test.ts。要改行为,先改并测那个 .ts,再动组件

时间线子系统内部:

纯文本timeline/
├── core/        rows / spans / time / constants / timelineTypes(纯函数,全部有测试)
├── model/       timelineModel.ts(带测试)
├── dnd/         engine.ts(拖拽引擎,带测试)
├── hooks/       runtime、归一化、范围、选择、键盘快捷键、DnD 绑定、音频峰值
│   ├── actions/ 音频 / 字幕 / 缩放区域动作
│   └── utils/   放置、通知、选择工具(带测试)
├── components/  axis / markers / overlays / playhead / toolbar / viewport / waveform / wrapper
├── Item.tsx / Row.tsx / TimelineEditor.tsx
└── sourceAudioTracks.ts / timelineLayout.ts / zoomSuggestionUtils.ts

9.3 导出引擎(src/lib/exporter/

这是「录完之后怎么出片」的核心,也是测试最密的目录(27 个测试文件)。三条路线:

  1. 原生静态布局导出(快,主流):nativeStaticLayoutRoutePlan.ts 决定走 cuda-overlay / cuda-scale-cpu-pad / cuda-static-composite / nvidia-cuda-compositor / windows-d3d11-compositor 哪条,再由 IPC 调原生合成器,最后用 muxer.ts 封装。
  2. 原生逐帧导出nativeVideoExport.ts(主进程)+ nativeFrameCapture.ts / modernFrameRenderer.ts(渲染侧),支持 rawvideoh264-stream 两种输入模式。
  3. 浏览器导出回退modernVideoExporter.ts / videoExporter.ts,带 streamingDecodePipeline / streamingDecoder 流式解码。

音频侧:audioRoutingEngine 决定路由,sourceTrackRoutingPolicy / editedTrackStrategy 决定「直接复制源音轨」还是「离线渲染编辑后的音轨」,audioEncoder / offlineAudioProcessor 负责编码,exportBitrate / exportTuning / videoColorSpace 管参数。

其他:gifExporter.ts(GIF 输出)、captionRenderer.ts / annotationRenderer.ts(字幕与注释烧录)、exportSavePolicy.ts(保存策略,含覆盖确认)、finalizationTimeout.ts(收尾超时保护)、backendPolicy.ts(后端选择)。

backendPolicyexportSavePolicy 这类"策略"文件都带测试,改判断条件时务必先看测试里约定的优先级。


10. 数据与文件位置

userData 根目录

环境路径
开发(VITE_DEV_SERVER_URL 存在)app.getPath("appData")/Recordly-dev(Windows 即 %APPDATA%\Recordly-dev
正式app.getPath("userData"),产品名 Recordly

目录与文件清单(electron/ipc/constants.ts

名称位置说明
录像目录<userData>/recordings可被用户改到别处(chooseRecordingsDirectory
项目目录<userData>/Projects默认项目存放地
最近项目<userData>/recent-projects.json最多 16
快捷键<userData>/shortcuts.json
录制设置<userData>/recordings-settings.json麦克风 / 系统音频 / 摄像头
倒计时设置<userData>/countdown-settings.json
应用设置<userData>/app-settings.json
whisper 模型<userData>/whisper/ggml-small.bin从 HuggingFace 下载

文件格式约定

后缀含义
.recordly项目文件(JSON)。兼容旧后缀 .openscreen
.preview.png项目缩略图
.recordly-session.json录制会话清单
recording-*自动录像文件名前缀

自动清理策略

自动录像保留 最近 20 个不超过 14 天AUTO_RECORDING_RETENTION_COUNT / AUTO_RECORDING_MAX_AGE_MS),逻辑在 electron/ipc/recording/prune.ts(带测试)。

光标遥测

  • 版本 CURSOR_TELEMETRY_VERSION = 2,采样间隔 33ms(约 30Hz),上限 1 小时 样本量。
  • 数据点包含位置、点击类型、光标类型,供编辑器的缩放建议与光标重绘使用。

11. 国际化

  • 支持 10 种语言src/i18n/config.ts):enesfrdeitnlkopt-BRzh-CNzh-TW。默认 en
  • 7 个命名空间commonlauncheditortimelinesettingsdialogsshortcuts
  • 文件位于 src/i18n/locales/<locale>/<namespace>.json
  • 用法:src/contexts/I18nContext.tsx 提供 useI18n(),取词形如 t("app.editorTitle", "Recordly Editor") —— 第二个参数是兜底文案
  • 校验:npm run i18n:checkscripts/i18n-check.mjs)。CI 里目前是 advisory(不阻塞),因为 main 上有已知的语言对齐欠账。
  • 翻译规范见仓库根目录的 TRANSLATION_GUIDE.md;有自动翻译工作流 .github/workflows/auto-translate-zh.yml
新增文案请同时enzh-CN,否则 i18n:check 会报差集。

12. 测试

Shellnpm test          # vitest --run(单次)
npm run test:watch

配置要点(vitest.config.ts):

  • environment: "node" —— 没有 DOM。要测组件得自己 mock 或在该文件加 environment 覆盖。
  • globals: true,可直接用 describe / it / expect
  • includesrc/**electron/** 下的 *.{test,spec}.*
  • @ 别名已配。

测试分布(共 134 个文件):

区域文件数覆盖内容
src/lib/exporter/27编码、音轨路由、帧渲染、封装、比特率、保存策略(最密集)
electron/38权限、导航、GPU 开关、窗口边界、媒体服务、录制各平台实现、项目原子保存、字幕与 ffmpeg
src/components/video-editor/timeline/12时间线 core 纯函数、DnD 引擎、键盘快捷键、范围、选择、布局
src/components/video-editor/videoPlayback/缩放变换、光标跟随 / 缩放 / 摇摆、场景动效、webcam 同步
src/components/video-editor/片段切分 / 变速 / 跨度、字幕操作、历史记录、项目脏态与持久化
src/lib/公告、壁纸、资源路径、媒体时间、pixi 生命周期
约定:易碎逻辑必须有测试。 现有代码里 hudMousePassthroughcursorScaleaudioResourceVersion 这类一看就容易错的文件都配了测试,新增同类逻辑请照做。

13. 代码规范

Biome(不是 ESLint + Prettier)。

Shellnpm run lint         # biome lint .
npm run lint:fix
npm run format       # biome format --write .
npm run format:check
npx tsc --noEmit     # 类型检查(构建脚本里是 npx tsc)

格式化约定(biome.json):

  • 缩进 TabindentStyle: "tab"indentWidth: 4
  • 行宽 100,换行符 LF,字符串 双引号
  • 自动整理 import(assist.actions.source.organizeImports: "on"

Lint 特点:

  • 没有启用 recommended 预设,每条规则显式列出 —— 想加规则要显式写。
  • noExplicitAny: errornoNonNullAssertedOptionalChain: errornoTsIgnore: error不要用 any@ts-ignore 走捷径
  • useExhaustiveDependencieswarn,但 useHookAtTopLevelnoUnusedVariableserror
  • 忽略 distdist-electronrelease.tmpelectron/native/**/build

TypeScript(tsconfig.json):strict: truenoUnusedLocalsnoUnusedParametersnoFallthroughCasesInSwitch,且排除测试文件(测试由 Vitest 负责)。


14. 环境变量与调试开关

变量作用
VITE_DEV_SERVER_URLvite-plugin-electron 注入。有值即 dev:userData 切到 Recordly-dev、跳过单实例锁
RECORDLY_SMOKE_EXPORT=1启动即进入编辑器冒烟导出,并打印 GPU 特性诊断
RECORDLY_SMOKE_EXPORT_INPUT冒烟导出的输入文件路径
RECORDLY_SMOKE_EXPORT_PROJECT冒烟导出的输入项目文件(优先于上一项)
RECORDLY_DEV_OPEN_RECORDING_INPUT启动后直接打开指定录像进编辑器
RECORDLY_DEV_PREVIEW_UPDATE=1dev 下预览更新提示 UI(macOS 走 toast,其他平台走原生对话框)
WHISPER_RUNTIME_ARCHSall / arm64 / x64,控制 whisper 编译目标架构
WHISPER_RUNTIME_ALLOW_MISSING=1缺 CMake 时不报错,直接没有字幕能力
CI=true让 whisper 缺 CMake 变成软失败(同时会影响其他脚本行为)
PACKAGED_SMOKE_ARCH_TAGS打包冒烟测试指定架构标签(CI 传 darwin-x64 / darwin-arm64

15. 打包与发布

Shellnpm run build:win      # NSIS 安装包
npm run build:mac      # dmg + zip(x64 / arm64)
npm run build:linux    # AppImage

相关脚本:

脚本用途
smoke:packaged-binaries校验打包产物中的原生二进制是否齐全
smoke:electron-main-cjs校验主进程产物是合法 CJS
normalize:electron-main-cjs产物规整
verify:macos-distributionmacOS 分发校验
checksums:release生成 SHA256 校验和文件
release:create创建 Release

发布流程的权威说明在 RELEASING.md,请以它为准。

GitHub Actions 流水线:

工作流触发作用
quality.ymlPR / push main质量门禁(见下节)
build.yml手动三平台构建 + 冒烟 + 校验和 + attest + 上传 artifact
release.yml正式发布
winget-releaser.yml发布到 winget
homebrew-tap.yml更新 Homebrew tap(recordly.rb
macos-release-candidate.ymlmacOS RC
auto-translate-zh.yml中文翻译自动化

16. CI 质量门禁

quality.yml 在 PR 与 push main 时执行(ubuntu,20 分钟超时):

步骤命令是否阻塞
安装依赖npm ci --ignore-scripts阻塞(注意跳过原生编译)
类型检查npx tsc --noEmit阻塞
Lintnpm run lint阻塞
格式检查npm run format:checkadvisory(continue-on-error
测试npm test阻塞
翻译校验npm run i18n:checkadvisory

提 PR 前本地跑这三条就够

Shellnpx tsc --noEmit && npm run lint && npm test

17. 常见问题

npm install 失败 / 卡在 postinstall
先看失败在哪一步。postinstall 分两段:rebuild:nativebuild:platform-native-helpers,日志里都有 [postinstall] Running npm script: xxx 前缀。
如果只是改前端,用第 3 节的 --ignore-scripts 方案绕开。

uiohook-napi 运行时崩溃 / ABI 不匹配
npm run rebuild:native(等价于 electron-rebuild --force --only uiohook-napi)。

没有 CMake,字幕功能不可用
Windows x64 通常会走预编译,不会遇到;其他情况装 CMake(含 VS 的 CMake 组件)后执行 npm run build:whisper-runtime
想先跳过:WHISPER_RUNTIME_ALLOW_MISSING=1

打包后 ffmpeg / 原生辅助程序找不到

  1. 确认它们在 asarUnpack 列表里;
  2. npm run smoke:packaged-binaries 定位缺哪个。

本地有日志、打包装没有
terser 的 drop_consoleconsole.log / console.debug 删了,属预期行为。

Windows 摄像头 / 麦克风不工作
主进程启动时会打印 [permissions] Camera access is "..." 警告。去「设置 → 隐私和安全性 → 相机 / 麦克风」开启。

macOS 录制失败或光标不动
需要 屏幕录制辅助功能 权限。应用内有跳转按钮(openScreenRecordingPreferences / openAccessibilityPreferences)。本地构建若被隔离:xattr -rd com.apple.quarantine /Applications/Recordly.app

Linux 编译报 X11 头文件缺失
.github/workflows/build.yml 里那一串:libx11-dev libxt-dev libxtst-dev libxkbfile-dev libxi-dev libxrandr-dev libxinerama-dev

Linux 屏幕共享弹两次选择框 / 托盘点了没反应
Wayland 已知问题,处理逻辑在 main.tssetDisplayMediaRequestHandler 里,改这块前先读完相关注释。

改了 windowType 相关代码后行为异常
回顾第 6 节:主进程靠 URL 里的 windowType=editor 判断窗口身份。

Vite 构建时抛 Electron main CJS smoke failed
构建守卫生效了,跑 npm run smoke:electron-main-cjs 看具体原因,通常是主进程被打成了 ESM。


18. 贡献流程

  1. main 切分支(仓库默认分支是 main,别用 master)。
  2. 按第 13 节的规范写代码,按第 12 节的习惯补测试。
  3. 本地过一遍:npx tsc --noEmit && npm run lint && npm test
  4. 提 PR,遵循 .github/pull_request_template.md
  5. CI 会跑质量门禁;仓库配置了 CodeRabbit(.coderabbit.yaml)做自动评审,其评审指令在 .github/instructions/general.instructions.md(要求:不打行内评论,只给一条汇总,含等级 A-F、阻塞问题、可选改进、是否可合并)。
  6. Issue 模板:.github/ISSUE_TEMPLATE/bug_report.ymlfeature_request.yml

扩展开发:Recordly 有社区扩展系统(光标点击音效、设备边框、浏览器外壳、壁纸、渲染钩子、设置面板等),接口说明见 EXTENSIONS.md,市场在 https://marketplace.recordly.dev/extensions


附:改动速查表

你想改什么先从哪个文件入手
HUD 按钮 / 录制控制src/components/launch/LaunchWindow.tsxRecordingControls.tsx
录制参数(麦克风、系统音频)electron/ipc/recording/ + electron/ipc/settings/recordingPreferencesStore.ts
时间线拖拽行为src/components/video-editor/timeline/enginetimeline/dnd/engine.ts)与 timeline/core/
导出画质 / 码率src/lib/exporter/exportBitrate.tsexportTuning.tsbackendPolicy.ts
导出后端选择src/components/video-editor/export/ + electron/ipc/export/native-video.ts
光标外观 / 跟随src/components/video-editor/videoPlayback/cursor*.ts
自动字幕electron/ipc/captions/(whisper + 分段 + 静音检测)
新增一个 IPCelectron/ipc/register/*preload.tselectron-env.d.ts
新增窗口electron/windows.ts + src/App.tsxwindowType 分支
加界面文案src/i18n/locales/{en,zh-CN}/*.json
原生辅助程序electron/native/ + scripts/build-*.mjs
打包产物内容electron-builder.json5
DISCUSSION

评论

登录后参与
请使用网站前台用户账号登录后发表评论。

正在加载评论...


合作热线
18865460927
公司地址
山东省东营市垦利区兴隆路8-5号
产品咨询
产品咨询
Copyright © 2014-2026 东营码良软件开发 Inc. 版权所有鲁ICP备2025202136号-2 | 经营许可证编号:豫B2-20190103豫公网安备41019602002340