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

在@ffmpeg/ffmpeg Worker中重构流式视频分片问题求助

问题解决:基于@ffmpeg/ffmpeg重构网络流视频

问题1:后续分片报无效数据的原因及修复

原因

你当前从response.body读取的value是HTTP传输的分块数据,并非视频本身的独立分片。第一个"分片"恰好包含视频文件的完整文件头(如MP4的ftyp/moov段),所以FFmpeg能识别;但后续的HTTP分块仅为文件的部分数据,没有完整的文件结构,因此触发Invalid data found错误。

修复方案

先将所有HTTP分块合并为完整的二进制文件,再传入FFmpeg处理:

// 修改流式获取视频的代码
await useFetch(Capacitor.convertFileSrc(file.path), {
  responseType: "stream",
  onResponse: async ({ response }) => {
    if (response.body) {
      const reader = response.body.getReader();
      const chunks = [];
      let totalLength = 0;

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        chunks.push(value);
        totalLength += value.length;
      }
      reader.releaseLock();

      // 合并所有HTTP分块为完整二进制文件
      const completeFile = new Uint8Array(totalLength);
      let offset = 0;
      for (const chunk of chunks) {
        completeFile.set(chunk, offset);
        offset += chunk.length;
      }
      file.completeFile = completeFile; // 用完整文件替代分块数组
    }
  },
});
// 修改文件写入代码
const constructFile = async (completeFile: Uint8Array, queueId: number) => {
  const fullFileName = `video-${queueId}_complete`;
  await ffmpeg.writeFile(fullFileName, completeFile);
  
  // 验证文件有效性
  await ffmpeg.exec(["-i", fullFileName]);
};

问题2:真正视频分片的合并方法

如果你的场景是处理独立的视频分片文件(如HLS的.ts分片),而非HTTP传输分块,可使用FFmpeg的concat解复用器高效合并:

  1. 生成分片列表文件
// 生成包含所有分片路径的文本文件
const chunkListContent = chunks.map((_, index) => `file 'video-${queueId}_chunk-${index}'`).join('\n');
await ffmpeg.writeFile(`chunk-list-${queueId}.txt`, chunkListContent);
  1. 执行合并命令
// 合并分片并输出完整视频(直接复制流,无重新编码)
await ffmpeg.exec([
  "-f", "concat",
  "-safe", "0",
  "-i", `chunk-list-${queueId}.txt`,
  "-c", "copy",
  `output-${queueId}.mp4`
]);

注意:该方法要求所有分片的编码参数(分辨率、码率、格式)完全一致;若参数不一致,需移除-c copy,让FFmpeg重新编码。

大视频处理替代方案:流式写入FFmpeg

若视频文件过大,合并成完整Uint8Array会占用过多内存,可直接将响应流传给FFmpeg,无需加载到内存:

await useFetch(Capacitor.convertFileSrc(file.path), {
  responseType: "stream",
  onResponse: async ({ response }) => {
    if (response.body) {
      const fullFileName = `video-${queueId}_complete`;
      // 直接将响应流写入FFmpeg
      await ffmpeg.writeFile(fullFileName, response.body);
      
      // 后续处理完整视频
      await ffmpeg.exec(["-i", fullFileName, "-c", "copy", `output-${queueId}.mp4`]);
    }
  },
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:12:02