ogg-opus协议解析示例

OGG 头的示意图

image

这张图画的很好,借用一下,图片来源:https://chenliang.org/2020/03/14/ogg-container-format/

 然后我们就一个具体的例子来解读,增强记忆

image

 

第一个页

第一部分:Ogg 页面头(Ogg Page Header)

4F 67 67 53 00 02 00 00 00 00 00 00 00 00 7B C0 CC 0B 00 00 00 00 01 BA D3 2F 01 13 4F 70 75 73 48 65 61 64 01 01 38 01 80 BB 00 00 00 00 00

前 27 字节是 Ogg 页面头(Ogg Page Header),标准长度为 27 字节。

Offset: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

Bytes: 4F 67 67 53 00 02 00 00 00 00 00 00 00 00 7B C0 CC 0B 00 00 00 00 01 BA D3 2F 01
ASCII: O g g S

字段字节说明
/* by yours.tools - online tools website : yours.tools/zh/formatperl.html */ capture_pattern/* by yours.tools - online tools website : yours.tools/zh/formatperl.html */ 4F 67 67 53"OggS"Ogg 文件标识符
version000Ogg 格式版本
header_type022页面类型:0x02 表示这是 初始页(bos),通常是头信息
granule_position00 00 00 00 00 00 00 000音频采样位置(此处为 0,因为是头页)
bitstream_serialno7B C0 CC 0B0x0BCC C07B流的唯一 ID(小端序)
page_sequence_no00 00 00 000页面序号,头页为 0
CRC_checksum01 BA D3 2FCRC32 校验和用于校验
page_segments011该页包含 1 个 segment

第二部分:Segment Table + OpusHead 数据

接下来是 segment table 和实际数据。

  • page_segments 是 01,表示有 1 个 segment。
  • segment table 是 1 字节:13 → 表示第一个 segment 长度为 0x13 = 19 字节

所以接下来的 19 字节是 OpusHead 数据:

Offset: 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
Bytes: 4F 70 75 73 48 65 61 64 01 01 38 01 80 BB 00 00 00 00 00
ASCII: O p u s H e a d

字段字节说明
magic_signature8 字节4F 70 75 73 48 65 61 64"OpusHead" ASCII
version1 字节01版本号,必须为 1
channel_count1 字节01声道数:1(单声道)
pre_skip2 字节(小端)38 01 → 0x0138 = 312编码器在解码时应跳过的样本数
input_sample_rate4 字节(小端)80 BB 00 00 → 0x0000BB80 = 48000 Hz输入采样率(仅作参考)
output_gain2 字节(小端)00 00增益(dB × 256),0 表示无增益
channel_mapping_family1 字节00通道映射族:0 表示无特殊映射(RTP 标准)

详细解释:

  • ✅ magic_signature"OpusHead",确认是 Opus 头。
  • ✅ version = 1:符合规范。
  • 🎧 channel_count = 1:单声道音频。
  • ⏩ pre_skip = 312:解码后应丢弃前 312 个样本,用于消除编码器引入的前导噪声。
  • 📏 input_sample_rate = 48000:原始输入采样率为 48 kHz(Opus 内部始终以 48kHz 运行,此字段仅作提示)。
  • 🔊 output_gain = 0:播放时无需调整音量。
  • 🔗 channel_mapping_family = 0:使用简单流,无复杂通道映射(适用于单声道或立体声)。

 

第二页

4F 67 67 53 00 00 00 00 00 00 00 00 00 00 7B C0 CC 0B 01 00 00 00 15 6E F0 0B 01 3D

4F 70 75 73 54 61 67 73 0C 00 00 00 4C 61 76 66 36 32 2E 34 2E 31 30 31 01 00 00 00 1D 00 00 00 65 6E 63 6F 64 65 72 3D 4C 61 76 63 36 32 2E 31 33 2E 31 30 31 20 6C 69 62 6F 70 75 73

Ogg Page Header 解析(前 27 字节)

偏移字节内容说明
0x004F 67 67 53"OggS"Ogg 页头标识
0x0400版本号0,标准版本
0x0500标志位0x00:普通页,非开始、非结束
0x0600 00 00 00 00 00 00 00Granule Position64位,当前为 0 → 通常是首帧之后的数据页或注释页
0x0E00 00 00 00Stream Serial Number流 ID = 0
0x127B C0 CC 0BPage Sequence No小端表示:0B CC C0 7B = 197,865,595(十进制)
0x1615 6E F0 0BChecksum小端:0B F0 6E 15 = 210,562,581(校验用)
0x1A01Segment 数量1 个 segment
0x1B3DSegment Table该 segment 长度为 0x3D = 61 字节

接下来的 61 字节是 Opus 的 注释头(Comment Header),结构如下:

1. “OpusTags” 标识(8 字节)

4F 70 75 73 54 61 67 73 → ASCII: "OpusTags"

✅ 表示这是 Opus 的 注释头(Comment Header),不是识别头(Identification Header)。

2. Vendor String Length(4 字节,小端) 

0C 00 00 00 → 0x0000000C = 12

→ Vendor 字符串长度为 12 字节

3. Vendor String(12 字节) 

4C 61 76 66 36 32 2E 34 2E 31 30 31 → "Lavf62.4.101"
  • Lavf = Libavformat(FFmpeg 的封装库)
  • 62.4.101 = FFmpeg 的版本号

👉 表示这个文件是 用 FFmpeg 62.4.101 版本生成的。

4. User Comment List Length(4 字节,小端)

01 00 00 00 → 0x00000001 = 1

→ 有 1 条用户注释

5. 第一个注释:长度 + 内容

长度(4 字节,小端): 

1D 00 00 00 → 0x1D = 29 字节
内容(29 字节): 
65 6E 63 6F 64 65 72 3D 4C 61 76 63 36 32 2E 31 33 2E 31 30 31 20 6C 69 62 6F 70 75 73

ASCII 解码: 

encoder=Lavc62.13.101 libopus
  • Lavc = Libavcodec(FFmpeg 的编码库)
  • 62.13.101 = 编码器版本
  • libopus = 使用的 Opus 编码器后端

👉 表示音频是用 FFmpeg 的 libavcodec 调用 libopus 编码器完成的。

 

第三页(第一个数据包)

4F 67 67 53 00 00 80 BB 00 00 00 00 00 00 7B C0 CC 0B 02 00 00 00 D0 E4 54 E5 32 3A 36 3E 39 37 36 32 3D 40 39 38 3C 3A 38 38 2F 33 36 33 3B 3C 3F 49 43 40 38 3A 40 3C 3A 3E 3A 3E 35 34 33 31 31 2F 2E 33 2F 33 35 31 37 3A 36 3E 39 78 80 D3 60 D2 DA CB 7F 25 98 67 83 D8 E8 67 61 E1 3C

Ogg Page Header 解析(前 27 字节)

偏移字节内容说明
0x004F 67 67 53"OggS"Ogg 标识
0x0400版本号0
0x0500标志位0x00 → 普通数据页
0x0680 BB 00 00 00 00 00 00Granule Position小端 64 位:0xBB80 = 48000
0x0E7B C0 CC 0BStream Serial No小端:0B CC C0 7B = 197,865,595
0x1202 00 00 00Page Sequence No小端:2 → 第 3 页
0x16D0 E4 54 E5Checksum0xE554E4D0(用于校验)
0x1A32Segment Count0x32 = 50 → 有 50 个 segments

 

Segment Table(Lacing Values)——接下来的 50 字节

从 offset 0x1B 开始,有 50 个字节,每个字节表示一个 segment 的长度(单位:字节),称为 lacing value。

这些值是: 

3A 36 3E 39 37 36 32 3D 40 39 38 3C 3A 38 38 2F 33 36 33 3B 3C 3F 49 43 40 38 3A 40 3C 3A 3E 3A 3E 35 34 33 31 31 2F 2E 33 2F 33 35 31 37 3A 36 3E 39

我们将其转换为 十进制长度(每个是 1 字节): 

58, 54, 62, 57, 55, 54, 50, 61, 64, 57, 56, 60, 58, 56, 56,
47, 51, 54, 51, 59, 60, 63, 73, 67, 64, 56, 58, 64, 60, 58,
62, 58, 62, 53, 52, 51, 49, 49, 47, 46, 51, 47, 51, 53, 49,
55, 58, 54, 62, 57

✅ 总共 50 个 Opus 数据包(packets),每个包的大小如上。

Granule Position = 48000

  • Opus 使用 48 kHz 内部采样率
  • Granule Position 表示“到本页为止累计的音频样本数”
  • 48000 = 正好 1 秒(48000 个样本)

👉 表示这是 前 1 秒音频的结束位置

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值