Windows下调用ffmpeg时Process.WaitForExitAsync无限阻塞问题
问题分析与解决方案
问题根源
你的代码在WaitForExitAsync处无限阻塞,核心原因是重定向了ffmpeg的标准输出/错误流,但未主动读取这些流的内容。
命令行执行时,控制台会自动处理ffmpeg的输出缓冲区,因此进程能正常退出;但在C#中手动开启RedirectStandardOutput和RedirectStandardError后,如果不读取流内容,操作系统的输出缓冲区会被填满,导致ffmpeg进程无法继续执行,也无法触发退出信号,最终让WaitForExitAsync一直等待。
解决方法
1. 异步读取输出流,避免缓冲区阻塞
启动进程后,必须同时异步读取StandardOutput和StandardError的内容,不能仅依赖WaitForExitAsync。可以用Task.WhenAll并行处理两个流的读取:
var ffmpegProcess = new Process { StartInfo = new ProcessStartInfo { FileName = _config.FfmpegExecutablePath, Arguments = CreateArgumentsForFfmpegProcessToRun(videoTempFilePath, thumbnailTempFilePath), RedirectStandardError = true, RedirectStandardOutput = true, // 无需给ffmpeg输入数据,关闭输入重定向 RedirectStandardInput = false, UseShellExecute = false, CreateNoWindow = true }, EnableRaisingEvents = true }; ffmpegProcess.Start(); // 并行读取两个输出流,释放缓冲区 var readTasks = new[] { ffmpegProcess.StandardOutput.ReadToEndAsync(), ffmpegProcess.StandardError.ReadToEndAsync() }; await Task.WhenAll(readTasks); await ffmpegProcess.WaitForExitAsync(); // 可选:读取输出内容用于日志排查 var outputLog = await readTasks[0]; var errorLog = await readTasks[1];
2. 优化ffmpeg命令消除警告
你命令行中出现的警告可以通过添加-update 1参数解决,该参数明确告诉ffmpeg输出单张图片而非序列,减少不必要的输出内容:
修改后的ffmpeg参数应为:
-i .\input.mp4 -ss 00:00:01.000 -vframes:v 1 -update 1 output.png
3. 关闭不必要的输入重定向
你的场景不需要向ffmpeg输入数据,因此将RedirectStandardInput设为false,减少资源占用,同时避免潜在的流阻塞风险。
补充说明
省略WaitForExitAsync时进程能生成文件,是因为短时间内输出缓冲区未被填满,进程能完成任务后退出,但这种方式不可靠——如果ffmpeg输出内容较多,依然会出现进程挂起的情况,必须通过主动读取流来彻底解决。
内容的提问来源于stack exchange,提问作者Iskander Raimbaev
相关产品推荐
相关产品推荐

