多线程
ffmpeg.wasm 中的多线程功能使 FFmpeg 能够通过 Web Worker 利用多个 CPU 核心进行并行处理,显著提高了资源密集型视频和音频处理任务的性能。本指南介绍了如何使用 ffmpeg.wasm 的多线程版本、其要求以及重要注意事项。
有关 ffmpeg.wasm 基本用法的详细信息,请参阅 基本用法。有关 FFmpeg Core Module 架构的详细信息,请参阅 FFmpeg Core Module。
ffmpeg.wasm 中的多线程概述
ffmpeg.wasm 提供了两种不同的核心实现:
- 单线程核心 (
@ffmpeg/core):在单个 worker 线程中运行的默认核心 - 多线程核心 (
@ffmpeg/core-mt):利用多个 Web Worker 进行并行处理的增强型核心
使用多线程版本 (@ffmpeg/core-mt) 时,FFmpeg 核心会启动额外的 web workers 来处理并行处理任务。这是通过 Emscripten 的 pthreads 实现实现的,使其能够同时利用多个 CPU 核心。
多线程的要求
使用多线程版本需要特定的浏览器特性和安全配置:
- SharedArrayBuffer 支持:浏览器必须支持
SharedArrayBuffer,它实现了线程间的高效内存共享。 - 跨源隔离 (Cross-Origin Isolation):您的应用程序必须是跨源隔离的。这需要特定的 HTTP 头:
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp
- workerURL 参数:与单线程版本不同,调用
load()时必须提供workerURL以指向多线程 worker 脚本
如果未满足这些要求,多线程版本将无法工作,因为 SharedArrayBuffer 仅在跨源隔离上下文中可用。
服务器配置
为了启用多线程所需的跨源隔离,您的服务器必须发送适当的 HTTP 头。以下是 vanilla-app 示例中使用的配置:
app.use((_, res, next) => {
res.set({
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Resource-Policy": "cross-origin",
"Origin-Agent-Cluster": "?1",
"Access-Control-Allow-Origin": "*",
});
next();
});这些头信息告诉浏览器您的页面需要跨源隔离,这对于 SharedArrayBuffer 正常运行是必要的。
架构
ffmpeg.wasm 的多线程架构由几个协同工作的组件组成:
多线程系统架构
多线程数据流
使用多线程版本
要使用多线程版本,您必须将 load() 方法指向 @ffmpeg/core-mt 资源。请注意,如果您使用的是 Vite 等构建工具,应使用 esm 分发版。
import { FFmpeg } from "@ffmpeg/ffmpeg";
import { toBlobURL } from "@ffmpeg/util";
const ffmpeg = new FFmpeg();
const load = async () => {
const baseURL = "https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm";
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"),
});
};性能和限制
PTHREAD_POOL_SIZE
多线程核心通常以固定的线程池大小编译(例如 PTHREAD_POOL_SIZE=32)。这决定了核心可以启动用于处理并行 FFmpeg 任务的 Web Workers 的最大数量。
性能优势
| 操作 | 优势 |
|---|---|
| x264/x265 编码 | 高(多线程帧/宏块编码) |
| 视频解码 | 中等至高(取决于编解码器支持) |
| 复杂滤镜 | 高(并行滤镜图执行) |
权衡
- 初始化时间:启动 worker 池比初始化单线程核心花费更多时间。
- 内存使用:
SharedArrayBuffer需要预先分配固定内存,且每个 worker 都有自己的栈。 - 复杂性:需要严格的 COOP/COEP 头,如果处理不当,可能会破坏第三方集成(如某些 OAuth 流程或 CDN)。
测试多线程
该仓库包含针对多线程的自动化测试。这些测试在headless Chrome环境中执行,并带有特定标志以启用隔离功能。
# Example CI test execution for MT
npx mocha-headless-chrome \
--args="--headless --disable-gpu --no-sandbox --enable-features=SharedArrayBuffer,CrossOriginIsolation" \
-a no-sandbox \
-f http://localhost:3000/tests/ffmpeg-core-mt.test.html您可以编程验证环境:
console.log('SharedArrayBuffer available:', typeof SharedArrayBuffer !== 'undefined');
console.log('crossOriginIsolated:', window.crossOriginIsolated);