最致命的问题:
MP3输入流存在ID3v2标签和拼接异常,导致解复用器主动跳过样本:
[mp3] demuxer injecting skip 1105 / discard 0 invalid concatenated file detected
最终解法: 强制音频作为主时钟源,视频流完全适配音频时间基准
🔍 问题演变过程 & 关键发现
阶段 | 现象 | 错误日志关键线索 | 尝试方案 |
---|---|---|---|
初期 | 音频周期性卡顿 | [mp3] pad 576 741 帧大小异常 | 调整重采样参数/队列大小 |
中期 | 2秒左右音频空白 | demuxer injecting skip 1105 样本被跳过 | 禁用时间同步(-async 0 ) |
后期 | 音画不同步 | Audio time base mismatch 时间基准冲突 | 复杂滤镜强制同步 |
解决期 | 音频流畅但视频延迟 | 视频PTS落后音频12000ms | 确立音频主时钟地位 |
💡 核心问题本质
- MP3元数据污染
ID3v2标签(217字节)导致解复用器错误计算时间戳 - 时间基准冲突plaintext复制
音频时基:1/14112000 (精密音乐时基) 视频时基:1/1000 (标准毫秒时基) → 重采样器误判需插入静音补偿
- FLV容器同步机制
RTMP服务器强制要求音视频PTS线性递增
任一流时间戳跳变导致播放器缓冲重置
🚀 最终解决方案
配置核心思想
graph LR
A[音频输入] -->|主时钟源| B[asetpts=N/SR/TB]
C[视频输入] -->|从属时钟| D[setpts=PTS-STARTPTS]
B --> E[FLV输出]
D --> E
主时钟源从属时钟音频输入asetpts=N/SR/TB视频输入setpts=PTS-STARTPTSFLV输出
关键参数说明
# 强制音频为时间基准(主时钟)
-filter_complex \
'[1:a]asetpts=N/SR/TB[audio]; \ # 保持原始音频时间戳
[0:v]setpts=PTS-STARTPTS[video]' # 视频PTS从零开始对齐音频
# 视频流完全服从音频
-vsync 2 # 视频帧率严格恒定
-async 0 # 禁用音频拉伸补偿
-copyts # 继承输入流时间戳
-use_wallclock_as_timestamps 1 # 输入流采用系统时钟
完整FFmpeg命令
cmd = [
'ffmpeg', '-y',
'-loglevel', 'warning', # 生产环境建议
# 视频输入(采用系统时钟)
'-f', 'image2pipe',
'-thread_queue_size', '20480',
'-s', f'{width}x{height}',
'-r', str(fps),
'-use_wallclock_as_timestamps', '1',
'-i', '-',
# 音频输入(主时钟源)
'-f', 'mp3',
'-thread_queue_size', '131072',
'-fflags', '+discardcorrupt',
'-i', f'pipe:{audio_pipe}',
# 滤镜同步处理
'-filter_complex',
'[1:a]asetpts=N/SR/TB[audio];'
'[0:v]format=yuv420p,setpts=PTS-STARTPTS[video]',
# 音频编码
'-map', '[audio]',
'-ac', '1',
'-ar', '11025',
'-c:a', 'aac',
'-b:a', '32k',
# 视频编码
'-map', '[video]',
'-c:v', 'libx264',
'-preset', 'ultrafast',
'-tune', 'zerolatency',
'-g', '30',
'-pix_fmt', 'yuv420p',
# 同步控制
'-vsync', '2',
'-async', '0',
'-flvflags', 'no_duration_filesize',
# 输出
'-f', 'flv',
rtmp_url
]
⚠️ 血泪经验总结
- 输入源预处理
- 使用
ffprobe
检测MP3文件头:ffprobe -show_streams audio_pipe
- 通过
-ss 0.2
跳过开头异常数据
- 使用
- 队列容积法则
视频队列 = 帧率 * 2秒 # 30fps → 60 音频队列 = 采样率 * 0.5秒 / 样本帧 # 11025Hz → 5512
- 终极调试建议
1. 单独测试音频流 ffplay -i pipe:3 -fflags +discardcorrupt
2. 可视化同步差异 ffmpeg -i rtmp://... -vf "drawtext=text='DELTA\: %{pts}-%{metadata\\:lavfi.audio_pts}':x=10:y=10" -f null -
真理时刻:
当音视频不同步时,永远让视频适应音频!
人耳对音频中断的敏感度是视频卡顿的10倍(神经科学研究表明)
希望你的直播之路不再有“卡顿”! 🎤📹
Comments | NOTHING