如何检测FFmpeg生成视频缩略图的任务是否完成?
异步等待FFmpeg进程完成,替代不靠谱的Task.Delay
嘿,你用Task.Delay(3000)的方式确实踩了个常见的坑——不同视频的处理时间差异太大,短的可能一秒搞定,长的要几十秒,硬编码延迟要么浪费时间,要么导致文件还没生成就去读,自然拿不到文件。
在C#里根本不用手动模拟Promise那套,Process类本身就提供了异步等待进程退出的方法,效果和JS里的promise.then()完全一致:等FFmpeg彻底干完活,再执行后续的GenerateThumbnailsAsync。
修改后的完整代码
public async Task GetVideoThumbnailsAsync(string videoPath, string videoId) { byte thumbnailWidth = 160; byte thumbnailHeight = 90; string fps = "1/2"; videoPath = Path.Combine(_environment.WebRootPath, videoPath); string videoThumbnailsPath = Path.Combine(_environment.WebRootPath, $"assets/images/video_thumbnails/{videoId}"); string outputImagePath = Path.Combine(videoThumbnailsPath, "item_%d.jpg"); Directory.CreateDirectory(videoThumbnailsPath); using (var ffmpeg = new Process()) { ffmpeg.StartInfo.Arguments = $" -i {videoPath} -vf fps={fps} -s {thumbnailWidth}x{thumbnailHeight} {outputImagePath}"; ffmpeg.StartInfo.FileName = Path.Combine(_environment.ContentRootPath, "FFmpeg/ffmpeg.exe"); // 加上这两行,方便排查FFmpeg执行出错的情况(比如视频损坏、参数不对) ffmpeg.StartInfo.RedirectStandardError = true; ffmpeg.StartInfo.UseShellExecute = false; ffmpeg.Start(); // 核心改动:异步等待FFmpeg进程完全退出,代替硬编码的Delay await ffmpeg.WaitForExitAsync(); // 可选但很有用:检查FFmpeg是否成功执行(退出码0通常代表成功) if (ffmpeg.ExitCode != 0) { string errorLog = await ffmpeg.StandardError.ReadToEndAsync(); // 这里可以根据业务需求记录日志或者抛出异常 throw new InvalidOperationException($"FFmpeg处理视频失败:{errorLog}"); } } // 现在百分百确定所有缩略图都生成好了,放心执行后续逻辑 await GenerateThumbnailsAsync(videoThumbnailsPath, videoId); }
关键细节解释
WaitForExitAsync():这是Process类的原生异步方法,会一直等FFmpeg进程终止才继续往下走,完美解决了硬编码延迟的问题——不管视频多大,都等它处理完再干活,和JS里Promise的异步等待逻辑完全匹配。- 错误排查:开启
RedirectStandardError后,可以读取FFmpeg的错误输出,万一出现视频无法解码、参数错误之类的问题,能快速定位原因,比瞎猜强多了。 - 资源管理:用
using包裹Process对象,进程用完会自动释放资源,不用手动操心内存泄漏的问题。
这样改完之后,你就再也不会遇到“获取到0个文件”的问题了,而且代码也更健壮、更符合异步编程的最佳实践。
内容的提问来源于stack exchange,提问作者user9235753
相关产品推荐
相关产品推荐

