浏览器中主线程向WebAssembly Worker线程流式传输视频数据可行性咨询
可行方案:流式传输视频数据到WASM Worker,绕过ArrayBuffer限制
完全可以实现无需创建大尺寸ArrayBuffer的流式传输方案,WASM技术本身支持这种流式处理模式,核心是利用浏览器的流API和FFmpeg WASM的虚拟文件系统能力,以下是具体实现思路:
1. 利用浏览器原生Transferable Streams
现代浏览器支持Transferable Streams,可以直接将文件的ReadableStream所有权转移到Worker线程,无需将整个文件加载到内存:
- 主线程中,从用户选择的File对象获取ReadableStream:
const stream = file.stream(); - 通过
worker.postMessage(stream, [stream])将流转移到Worker(第二个参数是转移列表,避免数据拷贝) - Worker线程接收流后,结合FFmpeg WASM的虚拟文件系统(如MEMFS),将流写入虚拟文件:
主流FFmpeg WASM封装库已原生支持ReadableStream作为输入,内部自动处理流式写入逻辑。// Worker内代码 import { createFFmpeg } from '@ffmpeg/ffmpeg'; const ffmpeg = createFFmpeg({ log: true }); await ffmpeg.load(); self.onmessage = async (e) => { const stream = e.data; // 将流写入虚拟文件系统 await ffmpeg.write('input.mp4', stream); // 执行压缩命令 await ffmpeg.run('-i', 'input.mp4', '-crf', '28', 'output.mp4'); // 处理输出... };
2. 手动分块读取+虚拟文件追加写入
如果需要兼容不支持Transferable Streams的旧浏览器,可以采用分块读取+追加写入的方式:
- 主线程将File对象按固定大小(如64MB)切片,用FileReader读取每个切片的ArrayBuffer,然后通过Transferable Objects转移到Worker:
// 主线程代码 const chunkSize = 64 * 1024 * 1024; // 64MB块 for (let start = 0; start < file.size; start += chunkSize) { const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); const reader = new FileReader(); reader.onload = () => { worker.postMessage({ type: 'chunk', data: reader.result }, [reader.result]); }; reader.readAsArrayBuffer(chunk); } // 发送结束信号 worker.postMessage({ type: 'end' }); - Worker线程接收每个块后,追加写入到虚拟文件系统:
FFmpeg可以直接读取虚拟文件系统中的文件,无需一次性加载整个文件到内存,自然绕过ArrayBuffer的大小限制。// Worker内代码 await ffmpeg.load(); // 初始化空文件 ffmpeg.FS.writeFile('input.mp4', new Uint8Array(0)); self.onmessage = async (e) => { if (e.data.type === 'chunk') { // 追加写入块 ffmpeg.FS.writeFile('input.mp4', new Uint8Array(e.data.data), { append: true }); } else if (e.data.type === 'end') { // 执行压缩 await ffmpeg.run('-i', 'input.mp4', '-crf', '28', 'output.mp4'); // 处理输出... } };
3. 关键注意事项
- 始终使用Transferable Objects传递数据块/流,避免内存拷贝,降低内存占用并提升性能。
- 确保使用的FFmpeg WASM版本支持流式输入或文件追加写入,建议使用最新版的封装库。
- FFmpeg命令无需额外调整,它本身支持读取流式或分块写入的文件。
这种流式处理方案完全可行,能有效解决2GB以上视频的输入限制问题,同时优化内存使用效率。
内容的提问来源于stack exchange,提问作者Fei
相关产品推荐
相关产品推荐

