AAC(Advanced Audio Coding)是一种音频编码技术,出现于1997年,基于MPEG-2的音频编码技术。AAC具有高效的数据压缩能力和较高的音质,适用于各种音频应用场景。例如,在智能设备中,AAC技术被广泛应用于提升用户体验,提供高质量的音频体验。
一、FFmpeg 支持的 AAC 编码器对比
编码器 | 特性 | 适用场景 |
---|---|---|
aac | FFmpeg 原生实现,2015年后稳定支持,支持 LC-AAC 规格,兼容性高但音质略逊于第三方编码器 | 基础音频编码、兼容性优先场景 |
libfdk_aac | 第三方编码器(需启用 --enable-nonfree 编译3),支持 HE-AAC v1/v2,音质最优 |
高音质需求(如音乐流媒体) |
libaac | 第三方编码器,非 GPL 协议,性能与兼容性介于原生与 libfdk_aac 之间 | 商业项目(需规避 GPL 限制) |
二、关键参数与封装格式
-
AAC 封装格式
- **ADTS (Audio Data Transport Stream)**:适用于流媒体传输(如直播),每帧含独立头部信息,支持随机解码。
- **ADIF (Audio Data Interchange Format)**:需完整文件头,适合本地存储(如 .m4a 文件)。
-
核心参数设置
- 比特率控制 :
- 恒定比特率(CBR):
-b:a 128k
(立体声推荐值)。 - 动态比特率(VBR):
-vbr 4
(libfdk_aac 支持,数值范围 1-5,越高音质越好)。
- 恒定比特率(CBR):
- 采样率与格式 :
- FFmpeg 新版本默认支持 32 位浮点型(
AV_SAMPLE_FMT_FLTP
),需确保输入 PCM 格式匹配。
- FFmpeg 新版本默认支持 32 位浮点型(
- HE-AAC 模式 :
- 启用 HE-AAC v1:
-profile:a aac_he
;HE-AAC v2:-profile:a aac_he_v2
(需 libfdk_aac)。
- 启用 HE-AAC v1:
- 比特率控制 :
三、命令行示例
-
基础转码(原生 AAC 编码器)
ffmpeg -i input.wav -c:a aac -b:a 128k output.m4a # 输出为 M4A 格式
-
高音质转码(libfdk_aac)
ffmpeg -i input.mp4 -c:v copy -c:a libfdk_aac -profile:a aac_he -b:a 64k output.mp4 # HE-AAC v1 低码率高音质
-
流媒体场景(ADTS 封装)
ffmpeg -i input.pcm -c:a aac -f adts output.aac # 生成 ADTS 格式音频流
四、代码编解码示例
4.1、 AAC编码示例(PCM → AAC)
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
int encode_pcm_to_aac(const char* input_pcm, const char* output_aac) {
const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC); // 查找编码器:ml-citation{ref="2" data="citationList"}
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
// 参数配置(48kHz双通道,s16格式)
codec_ctx->bit_rate = 128000;
codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16; // 输入格式需为s16le:ml-citation{ref="6" data="citationList"}
codec_ctx->sample_rate = 48000;
codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
codec_ctx->channels = 2;
// 设置编码器属性(兼容Android等平台)
av_opt_set(codec_ctx->priv_data, "profile", "aac_low", 0); // LC规格:ml-citation{ref="6" data="citationList"}
if (avcodec_open2(codec_ctx, codec, NULL) < 0) { // 打开编码器:ml-citation{ref="5" data="citationList"}
fprintf(stderr, "编码器初始化失败\n");
return -1;
}
AVFrame *frame = av_frame_alloc();
frame->nb_samples = codec_ctx->frame_size; // 典型值1024:ml-citation{ref="6" data="citationList"}
frame->format = codec_ctx->sample_fmt;
frame->channel_layout = codec_ctx->channel_layout;
av_frame_get_buffer(frame, 0);
AVPacket *pkt = av_packet_alloc();
FILE *aac_out = fopen(output_aac, "wb");
// 编码循环(逐帧处理PCM)
while (fread(frame->data, 1, frame->nb_samples * 4, pcm_in) > 0) { // s16双通道每帧4字节/样本:ml-citation{ref="1" data="citationList"}
avcodec_send_frame(codec_ctx, frame);
while (avcodec_receive_packet(codec_ctx, pkt) >= 0) {
fwrite(pkt->data, 1, pkt->size, aac_out); // 写入AAC裸流:ml-citation{ref="5" data="citationList"}
av_packet_unref(pkt);
}
}
// 资源清理...
}
4.2、 AAC解码示例(AAC → PCM)
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
int decode_aac_to_pcm(const char* input_aac, const char* output_pcm) {
const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_AAC); // 查找解码器:ml-citation{ref="8" data="citationList"}
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (avcodec_open2(codec_ctx, codec, NULL) < 0) { // 初始化解码器:ml-citation{ref="4" data="citationList"}
fprintf(stderr, "解码器打开失败\n");
return -1;
}
AVPacket packet;
AVFrame *frame = av_frame_alloc();
FILE *pcm_out = fopen(output_pcm, "wb");
// 解码循环(处理AAC裸流)
while (read_aac_data(&packet)) { // 需自行实现数据读取:ml-citation{ref="7" data="citationList"}
avcodec_send_packet(codec_ctx, &packet);
while (avcodec_receive_frame(codec_ctx, frame) >= 0) {
fwrite(frame->data, 1, frame->nb_samples * 4, pcm_out); // 输出s16le格式:ml-citation{ref="4" data="citationList"}
}
av_packet_unref(&packet);
}
// 资源清理...
}
4.3、关键参数配置
参数/函数 | 作用 | 示例值/说明 |
---|---|---|
av_opt_set |
设置编码器私有参数(如规格、码率模式) | av_opt_set(ctx, "profile", "aac_he") (HE-AAC) |
frame->nb_samples |
每帧采样数 | 1024(对应48kHz时21.3ms帧长) |
codec_ctx->bit_rate |
目标码率 | 64000、128000、192000 |
avcodec_send_frame |
向编码器提交原始数据 | 需保证帧大小与nb_samples 一致 |
4.4、开发注意事项
-
输入格式要求
- PCM需为s16le格式,采样率支持8k/16k/44.1k/48k等标准值
- 若输入格式不匹配(如f32le),需通过
libswresample
重采样
-
编译依赖
使用 libfdk_aac 需通过--enable-libfdk-aac
和--enable-nonfree
参数编译 FFmpeg -
延迟优化
实时流场景可添加-tune zerolatency
参数减少编码延迟。 -
多平台兼容性
- Android NDK需使用
libfdk_aac
替代默认编码器(需编译时启用--enable-libfdk-aac
) - iOS/macOS需处理音频会话中断(如来电时的解码器重置)
- Android NDK需使用
-
性能优化
- 启用多线程编码:
codec_ctx->thread_count = 4
- 实时流场景建议使用
AV_CODEC_CAP_DELAY
检测编码延迟
- 启用多线程编码:
4.5、编译与调试
# 编译命令(需链接FFmpeg库)
gcc aac_demo.c -o aac_demo -lavcodec -lavutil -lswresample
# 验证编码结果(播放PCM)
ffplay -f s16le -ar 48000 -ac 2 output.pcm
# 检查AAC文件信息
ffprobe output.aac