FFmpeg 是整个软件界非常著名的音视频等流媒体处理工具,ffmpeg.wasm是FFmpeg的纯WebAssembly(因为WebAssembly,让很多传统语言的工具也能在浏览器中运行) / JavaScript实现,可以直接在浏览器中进行视频和音频录制、转换和流传输。
概念
FFmpeg 本身是一个庞大的项目,包含许多组件和库文件,最常用的是它的命令行工具。ffmpeg.wasm 运行也需要知道一些常用的命令行。
FFmpeg 的命令行参数非常多,可以分成五个部分
ffmpeg {1} {2} -i {3} {4} {5}
上面命令中,五个部分的参数依次如下:
- 全局参数
- 输入文件参数
- 输入文件
- 输出文件参数
- 输出文件
常用的命令行参数:
-c
:指定编码器-c copy
:直接复制,不经过重新编码(这样比较快)-c:v
:指定视频编码器-c:a
:指定音频编码器-i
:指定输入文件-an
:去除音频流-vn
: 去除视频流-preset
:指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。-y
:不经过确认,输出时直接覆盖同名文件。
使用方法
了解了FFmpeg的命令行,那么就可以用ffmpeg.wasm的exec
方法运行传递参数,示例如下:
import { FFmpeg } from '@ffmpeg/ffmpeg'
import { fetchFile, toBlobURL } from '@ffmpeg/util'
const baseURL = 'https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm' // 多线程版本
// const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/esm' // 单线程版本
const ffmpeg = new FFmpeg()
async function transcode() {
ffmpeg.on('log', (log) => {
// 控制台输出
console.log(log.message)
})
ffmpeg.on('progress', ({ progress }) => {
// 处理进度
console.log(progress)
})
// 加载资源文件
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')
})
await ffmpeg.writeFile('test.avi', await fetchFile(视频地址))
await ffmpeg.exec(['-i', 'test.avi', 'test.mp4'])
const data = await ffmpeg.readFile('test.mp4')
const output = URL.createObjectURL(new Blob([(data as Uint8Array).buffer], { type: 'video/mp4' }))
console.log(output)
}
转换格式
demo:音频转换 - 一个安全免费的工具箱
// ffmpeg -i test.avi test.mp4
ffmpeg.exec(['-i', 'test.avi', 'test.mp4'])
只是转一下容器,内部的编码格式不变,所以使用-c copy
指定直接拷贝,不经过转码
// ffmpeg -i input.mp4 -c copy output.webm
ffmpeg.exec(['-i', 'input.mp4', '-c', 'copy', 'output.webm'])
转换编码
转换编码格式指的是, 将文件从一种编码转成另一种编码。比如视频转成 H.264 编码,一般使用编码器libx264
,所以只需指定输出文件的视频编码器即可。
// ffmpeg -i input.mp4 -c:v libx264 output.mp4
ffmpeg.exec(['-i', 'input.mp4', '-c:v', 'libx264', 'output.mp4'])
改变分辨率
从 1080p 转为 480p
// ffmpeg -i input.mp4 -vf scale=480:-1 output.mp4
ffmpeg.exec(['-i', 'input.mp4', '-vf', 'scale=480:-1', 'output.mp4'])
裁剪
截取原始视频里面的一个片段,输出为一个新视频。可以指定开始时间(start)和持续时间(duration),也可以指定结束时间(end)。
时间格式:00:01:50代表1分50秒, 15.2代表15.2秒
ffmpeg -ss 00:01:50 -i input.mp4 -t 10 -c copy output.mp4 // 持续时间
ffmpeg -ss 0 -i input.mp4 -to 15 -c copy output.mp4 // 结束时间
ffmpeg还支持很多功能,比如码率调整、截图、音轨处理、音视频合并等等,部分操作命令行参数会比较复杂,留个坑:等我开发完在线处理的工具再一一补充。
工具体验:https://app.timelessq.com/media
常见问题
- worker.js is not found
vue3+vite 项目,安装0.12的版本,本地跑项目的时候,出现worker.js找不到,如下 "node_modules/.vite/deps/worker.js?type=module&worker_file" is not found
解决方法:
在vite的配置文件中添加以下配置
export default {
optimizeDeps: {
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
}
}
- SharedArrayBuffer is not defined
在使用ffmpeg.wasm的多线程@ffmpeg/core-mt
版本,从CDN加载ffmpeg-core.js
等资源的时候会报错,因为SharedArrayBuffer 仅适用于跨源隔离的页面,所以需要设置Cross-Origin-Embedder-Policy: require-corp
和 Cross-Origin-Opener-Policy: same-origin
头才能使用 ffmpeg.wasm。
方法一:
使用单线程的版本@ffmpeg/core
方法二:
在服务器响应头中添加Cross-Origin-Embedder-Policy
、Cross-Origin-Opener-Policy
拿vite dev server举例
export default {
server: {
headers: {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
}
}
}
参考资料:
还没有评论,快来抢第一吧