利用ffmpeg库实现音频AAC编解码
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
相关文章:
利用ffmpeg库实现音频AAC编解码
AAC(Advanced Audio Coding)是一种音频编码技术,出现于1997年,基于MPEG-2的音频编码技术。AAC具有高效的数据压缩能力和较高的音质,适用于各种音频应用场景。例如,在智能设备中,AAC技术被广泛…...
微博ip属地不发微博会不会变
随着社交媒体的普及,微博作为其中的佼佼者,一直备受关注。而且微博上线了显示用户IP属地的功能,这一功能旨在减少冒充热点事件当事人、恶意造谣、蹭流量等不良行为,确保传播内容的真实性和透明度。然而,这也引发了一些…...
appium之Toast元素识别
Appium之Toast元素识别教程与实例 一、Toast简介 Toast是Android系统中的轻量级消息提示框,以浮动形式短暂显示(通常2-3秒),无法被点击且不会获取焦点。常见于登录失败、操作提示等场景,如“密码错误”或“网络异常”。…...
「JavaScript深入」WebSocket:高效的双向实时通信技术
WebSocket WebSocket 的特点1. 全双工通信2. 持久连接3. 低延迟4. 二进制和文本支持5. 连接管理6. 二进制数据传输 WebSocket 协议详解1. 握手过程2. 数据帧结构 WebSocket 的实现服务器端实现(Node.js ws库)1. 基础服务器2. 广播功能实现3. 心跳机制客…...
C#从入门到精通(1)
目录 第一章 C#与VS介绍 第二章 第一个C#程序 (1)C#程序基本组成 1.命名空间 2.类 3.Main方法 4.注释 5.语句 6.标识符及关键字 (2)程序编写规范 1.代码编写规则 2.程序命名方法 3.元素命名规范 第三章 变量 &…...
配置阿里云yum源
配置阿里云yum源 修改默认的yum仓库,把原有的移动到创建的目录里(踢出国外的yum源) # 切换到/ect/yum.repos.d/目录下 cd /etc/yum.repos.d/ # 新建repo目录 mkdir repo # 把原有的移动到创建的目录里 mv ./*.repo ./repo/配置yum源 # 找到…...
头歌实训--Pandas合并数据集--第3关:案例:美国各州的统计数据
任务描述 本关为练习关卡,请按照编程要求完成任务,获取美国各州2010年的人口密度排名。 import pandas as pd import numpy as npdef task3():#********** Begin **********##读取三个csv文件pop pd.DataFrame(pd.read_csv("./step3/state-popula…...
仿“东方甄选”直播商城小程序运营平台
在公域直播流量红利趋于饱和、流量成本大幅攀升的当下,私域直播为企业开辟了新的流量聚集和转化渠道,特别是对于那些希望在私域流量领域取得突破的品牌商家来说,直播场景以其独特的高频互动氛围,相比其他运营方式,展现…...
CentOS 7.9 安装 Python 3.10 详细步骤及常见问题解决
一、环境准备与依赖安装 更新系统与开发工具 sudo yum update -y sudo yum groupinstall "Development Tools" -y sudo yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel \ readline-devel tk-devel libffi-devel gdbm-devel db4-de…...
ORACLE 19.8版本数据库环境EXPDP导数据的报错处理
近期用户在做EXPDP导出时,报错异常termination终止;EXPDP本身是简单的功能并且这个环境也是经常做导出的,到底是什么原因导致了这个问题呢? 导出脚本报错: 分析导出日志,当时系统资源充足但是进程启动失败,…...
LabVIEW运动控制(二):EtherCAT运动控制器的多轴示教加工应用(下)
前面两节课程分别给大家介绍了“控制器连接、定时获取轴状态、轴坐标、控制器型号、轴参数设置、IO控制、Basic文件下载”(详情点击→LabVIEW运动控制(二):EtherCAT运动控制器的多轴示教加工应用(上)&#…...
Ubuntu Qt: no service found for - “org.qt-project.qt.mediaplayer“
1、前言 在一次项目过程中,因项目需求,需要将windows开发的Qt项目迁移到ubuntu系统中,且在某个功能项中需要播放音频,在windows系统中能够正常运行,但在ubuntu系统中却显示defaultServiceProvider::requestService(): …...
C++ 各种map对比
文章目录 特点比较1. std::map2. std::unordered_map3. std::multimap4. std::unordered_multimap5. hash_map(SGI STL 扩展) C 示例代码代码解释 特点比较 1. std::map 底层实现:基于红黑树(一种自平衡的二叉搜索树)…...
纯内网环境安装1Panel面板与商店应用
文章目录 前序准备开始联网机器配置1Panel配置安装所有离线需要的应用导出Docker镜像导出1Panel配置 离线机器配置安装1Panel覆盖配置导入容器镜像重建应用 关于Jar包的运行 前序 之前一篇文章讲解了如何在内网环境下安装1Panel并操作商店应用安装应用程序,但是在一…...
软件工程面试题(三)
1.简单介绍下java?Spring的AOP,IOC的讲述 对struts2的了解,1,2的比较 xml的了解 J2ee的webserviced的协议? Spring AOP:代理机制 Spring提供的自动代理机制 Spring的IoC来实组件之间的依赖关系注入, 使控制层及…...
【 C++】构造函数和成员函数
详细探讨 C 中的构造函数和成员函数(方法),并通过代码示例进行说明。 1. 构造函数 (Constructors) 目的: 构造函数是一种特殊的成员函数,其主要目的是在创建对象时初始化对象的数据成员。名称: 构造函数的…...
OpenCV计算摄影学(22)将输入的彩色图像转换为两种风格的铅笔素描效果函数pencilSketch()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 铅笔风格非写实线描图。 该函数通过图像处理技术将输入的彩色图像转换为两种风格的铅笔素描效果: dst1:炭笔效果的灰度图…...
Event driven agentic document workflows 笔记 - 1
1. 课程介绍 主题:与 LlamaIndex 合作构建的事件驱动代理文档工作流讲师:Laurie Voss(LlamaIndex 开发者关系副总裁) 2. 代理文档工作流简介 定义:基于代理的应用程序,用于自动化端到端文档处理工作流。…...
影响单模光纤耦合效率的分析
影响单模光纤耦合效率的因素 如果想使单模光纤的耦合效率最高,入射光束需要满足以下条件: (1)入射光束接近高斯光; (2)入射光束从光纤端面正入射; (3)入射…...
windows+ragflow+deepseek实战之一excel表查询
ragflows平台部署参考文章 Win10系统Docker+DeepSeek+ragflow搭建本地知识库 ragflow通过python实现参考这篇文章 ragflow通过python实现 文章目录 背景效果1、准备数据2、创建知识库3、上传数据并解析4、新建聊天助理5、测试会话背景 前面已经基于Win10系统Docker+DeepSeek+…...
从“不敢买大”到“按墙选屏”,海信电视如何凭百吋重构客厅?
电视买小了,成为茜茜新房入住后最大的遗憾。 新房装修的时候,茜茜担心电视买大了眼睛看着累,因此把尺寸选在了65吋。结果入住后,孩子看动画片嚷着“画面太小”,老公看球赛吐槽“看不清球员号码”,全家追剧…...
ABAP 长文本编辑器
加个屏幕 *&---------------------------------------------------------------------* *& Report YDEMO2 *&---------------------------------------------------------------------* *& *&---------------------------------------------------------…...
【K8S】ImagePullBackOff状态问题排查。
ImagePullBackOff 是在使用 Kubernetes(K8s)时经常遇到的一种错误状态,下面为你详细介绍其含义、可能的原因及解决办法。 含义 当你在 K8s 集群中创建一个 Pod 时,Kubelet 会尝试从指定的镜像仓库拉取所需的容器镜像。如果拉取镜…...
Logstash 使用指南
Logstash 是一个开源的数据收集引擎,能够从多种数据源收集数据,进行转换和过滤,并将数据发送到指定的目的地(如 Elasticsearch、文件、数据库等)。它是 Elastic Stack(ELK Stack)的重要组成部分…...
Python 位运算符大全
在 Python 中,位运算符用于对整数进行位级别的操作。位运算符直接操作二进制位,适用于处理二进制数据、位掩码、权限控制等场景。Python 提供了多种位运算符,包括按位与、按位或、按位异或、按位取反、左移和右移等。 1. 常见的位运算符 运算符描述示例&按位与a & b…...
MATLAB 调用arduino uno
为了授课,必须重新把arduino用上。 采用MATLAB编码,可以简化相关程序授课部分 1 安装包 MATLAB Support Package for Arduino Hardware - File Exchange - MATLAB Central (mathworks.com) 需要这个插件。 当然也可下载simulink的模块,但…...
Git——分布式版本控制工具使用教程
本文主要介绍两种版本控制工具——SVN和Git的概念,接着会讲到Git的安装,Git常用的命令,以及怎么在Vscode中使用Git。帮助新手小白快速上手Git。如果想直接上手用Vscode操作远程仓库则直接看7和9即可! 目录 1. SVN和Git介绍 1.1 …...
HarmonyOS 开发中条件渲染的选择:if/else 与取反操作的对比与实践
在HarmonyOS开发里,if/else 条件渲染和取反操作(常借助三元运算符)都能根据不同情况设置组件属性值。下面从多个维度分析如何选择,以及各自的利弊,并附上代码示例。 选择方法 简单二元条件:当条件只有两种…...
【数据分析】数据筛选与访问行列元素3
访问元素 .loc属性可以通过传入index的值访问行数据。 .loc属性允许传入两个参数,分别是index的值和columns的值,参数间用“逗号”隔开,这样便可以访问数据中的元素。 1. 访问单个元素 访问单个元素比较简单,只需要通过它的in…...
前沿技术一览科技改变生活新趋势
虚拟现实技术最近在教育里变得特别火。它能让人感觉像是真的到了另一个地方。比如学生戴上VR眼镜,就能“走进”历史事件的发生地或者深入细胞内部去了解生命科学。 这种学习方法能让知识更生动。学生不再只是看书听讲,而是可以亲手体验。比如在学习地理…...
