一、为什么要在浏览器里做 AI 视频编辑器
在线视频编辑器并不新鲜,但很多“在线编辑”实际上只是把浏览器作为操作界面:素材上传到服务器,模型在云端运行,成片也由服务端转码。
这种架构成熟、算力充足,却也带来几个明显问题:
1. 原始视频、声音和人像需要离开用户设备,隐私边界依赖平台承诺;
2. 大文件上传和服务端排队让“点一下、立即看结果”变得困难;
3. GPU 推理、转码和存储成本会随使用量线性上升;
4. 弱网或离线环境几乎无法工作。
与此同时,浏览器的能力边界正在发生变化。WebCodecs 开放了更底层的帧级编解码能力,WebGPU 可以执行通用 GPU 计算,AudioContext、OfflineAudioContext、Web Worker、OPFS 和 Service Worker 则分别补齐了音频处理、后台任务、本地持久化与缓存能力。阿里云开发者社区早期介绍 Web 多媒体技术时,也把 WebCodecs 和 WebGPU 视为浏览器多媒体的重要演进方向。
Timeline Studio 因此选择了“本地优先”而非“纯云端”的架构:项目素材默认留在本机;模型按需下载并缓存;预览、AI 推理和最终导出尽可能在浏览器内完成。当浏览器缺少某项能力时,再进行明确的兼容回退,而不是静默改变处理结果。
项目地址:[GitHub](https://github.com/MartinDelophy/ai-video-editor) | [在线体验](https://video-editor.ai-creator.top/)

## 二、整体架构:浏览器不只是 UI 层
Timeline Studio 当前基于 React 19 和 Vite 构建。编辑器内部可以分成五层:
```text
交互层 多轨时间线 / 预览画布 / 属性面板 / 移动端工作区
状态与模型层 片段、轨道、关键帧、撤销重做、吸附与派生视图
AI 能力层 TTS / Whisper ASR / 主体检测 / 抠图 / 人声分离 / 数字人
媒体运行层 原生媒体播放 / Canvas 合成 / Web Audio / Worker
导出与存储层 WebCodecs / MP4、WebM 封装 / 项目归档 / SW、OPFS 缓存
```
它和常见 Web 应用最大的不同,是“状态”不只是表单字段,而是一条可计算的媒体时间轴。任何一次切分、拖动或变速,都会同时影响:
- 片段在时间线上的起止位置;
- 素材内部的 source offset;
- 当前播放时间应读取的画面和声音;
- 波形、缩略图、字幕和关键帧的显示;
- 导出器在某个精确时间戳应合成的内容。
因此,我们没有让 DOM 的宽度和位置成为事实来源。片段始终以秒为单位保存 `start`、`duration`、`sourceStart` 等数据,像素宽度只是当前缩放比例下的投影。这样才能保证在不同缩放级别、桌面和移动端之间,片段时长不因 CSS 最小宽度而失真。
## 三、难点一:多轨时间线既要“像剪辑软件”,又要精确
Timeline Studio 的主画面轨采用连续、可重排的序列模型;字幕、贴纸、配音、音乐、视频原声和画中画则采用自由定时模型。两类轨道的行为并不相同:
- 拖动主画面片段,表达的是序列重排;
- 拖动字幕或音频片段,表达的是时间位置变化;
- 自由轨允许重叠,并自动装入同类型的额外子轨;
- 画中画可以跨轨拖回主画面,反之也可以从主轨转换为覆盖层。
如果把所有片段都套用同一套拖拽算法,界面看起来也许能动,但很快会遇到素材被覆盖、时长变化、音画错位等问题。我们的做法是把时间线行为拆成独立、可测试的领域操作,包括重排、切分、自由移动、锚点缩放、跨轨放置、吸附和源音频同步。
### 1. 用“透明命中区域”解决短片段可操作性
短音频在缩小时间线后可能只剩两三个像素。直接设置 `min-width` 虽然容易点击,却会让它在视觉上代表一个虚假的时长。
项目保留真实的片段宽度,同时在交互层增加透明命中区域。于是时间语义和可用性不再互相牺牲:看见的宽度仍然精确,手指或鼠标仍能选中片段。
### 2. 吸附不是局部计算
剪辑软件中的磁吸,需要比较当前片段的左右边界与所有其他轨道的起止边界。命中阈值后,数据层将时间对齐到目标边界,视图层再绘制一条贯穿轨道区的对齐线。
关键是不能只移动 DOM,也不能只在当前轨道内查找。否则松手后状态会回跳,或者字幕无法对齐画面、音频无法对齐转场。
### 3. 移动端需要重新定义手势优先级
桌面的 `mousedown` 逻辑不能直接复用到触屏:单指横移可能是拖片段,纵移应该滚动轨道,两指则是缩放。项目将手势识别成互斥状态,并在两指进入时回滚尚未提交的单指拖动。
移动端的播放头固定在轨道视口中央,缩放围绕固定播放头改变内容像素比例,抬手后不修改播放时间,也不偷偷切换刻度规则。这比简单地对容器做 CSS scale 更复杂,但更符合移动剪辑软件的操作模型。
## 四、难点二:端侧 AI 不是“加载一个模型”这么简单
Timeline Studio 把多类 AI 能力放进浏览器:
- 中文语音使用 Piper/VITS ONNX,并实现专用拼音音素转换;
- 英文语音使用 Kokoro 82M,其他多种语言使用浏览器 Piper 声音;
- 自动字幕默认使用 Whisper small q8 ONNX;
- 视觉能力包含主体检测、人像抠图与智能裁切;
- 音频工作流支持人声与伴奏分离;
- 数字人工作流组合音频驱动与 LivePortrait 神经渲染。
真正的工程问题集中在运行后端、任务隔离和大文件管理。
### 1. WebGPU 优先,但回退必须可观察
以中文 Piper 为例,运行时优先创建 WebGPU session;初始化失败时回退到 WASM。如果 WebGPU 初始化成功、但实际推理失败,还会释放这次假设并用同一份模型重新创建 WASM session。
这里有一个重要原则:回退不能伪装成成功的 WebGPU 运行。界面会报告实际后端与回退原因,模型加载、音素转换或推理失败时也不会静默换成另一位声音。对于生成式媒体,“结果可解释”比表面上的成功率更重要。
### 2. Worker 隔离重任务
ASR、视觉分析、人声分离、自动剪辑、增强和数字人分别运行在 Worker 中。主线程负责交互和状态协调,Worker 通过请求 ID 返回进度、结果或错误。
这不仅是性能优化,也是架构边界。模型推理常包含长时间的同步计算和大块 TypedArray;如果与时间线交互处于同一事件循环,播放头、拖拽和滚动都会出现明显卡顿。
### 3. 大模型需要分层缓存
模型第一次下载可能远大于应用本身。项目使用 Service Worker 缓存模型与运行时资源;中文语音模型还通过 OPFS 持久化配置与 ONNX 文件。再次使用时优先读取本地副本,缓存写入失败则仅降级为当前会话可用,不中断已经完成的下载。
这让“按需加载”真正成立:用户不需要在打开首页时下载所有模型,也不会在每次生成字幕或配音时重复承担网络成本。
### 4. 自动字幕还需要时间轴后处理
Whisper 给出的 chunk 时间戳并不天然适合剪辑时间线。项目把音频解码为 16 kHz 单声道,计算能量区间,再将字幕起止时间向附近的语音能量边界收敛。中文文本只进行有上下文、高置信的同音错误修正,避免把 ASR 变成不可控的文本改写器。
这一步看似不如“换更大的模型”醒目,却直接决定字幕条是否贴合波形,也决定用户后续需要多少人工调整。
## 五、难点三:流畅预览和确定性导出是两条不同的路径
浏览器视频编辑器很容易踩到一个坑:直接录制预览画布作为最终视频。
这种方式实现简单,但结果受主线程负载、显示器刷新率和媒体 seek 速度影响。机器一忙就可能丢帧;预览里某次跳帧,也会原样进入成片。它适合作为兼容方案,却不应是高质量导出的主路径。
Timeline Studio 因此将播放与导出分开:
### 1. 预览路径追求低延迟
播放时尽量复用浏览器原生媒体元素,让视频和音频持续运行;React 状态只以较低频率同步 UI。静止或跳转时,再把媒体时间校正到目标时间。这样不会要求 React 在每一帧都驱动视频播放。
### 2. 离线导出追求确定性
导出器先根据时长和帧率建立 frame plan。例如 30 fps 下,第 `n` 帧的时间戳固定为 `n / 30`。随后针对每个时间戳:
1. 定位主画面片段及其素材内部时间;
2. 顺序解码视频帧,无法使用 WebCodecs 时精确 seek 回退;
3. 解析转场、画中画、关键帧、遮罩、特效、字幕与贴纸;
4. 调用共享 Canvas 合成器绘制完整画面;
5. 把帧编码为 AVC、VP8 或 VP9;
6. 将编码帧封装为 MP4 或 WebM。
音频则使用 `OfflineAudioContext` 以 48 kHz 离线混合配音、视频原声和音乐,处理音量、淡入淡出、source offset 与播放速度。变速音频先走保音调 time-stretch,再进入混音图。最终 AAC 或 Opus 音轨与视频一起进入容器。
这套路径的价值不只在“质量更高”,更在可验证:给定同一项目状态和同一帧时间,合成器应得到同一画面。测试可以解码输出文件,检查尺寸、时长、帧数、字幕、透明贴纸以及真实音轨,而不只是判断下载按钮是否出现。
### 3. 预览和导出必须共享几何语义
项目没有复制两套字幕、遮罩和画面适配公式。预览和导出共同使用比例感知的字幕布局、媒体 contain/cover 几何、关键帧插值与遮罩路径。
例如默认 `contain` 会保留完整画面并产生黑边;只有用户明确选择填充时才裁切。选中媒体的变换框按素材本身的宽高比包住可见内容,而不是把 letterbox 区域也算进去。否则用户在预览中看到的边界,与导出中实际移动的图像就会不一致。
## 六、兼容性、安全边界与可安装体验
本地优先不等于浏览器能力完全一致。项目采用渐进增强策略:
- 推理后端优先 WebGPU,失败后明确回退 WASM;
- 视频导出优先 WebCodecs,MediaRecorder 仅作兼容后备;
- 模型缓存优先 OPFS 与 Service Worker,写入失败不阻断当前任务;
- 媒体 Worker 所需的跨域隔离由部署响应头统一配置;
- 应用通过 Web App Manifest 和缓存应用外壳支持 PWA 安装。
对于浏览器内 AI,能力检测应发生在具体功能入口,而不是简单地给整个应用贴上“支持/不支持”标签。一个设备可能不支持 WebGPU,但仍能通过 WASM 完成语音;可能无法使用某种硬件编码器,却仍能导出 WebM。细粒度降级能让更多用户完成工作,同时保留对实际运行路径的知情权。
## 七、测试策略:验证媒体语义,而不只是组件渲染
这类项目的高风险区域往往不在按钮样式,而在跨模块不变量:
- 切分后两段的总时长和 source offset 是否连续;
- 音频变速后,时间线、预览和导出是否同步;
- 缩放后片段像素宽度是否仍准确代表秒数;
- 字幕、贴纸和画中画的层级是否在导出中保持;
- 删除派生原声时,是否误删对应视频;
- 移动端双指缩放是否意外提交了单指拖动。
项目将这些规则尽量下沉为纯函数,通过 Vitest 覆盖时间线、波形、关键帧、吸附、音频同步、项目归档和离线导出;再用 Playwright 验证移动端属性面板、自动剪辑和多语言语音生成等完整流程。
我们得到的经验是:媒体编辑器的测试不能只断言 DOM。真正需要保护的是“某个时间点播放什么、导出什么”,以及一次编辑操作前后的时间语义是否守恒。
## 八、从这个项目得到的四点经验
### 1. 先定义时间模型,再写拖拽 UI
如果数据层无法准确表达自由片段、连续序列、source offset、播放速度和重叠关系,再漂亮的时间线也只能停留在演示阶段。
### 2. 预览和导出可以有不同的执行策略,但必须共享语义
预览追求实时,导出追求确定;两者不必共用同一个调度循环,却必须共用画面布局、关键帧、字幕、遮罩和时间解析规则。
### 3. 端侧 AI 的产品体验,一半来自模型以外
后端回退、Worker 隔离、下载进度、持久缓存、错误可见性以及结果与时间线的连接方式,往往比模型榜单上的小幅精度差异更影响真实可用性。
### 4. 移动端不是桌面版的缩小
固定播放头、互斥手势、底部属性抽屉、触摸命中区和紧凑轨道高度都需要独立设计。响应式 CSS 只能解决尺寸,不能解决交互模型。
## 九、下一步
Timeline Studio 当前仍在持续完善确定性离线导出、时间线可靠性和浏览器端到端验证。下一阶段计划提供版本化的无头命令执行器,让 Agent 不仅能生成一个不可逆的视频文件,还能交付可继续编辑的 `.timeline` 项目。
长期来看,浏览器端 AI 媒体工具不一定会取代云端工作站,但它已经能覆盖一类很有价值的场景:快速创作、隐私敏感素材、本地模型实验、低成本部署,以及可由 Agent 驱动的结构化编辑。
当编解码、GPU 推理、离线音频和持久存储都成为 Web 平台能力后,“浏览器只是前端”这个前提本身,正在失效。
---
## 参考资料
1. [Timeline Studio GitHub 仓库](https://github.com/MartinDelophy/ai-video-editor)
2. [阿里云开发者社区:走进 Web 多媒体技术](https://developer.aliyun.com/article/1101145)
3. [阿里云开发者社区:专访 W3C WebRTC Chair Bernard Aboba](https://developer.aliyun.com/article/781478)
4. [MDN:WebCodecs API](https://developer.mozilla.org/docs/Web/API/WebCodecs_API)
5. [ONNX Runtime Web 文档](https://onnxruntime.ai/docs/tutorials/web/)
前端开发、WebCodecs、WebGPU、ONNX Runtime、音视频、人工智能、PWA