0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

浏览器视频编辑器如何兼容 MKV?LibAV.js、WebCodecs 与 FFmpeg.wasm 实践

0
Posted at

前言

我们正在开发一款运行在浏览器中的 AI 视频编辑器,支持素材导入、时间线剪辑、字幕、AI 配音、音频处理和视频导出。

早期版本主要支持浏览器原生兼容较好的 MP4 和 WebM。但在真实使用中,用户还会上传 MKV、MOV 等文件,其中可能包含 H.264、H.265、AAC、AC3 等不同编码。它们能在桌面播放器中正常打开,却不一定能被浏览器直接播放。

为此,我们重新设计了媒体导入和导出链路。

一、格式兼容不只是扩展名

MP4、MKV、MOV 和 WebM 是容器,H.264、VP9、AAC 和 AC3 才是音视频编码。

同样是 MKV,内部可能是 H.264 + AAC,也可能是 H.265 + AC3。因此不能只根据文件名判断素材是否可用。导入时需要识别容器、视频编码、音频编码、时长、分辨率和轨道信息。

用户导入文件
    ↓
识别文件签名和容器
    ↓
探测音视频轨道
    ↓
检测浏览器解码能力
    ↓
选择成本最低的处理路径

二、为什么不把所有文件都交给 FFmpeg.wasm?

最直接的方案,是先把所有输入转成 MP4。它兼容性强,但在浏览器中也有明显成本:

  • WebAssembly 运行时较大;
  • 初始化和完整转码需要时间;
  • 原文件、中间数据与输出文件会同时占用内存;
  • 即使原视频已经是 H.264,也可能被重复编码。

因此,我们没有移除 FFmpeg.wasm,而是把它从默认入口调整为兼容回退方案。

三、混合媒体处理架构

目前编辑器采用三层处理方式:

浏览器原生能力
      ↓
LibAV.js + WebCodecs
      ↓
FFmpeg.wasm 兼容回退

浏览器原生路径

对于标准 MP4、WebM 等浏览器可以直接播放的素材,继续使用 video 元素和 Web Audio API。这条路径启动快、内存成本低,适合大多数用户。

LibAV.js + WebCodecs 路径

对于 MKV、MOV 等浏览器不能直接识别的容器,使用 LibAV.js 探测并解封装轨道,再把兼容的视频数据交给 WebCodecs。

例如,一个 MKV 中包含 H.264 视频和 AC3 音频时,可以分别处理:

H.264 视频 → 解封装 → WebCodecs 解码
AC3 音频  → LibAV.js 解码 → PCM/WAV

这样不必为了一个不兼容的音频轨道而重新编码整段视频。

FFmpeg.wasm 回退路径

如果遇到浏览器和 WebCodecs 都无法处理的编码、异常时间戳或特殊像素格式,再通过 FFmpeg.wasm 转码。

核心原则是:能原生处理就不转码,能解封装就不重新编码,只有必要时才走完整转码。

四、性能优化

为了避免扩展格式支持拖慢普通 MP4,我们做了几项调整。

延迟加载

LibAV.js 和 FFmpeg.wasm 不随首屏一起初始化。只有检测到需要兼容处理的文件时才动态加载。

使用 Web Worker

媒体探测、解封装和音频解码会消耗较多 CPU。把这些任务放进 Worker,可以避免阻塞时间线拖动和预览交互。

缓存探测结果

同一个素材的容器、编码、时长和轨道信息只探测一次,缩略图、预览和导出尽量复用结果。

支持任务取消

用户删除素材或关闭项目后,后台探测和解码任务会立即终止,避免继续消耗 CPU 与内存。

五、统一内部媒体模型

支持更多格式后,不能让时间线持续感知 MP4、MKV 和 MOV 的差异。

无论输入是什么格式,最终都会转换成统一的媒体描述,包含素材 ID、容器、时长、视频编码、分辨率、帧率、音频采样率和声道数。格式兼容层负责处理差异,时间线只面对统一的媒体源和时间范围。

这样后续增加新格式时,不需要重写剪辑、字幕与导出模块。

六、简化导出选项

底层能力增加后,我们曾在导出面板中提供编码器、分辨率、帧率、质量等级、关键帧间隔和多种预设。但对大多数用户来说,参数过多反而增加使用成本。

最终主要保留四种组合:

  • MP4 · H.264 + AAC:默认选项,兼容性最好;
  • MOV · H.264 + AAC:方便导入 Final Cut、Premiere 和 DaVinci;
  • WebM · VP9 + Opus:适合网页和较高压缩率;
  • WebM · VP8 + Opus:兼容较旧的 WebM 工作流。

高级参数主要保留视频码率和音频码率。底层能力可以复杂,但产品界面应该简单。

七、修复 5 秒视频导出成 17 秒的问题

改造过程中,我们遇到一个典型问题:浏览器中的时间线只有 5 秒,导出的文件却长达 17 秒。

原因是旧逻辑把“根据脚本文字估算的配音时长”也用于计算导出范围。即使真实时间线只有 5 秒,只要脚本估算为 17 秒,导出器就会继续生成空白帧。

修复后,导出时长只取时间线中真实存在的视觉、字幕、配音、音乐和贴纸轨道终点。

const frameCount = Math.ceil(duration * frameRate);

5 秒、30 fps 的项目应当导出 150 帧,而不是依赖播放状态或脚本预测值。

八、确定性离线渲染

高质量导出采用逐帧离线渲染:

时间线时间戳
    ↓
渲染当前画面
    ↓
WebCodecs 视频编码
    ↓
OfflineAudioContext 混音
    ↓
封装为 MP4、MOV 或 WebM

每一帧都由准确时间戳驱动,因此页面卡顿、后台标签页限速或预览掉帧不会改变最终文件的帧数和时长。MediaRecorder 仍然保留,但主要作为浏览器能力不足时的兼容方案。

九、验证真正的导出结果

导出成功不能只看是否生成了 Blob。自动化测试还会重新读取产物并验证:

  • 容器和编码格式;
  • 视频与音频轨道;
  • 分辨率和总时长;
  • 视频帧数;
  • 字幕与透明贴纸是否出现在画面中;
  • 音频轨道是否真实存在。

相比只判断界面是否显示“导出完成”,重新解析和解码产物更可靠。

总结

浏览器视频编辑器兼容 MKV 和 MOV,并不是简单增加两个扩展名,而是要解决容器探测、编解码能力判断、解封装、音频处理、时间戳和导出验证等一整套问题。

我们的最终选择是:优先浏览器原生处理,必要时使用 LibAV.js + WebCodecs,最后由 FFmpeg.wasm 兼容回退。

这样既保留了普通 MP4 的快速体验,也让 MKV、MOV 等素材有机会直接进入浏览器编辑流程。对于用户来说,最终体验仍然应该简单:上传素材、完成编辑、选择格式并导出。复杂性应该尽可能留在系统内部。

项目地址

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?