ffmpeg.wasm的使用教程

Posted apades

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ffmpeg.wasm的使用教程相关的知识,希望对你有一定的参考价值。

安装

首先肯定得先安装ffmpeg.wasm到项目中

yarn add @ffmpeg/ffmpeg @ffmpeg/core

在web使用时最好使用ffmpeg/@ffmpeg/dist/ffmpeg.min.js,因为这个包默认环境是node,打包出的是web,或者去看看怎么配置webpack等打包工具

启动

这个wasm需要使用SharedArrayBuffer api,服务器的response header必须有2个字段

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

如果再需要是本地测试,ffmpeg.wasm提供了以下服务器的脚本

const express = require('express');
const app = express();

app.use((_, res, next) => 
  res.header('Cross-Origin-Opener-Policy', 'same-origin');
  res.header('Cross-Origin-Embedder-Policy', 'require-corp');
  next();
);

app.use(express.static('./'));

const PORT = process.env.PORT || 8080;

app.listen(PORT, () => 
  console.log(`Server listening on port $PORT...`);
);

api

首先创建一个ffmpeg实例

import FFmpeg from 'ffmpeg/@ffmpeg/dist/ffmpeg.min.js'
// 加载外部核心文件
const ffmpeg = FFmpeg.createFFmpeg(
   corePath: 'node_modules/@ffmpeg/core/dist/ffmpeg-core.js',
   log: true
);

; (async () => 
	// 等待ffmpeg加载完成
   	await ffmpeg.load()
)()

加载完后ffmpeg主要用3个方法,这里关联性比较强就放一起了

// 创建视频,传入的必须是uni8类型
ffmpeg.FS('writeFile', 'input_v.webm', await readAsUni8(file_v))
// 命令运行,和本地方式一样
await ffmpeg.run('-i','input_v.webm', '-c','copy','output_v_cp.mp4')
// 读取视频数据
let outputData = ffmpeg.FS('readFile', 'output_v_cp.mp4')
let src = URL.createObjectURL(
    new Blob([outputData.buffer], 
        type: "video/mp4"
    )
);
// 删除视频
ffmpeg.FS('unlink', 'output_v_cp.mp4')

目前ffmpeg.FS就只有上面3个命令,以上就是基本用法了

chrome extension使用

这个相对麻烦一点

  1. 博主manifest为2.0,在里面加上"content_security_policy": "script-src 'self' 'unsafe-eval' ; object-src 'self';"这段,这样视频处理放在background就可以进行了
  2. 然后不太需要安装@ffmpeg/ffmpeg,除非你需要import type。你需要去把ffmpeg.wasm仓库clone下来,修改src\\browser\\getCreateFFmpegCore.js里的toBlobURL方法,不要让他转blobUrl输出,打包出来就能用了

最后想说的

真的很慢!!!!!!!ffmpeg.exe -i input.webm -ss 3 -to 20 -async 1 cut.webm 这个在页面上跑半天,2k以上跑还会出问题跑不了,但这个就很快了还能支持2k以上ffmpeg.exe -i input.webm -ss 3 -t 17 -async 1 -strict -2 -c:v copy -c:a copy cut.webm。总之性能坑很多,很多本地很快的命令在web上不一定很快,还需要找不同命令优化

纯前端实现音视频合成

通常,可能有纯视频与纯音频进行合成的需求,可以借助借助 ffmpeg.wasm 来实现。

关于 ffmpeg.wasm

FFmpeg 是C/C++编写的,是整个软件界非常著名的音视频等流媒体处理工具,非常强大。因为WebAssembly,ffmpeg.wasm 则是 FFmpeg 在浏览器中运行的版本。WebAssembly的兼容性如下:

由于要想使用 ffmpeg,需要引入ffmpeg.min.js,ffmpeg.min.js会去加载同源目录下 ffmpeg-core 资源,虽然也有CDN,但是毕竟都是外网,速度堪忧:

  • ffmpeg-core.js
  • ffmpeg-core.worker.js
  • ffmpeg-core.wasm (22.4M)

如何使用:

<script src="./ffmpeg.min.js"></script>
<script>
const  createFFmpeg, fetchFile  = FFmpeg;
const ffmpeg = createFFmpeg(
    corePath: "./ffmpeg-core.js",
    log: true,
);
// ...
</script>

视频与音频合成

首先在页面上创建一个 video 元素:

<video id="player" controls height="344" width="412"></video>

1. 单音频与视频合成实现

<script src="./ffmpeg.min.js"></script>
<script>
const  createFFmpeg, fetchFile  = FFmpeg;
const ffmpeg = createFFmpeg(
    corePath: "./ffmpeg-core.js",
    log: true,
);
(async () => 
    await ffmpeg.load();
    
    const dataInputVideo = await fetchFile('bj.mp4');
    const dataInputAudio = await fetchFile('record.mp3');

    ffmpeg.FS('writeFile', 'bj.mp4', dataInputVideo);
    ffmpeg.FS('writeFile', 'record.mp3', dataInputAudio);
    
    /** ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a:0 output.mp4 */
    await ffmpeg.run('-i', 'bj.mp4', '-i', 'record.mp3', '-c:v', 'copy', '-c:a', 'aac', '-strict', 'experimental', '-map', '0:v:0', '-map', '1:a:0', 'output.mp4');
    
    const data = ffmpeg.FS('readFile', 'output.mp4');
    const video = document.getElementById('player');
    video.src = URL.createObjectURL(new Blob([data.buffer],  type: 'video/mp4' ));
)();
</script>

 2. 视频指定位置合成多音频实现

(async () => 
    await ffmpeg.load();

    const dataInputVideo = await fetchFile('zhangxinxu.mp4');
    const dataInputAudio1 = await fetchFile('1.mp3');
    const dataInputAudio2 = await fetchFile('2.mp3');
    const dataInputAudio3 = await fetchFile('3.mp3');
    const dataInputAudio4 = await fetchFile('4.mp3');

    ffmpeg.FS('writeFile', 'zhangxinxu.mp4', dataInputVideo);
    ffmpeg.FS('writeFile', '1.mp3', dataInputAudio1);
    ffmpeg.FS('writeFile', '2.mp3', dataInputAudio2);
    ffmpeg.FS('writeFile', '3.mp3', dataInputAudio3);
    ffmpeg.FS('writeFile', '4.mp3', dataInputAudio4);

    await ffmpeg.run('-i', 'input.mp4', '-i', '1.mp3', '-i', '2.mp3', '-i', '3.mp3', '-i', '4.mp3',     
    '-filter_complex', '[1]adelay=2000|2000[aout1];[2]adelay=10000|10000[aout2];[3]adelay=15000|15000[aout3];[4]adelay=20000|20000[aout4];[aout1][aout2][aout3][aout4]amix=4[aout]',
    '-c:v', 'copy', '-c:a', 'aac', '-strict', 'experimental', '-map', '0:v:0', '-map', '[aout]', 'output.mp4');
    
    const data = ffmpeg.FS('readFile', 'output.mp4');
    const video = document.getElementById('player');
    video.src = URL.createObjectURL(new Blob([data.buffer],  type: 'video/mp4' ));
)();


adelay 表示 audio 插入位置的延时,管道符写法表示不同声道的延时。如果同时延时,管道符前后时间设为一样。

amix表示合并,多个音频合成一个。

总结

ffmpeg.wasm 的核心文件 ffmpeg-core 的体积的确有点大,就算Gzip为7M多。要想在用户侧使用,估计要么让用户首次安装 ffmpeg.wasm 插件,体验才可以。

以上是关于ffmpeg.wasm的使用教程的主要内容,如果未能解决你的问题,请参考以下文章

用WebAssembly在浏览器中对视频进行转码

如何在 ReactJS 项目中使用 ffmpeg.js

web前端教程视频教程在哪可以看?

web前端视频教程全集在哪下载?

视频教程webpack3.x视频教程 全网首发

视频分享Twitter前端CSS框架Bootstrap视频教程