C#调用FFmpeg单进程提取视频每第5帧合成新视频方法
FFmpeg单进程实现每5帧抽帧并生成新视频方案
你原有两步方案耗时高的核心原因是中间帧图片写入磁盘、再从磁盘读取编码的过程产生了大量冗余IO,完全可以通过单条FFmpeg命令在内存内完成抽帧、编码全流程,不需要生成任何中间图片文件。
实现逻辑
- 沿用你原有的
select滤镜逻辑筛选每第5帧 - 筛选后通过
setpts滤镜重置帧时间戳,避免输出视频出现时间轴错位、时长异常问题 - 处理后的帧直接送入编码器输出目标视频,全程无磁盘中间文件读写
基础命令格式
ffmpeg -i [输入视频路径] -vf "select=not(mod(n\,5)),setpts=N/[输出帧率]/TB" -r [输出帧率] [输出视频路径]
参数说明:
select=not(mod(n\,5)):筛选帧序号为0、5、10……的帧,和你原有抽帧逻辑完全一致setpts=N/[输出帧率]/TB:按指定输出帧率重新生成连续的时间戳-r [输出帧率]:强制输出视频的帧率,一般设置为原视频帧率除以5即可,和你之前读取图片序列时设置的framerate参数效果一致
示例:如果原视频为30fps,设置输出帧率为6fps(30/5),命令如下:
ffmpeg -i input.mp4 -vf "select=not(mod(n\,5)),setpts=N/6/TB" -r 6 -c:v libx264 -pix_fmt yuv420p output.mp4
附加的
-c:v libx264 -pix_fmt yuv420p参数是为了保证输出MP4格式的兼容性,所有主流播放器均可正常播放,如果需要输出AVI格式,替换为对应格式支持的编码器参数即可。
C# 调用代码适配
直接替换你原有两段进程启动的逻辑即可,不需要提前创建存储帧图片的文件夹:
// 替换为实际业务参数 string inputPath = "原视频完整路径"; string outputPath = "最终输出视频完整路径"; int standardFrameRate = 6; // 按实际需求设置输出帧率 string ffmpegPath = "ffmpeg可执行文件完整路径"; string ffmpegArgs = string.Format( "-i {0} -vf \"select=not(mod(n\\,5)),setpts=N/{1}/TB\" -r {1} -c:v libx264 -pix_fmt yuv420p {2}", inputPath, standardFrameRate, outputPath ); ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = ffmpegPath, Arguments = ffmpegArgs, UseShellExecute = false, CreateNoWindow = true }; Process exeProcess = Process.Start(startInfo); exeProcess.WaitForExit();
调整说明
- 如果你需要从第1帧开始计数,选中第5、10、15……帧,把select判断条件修改为
select=not(mod(n+1\,5))即可 - 该方案相比原有两步方案,性能提升幅度通常在30%以上,磁盘性能越差提升越明显
内容的提问来源于stack exchange,提问作者mobile devteam
相关产品推荐
相关产品推荐

