Posted in

从外网爆??的视频压缩工具说起-FFmpeg.wasm – 掘金_AI阅读总结 — 包阅AI

包阅导读总结

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

前言

炸裂!💥🔥 《硅谷》压缩技术好像现世了!!!将视频压缩 80~90% 几乎不损失效果?基于 FF.gif

工具地址:tools.rotato.app/compress

最近有一个视频压缩网站忽然爆火外网,据说能够将视频压缩到原视频的10~20%,而且几乎不损失清晰度,不影响视频播放效果。

这个工具无需注册,可以免费使用;视频处理我们一般都会使用FFmpeg,这个工具也不例外,官方说明了是基于FFmpeg的:

image.png

但是如果是服务端调用FFmpeg,那网站的开发者真是大善人了,查看网站的请求,发现:

image.png

该网站是使用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的资源代替umdunpkg.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,都是真金白银,而且如果服务器资源有限,会出现排队等待的情况。

而如果是在浏览器端执行就能避免上述问题,而且并不是所有操作都是耗时的,有些操作比如:

  1. 格式转换:当使用 -c copy 选项进行容器格式转换而无需重新编码时,操作会非常快。
  2. 视频裁剪:使用 -ss(开始时间)和 -t(持续时间)选项来裁剪视频片段时,如果视频已经被解码到内存中,这个操作可以很快完成。
  3. 音频提取:从视频中提取音频流(例如,使用 -vn 忽略视频并复制音频流)通常很快,尤其是当音频编码不需要重新编码时。

总结

FFmpeg.wasm存在着很多问题,但是它的存在让前端能够具有完备的音视频处理的能力;尽管性能比较差,至少已经解决了有没有的问题,Web可以根据自己的具体的业务使用相关功能,所以:

Fabrice Bellard牛逼