You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FFmpeg.wasm合并音视频触发Bad Memory错误(Chrome扩展Manifest V2)

问题描述

我正在开发基于Manifest V2的Chrome扩展,功能是获取视频URL与音频URL,通过FFmpeg.wasm(@ffmpeg/ffmpeg v0.9.6、@ffmpeg/core v0.8.5)合并后下载结果。但实际运行时未完成音视频合并,反而抛出Uncaught (in promise) Error: bad memory错误。

相关代码如下:

const onDownloadClickModal = async (event) => {
  const path = getPathInfo(event);
  const [videoUrl, audioUrl] = await getVideoUrl(path);

  let { createFFmpeg, fetchFile } = FFmpeg;
  let ffmpeg = createFFmpeg();
  await ffmpeg.load();
  ffmpeg.FS("writeFile", "video.mp4", await fetchFile(videoUrl));
  ffmpeg.FS("writeFile", "audio.mp4", await fetchFile(audioUrl));
  await ffmpeg.run("-i", "video.mp4", "-i", "audio.mp4", "-c", "copy", "output.mp4");
  let _data = await ffmpeg.FS("readFile", "output.mp4");
  let data = new Uint8Array(_data.buffer);

  const a = document.createElement("a");
  a.href = URL.createObjectURL(new Blob([data], { type: "video/mp4" }));
  a.download = "output.mp4"
  a.click();
  a.remove();
}
window.addEventListener("load", function () {
  if (!crossOriginIsolated) SharedArrayBuffer = ArrayBuffer;
  afterPageLoad();
});

已尝试的方案:

  • 参考使用同版本FFmpeg.wasm的用户代码;
  • 通过替换SharedArrayBuffer为ArrayBuffer解决其未定义问题;
  • 尝试添加跨域头Cross-Origin-Embedder-Policy: require-corp和Cross-Origin-Opener-Policy: same-origin,但Chrome扩展场景下无法生效。
解决方案

1. 显式分配足够内存

旧版本FFmpeg.wasm默认内存配额不足以处理较大的音视频文件,创建实例时手动指定更大内存:

let ffmpeg = createFFmpeg({
  mem: 4 * 1024 * 1024 * 1024, // 分配4GB内存,可根据文件大小调整
  log: true // 开启日志,方便排查执行过程中的问题
});

2. 禁用多线程绕开SharedArrayBuffer依赖

直接替换SharedArrayBuffer为ArrayBuffer会破坏FFmpeg.wasm的内存管理逻辑,改为在创建实例时禁用多线程,同时显式指定本地核心文件路径(避免扩展内跨域加载问题):

let ffmpeg = createFFmpeg({
  corePath: chrome.runtime.getURL('ffmpeg-core.js'), // 确保核心文件已打包进扩展,路径自行调整
  worker: false, // 禁用多线程,无需依赖SharedArrayBuffer
  log: true
});

3. 优化文件读取逻辑

Chrome扩展环境下直接使用fetchFile可能存在内存溢出或跨域问题,改用原生fetch转为ArrayBuffer后写入:

// 自定义fetch转ArrayBuffer函数
const getFileBuffer = async (url) => {
  const res = await fetch(url, { mode: 'cors' });
  return new Uint8Array(await res.arrayBuffer());
};

// 写入FFmpeg文件系统
ffmpeg.FS("writeFile", "video.mp4", await getFileBuffer(videoUrl));
ffmpeg.FS("writeFile", "audio.mp4", await getFileBuffer(audioUrl));

4. 调整FFmpeg合并命令

添加-y参数自动覆盖输出文件,同时明确映射音视频流,避免流匹配错误:

await ffmpeg.run(
  "-y", // 自动覆盖已存在的output.mp4
  "-i", "video.mp4",
  "-i", "audio.mp4",
  "-c:v", "copy", "-c:a", "copy", // 分别指定音视频编码复制
  "-map", "0:v:0", "-map", "1:a:0", // 映射第一个输入的视频流和第二个输入的音频流
  "output.mp4"
);

5. 及时清理内存避免泄漏

合并完成后清理临时文件并退出FFmpeg实例,释放占用的内存:

// 下载完成后执行清理
ffmpeg.FS("unlink", "video.mp4");
ffmpeg.FS("unlink", "audio.mp4");
ffmpeg.FS("unlink", "output.mp4");
ffmpeg.exit();

内容的提问来源于stack exchange,提问作者Ralkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 23:48:26