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

向Windows子进程标准输入发送Ctrl+C等控制字符的可靠方案咨询

你遇到的偶发失效问题核心原因是:Windows平台下重定向stdin后,ffmpeg默认会在部分场景下关闭stdin监听,导致你写入的Ctrl+C(0x03)字符没有被进程处理,和你用匿名管道还是命名管道/套接字重定向没有关系。

最可靠的优雅停止方案

不要通过stdin发字符,直接使用Windows原生控制台信号机制向ffmpeg进程发送CTRL_C_EVENT,实现100%可靠触发ffmpeg正常退出逻辑。

1. 调整CreateProcess创建ffmpeg子进程的参数

创建子进程时必须新增CREATE_NEW_PROCESS_GROUP标志,为ffmpeg创建独立进程组,这是后续发送控制台信号的前提。如果需要隐藏控制台窗口,额外加CREATE_NO_WINDOW标志即可。
示例代码:

STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi = {0};
// 核心创建标志:单独进程组 + 可选隐藏窗口
DWORD createFlags = CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW;

BOOL createRet = CreateProcess(
    NULL,
    (LPWSTR)your_ffmpeg_command_line, // 注意这里的命令行参数要可写
    NULL,
    NULL,
    FALSE,
    createFlags,
    NULL,
    NULL,
    &si,
    &pi
);

if (createRet) {
    // 保存ffmpeg进程ID和进程句柄供后续停止用
    g_ffmpeg_pid = pi.dwProcessId;
    g_ffmpeg_process_hdl = pi.hProcess;
    // 线程句柄用不到直接关闭
    CloseHandle(pi.hThread);
}

2. 停止录制时的信号发送逻辑

直接调用GenerateConsoleCtrlEvent发送CTRL+C信号,之后等待ffmpeg正常退出即可:

// 向ffmpeg所在进程组发送CTRL+C信号
BOOL sendRet = GenerateConsoleCtrlEvent(CTRL_C_EVENT, g_ffmpeg_pid);
if (sendRet) {
    // 等待最多5秒让ffmpeg写完视频文件尾部,时间可根据录制文件大小调整
    WaitForSingleObject(g_ffmpeg_process_hdl, 5000);
}

// 兜底判断:如果进程仍未退出再考虑强制杀死,正常场景不会走到这一步
DWORD exitCode = 0;
GetExitCodeProcess(g_ffmpeg_process_hdl, &exitCode);
if (exitCode == STILL_ACTIVE) {
    TerminateProcess(g_ffmpeg_process_hdl, 0);
}

// 关闭进程句柄释放资源
CloseHandle(g_ffmpeg_process_hdl);

其他可选方案说明

如果你坚持要通过stdin发送停止信号,只需要在ffmpeg启动参数中新增-stdin,强制ffmpeg开启stdin监听即可,能大幅降低原有逻辑的失效率,但稳定性仍然不如控制台信号方案。
你之前尝试的套接字重定向方案无需继续调试,Win32的SOCKET句柄不支持直接传入WriteFile写入,需要调用send接口,且即使写成功仍然会遇到stdin监听失效的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:27:06