Opus 音频编码格式

0 阅读26分钟

Opus 音频编码格式

2020年3月15日

目录


什么是音频编码?

想象一下,你录制了一段 1 分钟的音乐。如果直接保存原始音频数据,可能需要几十甚至上百 MB 的存储空间。这就像用相机拍摄照片时,如果保存 RAW 格式(原始数据),文件会非常大。

音频编码就像是给音频"打包压缩"的过程:

  • 编码(Encoding):将原始音频数据压缩成更小的文件,方便存储和传输
  • 解码(Decoding):将压缩后的文件还原成可以播放的音频
原始音频数据 (很大)  →  [编码器]  →  压缩后的文件 (很小)  →  [解码器]  →  可播放的音频

Opus 就是由 Xiph.Org 基金会开发的一种先进的音频编码格式,它在保证音质的同时,能够实现很高的压缩率,特别适合网络传输和实时通信。

音频编码基础知识

在深入了解 Opus 之前,我们需要先理解几个基本概念。

采样率(Sample Rate)

采样率是指每秒钟对声音进行采样的次数,单位是 Hz(赫兹)。

通俗理解:想象你在画一条曲线,采样率就是每秒画多少个点。点越多,曲线越平滑,音质越好。

采样率示意图:
低采样率 (8 kHz):  ●     ●     ●     ●     (点少,音质差)
高采样率 (48 kHz): ●●●●●●●●●●●●●●●●●●● (点多,音质好)

常见采样率

  • 8 kHz:电话音质(只保留人声的主要频率)
  • 16 kHz:语音通话(如微信语音)
  • 44.1 kHz:CD 音质(音乐标准)
  • 48 kHz:专业音频、视频制作
  • 96 kHz / 192 kHz:高保真录音

奈奎斯特采样定理:采样率必须是音频最高频率的 2 倍以上,才能完整还原音频。例如,要还原 20 kHz 的声音,采样率至少需要 40 kHz。

比特率(Bitrate)

比特率是指每秒钟传输或存储的音频数据量,单位是 kbps(千比特每秒)。

通俗理解:比特率就像视频的"清晰度"设置。比特率越高,音质越好,但文件也越大。

比特率对比(以 1 分钟音频为例):
- 32 kbps  →  约 240 KB  →  电话音质
- 64 kbps  →  约 480 KB  →  语音通话
- 128 kbps →  约 960 KB  →  MP3 标准音质
- 256 kbps →  约 1.9 MB  →  高质量音乐
- 320 kbps →  约 2.4 MB  →  MP3 最高质量

两种比特率模式

  • CBR(恒定比特率):每秒钟的数据量固定,文件大小可预测
  • VBR(可变比特率):根据音频复杂度动态调整,复杂部分用更多数据,简单部分用更少数据,整体音质更好

声道(Channels)

声道是指音频的独立音频轨道数量。

单声道 (Mono):        [音频]  →  一个喇叭播放
                      ↓

立体声 (Stereo):      [左声道]  →  左喇叭
                      [右声道]  →  右喇叭

5.1 环绕声:          [前左] [前右] [中置] [后左] [后右] [低音]

常见声道配置

  • 单声道(Mono):1 个声道,所有声音从一个位置发出
  • 立体声(Stereo):2 个声道,左右两个声道,最常见的音乐格式
  • 5.1 环绕声:6 个声道,包括 5 个主声道和 1 个低音声道
  • 7.1 环绕声:8 个声道,更高级的环绕声系统

音频编码的基本流程

音频编码的过程可以简化为以下几个步骤:

1. 原始音频信号(模拟或数字)
   ↓
2. 采样和量化(将连续信号转换为离散数据)
   ↓
3. 时域/频域分析(分析音频特征)
   ↓
4. 压缩编码(去除冗余信息,应用压缩算法)
   ↓
5. 打包成帧(将编码后的数据组织成数据包)
   ↓
6. 输出编码后的音频文件

关键概念

  • 时域:声音随时间变化的波形
  • 频域:声音的频率成分(哪些频率的声音存在)
  • 压缩:去除人耳听不到或不太敏感的信息,减小文件大小

Opus 编码简介

为什么需要 Opus?

在 Opus 出现之前,音频编码领域存在一些问题:

  • MP3:虽然流行,但音质和压缩率不是最优
  • AAC:需要专利授权,成本较高
  • Vorbis:免费但性能不如商业编码器
  • 实时通信:需要低延迟、高质量、低带宽的编码方案

Opus 的出现解决了这些问题:免费、开源、高质量、低延迟、优秀的压缩率

Opus 的技术特点

Opus 是一个混合编码器,它能够根据音频内容自动选择最适合的编码技术:

  1. 自适应编码:自动识别是语音还是音乐,选择最优编码方式
  2. 低延迟:延迟可低至 2.5ms,非常适合实时通信
  3. 高质量:在相同比特率下,音质通常优于 MP3 和 AAC
  4. 宽比特率范围:支持 6 kbps 到 510 kbps
  5. 多采样率支持:支持 8 kHz 到 48 kHz 的采样率

Opus 的编码模式

音频信号处理中将音频(Audio)分为两大类:语音(Speech)音乐(Music)

音频分类:
┌─────────────────────────────────────┐
│           音频 (Audio)               │
├──────────────────┬──────────────────┤
│   语音 (Speech)  │   音乐 (Music)   │
│                  │                  │
│ 频率: 300-3400Hz │ 频率: 20-20000Hz │
│ 特点: 规律性强   │ 特点: 频率范围广 │
│ 适合: 线性预测   │ 适合: 频域变换   │
└──────────────────┴──────────────────┘

由于两类音频频率范围各有特点,Opus 采用了两种不同的编码技术:

1. SILK 模式(语音编码)

线性预测(Linear Prediction,LP):基于语音信号的规律性,预测下一个采样点的值。

通俗理解:就像天气预报,根据过去几天的天气模式,预测明天的天气。语音信号有很强的规律性,可以基于前面的声音预测后面的声音。

SILK 编码原理:
过去的声音 → [预测模型] → 预测的声音
实际声音 - 预测声音 = 误差(很小,容易压缩)

特点

  • 适合处理语音(人声)
  • 支持 NB、MB、WB 带宽
  • 帧长:10ms ~ 60ms(较长,适合语音的连续性)
2. CELT 模式(音乐编码)

改进的离散余弦变换(MDCT):将音频从时域转换到频域,利用人耳的听觉特性进行压缩。

通俗理解:就像把一首歌分解成不同频率的音符,然后去除人耳听不到或不太敏感的部分。

CELT 编码原理:
时域波形 → [频域变换] → 频率成分
去除人耳不敏感的频率 → 压缩后的数据

特点

  • 适合处理音乐(包含各种频率)
  • 支持 NB、WB、SWB、FB 带宽
  • 帧长:2.5ms ~ 20ms(较短,适合音乐的快速变化)
3. Hybrid 模式(混合模式)

混合模式:同时使用 SILK 和 CELT,SILK 处理低频部分,CELT 处理高频部分。

应用场景:既包含语音又包含音乐的音频,或者需要高质量全频段编码的场景。

Hybrid 模式:
音频信号
├─ 低频部分 → SILK 编码(语音优化)
└─ 高频部分 → CELT 编码(音乐优化)

技术来源

  • SILK:来自 Skype 发明的 SILK 编解码器
  • CELT:来自 Xiph.Org 基金会早期开发的 CELT 格式(现已合并到 Opus)

Opus 的音频带宽

为了对不同频率的音频应用不同的编码技术,Opus 将音频频率带宽做了如下划分:

缩写(全称)音频带宽应用采样率适用场景
NB (narrowband)4 kHz8 kHz电话音质,语音通话
MB (medium-band)6 kHz12 kHz中等质量语音
WB (wideband)8 kHz16 kHz高质量语音通话
SWB (super-wideband)12 kHz24 kHz超宽频语音,接近音乐质量
FB* (fullband)20 kHz48 kHz全频段,音乐和高质量音频

说明:根据奈奎斯特采样定理,应用 48 kHz 的采样率,实际上可以处理 24 kHz 以内的音频信号,但是即便如此,Opus 也不会处理超过 20 kHz 的音频,因为超过 20 kHz 的音频人耳已经很难听到了。

带宽选择建议

语音通话    → NB 或 WB  (节省带宽)
音乐播放    → FB        (保证音质)
语音会议    → SWB       (平衡质量和带宽)

Opus 的帧结构

Opus 编码器在处理音频的时候,会将音频划分成多个(Frame)之后,针对每帧来处理。

帧的概念:就像电影是由一帧一帧的画面组成,音频也是由一帧一帧的音频数据组成。

音频流 = 帧1 + 帧2 + 帧3 + ... + 帧N

Opus 支持的帧长有:2.5ms、5ms、10ms、20ms、40ms、60ms

帧长选择的影响

  • 短帧(2.5ms ~ 10ms):延迟低,适合实时通信,但压缩效率稍低
  • 长帧(20ms ~ 60ms):压缩效率高,文件更小,但延迟较高

不同模式支持的帧长

  • SILK 模式:帧长 10ms ~ 60ms(适合语音的连续性)
  • CELT 模式:帧长 2.5ms ~ 20ms(适合音乐的快速变化)
  • Hybrid 模式:帧长 10ms 或 20ms(平衡两种模式)

为了对不同频率的音频应用不同的编码技术,Opus 音频频率带宽做了如下划分和命名:

缩写(全称)音频带宽应用采样率
NB (narrowband)4 kHz8 kHz
MB (medium-band)6 kHz12 kHz
WB (wideband)8 kHz16 kHz
SWB (super-wideband)12 kHz24 kHz
FB* (fullband)20 kHz48 kHz

根据奈奎斯特采样定理,应用 48 kHz 的采样率,实际上可以处理 24 kHz 以内的音频信号,但是即便如此,Opus 也不会处理超过 20 kHz 的音频,因为超过 20 kHz 的音频人耳已经很难听到了。

Opus 包结构

Opus 编码器处理原始数据输出一串包(Packet),一个包里面可能包含多个编码后的音频帧数据,只是这些音频帧的参数必须是一致的,例如:编码模式、音频带宽、帧大小以及声道数。

下面详细描述 Opus 包的结构。

TOC 字节

每个 Opus 包以一个 TOC(Table of Contents,目录表)字节开头,这个字节就像是整个包的"身份证",告诉解码器这个包的基本信息。

TOC 字节结构

 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| config | s| c |
+-+-+-+-+-+-+-+-+
 ↑        ↑  ↑
 │        │  └─ 帧数 (c): 2 bits, 表示包中有多少帧
 │        └─ 立体声标志 (s): 1 bit, 0=单声道, 1=立体声
 └─ 配置数 (config): 5 bits, 表示编码配置(模式、带宽、帧长)

通俗理解:TOC 字节就像快递包裹上的标签,告诉你:

  • config:这个包裹是用什么方式打包的(编码模式)
  • s:里面装的是单件还是双件(单声道还是立体声)
  • c:包裹里有多少个小包(有多少帧)

这个字节由三部分组成:配置数(config),立体声标志(s),帧数(c)。

配置数(config)详解

前 5 位(bit 0-4)的配置数定义了 32 种编码配置(2^5 = 32),不同的编码模式、音频带宽和帧长度组成了这 32 种配置。

配置数分布图

配置数范围    编码模式      音频带宽    支持的帧长
─────────────────────────────────────────────────
0-3          SILK-only    NB         10, 20, 40, 60 ms
4-7          SILK-only    MB         10, 20, 40, 60 ms
8-11         SILK-only    WB         10, 20, 40, 60 ms
12-13        Hybrid       SWB        10, 20 ms
14-15        Hybrid       FB         10, 20 ms
16-19        CELT-only    NB         2.5, 5, 10, 20 ms
20-23        CELT-only    WB         2.5, 5, 10, 20 ms
24-27        CELT-only    SWB        2.5, 5, 10, 20 ms
28-31        CELT-only    FB         2.5, 5, 10, 20 ms

详细配置表如下:

配置数(config)编码模式音频带宽帧长度
0...3SILK-onlyNB10, 20, 40, 60 ms
4...7SILK-onlyMB10, 20, 40, 60 ms
8...11SILK-onlyWB10, 20, 40, 60 ms
12...13HybridSWB10, 20 ms
14...15HybridFB10, 20 ms
16...19CELT-onlyNB2.5, 5, 10, 20 ms
20...23CELT-onlyWB2.5, 5, 10, 20 ms
24...27CELT-onlySWB2.5, 5, 10, 20 ms
28...31CELT-onlyFB2.5, 5, 10, 20 ms

立体声标志位(s)

  • 0:单声道(Mono),一个音频轨道
  • 1:立体声(Stereo),两个音频轨道(左右声道)

帧数(c):TOC 字节的最后两位(bit 6-7)表示包中包含的帧数类型:

c 值含义说明包类型
0单帧包一个包中只有一帧音频0 号包
1双帧等长包一个包中有两帧音频,并且大小相同1 号包
2双帧不等长包一个包中有两帧音频,但是大小不同2 号包
3多帧包一个包中有任意数量的帧(1 个或多个)3 号包

示例

TOC 字节 = 0b10101010
          │││││││└─ c = 10 (二进制) = 22号包(双帧不等长)
          ││││││└── s = 1 → 立体声
          │││││└─── config = 10101 (二进制) = 21 → CELT-only, WB, 10ms
          └└└└└──── (前5位)

不同帧结构的包

根据一个包的 TOC 字节中帧数(c)的不同取值,我们把这个包命名为:c 号包

包类型总览

Opus 包类型
├─ 0 号包:单帧包(最简单,一包一帧)
├─ 1 号包:双帧等长包(两帧大小相同)
├─ 2 号包:双帧不等长包(两帧大小不同,需要长度编码)
└─ 3 号包:多帧包(可包含任意数量的帧,支持 CBR/VBR)

下面我们详细介绍这 4 种不同帧结构的包。

帧长度编码
当一个包含有多个 VBR 的音频帧时,那么除了最后一个音频帧,前面几个帧都需要对帧的长度进行编码。存储帧长度的编码占用 1 ~ 2 个字节,其规则如下:
- 第一个字节取值为 0:表示没有任何帧数据(这通常是非连续传输(DTX)或者音频包丢失)
- 第一个字节取值为 1 ~ 251:表示第一帧的字节数
- 第一个字节取值为 252 ~ 255:第二个字节也参与编码帧长度,第一帧的总字节数为:(第二字节*4)+第一字节

因此一个帧的最大长度为:255 * 4 + 255 = 1275 字节。对于一个 20ms 的帧来说,这个长度代表 510 kbit/s 的码率。这个码率几乎是立体声音乐的有损压缩编码最高有效码率。超过这个码率,最好采用无损编码。这也是 MDCT 算法的最高有效码率,超过这个值,在增加码率进行编码,音频的质量也不会跟着提高。

0 号包: 一个包只包含一帧音频

特点:最简单的包结构,一个包只包含一帧音频数据。

结构示意图

┌─────────────────────────────────────┐
│  TOC 字节 (1 byte)                  │ ← 标识:c=0
│  config | s | 0 | 0                 │
├─────────────────────────────────────┤
│  压缩后的音频帧 (N-1 bytes)          │ ← 音频数据
│  (可能为 0 字节,表示空帧)            │
└─────────────────────────────────────┘

二进制结构

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config | s|0|0|                                               |
+-+-+-+-+-+-+-+-+                                               |
|                    Compressed frame 1 (N-1 bytes)...          |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

说明

  • 包总大小 = 1 字节(TOC)+ 帧大小
  • 帧大小可以是 0 字节(空帧),这种情况下包只有 1 个 TOC 字节
  • 空帧通常用于非连续传输(DTX)或表示音频包丢失
1 号包: 一个包里面含有两个大小相同的帧

特点:包含两个大小完全相同的帧,不需要额外的长度编码。

结构示意图

┌─────────────────────────────────────┐
│  TOC 字节 (1 byte)                  │ ← 标识:c=1
│  config | s | 0 | 1                 │
├─────────────────────────────────────┤
│  帧1 ((N-1)/2 bytes)                │ ← 第一帧
├─────────────────────────────────────┤
│  帧2 ((N-1)/2 bytes)                │ ← 第二帧(与帧1大小相同)
└─────────────────────────────────────┘
总大小 = 1 + 2×帧大小 = 奇数

为什么大小必须是奇数?

  • 包总大小 = 1(TOC)+ 2×帧大小
  • 因为有两个相同大小的帧,所以 (N-1) 必须是偶数
  • 因此 N(总大小)必须是奇数
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config | s|0|1|                                               |
+-+-+-+-+-+-+-+-+                                               :
|             Compressed frame 1 ((N-1)/2 bytes)...             |
:                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               :
|             Compressed frame 2 ((N-1)/2 bytes)...             |
:                                               +-+-+-+-+-+-+-+-+
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2 号包: 一个包里面含有两个大小不同的帧

特点:包含两个大小不同的帧,需要额外的长度编码来标识第一帧的大小。

结构示意图

┌─────────────────────────────────────┐
│  TOC 字节 (1 byte)                  │ ← 标识:c=2
│  config | s | 1 | 0                 │
├─────────────────────────────────────┤
│  帧1长度编码 (1-2 bytes)             │ ← 告诉解码器帧1有多大
├─────────────────────────────────────┤
│  帧1数据 (N1 bytes)                  │ ← 第一帧(大小由上面指定)
├─────────────────────────────────────┤
│  帧2数据 (剩余字节)                   │ ← 第二帧(大小=总大小-1-N1-帧1)
└─────────────────────────────────────┘

为什么需要长度编码? 因为两帧大小不同,解码器需要知道第一帧在哪里结束,第二帧从哪里开始。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config | s|1|0|                                               |
+-+-+-+-+-+-+-+-+                                               :
| N1 (1-2 bytes):                                               :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame 1 (N1 bytes)...                :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame 2 (remaining bytes)...         :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3 号包: 一个包里面含有任意帧

特点:最灵活的包类型,可以包含 1 个或多个帧,支持 CBR 和 VBR 两种模式。

结构示意图

3 号包类型
├─ CBR 模式(恒定比特率)
│  └─ 所有帧大小相同,只需编码帧数量
│
└─ VBR 模式(可变比特率)
   └─ 每帧大小可能不同,需要编码每帧的长度

CBR vs VBR 对比

特性CBR(恒定比特率)VBR(可变比特率)
帧大小所有帧大小相同每帧大小可能不同
长度编码只需编码帧数量需要编码每帧的长度
文件大小可预测根据内容变化
音质固定质量复杂部分质量更好
适用场景流媒体、实时传输文件存储、高质量需求

通俗理解

  • CBR:就像固定工资,每个月收入一样,容易规划
  • VBR:就像按工作量计酬,复杂的工作给更多钱,简单的工作给少一点,总体更合理

对于 CBR 的 3 号包,所有帧的大小都相同,其结构如下:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config | s|1|1|0|p|     M | Pad len (Opt) : N1 (1-2 bytes):  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame 1 (N1 bytes)...                :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame 2 (N1 bytes)...                :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                              ...                              :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame M (N1 bytes)...                :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                  Opus Padding (Optional)...                   :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

对于 VBR 的 3 号包,在第一帧前面,添加帧长度编码,表示最后一个帧的大小。如果这个编码的值为 N[M],那么后面 M 个帧的总大小为 N1 + N2 + ... + N[M]。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config | s|1|1|1|p|     M | Padding length (Optional)          :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: N1 (1-2 bytes):     ...       :     N[M-1] | N[M]             :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame 1 (N1 bytes)...                :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:               Compressed frame 2 (N2 bytes)...                :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                              ...                              :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
:              Compressed frame M (N[M] bytes)...               :
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
:                  Opus Padding (Optional)...                   :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

从上面的描述我们可以看到,实际上这个额外的帧长度编码都是在原来的包结构基础上,插入到了第一帧数据的前面。

多声道支持

在一些场景下,带分界包有实际的用途。根据标准,Opus 只能编码单声道或者双声道立体声音频。因此一个 Opus 码流要不就是单声道的,要不就是双声道的。

多声道处理方案:如果要传输或者存储多声道(大于2)的音频,就需要复合多个 Opus 流。

示例:5.1 环绕立体声

5.1 环绕立体声有 6 个声道:

5.1 声道布局:
     [前左]  [前右]
        [中置]
     [后左]  [后右]
        [低音]

假设 5.1 环绕立体声由 2 个双声道和 2 个单声道的 Opus 流组成:

  • 流1:前左 + 前右(双声道)
  • 流2:中置(单声道)
  • 流3:后左 + 后右(双声道)
  • 流4:低音(单声道)

复合包结构

复合音频包
├─ Opus 包1(前左+前右,带分界)
├─ Opus 包2(中置,带分界)
├─ Opus 包3(后左+后右,带分界)
└─ Opus 包4(低音,无分界,可推断)

为了让解码器能够顺利从复合音频包中识别出各个包,前三个包需要采用带分界格式的编码。最后一个包不需要分界,因为可以通过总大小推断出来。

Opus 的应用场景

Opus 由于其优秀的特性,被广泛应用于各种场景:

1. 实时语音/视频通话

  • WebRTC:网页实时通信标准
  • VoIP:网络电话
  • 视频会议:Zoom、Teams 等(部分使用)
  • 游戏语音:Discord、TeamSpeak 等

优势:低延迟(可低至 2.5ms),高质量,低带宽占用

2. 流媒体服务

  • 音乐流媒体:部分平台使用 Opus
  • 播客:高质量音频内容
  • 在线广播:网络电台

优势:优秀的压缩率,节省带宽和存储成本

3. 文件存储

  • 音频文件:.opus 格式
  • 容器格式:WebM、MKV 等视频容器中的音频轨道

优势:免费开源,无需专利授权

4. 嵌入式设备

  • IoT 设备:智能音箱、智能家居
  • 移动设备:Android 系统原生支持

优势:资源占用少,性能优秀

Opus 的优缺点

优点 ✅

  1. 免费开源:无需专利授权,可自由使用
  2. 高质量:相同比特率下音质通常优于 MP3 和 AAC
  3. 低延迟:最低延迟可至 2.5ms,适合实时通信
  4. 灵活性高:支持多种采样率、比特率、帧长
  5. 标准化:IETF RFC 6716 标准,广泛支持
  6. 压缩效率高:优秀的压缩率,节省带宽和存储

缺点 ❌

  1. 兼容性:不如 MP3 普及,部分老旧设备不支持
  2. 编码复杂度:编码过程相对复杂,需要一定计算资源
  3. 多声道限制:原生只支持单声道和立体声,多声道需要复合流
  4. 文件格式:.opus 格式不如 .mp3 常见

适用场景建议

推荐使用 Opus:
✓ 实时通信应用(语音/视频通话)
✓ 需要低延迟的场景
✓ 需要高质量压缩的场景
✓ 开源项目或需要避免专利问题
✓ 流媒体服务

不推荐使用 Opus:
✗ 需要最大兼容性的场景(用 MP3)
✗ 需要无损音质的场景(用 FLAC)
✗ 老旧设备或系统不支持

其他常见音频编码格式

为了更全面地了解音频编码领域,我们简单介绍几种其他常见的音频编码格式。

MP3

**MP3(MPEG-1 Audio Layer III)**是最流行的音频编码格式之一。

特点

  • ✅ 兼容性极好,几乎所有设备都支持
  • ✅ 压缩率高,文件小
  • ❌ 需要专利授权(虽然大部分专利已过期)
  • ❌ 音质在低比特率下不如现代编码器
  • ❌ 不支持低延迟实时编码

应用场景:音乐播放、播客、通用音频文件

技术原理:使用心理声学模型,去除人耳听不到的声音成分。

MP3 编码流程:
原始音频 → [心理声学分析][频域变换][量化][霍夫曼编码] → MP3 文件

AAC

**AAC(Advanced Audio Coding)**是 MP3 的继任者,由多个公司联合开发。

特点

  • ✅ 音质优于 MP3(相同比特率下)
  • ✅ 压缩效率更高
  • ✅ 广泛支持(iTunes、YouTube 等)
  • ❌ 需要专利授权
  • ❌ 编码复杂度较高

应用场景:iTunes、YouTube、移动设备、数字广播

技术原理:改进的频域编码,使用更先进的压缩算法。

AAC vs MP3:
相同比特率下,AAC 音质通常更好
128 kbps AAC ≈ 192 kbps MP3

Vorbis (OGG)

Vorbis是 Xiph.Org 基金会开发的开源音频编码格式,通常以 OGG 容器格式存储。

特点

  • ✅ 完全免费开源
  • ✅ 音质优秀
  • ✅ 无专利限制
  • ❌ 兼容性不如 MP3
  • ❌ 编码速度较慢

应用场景:开源项目、游戏音频、部分流媒体服务

技术原理:使用改进的 MDCT 变换和矢量量化。

FLAC

**FLAC(Free Lossless Audio Codec)**是一种无损音频编码格式。

特点

  • 无损压缩:100% 还原原始音频
  • ✅ 免费开源
  • ✅ 压缩率约 50%(比原始 WAV 小一半)
  • ❌ 文件仍然较大(比有损编码大很多)
  • ❌ 不适合低带宽传输

应用场景:音乐制作、音频存档、Hi-Fi 音频

技术原理:使用预测编码和熵编码,不丢失任何信息。

有损 vs 无损:
有损编码(MP3/AAC/Opus):文件小,音质略有损失
无损编码(FLAC):文件大,音质完美

Opus 编码流程示例

为了更好地理解 Opus 编码的完整过程,我们来看一个完整的编码流程:

原始音频输入
    ↓
[1. 音频分析]
    ├─ 判断是语音还是音乐?
    ├─ 分析频率范围
    └─ 确定最佳编码模式(SILK/CELT/Hybrid)
    ↓
[2. 参数选择]
    ├─ 选择采样率(8-48 kHz)
    ├─ 选择比特率(6-510 kbps)
    ├─ 选择帧长(2.5-60 ms)
    └─ 选择音频带宽(NB/WB/SWB/FB)
    ↓
[3. 分帧处理]
    └─ 将音频分割成多个帧
    ↓
[4. 编码处理]
    ├─ SILK 模式:线性预测编码
    ├─ CELT 模式:MDCT 频域变换
    └─ Hybrid 模式:混合编码
    ↓
[5. 打包]
    ├─ 生成 TOC 字节
    ├─ 组织帧数据
    └─ 生成 Opus 包
    ↓
Opus 编码后的数据

实际应用示例

假设我们要编码一段 1 秒的语音(16 kHz 采样率,单声道):

原始数据:
- 采样率:16 kHz
- 声道:单声道
- 原始大小:16,000 采样 × 2 字节 = 32 KB

Opus 编码(选择 WB,32 kbps):
- 编码模式:SILK(语音)
- 音频带宽:WB(8 kHz)
- 帧长:20 ms
- 帧数:50 帧(1000 ms ÷ 20 ms)
- 编码后大小:约 4 KB(32 kbps × 1 秒 ÷ 8)

压缩比:32 KB → 4 KB = 8:1

解码流程(反向过程):

Opus 编码数据
    ↓
[1. 解析 TOC]
    └─ 读取配置信息
    ↓
[2. 解包]
    └─ 提取各个帧的数据
    ↓
[3. 解码]
    ├─ SILK 解码:线性预测解码
    ├─ CELT 解码:MDCT 逆变换
    └─ Hybrid 解码:混合解码
    ↓
[4. 重构音频]
    └─ 将帧重新组合成连续音频
    ↓
可播放的音频输出

音频编码格式对比

格式类型音质压缩率延迟专利兼容性主要用途
Opus有损⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐免费⭐⭐⭐实时通信、流媒体
MP3有损⭐⭐⭐⭐⭐⭐⭐⭐⭐部分过期⭐⭐⭐⭐⭐通用音频
AAC有损⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐需授权⭐⭐⭐⭐移动设备、流媒体
Vorbis有损⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐免费⭐⭐开源项目
FLAC无损⭐⭐⭐⭐⭐⭐⭐⭐N/A免费⭐⭐⭐音乐制作、存档

选择建议

实时通信    → Opus(低延迟、高质量)
音乐播放    → AAC 或 Opus(平衡质量和兼容性)
最大兼容性  → MP3(几乎所有设备支持)
开源项目    → Opus 或 Vorbis(避免专利问题)
无损需求    → FLAC(完美音质)

比特率对比(相同音质水平):

电话音质:     Opus 16-32 kbps  vs  MP3 64 kbps
语音通话:     Opus 32-64 kbps  vs  MP3 96-128 kbps
标准音乐:     Opus 64-128 kbps vs  MP3 128-192 kbps
高质量音乐:   Opus 128-256 kbps vs MP3 256-320 kbps

可以看出,Opus 在相同音质下需要的比特率更低,压缩效率更高。

总结

通过本文档,我们全面了解了 Opus 音频编码格式:

核心要点回顾

  1. Opus 是什么:一种免费、开源、高质量的音频编码格式,特别适合实时通信和流媒体应用。

  2. 技术优势

    • 混合编码:自动选择 SILK(语音)或 CELT(音乐)模式
    • 低延迟:最低可至 2.5ms
    • 高质量:相同比特率下音质优于 MP3 和 AAC
    • 灵活性:支持多种采样率、比特率和帧长
  3. 包结构

    • TOC 字节:包的"身份证",包含配置信息
    • 4 种包类型:0 号(单帧)、1 号(双帧等长)、2 号(双帧不等长)、3 号(多帧)
  4. 应用场景

    • 实时通信(WebRTC、VoIP)
    • 流媒体服务
    • 文件存储
    • 嵌入式设备
  5. 与其他格式对比

    • 相比 MP3:音质更好,压缩率更高,但兼容性稍差
    • 相比 AAC:免费开源,无需专利授权
    • 相比 FLAC:有损压缩,但文件小很多

快速参考

选择 Opus 的场景

  • ✅ 需要低延迟的实时通信
  • ✅ 需要高质量压缩
  • ✅ 开源项目或需要避免专利问题
  • ✅ 网络传输和流媒体

不选择 Opus 的场景

  • ❌ 需要最大兼容性(用 MP3)
  • ❌ 需要无损音质(用 FLAC)
  • ❌ 老旧设备不支持

进一步学习

  • 实践:尝试使用 FFmpeg 等工具进行 Opus 编码/解码
  • 深入:阅读 RFC 6716 标准文档了解技术细节
  • 应用:在 WebRTC 或实时通信项目中应用 Opus

参考文献

[1] Opus 音频编码格式: chenliang.org/2020/03/15/…
[2] Voice frequency: en.wikipedia.org/wiki/Voice_…
[3] CELT: en.wikipedia.org/wiki/CELT
[4] Definition of the Opus Audio Codec: tools.ietf.org/html/rfc671…
[5] 5.1 surround sound: en.wikipedia.org/wiki/5.1_su…