尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

音频格式解码之opus

音频格式解码之opus
📅 发布时间:2026/6/26 22:46:05

opus是一种有损编码格式,与Vorbis同率属于Xiph.Org基金会,并且也进行了标准化。当前opus不仅取代了Vorbis,还成为了webrtc的标准音频格式。opus也基于ogg,ogg的介绍请参考音频格式之OGG-CSDN博客 , 本文主要介绍opus格式。

一、opus 在ogg中的格式

1.1 opus ogg 流

Page 0 Pages 1 ... n Pages (n+1) ... +------------+ +---+ +---+ ... +---+ +-----------+ +---------+ +-- | | | | | | | | | | | | | |+----------+| |+-----------------+| |+-------------------+ +----- |||ID Header|| || Comment Header || ||Audio Data Packet 1| | ... |+----------+| |+-----------------+| |+-------------------+ +----- | | | | | | | | | | | | | +------------+ +---+ +---+ ... +---+ +-----------+ +---------+ +-- ^ ^ ^ | | | | | Mandatory Page Break | | | ID header is contained on a single page | 'Beginning Of Stream'

opus的ogg流,主要由ID Header、 Comment Header和AudioData Packet组成,

ID Header:是 Ogg Opus 文件格式的第一个数据包,用于唯一标识一个流为 Opus 音频。它包含了解码 Opus 音频所需的基本元数据。

Comment Header:是 Ogg Opus 文件格式的第二个必需数据包,包含用户提供的元数据信息。它采用与 Ogg Vorbis 评论头相同的格式(但没有 Vorbis 规范中规定的最终"帧位")。

Audio Data Packet:是 Ogg Opus 流中包含实际音频数据的数据包。在 ID Header 和 Comment Header 之后,所有后续的页面都包含音频数据。

1.2ID Header

根据 RFC 7845(Ogg Opus Encapsulation)规范,ID Header 的二进制结构如下:

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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 'O' | 'p' | 'u' | 's' | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 'H' | 'e' | 'a' | 'd' | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version = 1 | Channel Count | Pre-skip | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Input Sample Rate (Hz) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Output Gain (Q7.8 in dB) | Mapping Family| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ : | | : Optional Channel Mapping Table... : | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

1.2.1 属性介绍

字段位含义
Magic64Opus 文件标识"OpusHead"
Version8版本 ,固定为1
Channel Count8声道数
Pre-skip16无预跳过
Input Sample Rate32采样率,这是原始输入(编码前)的采样率,单位为赫兹。这个字段并不是用于播放编码数据的采样率。
Output Gain16增益调整,

sample *= pow(10, output_gain/(20.0*256))

Mapping Family8标准立体声(无映射表)

Channel Mapping Table

NMapping Family > 0时才有,从编码流到输出通道的映射

1,channel count

这是输出通道的数量。这可能与编码通道的数量不同,编码通道数量可能会在每个数据包中变化。这个值不能为零。最大允许值取决于通道映射类型,并可能大到 255

2,Pre-skip

这是在开始播放时需要从解码器输出丢弃的样本数(48 kHz),同时也是计算页面 PCM 样本位置时需要从页面颗粒位置中减去的数值。在裁剪已有的 Ogg Opus 流的开头时,建议预跳至少 3,840 个样本(80 毫秒),以确保解码器完全收敛。

3,Input Sample Rate

这是原始输入的采样率(编码前),单位是赫兹。这个字段_不是_用于播放编码后数据的采样率。

Opus 可以在 4、6、8、12 和 20 kHz 的内部音频带宽之间切换。流中的每个数据包可以有不同的音频带宽。无论音频带宽如何,参考解码器都支持以 8、12、16、24 或 48 kHz 的采样率解码任何流。传递给编码器的音频的原始采样率不会通过有损压缩被保留。

4,Output Gain

这是在解码时要应用的增益。它是将解码器输出缩放到期望播放音量的因子的 20*log10 值,以 16 位有符号二进制补码定点值存储,带有 8 位小数(Q-表示法)

5,Mapping Family

家族值定义

家族值名称说明
0默认映射单声道或立体声,无映射表
1环绕声映射支持多通道环绕声格式
2Ambisonics支持 Ambisonics 格式

家族 0(默认映射)

最简单的映射方式,无需显式映射表:

输出通道数 CStream Count NCoupled Count M通道含义
11(默认)0(默认)单声道
21(默认)1(默认)立体声(左、右)

家族 1(环绕声映射)

支持标准环绕声配置:

通道数配置名称通道顺序
3立体声 + 低频效果 (LFE)FL, FR, LFE
4四声道FL, FR, BL, BR
55.0FL, FR, FC, BL, BR
65.1FL, FR, FC, LFE, BL, BR
76.1FL, FR, FC, LFE, BL, BR, BC
87.1FL, FR, FC, LFE, BL, BR, SL, SR

6,Channel Mapping Table

Channel Mapping Table 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 +-+-+-+-+-+-+-+-+ | Stream Count | N +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Coupled Count | Channel Mapping... : M + C bytes +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段大小说明
Stream Count (N)1 字节编码流总数
Coupled Count (M)1 字节立体声流数量(前 M 个流为立体声)
Channel MappingC 字节输出通道到解码通道的映射表
Channel Mapping值范围含义
0到2M-1立体声流的通道(偶数=左,奇数=右)
2M到M+N-1单声道流的通道
255静音通道
  • Mapping Family决定通道语义(单声道/立体声/环绕声/Ambisonics)
  • Stream Count (N)和Coupled Count (M)定义编码流结构
  • Channel Mapping Table定义从解码通道到输出通道的映射关系
  • 支持灵活的通道配置和静音通道处理

1.3 Comment Header

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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 'O' | 'p' | 'u' | 's' | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 'T' | 'a' | 'g' | 's' | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Vendor String Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | : Vendor String... : | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | User Comment List Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | User Comment #0 String Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | : User Comment #0 String... : | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | User Comment #1 String Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ : :
字段位值举例说明
Magic64"OpusTags"标识
Vendor Length320x0000000C = 12Vendor 字符串长度
Vendor StringN"LibOpus 1.4"Vendor Length决定长度,编码器信息
Comment Count320x00000002 = 2Comment 的数量,决定后面Comment Block的数量
Comment 0 Length320x0000000C = 12第一个评论长度
Comment 0N"TITLE=听妈妈的话"标题
Comment 1 Length320x0000000E = 14第二个评论长度
Comment 1N"ARTIST=周杰伦"艺术家:

这个主要储存相关记录信息, 具体可以参考“标准元数据标签” 介绍TITLE/ARTIST/DATE等 元数据。 本章节不赘述,这些元数据都是通用格式。

二,opus格式

opus音频数据的格式,对应OGG中 audio data packet,ogg打包opus的音频数据。opus包的大小在内部没有存储,因此需要外部封装的容器存储,或者自己扩展一个opus packet的长度字节。

Opus Packet Structure ┌──────────────────────────────────────────────────────────────────────┐ │ TOC Byte │ Frame Size(s) │ Audio Data │ Extensions │ │ (1 byte) │ (0-2 bytes) │ (variable) │ (可选) │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ ▼ ▼ ▼ ▼ 编码模式/带宽 帧大小信息 压缩音频数据 LBRR/DRED等 /通道数/帧数 (VBR模式) 扩展数据

2.1,TOC字节 1字节(根据opus源码解析)

TOC 字节是 Opus 包的第一个字节,包含了关键的编码参数

TOC 8位格式 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | frame Count | channels | bandwidth | mode +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
位字段含义
7-5mode编码模式(0=SILK, 1=HYBRID, 2=CELT, 3=保留)
4-3bandwidth带宽 与模式共同计算如
2channels通道数(0=单声道, 1=立体声)
1-0frame_count帧数量指示符

1,frame_count(帧数量指示)

switch (toc & 0x3) { case 0: // 00: 1个帧 count = 1; break; case 1: // 01: 2个CBR帧 count = 2; cbr = 1; break; case 2: // 10: 2个VBR帧 count = 2; // 需要解析帧大小 break; case 3: // 11: 多个帧(0-120ms) // 第二个字节包含帧数和标志 break; }

2,bandwidt 音频带宽

带宽的解析取决于编码模式:

如: SILK 模式(Mode = 0):

值带宽名称频率范围
0Narrowband (NB)4 kHz
1Mediumband (MB)6 kHz
2Wideband (WB)8 kHz
3Superwideband (SWB)12 kHz

3,mode 编码模式

值模式名称说明
0SILK_ONLY纯 SILK 模式,适用于语音
1HYBRID混合模式,同时使用 SILK 和 CELT
2CELT_ONLY纯 CELT 模式,适用于音乐
3保留未使用

2.2, 解码流程

┌─────────────────────┐ │ 输入 Opus 数据包 │ └──────────┬──────────┘ │ ┌──────────▼──────────┐ │ 读取 TOC 字节 │ │ (解析 Mode/BW/C/F) │ └──────────┬──────────┘ │ ┌──────────▼──────────┐ │ 判断帧结构类型 │ │ (F=0/1/2/3) │ └──────────┬──────────┘ │ ┌──────────────────────┼──────────────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ F=0 │ │ F=1/2 │ │ F=3 │ │ 单帧 │ │ 双帧 │ │ 多帧 │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 直接解码 │ │ 解析大小 │ │ 解析帧头 │ │ 单帧 │ │ 后解码 │ │ +大小 │ └──────────┘ └──────────┘ └────┬─────┘ │ ▼ ┌──────────┐ │ 解码所有帧│ └──────────┘

帧的长度通过,ogg等容器格式获取,就是这整个opus packet包的大小;

opus-packet size -1 = len;

2.2.1 单帧模式(F=0)

这种结构最简单,整个剩余数据就是一帧数据。只需要解码这一帧就好。

Single Frame Packet ┌─────────────────┐ │ TOC (1 byte) │ │ Audio Data len-1 │ └─────────────────┘

2.2.2 双帧 CBR 模式(F=1)

两帧大小相等,无需显式编码, 两个帧的长度分别占总长度的一半;

Two CBR Frames Packet ┌─────────────────────────┐ │ TOC (1 byte) │ │ Frame 1 Data │ │ Frame 2 Data │ (大小 = (len-1) / 2)两帧等长,无显式大小信息: └─────────────────────────┘

2.2.3 双帧 VBR 模式(F=2)

Two VBR Frames Packet ┌─────────────────────────┐ │ TOC (1 byte) │ │ Size 1 (1-2 bytes) │ │ Frame 1 Data 第一帧大小通过计算获取 │ │ Frame 2 Data │ (大小 = 剩余长度) └─────────────────────────┘

第一帧大小显式编码,第二帧占剩余空间,Opus 使用可变长度编码(VLE)来表示帧大小,第一帧的计算公式为:

static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) { if (len < 1) { *size = -1; return -1; } else if (data[0] < 252) { // 单字节编码:0-251 *size = data[0]; return 1; } else if (len < 2) { *size = -1; return -1; } else { // 双字节编码:252-1275 *size = 4 * data[1] + data[0]; return 2; } }
范围编码方式字节数
0-251直接编码1 字节
252-12754 * data[1] + data[0]2 字节

2.2.4 多帧模式(F=3)

Multi-Frame Packet ┌────────────────────────────────────────┐ │ TOC (1 byte) │ │ Frame Info (1 byte) │ │ - bits 0-5: 帧数量 N │ │ - bit 6: 填充标志 │ │ - bit 7: CBR/VBR标志 (0=VBR) │ │ Padding Bytes (if padded) │ │ Size 1 (VBR only, 1-2 bytes) │ │ ... │ │ Size N-1 (VBR only, 1-2 bytes) │ │ Frame 1 Data │ │ ... │ │ Frame N Data │ │ Extensions (可选) len -以上所有字节 │ └────────────────────────────────────────┘

1 Frame Info

这种模式新增了一个Frame Info, 用于获取帧数量,和帧格式标志。

Frame Info (1 byte) │ │ - bits 0-5: 帧数量 N │ │ - bit 6: 填充标志 │ │ - bit 7: CBR/VBR标志 (0=VBR)

2.2.5 扩展数据(Extensions)

Opus 包末尾可以包含扩展数据,如 LBRR(低比特率冗余)和 DRED(解码器冗余):

扩展类型

ID类型说明
0填充无意义填充字节
1帧分隔符标记帧边界
2重复指示符后续帧重复相同扩展
3-31短扩展载荷长度 0-1 字节
32-127长扩展载荷长度可变

相关新闻

  • SQL注入漏洞复现:从手工测试到自动化利用的实战指南
  • ComfyUI-Impact-Pack V8:解决AI图像细节模糊的5大核心技术方案
  • 基于Fisher-Kolmogorov方程与几何简化的大脑疾病蛋白传播动力学建模

最新新闻

  • 视频编码识别与处理:从原理到工具,快速解决播放兼容问题
  • 从双曲几何到AdS时空:Weil-Petersson度量与重正化面积的深刻联系
  • 终极指南:5分钟快速上手ExtractorSharp游戏资源编辑器
  • Frida Gadget配置文件详解:从基础集成到高级动态分析实战
  • 5分钟实战:用Aircrack-ng抓取WiFi握手包,从原理到硬件避坑指南
  • 139、飞控中的气压计选型:MS5611、BMP280

日新闻

  • 单节点跑业务稳如泰山 扩容高可用集群反而频繁卡死 复盘完整连接交互揪出深层根因
  • Boss直聘批量投递工具:5倍效率提升的求职价值重构指南
  • 3分钟解锁VLC点击暂停插件:让视频控制变得如此简单!

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号