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

如何在Node.js中停止FFmpeg编码并保留完整音视频数据?

解决方案

核心思路

移除-shortest参数,改用向FFmpeg进程发送优雅停止命令的方式,让FFmpeg处理完所有已缓存的音视频数据后再终止编码,避免音频截断。

具体步骤

  1. 调整FFmpeg参数:删除原命令中的-shortest——这个参数会强制FFmpeg在最短输入流结束时立刻终止,直接丢弃未处理的音频缓冲区数据,正是导致音频被截断的原因。
  2. 发送优雅停止信号:当调用inputStream.end()停止图片流后,向FFmpeg的标准输入写入字符q。这是FFmpeg内置的交互停止指令,触发后FFmpeg会完成当前所有已接收数据的编码、排空缓冲区,再正常退出。

修改后的代码示例

const child = require("child_process");
const stream = require("stream");

let inputStream = new stream.PassThrough();
let ffmpeg = child.spawn("ffmpeg.exe", [
    "-f", "image2pipe", "-r", "24", "-fflags", "nobuffer",
    "-i", "pipe:0",
    "-f", "dshow",
    "-sample_rate", "48000",
    "-i", 'audio="Microphone"',
    "-acodec", "pcm_s16le",
    "-ac", "2",
    "-ar", "48000",
    "-vcodec", "libx264",
    "-crf", "10",
    "-preset", "veryfast",
    "-framerate", "1",
    "output.mkv"
]);

inputStream.pipe(ffmpeg.stdin);

// 监听FFmpeg退出事件,确认编码完成状态
ffmpeg.on('exit', (code, signal) => {
    console.log(`FFmpeg编码完成,退出代码:${code}`);
});

// 封装停止编码的方法
function stopEncoding() {
    inputStream.end();
    // 监听图片流写入完成事件,确保最后一批数据进入FFmpeg缓冲区
    inputStream.on('finish', () => {
        ffmpeg.stdin.write('q');
    });
}

额外说明

  • 利用inputStream的finish事件替代固定延迟,能更准确地判断图片流是否完全写入FFmpeg,避免因延迟设置不当导致的问题。
  • 如果遇到FFmpeg仍无法正常排空音频缓冲区的情况,可以尝试添加-flush_packets 1参数强制FFmpeg实时刷新数据包,进一步降低数据丢失概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:47:36