音频编码入门:深入理解AAC与PCM的核心差异与应用场景
基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。架构理解:掌握实时语音应用的完整技术链路(ASR→LLM→TTS)技能提升:学会申请、配置与调用火山引擎AI服务定制能力:通过代码修改自定义角色性
快速体验
在开始今天关于 音频编码入门:深入理解AAC与PCM的核心差异与应用场景 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。
我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API?
这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。

从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验
音频编码入门:深入理解AAC与PCM的核心差异与应用场景
刚接触音频开发的程序员们,是否经常被各种音频格式搞得晕头转向?今天我们就来聊聊最常见的两种格式——PCM和AAC,它们就像音频世界的"原材料"和"压缩包",用对了能让应用如虎添翼,用错了可能导致音质惨不忍睹或者流量爆炸。
为什么需要了解音频编码?
想象一下,你开发了一个语音聊天App,用户抱怨通话时声音断断续续,或者发现App特别耗流量。这些问题很可能就出在音频编码的选择上。PCM和AAC是两种完全不同的编码思路:
- PCM(Pulse Code Modulation,脉冲编码调制)是原始音频数据,相当于未经压缩的"数字录音"
- AAC(Advanced Audio Coding,高级音频编码)是经过智能压缩的音频格式,会舍弃人耳不易察觉的声音细节
新手最容易犯的错就是无脑使用PCM传输音频,导致:
- 带宽浪费:1分钟立体声PCM音频可能占用10MB流量
- 存储压力:用户录音文件体积暴涨
- 延迟增加:大数据量导致网络传输变慢
反过来,如果对音质要求高的场景(如音乐制作)错误使用AAC,会导致:
- 高频细节丢失:乐器声音变得"闷闷的"
- 多次转码损耗:每次编辑保存都造成音质下降
PCM vs AAC技术参数对比
先看一个直观的参数对比表:
| 特性 | PCM | AAC |
|---|---|---|
| 数据性质 | 原始音频数据 | 压缩音频数据 |
| 压缩率 | 无压缩(1:1) | 通常10:1~20:1 |
| 采样率支持 | 任意(常见44.1kHz/48kHz) | 固定(8kHz-96kHz) |
| 位深 | 16bit/24bit/32bit | 压缩后无固定位深 |
| 音质 | 无损 | 有损(但人耳难察觉差异) |
| 典型文件扩展名 | .wav .pcm | .aac .m4a .mp4 |
| CPU占用 | 低 | 编码时较高 |
AAC的压缩原理很有意思,它利用了"心理声学模型"——简单说就是人耳对某些频率不敏感,比如:
- 同时出现强音和弱音时,弱音会被掩盖
- 极高和极低频率人耳分辨能力差
- 某些方向的声波人耳难以定位
通过频谱图可以明显看到,AAC会智能保留主要频率(下图红色部分),而舍弃次要信息(蓝色部分):

实战代码示例
FFmpeg格式转换
最常用的PCM转AAC命令(需要安装FFmpeg):
ffmpeg -f s16le -ar 44100 -ac 2 -i input.pcm \
-c:a aac -b:a 128k -profile:a aac_low output.aac
关键参数说明:
-f s16le: 指定输入是16bit小端PCM-ar 44100: 采样率44.1kHz-ac 2: 双声道立体声-b:a 128k: 设置比特率为128kbps(音质与体积的平衡点)-profile:a aac_low: 使用低复杂度配置(适合移动设备)
Android实时编码示例
Android上采集PCM并实时编码为AAC的代码框架:
// 1. 配置AudioRecord采集PCM
int bufferSize = AudioRecord.getMinBufferSize(44100,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
44100, AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
// 2. 创建AAC编码器
MediaCodec encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = MediaFormat.createAudioFormat("audio/mp4a-latm", 44100, 2);
format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
format.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel.AACObjectLC);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// 3. 启动编码线程(简略版)
encoder.start();
while (recording) {
ByteBuffer[] inputBuffers = encoder.getInputBuffers();
int inputIndex = encoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
ByteBuffer buffer = inputBuffers[inputIndex];
int readSize = recorder.read(buffer, buffer.remaining());
if (readSize > 0) {
encoder.queueInputBuffer(inputIndex, 0, readSize,
System.nanoTime()/1000, 0);
}
}
// ...处理输出数据
}
进阶优化与注意事项
实时编码延迟优化
移动端实时通话场景下,这三个参数直接影响延迟:
- 采集缓冲区大小:太小会导致CPU负载高,太大会增加延迟
- 编码帧大小:AAC通常每帧1024个样本(约23ms@44.1kHz)
- 网络发送间隔:建议累积2-3帧再发送减少包头开销
经验值参考:
- 语音通话:20ms采集缓冲区+64kbps码率
- 音乐直播:50ms缓冲区+128kbps码率
法律风险提示
注意:AAC是专利技术,商业应用需要获得授权!个人学习和非商业应用通常没问题,但产品化前请务必确认授权情况。作为替代方案可以考虑Opus编码(后面会提到)。
常见问题排查指南
遇到音频问题?先检查这三个典型场景:
-
杂音/爆音问题
- 现象:播放时有"噼啪"声
- 原因:采样率不匹配(如44.1kHz转48kHz未重采样)
- 解决:统一所有环节的采样率,或用
swresample正确转换
-
AAC编码失败
- 现象:MediaCodec报错"配置失败"
- 原因:不支持的参数组合(如采样率32000+HE-AAC)
- 解决:改用标准参数,或检查设备支持的编码规格
-
音量突然变小
- 现象:转码后音量降低30%
- 原因:PCM是整数格式而AAC使用浮点,未做归一化处理
- 解决:编码前对PCM数据进行峰值检测和增益调整
思考与拓展
现在你已经掌握了AAC和PCM的核心知识,不妨尝试以下实验:
- 用FFmpeg将同一段音乐分别保存为PCM和不同码率的AAC,用频谱分析工具观察差异
- 在Android设备上测试实时编码的CPU占用与延迟关系
- 探索Opus编码——一种更适合实时通信的开源编码格式,对比它与AAC在语音通话中的表现
想亲手实践更多AI与音视频技术的结合?推荐体验从0打造个人豆包实时通话AI实验,用火山引擎的语音大模型构建属于你的智能语音助手,实战中巩固音频处理知识。我自己尝试后发现,把理论知识和实际应用结合起来学习,效果会事半功倍。
实验介绍
这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。
你将收获:
- 架构理解:掌握实时语音应用的完整技术链路(ASR→LLM→TTS)
- 技能提升:学会申请、配置与调用火山引擎AI服务
- 定制能力:通过代码修改自定义角色性格与音色,实现“从使用到创造”
从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验
更多推荐

所有评论(0)