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

FFmpeg进程在C#中阻塞无法退出问题及替代方案咨询

FFmpeg进程在C#中WaitForExit卡住的原因及解决方法

我来帮你拆解这个问题——你遇到的其实是进程输出缓冲区阻塞导致的经典死锁场景,加-loglevel quiet能解决只是因为它砍掉了FFmpeg的日志输出,从根源上避免了缓冲区溢出的问题。

问题根源

当你在C#中开启RedirectStandardOutput和RedirectStandardError后,FFmpeg的所有输出(包括默认的大量日志信息)都会被导向到对应的内存缓冲区里。如果这些缓冲区被填满了,FFmpeg就会暂停执行,等待程序读取缓冲区内容才能继续运行。

而你的原代码先调用了WaitForExit(),此时程序会一直等待FFmpeg退出,但FFmpeg因为缓冲区满了卡在那里无法继续执行,两者互相等待,自然就形成了死锁。添加-loglevel quiet后,FFmpeg几乎不输出任何日志,缓冲区不会被填满,进程就能正常执行完成,WaitForExit()也能顺利返回。

无需添加-loglevel quiet的解决方法

核心思路是在等待进程退出前,先异步读取标准输出和错误输出,避免缓冲区被占满。这里有两种常用的实现方式:

方法1:使用异步读取事件

给OutputDataReceived和ErrorDataReceived事件绑定处理方法,异步读取输出内容,确保缓冲区不会阻塞:

using (Process process = new Process())
{
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.FileName = FileName; // ffmpeg.exe路径
    process.StartInfo.Arguments = Arguments; // -ss 0 -i output.mp4 -t 10 -an -y test.mp4

    // 绑定输出读取事件(可根据需求处理输出内容)
    process.OutputDataReceived += (sender, e) => 
    { 
        if (!string.IsNullOrEmpty(e.Data)) 
        { 
            // 比如将输出记录到日志
            // Console.WriteLine($"FFmpeg输出: {e.Data}");
        } 
    };
    process.ErrorDataReceived += (sender, e) => 
    { 
        if (!string.IsNullOrEmpty(e.Data)) 
        { 
            // 处理错误输出
            // Console.WriteLine($"FFmpeg错误: {e.Data}");
        } 
    };

    process.Start();

    // 启动异步读取
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    process.WaitForExit();
}

方法2:用Task并行读取输出

如果需要最终收集所有输出内容,可以用Task并行读取StandardOutput和StandardError,避免单线程等待导致的死锁:

using (Process process = new Process())
{
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.FileName = FileName;
    process.StartInfo.Arguments = Arguments;

    process.Start();

    // 并行启动读取任务
    Task<string> outputTask = process.StandardOutput.ReadToEndAsync();
    Task<string> errorTask = process.StandardError.ReadToEndAsync();

    process.WaitForExit();

    // 获取最终输出结果
    string output = outputTask.Result;
    string error = errorTask.Result;

    return output;
}

这两种方法都能在保留FFmpeg正常日志输出的前提下,避免缓冲区阻塞导致的死锁,让WaitForExit()正常工作。

内容的提问来源于stack exchange,提问作者Srdjan M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:26:48