【秒懂音视频开发】15

您所在的位置:网站首页 aac_ld 【秒懂音视频开发】15

【秒懂音视频开发】15

2024-07-10 11:04| 来源: 网络整理| 查看: 265

本文将分别通过命令行、编程2种方式进行AAC编码实战,使用的编码库是libfdk_aac。

要求

fdk-aac对输入的PCM数据是有参数要求的,如果参数不对,就会出现以下错误:

[libfdk_aac @ 0x7fa3db033000] Unable to initialize the encoder: SBR library initialization error Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height Conversion failed! 采样格式

必须是16位整数PCM。

采样率

支持的采样率有(Hz):

8000、11025、12000、16000、22050、24000、32000 44100、48000、64000、88200、96000 命令行 基本使用

最简单的用法如下所示:

# pcm -> aac ffmpeg -ar 44100 -ac 2 -f s16le -i in.pcm -c:a libfdk_aac out.aac # wav -> aac # 为了简化指令,本文后面会尽量使用in.wav取代in.pcm ffmpeg -i in.wav -c:a libfdk_aac out.aac

-ar 44100 -ac 2 -f s16le

PCM输入数据的参数

-c:a

设置音频编码器 c表示codec(编解码器),a表示audio(音频) 等价写法 -codec:a -acodec 需要注意的是:这个参数要写在aac文件那边,也就是属于输出参数

默认生成的aac文件是LC规格的。

ffprobe out.aac # 输出结果如下所示 Audio: aac (LC), 44100 Hz, stereo, fltp, 120 kb/s 常用参数 -b:a 设置输出比特率 比如-b:a 96k ffmpeg -i in.wav -c:a libfdk_aac -b:a 96k out.aac -profile:a 设置输出规格 取值有: aac_low:Low Complexity AAC (LC),默认值 aac_he:High Efficiency AAC (HE-AAC) aac_he_v2:High Efficiency AAC version 2 (HE-AACv2) aac_ld:Low Delay AAC (LD) aac_eld:Enhanced Low Delay AAC (ELD) 一旦设置了输出规格,会自动设置一个合适的输出比特率 也可以用过-b:a自行设置输出比特率 ffmpeg -i in.wav -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k out.aac -vbr 开启VBR模式(Variable Bit Rate,可变比特率) 如果开启了VBR模式,-b:a选项将会被忽略,但-profile:a选项仍然有效 取值范围是0 ~ 5 0:默认值,关闭VBR模式,开启CBR模式(Constant Bit Rate,固定比特率) 1:质量最低(但是音质仍旧很棒) 5:质量最高 VBR kbps/channel AOTs 1 20-32 LC、HE、HEv2 2 32-40 LC、HE、HEv2 3 48-56 LC、HE、HEv2 4 64-72 LC 5 96-112 LC

AOT是Audio Object Type的简称。

ffmpeg -i in.wav -c:a libfdk_aac -vbr 1 out.aac 文件格式

我曾在《重识音频》中提到,AAC编码的文件扩展名主要有3种:aac、m4a、mp4。

# m4a ffmpeg -i in.wav -c:a libfdk_aac out.m4a # mp4 ffmpeg -i in.wav -c:a libfdk_aac out.mp4 编程

需要用到2个库:

extern "C" { #include #include } // 错误处理 #define ERROR_BUF(ret) \ char errbuf[1024]; \ av_strerror(ret, errbuf, sizeof (errbuf)); 函数声明

我们最终会将PCM转AAC的操作封装到一个函数中。

extern "C" { #include } // 参数 typedef struct { const char *filename; int sampleRate; AVSampleFormat sampleFmt; int chLayout; } AudioEncodeSpec; class FFmpegs { public: FFmpegs(); static void aacEncode(AudioEncodeSpec &in, const char *outFilename); }; 函数实现 变量定义 // 编码器 AVCodec *codec = nullptr; // 上下文 AVCodecContext *ctx = nullptr; // 用来存放编码前的数据 AVFrame *frame = nullptr; // 用来存放编码后的数据 AVPacket *pkt = nullptr; // 返回结果 int ret = 0; // 输入文件 QFile inFile(in.filename); // 输出文件 QFile outFile(outFilename); 获取编码器

下面的代码可以获取FFmpeg默认的AAC编码器(并不是libfdk_aac)。

AVCodec *codec1 = avcodec_find_encoder(AV_CODEC_ID_AAC); AVCodec *codec2 = avcodec_find_encoder_by_name("aac"); // true qDebug() bit_rate = 32000; // 规格 ctx->profile = FF_PROFILE_AAC_HE_V2; 打开编码器 // 打开编码器 ret = avcodec_open2(ctx, codec, nullptr); if (ret < 0) { ERROR_BUF(ret); qDebug() format = ctx->sample_fmt; // 声道布局 frame->channel_layout = ctx->channel_layout; // 创建AVFrame内部的缓冲区 ret = av_frame_get_buffer(frame, 0); if (ret < 0) { ERROR_BUF(ret); qDebug() format); // 改为真正有效的样本帧数量 frame->nb_samples = ret / (chs * bytes); } // 编码 if (encode(ctx, frame, pkt, outFile) < 0) { goto end; } } // flush编码器 encode(ctx, nullptr, pkt, outFile);

encode函数专门用来进行编码,它的实现如下所示。

// 音频编码 // 返回负数:中途出现了错误 // 返回0:编码操作正常完成 static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, QFile &outFile) { // 发送数据到编码器 int ret = avcodec_send_frame(ctx, frame); if (ret < 0) { ERROR_BUF(ret); qDebug()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3