使用libavformat封装H264+AAC为TS文件VLC无音频问题求助
问题根因分析
- 音视频帧写入顺序错误:当前代码先循环写完所有H264视频包,再循环写所有AAC音频包,而
av_interleaved_write_frame依赖输入的包按时间戳递增交错提供,将音视频包完全分段写入会导致TS文件的音视频时间轴完全错开。TS格式对帧交错的要求远高于MP4,VLC的解码逻辑容错性低于Win10自带播放器,识别不到连续可播放的音频帧序列就会没有声音,ffprobe解析全局流信息时也会因为音频帧都集中在文件尾部、头部没有有效音频参数样本而识别为声道数0。 - 音频PTS计算逻辑错误:代码复用了视频PTS的计算逻辑,用
in_stream->r_frame_rate计算音频帧间隔,但是音频流没有帧速率的概念,AAC每帧的时长固定为1024/采样率秒,用r_frame_rate计算出来的PTS完全错误,会导致播放器认为音频帧的时间戳无效直接丢弃。 - 裸AAC流缺失ADTS头:TS封装的AAC流要求每个AAC帧前带ADTS头存储采样率、声道数、码率等参数,如果输入的aoutput.aac是不带ADTS头的裸AAC流,MP4封装会把参数存在moov box里能正常识别,但TS没有全局存储音频参数的位置,只能从每个帧的ADTS头读取,就会出现参数识别失败声道数为0的问题。
- TS流专属参数未配置:复制完编解码参数后直接把
codec_tag设为0,TS封装要求音频流设置正确的stream_id,且AAC的codec_tag需要符合TS标准,未正确配置会导致PMT表中音频流的参数描述错误。
修复方案
- 修改帧读取逻辑为音视频交错写入:每次循环分别读取一帧视频和一帧音频,比较两者的PTS,先写入时间戳更小的包,保证写入顺序符合时间轴递增的要求。
- 修正音频PTS计算逻辑:
// 替换原有音频PTS计算代码 static int audio_frame_count = 0; const int aac_samples_per_frame = 1024; int sample_rate = in_stream->codecpar->sample_rate; pkt->pts = pkt->dts = audio_frame_count * aac_samples_per_frame; pkt->duration = aac_samples_per_frame; audio_frame_count++;
- 确认输入AAC流带ADTS头,如果是裸流,在封装前给每个AAC帧加上ADTS头,或者给输出音频流的codecpar补充完整的声道数、采样率、格式等参数,同时开启TS裸AAC支持。
- 配置TS流专属参数,创建输出流后添加对应配置:
// 视频流创建后设置 outstream->time_base = (AVRational){1, 90000}; outstream->id = 0x100; outstream->codecpar->codec_tag = av_codec_get_tag(avformat_get_mpegts_codec_tags(), outstream->codecpar->codec_id); // 音频流创建后设置 outstream->time_base = (AVRational){1, outstream->codecpar->sample_rate}; outstream->id = 0x101; outstream->codecpar->codec_tag = av_codec_get_tag(avformat_get_mpegts_codec_tags(), outstream->codecpar->codec_id);
内容的提问来源于stack exchange,提问作者Xia Qizhen
相关产品推荐
相关产品推荐

