ffmpeg.wasm纯前端实现音、视频处理

ffmpeg.wasm纯前端实现音、视频处理

2024年10月30日 阅读:25 字数:997 阅读时长:3 分钟

借助FFmpeg的WebAssembly在web端实现音频、视频的格式转换、流传输、裁剪合并等处理。

FFmpeg 是整个软件界非常著名的音视频等流媒体处理工具,ffmpeg.wasm是FFmpeg的纯WebAssembly(因为WebAssembly,让很多传统语言的工具也能在浏览器中运行) / JavaScript实现,可以直接在浏览器中进行视频和音频录制、转换和流传输。

概念

FFmpeg 本身是一个庞大的项目,包含许多组件和库文件,最常用的是它的命令行工具。ffmpeg.wasm 运行也需要知道一些常用的命令行。

FFmpeg 的命令行参数非常多,可以分成五个部分

ffmpeg {1} {2} -i {3} {4} {5}

上面命令中,五个部分的参数依次如下:

  1. 全局参数
  2. 输入文件参数
  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

4b5da75375f6dc10.png

在使用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-PolicyCross-Origin-Opener-Policy

拿vite dev server举例

export default {
  server: {
    headers: {
      "Cross-Origin-Embedder-Policy": "require-corp",
      "Cross-Origin-Opener-Policy": "same-origin",
    }
  }
}

 

参考资料:

推荐阅读

恰饭区

评论区 (0)

0/500

还没有评论,快来抢第一吧