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

如何向boost::process发送Ctrl+C信号触发FFmpeg数据刷新?

解决boost::process终止FFmpeg时无法获取刷新数据的问题

你用GenerateConsoleCtrlEvent(CTRL_C_EVENT, c.id())无效的核心原因是:FFmpeg进程和主进程不在同一个控制台进程组。Windows的GenerateConsoleCtrlEvent默认向指定进程组的所有进程发信号,但boost::process默认启动子进程时会创建新的控制台组,导致信号无法传到FFmpeg。

以下是两种可行的解决办法:

方法一:确保FFmpeg与主进程同属一个控制台组

启动FFmpeg时不设置CREATE_NEW_PROCESS_GROUP标志(boost::process默认行为),让它继承主进程的控制台组。发送信号时,将第二个参数设为0(表示当前控制台组),同时主进程要先忽略自身的Ctrl+C信号,避免被连带终止:

#include <boost/process.hpp>
#include <windows.h>

namespace bp = boost::process;

int main() {
    // 启动FFmpeg,不创建新控制台组
    bp::child ffmpeg_proc("ffmpeg -i input.mp4 -f rawvideo pipe:1",
        bp::std_out > bp::pipe(),
        bp::creation_flags(CREATE_NO_WINDOW) // 仅隐藏窗口,不创建新进程组
    );

    // 主进程忽略Ctrl+C信号,避免自身被终止
    SetConsoleCtrlHandler(nullptr, TRUE);

    // 向当前控制台组发送Ctrl+C信号(FFmpeg会收到)
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);

    // 等待FFmpeg自行退出,确保它完成stdout刷新
    ffmpeg_proc.wait();

    // 读取管道中剩余的输出数据
    // ...
}

如果需要单独给FFmpeg的进程组发信号,可以启动时设置CREATE_NEW_PROCESS_GROUP,此时子进程ID就是进程组ID:

bp::child ffmpeg_proc("ffmpeg -i input.mp4 -f rawvideo pipe:1",
    bp::std_out > bp::pipe(),
    bp::creation_flags(CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP)
);

// 发送信号到FFmpeg的进程组
GenerateConsoleCtrlEvent(CTRL_C_EVENT, ffmpeg_proc.id());

方法二:用boost::process的POSIX信号接口发送SIGINT

boost::process封装了跨平台的信号发送接口,Windows下底层会处理控制台组问题,直接调用即可:

#include <boost/process.hpp>
#include <boost/process/signal.hpp>

namespace bp = boost::process;

int main() {
    bp::child ffmpeg_proc("ffmpeg -i input.mp4 -f rawvideo pipe:1",
        bp::std_out > bp::pipe()
    );

    // 发送SIGINT信号(等效于Ctrl+C)
    bp::signal::send(SIGINT, ffmpeg_proc);

    ffmpeg_proc.wait();
    // 读取剩余输出...
}

重要提示

发送信号后不要立刻调用terminate(),必须等待FFmpeg自行退出,这样它才有足够时间将缓存的数据刷新到stdout。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:29:50