推荐用 FFmpeg.AutoGen 直接调用 FFmpeg C API:避免进程启动问题,内存可控、无子进程、支持调试;需正确初始化、校准时间戳、及时释放资源;Accord.Video.FFMPEG 仅支持解码,不支持编码。

用 FFmpeg.AutoGen 调用 FFmpeg 做转码,别碰 ffmpeg.exe 进程启动
直接调用命令行 ffmpeg.exe 看似简单,但 Windows 权限、路径空格、编码参数逃逸、进程僵死都会让你在批量处理时突然卡住或崩溃。C# 里更稳的方式是用 FFmpeg.AutoGen(官方 C API 的 .NET 绑定),它把 FFmpeg 编译成 DLL 静态链接,内存可控、无子进程、支持断点调试。
实操建议:
- 用
NuGet安装FFmpeg.AutoGen,再手动把对应平台的avcodec-*.dll等文件复制到bin/Debug下(注意 x64/x86 匹配) - 初始化必须调用
ffmpeg.avdevice_register_all()和ffmpeg.avformat_network_init(),否则打开网络流或某些封装格式会失败 - 解码时别直接读
AVPacket时间戳——要先用av_frame_get_best_effort_timestamp()校准,否则裁剪精度偏差可能达几百毫秒 - 转码后记得调用
av_packet_unref(),否则内存泄漏比用Process.Start还隐蔽
Accord.Video.FFMPEG 只能读帧,不能写视频
这个包名字带 FFMPEG,但底层只是用 FFmpeg 解封装 + 解码,输出的是 Bitmap 或 double[][] 帧数据,所有“写回视频”操作都得你自己搭编码器链路。很多人以为调用 VideoFileReader.ReadVideoFrame() 后接个 VideoFileWriter.WriteVideoFrame() 就能保存,结果发现后者根本不存在——Accord.Video.FFMPEG 没提供编码能力。
常见错误现象:
- 试图用
VideoFileWriter写 MP4 报错:System.NotImplementedException: The method or operation is not implemented. - 用
Accord.Imaging.Filters处理完帧,却卡在“怎么存回去”上,最后被迫切回 FFmpeg 命令行
替代方案:
- 用
FFmpeg.AutoGen自己写编码循环(推荐,控制力强) - 或改用
OpenCvSharp的Cv2.VideoWriter(支持 X264 编码,但需提前编译带 FFMPEG 支持的 OpenCV)
裁剪视频用 -ss 和 -t,但顺序和关键帧决定快慢
命令行里写 ffmpeg -i in.mp4 -ss 00:01:30 -t 10 -c copy out.mp4 看似高效,但实际行为取决于 -ss 放的位置:放前面是「先 seek 再解封装」,快但不准;放后面是「解完再丢帧」,准但慢。C# 调用时如果没显式控制位置,很可能默认走慢路。
实操要点:
- 硬切(不重编码)必须用
-ss在-i前,且确保起始时间落在关键帧上,否则会黑屏或花屏 - 想精确到帧?只能重编码:把
-ss放-i后,加-avoid_negative_ts make_zero防止 PTS 错乱 -
FFmpeg.AutoGen中对应逻辑是调av_seek_frame()后检查返回值,不是 0 就说明没找到关键帧,得手动向前找
合并多个视频,别用 concat 协议拼文件名字符串
网上教程常教你在 C# 里拼 "file 'a.mp4'\nfile 'b.mp4'" 写进临时 txt,再传给 -f concat。这在路径含中文、空格或特殊符号时必炸,错误信息通常是:Invalid data found when processing input 或 No such file or directory。
安全做法:
- 所有输入路径先用
Uri.EscapeDataString()编码,再写入 concat 文件 - 或者绕过 concat 协议,用
avformat_open_input()逐个打开,把每个流的AVStream.time_base对齐后再 mux 到同一个AVFormatContext - 注意音视频流时间基(
time_base)不一致会导致合并后音画不同步,必须统一转成1/1000这类常用值再做av_rescale_q()
最麻烦的不是代码,是不同来源视频的 AVCodecParameters.codec_tag 不兼容——比如一个 H.264 是 avc1,另一个是 avc3,合并时 FFmpeg 会静默失败,日志里只有一句 Could not write header。

















