FFmpeg 性能优化最佳实践:多线程、零拷贝与流水线

📅 2026/7/9 1:10:56
FFmpeg 性能优化最佳实践:多线程、零拷贝与流水线
FFmpeg 性能优化最佳实践多线程、零拷贝与流水线FFmpeg 默认参数能用但不一定快。批量处理视频、实时拉流、嵌入式设备上性能优化就很重要了。这篇总结我实际项目里用到的优化手段多线程、硬件加速、减少拷贝、流水线处理、参数调优——从命令行到代码层面都覆盖。大家好我是黒漂技术佬。一开始用 FFmpeg 我也是直接默认参数跑能用是能用但批量处理几百个视频的时候慢得离谱RK3588 上同时拉两路流 CPU 就满了。后来一点点优化速度提升了好几倍。这篇把能优化的地方按效果排序从最简单的参数调到架构层面的流水线设计都讲。一、优化优先级先给个结论按投入产出比排序优先级优化手段效果难度⭐⭐⭐⭐⭐硬件加速编解码3-10 倍中⭐⭐⭐⭐减少编码次数stream copy几十倍低⭐⭐⭐⭐多线程2-4 倍低⭐⭐⭐减少格式转换20-50%中⭐⭐⭐滤镜顺序优化10-30%低⭐⭐零拷贝 / 硬件帧传递20-40%高⭐⭐输入输出优化10-20%中⭐编译优化10-15%高硬件加速和 stream copy 是收益最大的优先搞。二、第一优先级能 copy 就别编码这是最简单但最容易被忽略的优化。什么情况可以 copy只要视频画面不需要改不缩放、不裁剪、不加滤镜只是换封装、改音轨、拼接就可以-c copy。# 不好重新编码慢ffmpeg-iinput.mp4 output.mkv# 好直接复制流秒级完成ffmpeg-iinput.mp4-ccopy output.mkv复制流的速度只受硬盘读写限制比编码快几十上百倍。部分 copy视频不用改音频要转ffmpeg-iinput.mp4-c:vcopy-c:aaac-b:a128k output.mp4视频 copy音频重新编码。比全重新编码快很多。常见可以 copy 的场景格式转换MP4 → MKV → TS音视频分离、合并拼接视频参数一致时提取音频/视频加字幕软字幕不是烧录 一个原则画面没改就用 copy。加滤镜、改分辨率、加水印——这些改了画面的才需要重新编码。三、第二优先级硬件加速上一篇专门讲过这里再强调一下优先级命令行# RK3588 全硬件转码ffmpeg-hwaccelrkmpp-iinput.mp4-c:vh264_rkmpp-b:v2M output.mp4# NVIDIA 全硬件转码ffmpeg-hwaccelcuda-iinput.mp4-c:vh264_nvenc-crf23output.mp4代码里硬解硬编零拷贝传递性能最优。嵌入式项目这是必须做的。混合方案解码用硬件处理用 CPU编码再用硬件——比全软快很多。四、第三优先级多线程编码多线程libx264/x265 默认就是多线程的一般自动检测 CPU 核心数。但可以手动调ffmpeg-iinput.mp4-c:vlibx264-threads8-crf23output.mp4解码多线程ffmpeg-threads8-iinput.mp4 output.mp4H.264 软解多线程提升有限一般 2-3 倍因为解码依赖关系强。滤镜多线程部分滤镜支持多线程比如 scaleffmpeg-iinput.mp4-vfscale1920:1080:flagsbicubic:threads4output.mp4不是线程越多越快超过物理核心数之后再增加线程反而因为上下文切换变慢。一般设为 CPU 核心数就好。五、第四优先级减少格式转换每一次像素格式转换都是一次全图拷贝开销不小。YUV → RGB 是大头解码出来是 YUV420P图像处理很多要 RGB。这个转换开销不小。优化思路能在 YUV 空间处理就别转 RGB比如缩放、裁剪、大部分滤镜转一次就够了别来回转用 swscale 的快速算法bilinear 比 lanczos 快减少中间格式比如解码 → 缩放 → 编码。如果缩放前后都是 YUV就不用转 RGB。swscale 算法选择# 最快质量一般scale1280:720:flagsfast_bilinear# 平衡默认scale1280:720:flagsbicubic# 质量最好最慢scale1280:720:flagslanczos做预览、缩略图用 fast_bilinear 就行省时间。六、第五优先级滤镜顺序优化滤镜链的顺序影响性能。原则是尽早减少像素量。先裁剪后缩放# 好先裁掉多余像素缩放处理的像素少ffmpeg-iinput.mp4-vfcrop640:480,scale320:240output.mp4# 不好先缩再裁白处理了很多像素ffmpeg-iinput.mp4-vfscale640:480,crop320:240output.mp4先降采样再做复杂滤镜先缩小再做复杂处理处理的数据量小很多。能合并的滤镜合并有些滤镜可以组合到同一个 filter 里减少数据拷贝次数。七、第六优先级输入输出优化读文件本地文件一般没问题网络流加大缓冲区减少阻塞ffmpeg-rtsp_transporttcp-buffer_size2000000-irtsp://地址...写文件输出到 SSD 比 HDD 快很多大量小文件抽帧的时候IO 开销很大考虑批量写入或内存缓冲管道代替临时文件两步处理不要存中间文件用管道连起来# 不好中间文件占空间还有 IO 开销ffmpeg-iinput.mp4-c:vlibx264-crf23temp.mp4 ffmpeg-itemp.mp4-vfscale720:-1 output.mp4# 好管道连接一次 IOffmpeg-iinput.mp4-c:vlibx264-crf23-fmatroska -|\ffmpeg-i--vfscale720:-1 output.mp4代码里更明显解码后直接送滤镜再编码中间不写文件。八、第七优先级流水线与并行处理多文件并行处理批量转码的时候别一个一个来同时跑几个 FFmpeg 进程。但注意软编码 CPU 密集型同时跑太多反而慢争抢 CPU硬件编码有通道数限制硬盘 IO 可能成为瓶颈一般同时跑 2-4 个比较合适看机器配置。流水线处理一个视频的处理拆成多个阶段流水线式读文件 → 解码 → 滤镜 → 编码 → 写文件FFmpeg 内部本来就是多线程流水线的但自己写代码的时候要注意别在某一步阻塞。多线程设计建议解码线程读 packet 解码处理线程滤镜、AI 识别编码线程编码 写文件用队列串起来各阶段并行。九、第八优先级编译优化自己编译 FFmpeg可以开启一些优化编译选项./configure\--enable-gpl\--enable-libx264\--enable-librkmpp\# RK3588 硬件加速--enable-hardcoded-tables\--optflags-O3\--enable-pic针对特定 CPU 优化--cpucortex-a76# RK3588 的大核针对 ARM 平台交叉编译的时候指定 CPU 型号能生成更优化的指令。裁剪不需要的功能只编你需要的编码器解码器体积小、加载快。一般默认编译的 FFmpeg 就够用了编译优化提升有限不到万不得已不用折腾。十、代码层面的优化1. 复用对象循环里不要反复 alloc/freepacket 和 frame 分配一次反复用unref 清数据就行。// 好分配一次循环里复用AVPacket*pktav_packet_alloc();while(...){av_read_frame(fmt_ctx,pkt);// 处理...av_packet_unref(pkt);}av_packet_free(pkt);2. 减少内存拷贝直接操作 frame 的 data 指针别自己再 memcpy 一份能用引用计数ref/unref就别拷贝数据av_frame_ref()只是增加引用不拷贝数据3. 合理的缓冲区大小读网络流的时候缓冲区太小会频繁 IO太大占内存。根据实际场景调。4. 跳过不需要的流文件里有视频、音频、字幕只需要视频的话其他流不要打开解码器。// 只处理视频流其他直接忽略if(pkt-stream_indexvideo_idx){// 解码...}5. 丢帧策略实时处理场景比如直播分析处理不过来就丢帧保证延迟。// 队列太长了就丢旧帧if(packet_queue_sizeMAX_QUEUE_SIZE){// 丢一帧...}十一、性能分析方法优化之前先测瓶颈在哪别瞎优化。命令行测速度timeffmpeg-iinput.mp4-c:vlibx264-crf23-fnull -看 fps 和总耗时。看 CPU 占用top/ 任务管理器看是 CPU 瓶颈还是 IO 瓶颈。CPU 100% → 计算瓶颈优化编码或上硬件加速CPU 很低但速度慢 → IO 瓶颈或网络瓶颈代码里打点每个阶段加时间统计doublet0av_gettime_relative()/1000000.0;// 解码...doublet1av_gettime_relative()/1000000.0;printf(解码耗时: %.3fms\n,(t1-t0)*1000);找到最慢的那一步针对性优化。十二、我项目里的优化路径售货柜项目RK3588 IPC YOLO的优化过程第一版软解 转 RGB YOLO一路 1080p 30fpsCPU 占满只能跑到 10fps第二版硬解 YUV 直接送模型硬解放出 CPUYOLO 用 RKNN NPU 加速跑到 25fpsCPU 占用 30%第三版按需抽帧 事件触发没人的时候每秒抽 1 帧做检测开门事件触发才全帧率识别平时 CPU 占用 10%功耗也降了第四版多流水线并行解码、预处理、推理、后处理流水线同时处理两路摄像头无压力优化是循序渐进的先搞大头再抠细节。十三、本篇小结最大优化能 copy 就别编码速度差几十倍第二大硬件加速硬解硬编快 3-10 倍第三多线程、滤镜顺序优化、减少格式转换代码层面复用对象、减少拷贝、跳过不需要的流优化前先测瓶颈别盲目优化嵌入式项目硬解硬编 NPU 推理 按需处理是性能最优解下一篇是本系列最后一篇售货柜实战——IPC 拉流 → 抽帧 → YOLO 识别完整流水线把前面讲的所有知识串到一个实际项目里。我是黒漂技术佬。