Test
背景痛点分析
在视频会议、直播连麦等场景下,画中画效果需要解决三个核心问题:
- 音视频同步:子画面与主画面超过 3 帧不同步就会明显感知
- 分辨率自适应:不同输入源的分辨率 / 宽高比动态适配
- 性能开销:4K 视频合成时 CPU 占用率常超过 200%

技术方案对比
| 方案类型 | 延迟(ms) | CPU 占用率 | 开发复杂度 |
|—————-|———|———-|————|
| filter_complex | 12.5 | 65% | 低 |
| 独立进程 | 32.8 | 82% | 高 |
测试环境:Intel i7-11800H/32GB RAM/Ubuntu 20.04
基础实现
命令行方案
ffmpeg -i main.mp4 -i sub.mp4 \
-filter_complex \
"[1]scale=iw/3:ih/3 [sub]; \
[0][sub]overlay=W-w-10:H-h-10:enable='between(t,5,20)'" \
-c:v libx264 -preset fast output.mp4
关键参数解析:
scale=iw/3:ih/3将子画面缩放到原尺寸 1 /3overlay=W-w-10:H-h-10定位到主画面右下角(距边界 10 像素)enable='between(t,5,20)'控制仅在 5 -20 秒显示画中画
API 实现(C++ 核心代码)
// 创建滤镜图
AVFilterGraph *graph = avfilter_graph_alloc();
// 构建 overlay 滤镜
AVFilterContext *overlay_ctx;
avfilter_graph_create_filter(&overlay_ctx,
avfilter_get_by_name("overlay"),
"pip", "x=W-w-10:y=H-h-10", NULL, graph);
// 处理帧数据
while (av_read_frame(fmt_ctx, &packet) >= 0) {if (packet.stream_index == video_stream_idx) {avcodec_send_packet(dec_ctx, &packet);
while (avcodec_receive_frame(dec_ctx, frame) == 0) {
// 手动设置 PTS
frame->pts = av_rescale_q(frame_num++,
(AVRational){1, 25},
out_stream->time_base);
av_buffersrc_add_frame(src_ctx, frame);
}
}
}
性能优化
VAAPI 硬件加速
ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi \
-i input.mp4 -vf "hwupload,overlay_vaapi" output.mp4
线程池配置
# ~/.ffmpeg/ffmpeg.conf
thread_type frame
thread_count 8
优化前后对比(4K@30fps):
| 配置项 | 帧处理时间 | 内存占用 |
|————–|————|———-|
| 默认参数 | 42ms | 1.2GB |
| 优化后参数 | 18ms | 680MB |
常见问题
- PTS 校准错误:
- 必须统一所有输入流的时间基(time_base)
-
使用
av_rescale_q()进行时间戳转换 -
内存泄漏检测:
- 使用 Valgrind 检查
av_frame_alloc()/av_packet_alloc() - 特别注意滤镜图的释放
avfilter_graph_free()
延伸方向
可以尝试编译 FFmpeg 的 WebAssembly 版本,在浏览器中实现画中画处理。实测表明:
- 使用 SIMD 指令后性能提升 3 倍
- 但 WebAssembly 版延迟比原生方案高 2 - 3 倍

通过上述方案,我们在直播系统中实现了 <2ms 的合成延迟,CPU 占用率控制在 40% 以下。关键点在于硬件加速与合理的线程模型设计。
正文完
评论(没有评论)