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

C#调用ffmpeg录制桌面如何正确停止保存文件并隐藏黑窗口

C# 调用ffmpeg录屏隐藏控制台窗口方案

问题现象

使用C#调用ffmpeg通过gdigrab采集桌面录制视频时,直接调用Process.Close()终止进程会导致录制文件无法正常写入落盘;通过重定向标准输入向ffmpeg发送q键可实现进程正常退出、文件完整保存,但运行过程中会弹出ffmpeg的黑色控制台窗口:
ffmpeg运行时弹出的黑色控制台窗口

问题根因

  • 原代码ProcessStartInfo.CreateNoWindow属性设为false,该值为true时才能阻止进程创建新控制台窗口
  • 未配置ProcessStartInfo.WindowStyle为隐藏状态
  • 初版代码存在配置顺序错误:在调用Process.Start()方法后才修改UseShellExecute、CreateNoWindow属性,此类启动参数必须在进程启动前设置才会生效
  • 初版ffmpeg启动参数存在笔误:- pix_fmt多了多余空格,会导致像素格式参数解析失败
  • 原停止逻辑在发送q指令后立刻调用Close(),未等待ffmpeg完成文件头、索引写入收尾,仍存在文件损坏风险

修正方案

  • 所有进程启动参数全部放在Process.Start()调用前配置
  • 将CreateNoWindow属性设为true
  • 将WindowStyle属性设为ProcessWindowStyle.Hidden
  • 修正ffmpeg参数的空格笔误
  • 发送q退出指令后,等待进程自然退出,设置合理超时避免程序卡死,最后回收进程资源
  • 输出文件名建议添加.mp4后缀,避免ffmpeg无法识别输出封装格式

修正后完整代码

FFmpeg录制类

using System;
using System.Diagnostics;

namespace Testings
{
    internal class FFmpeg_Capture
    {
        private Process _ffmpegProcess;

        public FFmpeg_Capture()
        {
            _ffmpegProcess = new Process();
        }

        public void Start(string outputFileName, int framerate)
        {
            // 回收已有未退出进程
            if (_ffmpegProcess != null && !_ffmpegProcess.HasExited)
            {
                _ffmpegProcess.Close();
                _ffmpegProcess.Dispose();
            }
            _ffmpegProcess = new Process();

            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = @"D:\Captured Videos\ffmpeg.exe",
                WorkingDirectory = @"D:\Captured Videos\",
                // 隐藏控制台窗口核心配置
                UseShellExecute = false,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden,
                // 重定向标准输入用于发送退出指令
                RedirectStandardInput = true,
                Arguments = $"-y -f gdigrab -framerate {framerate} -i desktop -preset ultrafast -pix_fmt yuv420p {outputFileName}"
            };

            _ffmpegProcess.StartInfo = startInfo;
            _ffmpegProcess.Start();
        }

        public void Stop()
        {
            if (_ffmpegProcess == null || _ffmpegProcess.HasExited)
            {
                return;
            }
            // 写入q指令触发ffmpeg正常退出
            _ffmpegProcess.StandardInput.Write('q');
            _ffmpegProcess.StandardInput.Flush();
            // 最多等待5秒,让ffmpeg完成文件收尾写入
            _ffmpegProcess.WaitForExit(5000);
            // 回收进程资源
            _ffmpegProcess.Close();
            _ffmpegProcess.Dispose();
        }
    }
}

窗体调用逻辑

private bool recordToggle = false;
private readonly FFmpeg_Capture record = new FFmpeg_Capture();

private void btnRecord_Click(object sender, EventArgs e)
{
    recordToggle = !recordToggle;
    if (recordToggle)
    {
        btnRecord.Text = "Stop";
        // 文件名添加mp4后缀,明确输出格式
        record.Start("Testing.mp4", 60);
    }
    else
    {
        btnRecord.Text = "Record";
        record.Stop();
    }
}

注意事项

  • 无需额外将q转为GBK编码字节写入,直接通过StandardInput.Write写入字符即可被ffmpeg识别
  • WaitForExit的超时时间可根据实际磁盘写入性能调整,设置超时是为了避免ffmpeg异常卡死时主程序无响应
  • 若需要获取ffmpeg运行日志,可额外配置重定向标准输出、标准错误流,不会影响窗口隐藏效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:22:02