ogg

ogg

    正在检查是否收录...

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

字段字节说明
capture_pattern 4F 67 67 53 "OggS" Ogg 文件标识符
version 00 0 Ogg 格式版本
header_type 02 2 页面类型:0x02 表示这是 初始页(bos),通常是头信息
granule_position 00 00 00 00 00 00 00 00 0 音频采样位置(此处为 0,因为是头页)
bitstream_serialno 7B C0 CC 0B 0x0BCC C07B 流的唯一 ID(小端序)
page_sequence_no 00 00 00 00 0 页面序号,头页为 0
CRC_checksum 01 BA D3 2F CRC32 校验和 用于校验
page_segments 01 1 该页包含 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_signature 8 字节 4F 70 75 73 48 65 61 64 "OpusHead" ASCII
version 1 字节 01 版本号,必须为 1
channel_count 1 字节 01 声道数:1(单声道)
pre_skip 2 字节(小端) 38 01 → 0x0138 = 312 编码器在解码时应跳过的样本数
input_sample_rate 4 字节(小端) 80 BB 00 00 → 0x0000BB80 = 48000 Hz 输入采样率(仅作参考)
output_gain 2 字节(小端) 00 00 增益(dB × 256),0 表示无增益
channel_mapping_family 1 字节 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 字节)

偏移字节内容说明
0x00 4F 67 67 53 "OggS" Ogg 页头标识
0x04 00 版本号 0,标准版本
0x05 00 标志位 0x00:普通页,非开始、非结束
0x06 00 00 00 00 00 00 00 00 Granule Position 64位,当前为 0 → 通常是首帧之后的数据页或注释页
0x0E 00 00 00 00 Stream Serial Number 流 ID = 0
0x12 7B C0 CC 0B Page Sequence No 小端表示:0B CC C0 7B = 197,865,595(十进制)
0x16 15 6E F0 0B Checksum 小端:0B F0 6E 15 = 210,562,581(校验用)
0x1A 01 Segment 数量 1 个 segment
0x1B 3D Segment 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 字节)

偏移字节内容说明
0x00 4F 67 67 53 "OggS" Ogg 标识
0x04 00 版本号 0
0x05 00 标志位 0x00 → 普通数据页
0x06 80 BB 00 00 00 00 00 00 Granule Position 小端 64 位:0xBB80 = 48000
0x0E 7B C0 CC 0B Stream Serial No 小端:0B CC C0 7B = 197,865,595
0x12 02 00 00 00 Page Sequence No 小端:2 → 第 3 页
0x16 D0 E4 54 E5 Checksum 0xE554E4D0(用于校验)
0x1A 32 Segment Count 0x32 = 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 秒音频的结束位置

 

  • 本文作者:WAP站长网
  • 本文链接: https://wapzz.net/post-27877.html
  • 版权声明:本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。
本站部分内容来源于网络转载,仅供学习交流使用。如涉及版权问题,请及时联系我们,我们将第一时间处理。
文章很赞!支持一下吧 还没有人为TA充电
为TA充电
还没有人为TA充电
0
0
  • 支付宝打赏
    支付宝扫一扫
  • 微信打赏
    微信扫一扫
感谢支持
文章很赞!支持一下吧
关于作者
2.8W+
9
1
2
WAP站长官方

再见 Claude,封禁中国等 “敌对国家” 的公司使用!脸都不要了?

上一篇

技术面:Java并发(线程池、ForkJoinPool)

下一篇
评论区
内容为空

这一切,似未曾拥有

  • 复制图片
按住ctrl可打开默认菜单