【秒懂音视频开发】15 |
您所在的位置:网站首页 › aac_ld › 【秒懂音视频开发】15 |
本文将分别通过命令行、编程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 LCAOT是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 |