包阅导读总结
1. 关键词:FFmpeg.wasm、视频压缩、浏览器端、音视频处理、性能差距
2. 总结:
– 外网爆火的视频压缩网站基于 FFmpeg.wasm,能大幅压缩视频且几乎不损清晰度。
– 介绍了 FFmpeg.wasm 在浏览器端的使用方法,包括加载资源、处理文件等步骤。
– 提到多线程版本虽快但存在问题,且性能与 C 语言版 FFmpeg 有差距。
– 强调其虽有不足,但让前端有了音视频处理能力。
3. 主要内容:
– 外网爆火的视频压缩网站
– 能将视频压缩到原大小的 10 – 20%,几乎不损失清晰度,不影响播放效果。
– 工具地址:tools.rotato.app/compress
– FFmpeg.wasm 介绍
– 是基于 WebAssembly 技术,可在浏览器中运行 FFmpeg 命令行工具实现音视频处理的库。
– 在浏览器端使用
– 安装相关类库:npm install @ffmpeg/ffmpeg @ffmpeg/util
– 核心流程包括加载资源、写入处理文件、执行命令、获取处理完成的文件。
– 多线程处理
– 多线程版本比单线程快 2 倍左右。
– 使用时需修改引用资源并引入 workerURL,页面 Header 需添加特定设置。
– 存在如在 Chrome 中无法执行命令等问题。
– 性能对比
– 与 C 语言版本的 FFmpeg 有 10 – 20 倍性能差距。
– 总结
– 虽有问题,但让前端具备音视频处理能力,可根据具体业务使用相关功能。
思维导图:
文章地址:https://juejin.cn/post/7401027594231431208
文章来源:juejin.cn
作者:x007xyz
发布时间:2024/8/10 8:29
语言:中文
总字数:1578字
预计阅读时间:7分钟
评分:91分
标签:视频压缩,FFmpeg.wasm,WebAssembly,浏览器端处理,性能优化
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
前言
工具地址:tools.rotato.app/compress
最近有一个视频压缩网站忽然爆火外网,据说能够将视频压缩到原视频的10~20%,而且几乎不损失清晰度,不影响视频播放效果。
这个工具无需注册,可以免费使用;视频处理我们一般都会使用FFmpeg
,这个工具也不例外,官方说明了是基于FFmpeg
的:
但是如果是服务端调用FFmpeg
,那网站的开发者真是大善人了,查看网站的请求,发现:
该网站是使用FFmpeg.wasm
在浏览器端进行视频压缩的,这样消耗的就是客户端的计算资源,也没有上传下载文件的需求了。
FFmpeg.wasm
FFmpeg
是一个音视频处理的C语言工具库,市面上几乎所有音视频处理软件都是基于FFmpeg
实现的;而FFmpeg.wasm
是一个基于WebAssembly
技术实现的,可以在浏览器中运行 FFmpeg 命令行工具,实现音视频处理功能的库。
在浏览器端使用
使用FFmpeg.wasm
其实比较简单,首先安装相关类库:
npm install @ffmpeg/ffmpeg @ffmpeg/util
然后使用官方的示例代码
function() { const [loaded, setLoaded] = useState(false); const ffmpegRef = useRef(new FFmpeg()); const videoRef = useRef(null); const messageRef = useRef(null); const load = async () => { const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd' const ffmpeg = ffmpegRef.current; ffmpeg.on('log', ({ message }) => { messageRef.current.innerHTML = message; console.log(message); }); await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'), wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'), }); setLoaded(true); } const transcode = async () => { const ffmpeg = ffmpegRef.current; await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm')); await ffmpeg.exec(['-i', 'input.webm', 'output.mp4']); const data = await ffmpeg.readFile('output.mp4'); videoRef.current.src = URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'})); } return (loaded ? ( <> <video ref={videoRef} controls></video><br/> <button onClick={transcode}>Transcode webm to mp4</button> <p ref={messageRef}></p> <p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p> </> ) : ( <button onClick={load}>Load ffmpeg-core (~31 MB)</button> ) );}
官方提供的是一个React
的示例,核心流程为:
第1步,调用load方法加载相关资源:
await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'), wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),});
第2步,写入需要处理的文件
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
第3步,执行命令
await ffmpeg.exec(['-i', 'input.webm', 'output.mp4']);
第4步,获取处理完成的文件
const data = await ffmpeg.readFile('output.mp4');
需要注意:如果使用vite构建项目需要使用
esm
的资源代替umd
unpkg.com/@ffmpeg/cor…=>unpkg.com/@ffmpeg/cor…
多线程处理
FFmpeg.wasm
提供单线程和多线程两个版本,官方表示多线程版本会比单线程版本快2倍左右;使用多线程版本的流程如下:
首先,修改引用的资源,并且需要额外引入workerURL
:
await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'), wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'), workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),});
其次,多线程版本使用到SharedArrayBuffer,采用 SharedArrayBuffer,需要页面 Header 添加
Cross-Origin-Embedder-Policy: require-corpCross-Origin-Opener-Policy: same-origin
但是,在实际使用多线程版本的过程还存在其他问题:
在Chrome浏览器中无法执行命令,并且没有错误提示
具体现象为在执行第一帧之后就卡住,同时也不报错,官方有多个相关issue,并且一直没有关闭;可能原因是 wasm 采用的线程数量过大,使得其使用的内存超过 chrome 的限制,导致无法执行;不过无法判断 wasm 是否是通过navigator.hardwareConcurrency
(用户计算机的处理器数)来确定线程数量。
部分用户通过添加线程控制,比如-threads 4
,就可以顺利执行多线程指令;但是有部分还是反馈无法执行。
所以:
谨慎使用多线程版本
性能对比
# | FFmpeg | core v0.12.3 | core-mt v0.12.3 |
---|---|---|---|
Avg | 5.2 sec | 128.8 sec (0.04x) | 60.4 sec (0.08x) |
Max | 5.3 sec | 130.7 sec | 63.9 sec |
Min | 5.1 sec | 126.6 sec | 59 sec |
相较于C语言版本的FFmpeg
,无论是单核还是多核版本的FFmpeg.wasm
都远远不如,存在着10-20倍的性能差距。
但是在Web端,如果使用服务端调用FFmpeg
的方式处理视频,存在消耗服务器资源、消耗带宽,这些可都是money,都是真金白银,而且如果服务器资源有限,会出现排队等待的情况。
而如果是在浏览器端执行就能避免上述问题,而且并不是所有操作都是耗时的,有些操作比如:
- 格式转换:当使用 -c copy 选项进行容器格式转换而无需重新编码时,操作会非常快。
- 视频裁剪:使用 -ss(开始时间)和 -t(持续时间)选项来裁剪视频片段时,如果视频已经被解码到内存中,这个操作可以很快完成。
- 音频提取:从视频中提取音频流(例如,使用 -vn 忽略视频并复制音频流)通常很快,尤其是当音频编码不需要重新编码时。
总结
FFmpeg.wasm
存在着很多问题,但是它的存在让前端能够具有完备的音视频处理的能力;尽管性能比较差,至少已经解决了有没有的问题,Web可以根据自己的具体的业务使用相关功能,所以:
Fabrice Bellard牛逼