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

Node.js child_process调用ffmpeg报错:TypeError: Cannot read property '_writableState' of undefined

解决Node.js child_process调用ffmpeg时的TypeError: Cannot read property '_writableState' of undefined问题

我一眼就看出问题出在你处理ffmpeg.stdin.write的方式上,咱们一步步拆解:

错误根源

你写的frames.forEach(ffmpeg.stdin.write)这行代码有个典型的JavaScript上下文丢失问题:当你直接把ffmpeg.stdin.write作为forEach的回调函数时,这个方法的this指向不再是ffmpeg.stdin这个可写流对象了,而是变成了undefined(严格模式下)。而write方法内部需要依赖this来访问流的_writableState属性,所以才会抛出这个错误。

快速修复

有两种简单的方式解决这个上下文问题:

方式1:用箭头函数包裹(推荐)

箭头函数会自动继承外部的上下文,确保write方法的this正确指向ffmpeg.stdin:

frames.forEach(frame => ffmpeg.stdin.write(frame))

方式2:用bind绑定上下文

显式把write方法的this绑定到ffmpeg.stdin上:

frames.forEach(ffmpeg.stdin.write.bind(ffmpeg.stdin))

代码里的其他坑

除了这个错误,你的代码还有几个需要修正的地方,否则后续可能还会出问题:

  1. stderr事件监听错误
    你写的ffmpeg.stderr.on("data", reject(data))会立即调用reject,而不是等到stderr有数据时才触发。应该改成:

    ffmpeg.stderr.on("data", (data) => reject(new Error(data.toString())))
    

    (把Buffer转成字符串,方便查看错误信息)

  2. 没有关闭stdin
    发送完所有帧后,需要调用ffmpeg.stdin.end()告诉ffmpeg没有更多输入了,否则ffmpeg会一直等待输入,进程永远不会退出。

  3. ffmpeg输出逻辑矛盾
    你当前的ffmpeg命令是把结果写入output.mkv文件,但同时又在监听stdout收集数据——这是冲突的。如果你的目标是获取编码后的视频数据(而不是写入文件),需要调整ffmpeg参数,把输出重定向到stdout:

    const ffmpeg = spawn("ffmpeg", [
      "-f", "image2pipe",
      "-i", "-",
      "-f", "matroska",  // 指定输出格式
      "-"                // 输出到stdout
    ])
    

    如果你的目标是生成output.mkv文件,那stdout不会有数据,Buffer.concat(chunks)会是空的,需要调整Promise的resolve逻辑(比如resolve文件路径或者成功状态)。

修复后的完整代码

这里给出一个兼顾正确性和健壮性的版本:

import { spawn } from "child_process"

export default frames => {
  // 调整ffmpeg参数,输出到stdout(如果要写文件,改回"output.mkv"即可)
  const ffmpeg = spawn("ffmpeg", [
    "-f", "image2pipe",
    "-i", "-",
    "-f", "matroska",
    "-"
  ])

  // 正确发送每帧数据
  frames.forEach(frame => ffmpeg.stdin.write(frame))
  // 关闭stdin,告知ffmpeg输入结束
  ffmpeg.stdin.end()

  return new Promise((resolve, reject) => {
    const chunks = []
    ffmpeg.stdout.on("data", chunk => chunks.push(chunk))
    
    // 处理错误输出
    ffmpeg.stderr.on("data", (data) => reject(new Error(`ffmpeg error: ${data.toString()}`)))
    
    // 处理进程退出
    ffmpeg.on("close", code => {
      if (code !== 0) {
        return reject(new Error(`ffmpeg exited with code ${code}`))
      }
      resolve(Buffer.concat(chunks))
    })
    
    // 处理进程启动失败的情况
    ffmpeg.on("error", err => reject(new Error(`Failed to spawn ffmpeg: ${err.message}`)))
  })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:13:32