如何将短视频片段转成TS格式且消除段间音频间隙?
我尝试用ffmpeg将一系列短视频片段(H.264视频+WAV音频)转成TS格式,生成的TS文件能正常播放,但在HLS播放器中播放时,片段之间存在明显的短暂音频间隙。如果先将所有片段拼接为单个文件,再转成TS格式并分割片段,播放则完全正常。
当前单独转码每对片段的命令:
ffmpeg -y -i seg_0.mp4 -i seg_0.wav -c:a libvo_aacenc -c:v copy -bsf:v h264_mp4toannexb seg_0.ts ffmpeg -y -i seg_1.mp4 -i seg_1.wav -c:a libvo_aacenc -c:v copy -bsf:v h264_mp4toannexb -output_ts_offset 2.01 seg_1.ts ffmpeg -y -i seg_2.mp4 -i seg_2.wav -c:a libvo_aacenc -c:v copy -bsf:v h264_mp4toannexb -output_ts_offset 4.02 seg_2.ts
手动生成M3U8后播放存在音频间隙;但先拼接再转码分割的命令播放正常:
ffmpeg -y -f concat -i mp4_list.txt -f concat -i wav_list.txt -c:a libvo_aacenc -c:v copy -bsf:v h264_mp4toannexb -flags +cgop -g 30 -hls_time 2 out2.m3u8
需求:在仍单独编码每个片段的前提下,消除HLS播放时的音频间隙。
1. 替换编码器并强制音频帧对齐
libvo_aacenc是老旧编码器,对无缝衔接的支持较差,建议替换为ffmpeg原生aac编码器,并指定统一的音频参数,保证帧对齐:
ffmpeg -y -i seg_0.mp4 -i seg_0.wav -c:a aac -b:a 128k -ac 2 -ar 44100 -c:v copy -bsf:v h264_mp4toannexb seg_0.ts
后续片段保留-output_ts_offset的同时,沿用相同的音频编码参数,确保前后片段的音频格式完全一致。
2. 强制视频关键帧对齐(CGOP)
单独转码时,若视频片段开头无关键帧,播放器切换片段时会等待关键帧加载,间接导致音频间隙。添加与拼接转码一致的关键帧参数:
ffmpeg -y -i seg_1.mp4 -i seg_1.wav -c:a aac -b:a 128k -c:v copy -bsf:v h264_mp4toannexb -flags +cgop -g 30 -output_ts_offset 2.01 seg_1.ts
注意:如果原视频片段本身没有开头关键帧,
-c:v copy无法添加关键帧,此时需要重新编码视频:将-c:v copy替换为-c:v libx264 -flags +cgop -g 30
3. 精确控制时间戳与音视频同步
添加时间码写入参数,帮助播放器更精准同步音视频;同时确保音视频时长完全匹配:
ffmpeg -y -i seg_2.mp4 -i seg_2.wav -c:a aac -b:a 128k -c:v copy -bsf:v h264_mp4toannexb -flags +cgop -g 30 -output_ts_offset 4.02 -write_tmcd 1 -shortest -align 1 seg_2.ts
-write_tmcd 1:写入时间码信息-shortest:确保音视频长度一致-align 1:强制音视频帧对齐
4. 用ffmpeg生成标准M3U8
手动编写M3U8容易出现时长、时间戳错误,建议转完所有TS片段后,用ffmpeg生成标准HLS播放列表:
# 先创建ts_list.txt,内容为所有TS片段路径: # file 'seg_0.ts' # file 'seg_1.ts' # file 'seg_2.ts' ffmpeg -f concat -i ts_list.txt -c copy -hls_time 2 -hls_segment_type mpegts final.m3u8
拼接后转码时,ffmpeg会全局处理音视频的帧对齐、关键帧分布和时间戳同步;而单独转码时每个片段是独立处理的,缺少全局同步逻辑。上述方案是将拼接转码的全局约束,应用到每个单独片段的转码过程中,让播放器切换片段时能实现无缝衔接。
内容的提问来源于stack exchange,提问作者Zvika

