基于FFmpeg和Wasm的Web端视频截帧方案

导读

基于实际业务需求,介绍了自定义Wasm截帧方案的实现原理和实现方案。解决传统的基于canvas的截帧方案所存在的问题,更高效灵活的实现截帧能力。

全文10103字,预计阅读时间26分钟。

一、项目背景

在视频编辑器里常见这样的功能,在用户上传完视频后抽取关键帧 ,提供给用户以便快捷选取封面,如下图:

在本文中,我们将探讨一种使用FFmpeg和WebAssembly(Wasm)的Web端视频截帧方案,以解决传统的基于canvas的截帧方案所存在的问题。通过采用这种新方法,我们可以克服video标签的限制,实现更高效、更灵活的视频截帧功能。

首先,我们需要了解一下传统的Web截帧方案的局限性。虽然该方案在处理一些常见的视频格式(如MP4、WebM和OGG)时表现良好,但其存在以下缺陷:

  • 类型有限:video标签支持的视频格式十分有限,无法处理一些其他常见的视频格式,如FLV、MKV和AVI等。
  • DOM依赖:该方案依赖于DOM,只能在主线程中完成。这意味着在处理大量截帧任务时,可能会对页面性能产生负面影响。
  • 抽帧策略局限:传统方案无法精确控制抽帧策只能传递时间交给浏览器,设置currentTime时会解码寻找最接近的帧,而非关键帧。

为解决上述问题,选取FFmpeg+Wasm的方案,通过自定义编译FFmpeg,在web-worker里执行rgb24格式数据到ImageData的运算,再传递结果给主线程,实现。

二、Wasm核心原理

2.1 Wasm是什么

用官网的话说,WebAssembly(缩写为Wasm)是一种用于基于堆栈的虚拟机的二进制指令格式。

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.
---  https://webassembly.org/

Wasm 可以看作一种容器技术,它定义了一种独立的、可移植的虚拟机,可以在各种平台上执行,类比于docker,但更为轻量。WebAssembly 于2017年粉墨登场,2019年12月正式认证为Web标准之一并被推荐,拥有高性能、跨平台、安全性、多语言高可移植等优势。

业界有很多Wasm虚拟机的实现,包含解释器,单层/多层AOT、JIT模式。

2.2 chrome如何运行Wasm

浏览器内置JIT引擎,V8使用了分层编译模式(Tiered)来编译和优化 WASM 代码。分层编译模式包括两个主要的编译器:

  1. 基线编译器(Baseline compiler) Liftoff编译器
  2. 优化编译器(Optimizing compiler) TurboFun编译器

2.2.1 Liftoff 编译器

当 WASM 代码首次加载时,V8 使用 Liftoff 编译器进行快速编译。Liftoff 是一个线性时间编译器,它可以在极短的时间内为每个 WASM 指令生成机器代码。这意味着,它可以尽快地生成可执行代码,从而缩短代码加载时间。

然而,Liftoff 编译器的优化空间有限。它采用一种简单的一对一映射策略,将 WASM 指令独立地转换为机器代码,而不进行任何高级优化。这使得生成的代码性能较低。

2.2.2 TurboFan 编译器

对于那些被频繁调用的热函数(Hot Functions),V8 会使用 TurboFan 编译器进行优化编译。TurboFan 是一个更高级的编译器,能够执行各种复杂的优化技术,如内联缓存(Inline Caching)、死代码消除(Dead Code Elimination)、循环展开(Loop Unrolling)和常量折叠(Constant Folding)等,从而显著提高代码的运行效率。

V8 会监控 WASM 函数的调用频率。一旦一个函数达到特定的阈值,它就会被认为是Hot,并在后台线程中触发重新编译。在优化编译完成后,新生成的 TurboFan 代码会替换原有的 Liftoff 代码。之后对该函数的任何新调用都将使用 TurboFan 生成的新的优化代码,而不是 Liftoff 代码。

2.2.3 流式编译与代码缓存

V8 引擎支持流式编译(Streaming Compilation),这意味着 WASM 代码可以在下载的同时进行编译。这大大缩短了从加载到可执行的总时间。流式编译在基线编译阶段(Liftoff 编译器)尤为重要,因为它可以确保 WASM 代码在最短的时间内变得可运行。

为了进一步提高性能和加载速度,V8 引擎支持代码缓存(Code Caching)机制。代码缓存可以将编译后的 WASM 代码存储在缓存中,以便在将来需要时直接从缓存中加载,而无需重新编译。这大大缩短了页面加载时间,提高了用户体验。目前WebAssembly 缓存仅针对流式 API 调用, compileStreaming 和 instantiateStreaming 这两个API,使用流式API拥有更好的性能。对于缓存的工作原理:

  1. 当TurboFan完成编译后,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值