音视频入门基础:FLV专题(21)——FFmpeg源码中,获取FLV文件音频信息的实现(上)

由于本文篇幅较长,分为上、中、下三篇。

一、引言

通过FFmpeg命令可以获取到FLV文件的音频压缩编码格式、音频采样率、通道数、音频码率信息:

cpp 复制代码
./ffmpeg -i XXX.flv

而由《音视频入门基础:FLV专题(9)------Script Tag简介》和《音视频入门基础:FLV专题(18)------Audio Tag简介》可以知道:FLV文件中名称为"onMetadata"的Script Tag、每个Audio Tag的AudioTagHeader、AudioSpecificConfig都会包含音频信息。

名称为"onMetadata"的Script Tag:

每个Audio Tag的AudioTagHeader:

AudioSpecificConfig:

可以看到,FLV文件中的上述三个地方都会存在音频信息,有些信息比如:音频压缩编码格式、音频采样率、通道数甚至是重复的。所以FFmpeg到底获取的是哪个地方的音频信息呢,本文为大家揭开谜底。

二、音频压缩编码格式

FFmpeg获取FLV文件的音频压缩编码格式,获取的是Audio Tag的AudioTagHeader中的音频压缩编码格式。由《音视频入门基础:FLV专题(18)------Audio Tag简介》可以知道,AudioTagHeader存在一个占4位的SoundFormat属性,表示音频的压缩编码格式:

0:Linear PCM, platform endian

1:ADPCM

2:MP3

3:Linear PCM, little endian

4:Nellymoser 16 kHz mono

5:Nellymoser 8 kHz mono

6:Nellymoser

7:G.711 A-law logarithmic PCM

8:G.711 mu-law logarithmic PCM

9:reserved

10:AAC

11:Speex

14:MP3 8 kHz

15:Device-specific sound

由《音视频入门基础:FLV专题(19)------FFmpeg源码中,解码Audio Tag的AudioTagHeader,并提取AUDIODATA的实现》可以知道,FFmpeg源码中使用flv_read_packet函数来读取每个Tag的信息。如果判断出该Tag为Audio Tag,flv_read_packet函数中会通过下面代码块将AudioTagHeader的SoundFormat属性提取出来,转换得到音频压缩编码格式。将音频压缩编码格式赋值给st->codecpar->codec_id中。st->codecpar为指向一个AVCodecParameters类型变量的指针:

cpp 复制代码
        if (!st->codecpar->codec_id) {
            flv_set_audio_codec(s, st, st->codecpar,
                                flags & FLV_AUDIO_CODECID_MASK);
        //...
        }

然后在flv_read_packet函数外部,通过avcodec_parameters_to_context函数将AVCodecParameters的codec_id赋值给AVCodecContext的codec_id:

cpp 复制代码
int avcodec_parameters_to_context(AVCodecContext *codec,
                                  const AVCodecParameters *par)
{
//...
    codec->codec_id   = par->codec_id;
//...
}

然后在dump_stream_format函数中,通过avcodec_string函数中的语句:codec_name = avcodec_get_name(enc->codec_id) 拿到AVCodecContext的codec_id对应的音频压缩编码格式名称。最后再在dump_stream_format函数中将音频压缩编码格式打印出来:

cpp 复制代码
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
{
//...
    codec_name = avcodec_get_name(enc->codec_id);
//...
}

所以FFmpeg获取FLV文件的音频压缩编码格式,获取的是Audio Tag的AudioTagHeader中的音频压缩编码格式:

三、音频压缩编码格式的profile

音频压缩编码格式还有附带的profile(规格)。比如音频压缩编码格式为AAC,根据《ISO14496-3-2009.pdf》第124页,还有AAC Main、AAC LC、AAC SSR、AAC LTP这几种规格:

FFmpeg获取FLV文件的音频压缩编码格式的profile,获取的是AudioSpecificConfig中的audioObjectType。由《音视频入门基础:AAC专题(11)------AudioSpecificConfig简介》可以知道,FLV文件中的音频为AAC时,正常情况下它必定存在一个Audio Tag包含Audio Specific Config,而Audio Specific Config中存在一个占5位或11位的audioObjectType属性,表示音频对象类型:

0: Null

1: AAC Main

2: AAC LC (Low Complexity)

3: AAC SSR (Scalable Sample Rate)

4: AAC LTP (Long Term Prediction)

5: SBR (Spectral Band Replication)

6: AAC Scalable

7: TwinVQ

8: CELP (Code Excited Linear Prediction)

9: HXVC (Harmonic Vector eXcitation Coding)

10: Reserved

11: Reserved

12: TTSI (Text-To-Speech Interface)

13: Main Synthesis

14: Wavetable Synthesis

15: General MIDI

16: Algorithmic Synthesis and Audio Effects

17: ER (Error Resilient) AAC LC

18: Reserved

19: ER AAC LTP

20: ER AAC Scalable

21: ER TwinVQ

22: ER BSAC (Bit-Sliced Arithmetic Coding)

23: ER AAC LD (Low Delay)

24: ER CELP

25: ER HVXC

26: ER HILN (Harmonic and Individual Lines plus Noise)

27: ER Parametric

28: SSC (SinuSoidal Coding)

29: PS (Parametric Stereo)

30: MPEG Surround

31: (Escape value)

32: Layer-1

33: Layer-2

34: Layer-3

35: DST (Direct Stream Transfer)

36: ALS (Audio Lossless)

37: SLS (Scalable LosslesS)

38: SLS non-core

39: ER AAC ELD (Enhanced Low Delay)

40: SMR (Symbolic Music Representation) Simple

41: SMR Main

42: USAC (Unified Speech and Audio Coding) (no SBR)

43: SAOC (Spatial Audio Object Coding)

44: LD MPEG Surround

45: USAC

由《音视频入门基础:AAC专题(12)------FFmpeg源码中,解码AudioSpecificConfig的实现》可以知道,FFmpeg源码中使用decode_audio_specific_config_gb函数来读取AudioSpecificConfig的信息。decode_audio_specific_config_gb函数中会调用ff_mpeg4audio_get_config_gb函数,而ff_mpeg4audio_get_config_gb函数中,通过语句:c->object_type = get_object_type(gb) 获取AudioSpecificConfig的audioObjectType属性。执行decode_audio_specific_config_gb函数后,m4ac指向的变量会得到从AudioSpecificConfig中解码出来的属性:

cpp 复制代码
static inline int get_object_type(GetBitContext *gb)
{
    int object_type = get_bits(gb, 5);
    if (object_type == AOT_ESCAPE)
        object_type = 32 + get_bits(gb, 6);
    return object_type;
}

然后在decode_audio_specific_config_gb函数外部,通过aac_decode_frame_int函数将上一步得到的audioObjectType属性赋值给AVCodecContext的profile:

cpp 复制代码
static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
                                int *got_frame_ptr, GetBitContext *gb,
                                const AVPacket *avpkt)
{
//...
    // The AV_PROFILE_AAC_* defines are all object_type - 1
    // This may lead to an undefined profile being signaled
    ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
//...
}

然后在dump_stream_format函数中,通过avcodec_string函数中的语句:profile = avcodec_profile_name(enc->codec_id, enc->profile)拿到上一步中得到的AVCodecContext的profile。最后再在dump_stream_format函数中将profile打印出来:

cpp 复制代码
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
{
//...
    profile = avcodec_profile_name(enc->codec_id, enc->profile);
//...
}

所以FFmpeg获取FLV文件的音频压缩编码格式的profile,获取的是AudioSpecificConfig中的audioObjectType:

相关推荐
郑午时光6 小时前
全球首发!2026年适合IP短剧长视频的AI视频生成工具,即梦seedance2.5轻松做短剧
人工智能·tcp/ip·音视频
苏灿烤鱼10 小时前
从微信公众号内容到视频号视频:自动化视频生成的技术实现
人工智能·python·ffmpeg
Fluxart.ai10 小时前
AI 视频生成接入电商流水线的工程实践:从单条测试到日均 50 条的踩坑全记录
音视频
IT小白杨10 小时前
2026年短视频平台风控技术解析:设备指纹体系、行为建模与环境隔离的边界在哪里
chrome·经验分享·架构·音视频·安全架构·指纹浏览器
桐桐桐12 小时前
视频画面裁剪与尺寸压缩实战:ffmpeg crop/scale 用法与在线替代
ffmpeg·音视频·视频
阿童木写作13 小时前
跨境电商图片翻译工具推荐:批量AI翻译+视频字幕+智能抠图
大数据·人工智能·python·音视频
勤劳X码农14 小时前
2026年四款免费配音轻量工具参数记录与实测数据
音视频
乐橙开放平台14 小时前
老旧小区监控事件驱动派单:基于 setMessageCallback 的 msgType 分级与工单闭环实现
后端·物联网·音视频
lailai041015 小时前
视频离线观看工具的多维度比较分析
音视频
程序员老陆17 小时前
音频为什么不编码成“声卡格式”(例如S16)?因为声卡只负责响,编码器只负责省
ffmpeg·音视频