【音视频】视频转码性能调优

这个系列文章我们来介绍一位海外工程师如何探索安卓音视频基础技术,对于想要开始学习音视频技术的朋友,这些文章是份不错的入门资料,本篇介绍视频转码性能调优。

——来自公众号“关键帧Keyframe”的分享

1、转码管道与延迟拆解

输入→解复用→解码→滤镜→编码→复用→输出
 │     │      │     │     │      │     │
 I/O  内存   多线程  SIMD  硬编   缓冲  协议

瓶颈分布:

  • I/O 等待 30 %
  • 内存拷贝 25 %
  • 编码 20 %(可硬加速)
  • 线程同步 15 %
  • 协议缓冲 10 %

2、内存管理优化

2.1、对齐分配(64 B 缓存行)

void *buf = av_malloc(size);        // 64 B 对齐
void *arr = av_malloc_array(n, sz); // 溢出检查

使用标准 malloc 会禁用 SIMD 并触发额外拷贝。

2.2、内存池与零拷贝

// 1. 预分配池
AVBufferRef *pool = av_buffer_pool_init(frame_size, av_buffer_alloc);

// 2. 引用计数共享
AVFrame *f = av_frame_alloc();
f->buf[0] = av_buffer_ref(shared_buf);   // 无 memcpy

收益:4K60 场景下 CPU 占用 ↓ 18 %

3、I/O 子系统调优

3.1、协议超时与非阻塞

AVDictionary *opts = NULL;
av_dict_set(&opts, "timeout", "3000000", 0);      // HTTP 3 s
av_dict_set(&opts, "stimeout", "3000000", 0);     // RTSP 3 s
av_dict_set(&opts, "rtsp_transport", "tcp", 0);   // 强制 TCP

// 中断回调防止卡死
static int interrupt_cb(void *ctx){
    return (av_gettime() - g_last_pkt > 3*1000000) ? -1 : 0;
}
fmt_ctx->interrupt_callback.callback = interrupt_cb;

3.2、缓冲与块大小

av_dict_set(&opts, "buffer_size", "4M", 0);   // 网络读缓存
av_dict_set(&opts, "max_delay", "500000", 0); // 输出最大缓冲 500 ms
av_dict_set(&opts, "flush_packets", "1", 0);  // 立即刷包

4、编解码器层优化

4.1、多线程模型

codec_ctx->thread_type = FF_THREAD_FRAME | FF_THREAD_SLICE;
codec_ctx->thread_count = av_cpu_count();      // 物理核数

规则

  • 帧级并行 ≥ 1080p
  • 片级并行 ≥ 720p

4.2、线程与切片联动

codec_ctx->slices = codec_ctx->thread_count;   // 一核一片

4K60 实测 ↑ 2.8× 吞吐 vs 单线程

5、硬件加速集成(CPU ↓ 60–80 %)

平台命令行示例
Intel QSVffmpeg -hwaccel qsv -c:v h264_qsv -preset veryfast
NVIDIA NVENCffmpeg -hwaccel cuda -c:v h264_nvenc -preset p1 -tune ll
Apple VTffmpeg -hwaccel videotoolbox -c:v h264_videotoolbox -realtime 1
Androidffmpeg -hwaccel mediacodec -c:v h264_mediacodec

零拷贝链路
AVHWFramesContext → GPU 内存终身不落地 CPU

6、分布式转码(Hadoop 案例)

输入视频 → 按 GOP 切分 → Map 节点并行转码 → Reduce 合并 → 输出
  • 切分策略:每个 Map 负责 2 s GOP(48–60 帧)
  • 线性扩展:10 节点 ≈ 10× 吞吐(论文实测)
  • FFmpeg 参数-ss start -t duration -avoid_negative_ts make_zero

7、性能监控与指标

指标目标采集方式
转码速度≥ 1.5× 实时frames / elapsed
CPU 占用< 80 % / 核top -p
GPU 利用率> 70 %nvidia-smiintel_gpu_top
内存峰值稳定无泄漏av_malloc_stats()
帧丢失率0 %序列号缺口检测

实时仪表盘
Prometheus + Grafana,每 200 ms 采样

8、高级优化技术

8.1、SIMD 自动检测

av_cpu_count();              // 核心数
av_get_cpu_flags();          // 返回 AV_CPU_FLAG_AVX2 等

FFmpeg 已内建 x86 SSE/AVXARM NEONPowerPC AltiVec 路径;
保证内存 64 B 对齐即可自动启用。

8.2、缓存友好遍历

// 结构体数组(SoA)替代数组结构(AoS)
for (int i = 0; i < n; i += 8) {
    __builtin_prefetch(&y[i + 64]);   // 预取
    process(y[i], u[i], v[i]);
}

8.3、零拷贝管道

AVFrame *hw_frame = av_frame_alloc();
av_hwframe_get_buffer(hw_frames_ctx, hw_frame, 0);
// hw_frame 全程 GPU,无 memcpy

9、质量 vs 性能权衡

场景presetCRF线程硬件
实时直播ultrafast28单线程NVENC
VOD 离线slow23全核软件 x264
云转码medium25逻辑核QSV

自适应码率

if (cpu_usage > 80) {
    codec_ctx->bit_rate *= 0.8;
    codec_ctx->crf += 2;
}

10、错误处理与重试

format_ctx->flags |= AVFMT_FLAG_NONBLOCK;
av_dict_set(&opts, "stimeout", "5000000", 0); // 5 s

int retry = 0, max = 5, base = 1000;
while (retry < max) {
    if (avformat_open_input(&fmt_ctx, url, nullptr, &opts) == 0) break;
    av_usleep(base * (1 << retry) * 1000);   // 指数退避
    retry++;
}

11、一行命令模板

ffmpeg -thread_queue_size 512 -i input.mp4 \
       -c:v h264_nvenc -preset p1 -tune ll -rc cbr -b:v 3M -maxrate 3M -bufsize 1M \
       -c:a aac -b:a 128k -ar 48000 \
       -f flv -flush_packets 1 -max_delay 500000 rtmp://server/live/stream

4K60 实测 整体延迟 60 ms,CPU 占用 < 15 %

12、结论与路线图

  1. 内存对齐 + 池化 → 消除 25 % CPU 浪费
  2. 多线程 + 切片 → 2–3× 吞吐
  3. 硬件加速 → 功耗 ↓ 60 %,延迟 ↓ 50 %
  4. 分布式 GOP 切分 → 线性扩展
  5. 持续监控 + 自适应码率 → 质量与性能双达

学习和提升音视频开发技术,推荐你加入我们的知识星球:【关键帧的音视频开发圈】

【音视频】视频转码性能调优

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论