Audio container toolkit in pure MoonBit: Ogg page/packet read and write, CRC-32 verification, WAV parsing and encoding, and an Ogg-to-WAV transcoding pipeline
作者:WangYF0829(王轶凡)|创建日期:2026-10-13|用途:moonmux 项目文档
| 环节 | 生态现状 |
|---|---|
| 读容器(demux) | 有:isobmff(MP4 解析)、moontsinspect(TS 检查) |
| 解码 | 有:moonopus、moonvorbis、mp3.mbt、moon-wav |
| 播放 | 有:moon_rodio |
| 写容器(mux) | 没有 |
| 转码管线 | 没有 |
| 模块 | 内容 | 状态 |
|---|---|---|
| ogg/ | 页 / 段 / 包解析与序列化;Ogg 专用 CRC-32;多逻辑流交织;物理流链接与拆分;按大小攒页;granule 二分定位;结构体检(分级 + 坏页重同步);页级补丁 | 已完成 |
| codec/ | 编解码头解析(OpusHead / Vorbis ID)、时长换算、VorbisComment / OpusTags 读写 | 已完成 |
| manifest/ | demux/mux 的流目录清单(流号、包数、链序号、逐包粒度)的解析与生成 | 已完成 |
| wav/ | WAV(RIFF/PCM)读写 | 已完成 |
| pipeline/ | Ogg(Opus / Vorbis)→ WAV 转码管线 | 已完成 |
| cmd/main/ | 命令行工具:info、demux、mux、cat、split、extract、dump、tags、tag、seek、verify、to-wav | 已完成 |
moon add WangYF0829/moonmux| 退出码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 数据校验未通过(输入不是合法 Ogg、被截断、清单与目录不符、verify 的 error / CRC 失败) |
| 2 | 用法或 I/O 错误(参数错、文件读不到、拒绝覆盖非空目录等) |
| 项 | 上限 | 原因 |
|---|---|---|
| 单文件大小 | 2 GiB | MoonBit Int 是 32 位,页偏移与长度都用它;@fs 也只有整文件 API |
| demux 包数 | 999999 | 包文件名固定 6 位,超过后字典序错乱、mux 读回顺序不对 |
| to-wav PCM 预算 | 256 MiB(MOONMUX_MAX_PCM_MB 可调大) | 整条链路没有流式写接口,PCM 必须攒齐再落盘;实测峰值约为预算的 3–4 倍。外部解码器一次返回整段 PCM,恶意伪造的 granule 仍可能造成超出预算的瞬时分配 |
| chop Opus 时间戳 | 页精度,约 ±1 页 | 不重写 OpusHead 的 pre-skip;裁剪后首个数据页可能多带不到一页的前导样本 |
| to-wav 速度 | Opus 约 1.5× 实时;Vorbis 约 80× 实时 | 纯 MoonBit 解码器;Vorbis 路径明显更慢,长文件请先 split |
| chained 拆分 | 整段都由单页流组成时无法拆分 | 与「一段内交织两条单页流」字节相同,规格上不可判定(保守不切) |
| 裁剪流时长 | 上界 | 容器层拿不到首个音频页的样本数,精确值需解码 |
irm https://cli.moonbitlang.cn/install/powershell.ps1 | iexmoon versionmoon build
moon test# 查看容器信息(自动识别 Ogg 与 WAV)
# Ogg:格式、流号、页数、包数、负载字节、各流末粒度;能识别音频流时再给编码/声道/采样率/时长
# WAV:声道、采样率、位深、PCM 字节数、帧数与时长
moonmux info input.ogg
moonmux info input.wav
moonmux info input.ogg --json # 单行 JSON,便于脚本处理
# 注:时长为「末粒度 − 首粒度 − pre-skip」,对裁剪过的流是上界
# 结构体检:逐页 CRC + 页序号连续性 + BOS / EOS 完备性 + 段表一致性
# 用于判断文件是容器损坏还是编码问题,并给出损坏的具体位置
moonmux verify input.ogg
moonmux verify input.ogg --json # 完整 findings(文本只铺前 10 条)
# 解复用:按逻辑流拆出包,每条流一个子目录(s1/、s2/……)
moonmux demux input.ogg ./packets/
# 复用:把包重新封装成 Ogg
# 目录里有子目录 → 每个子目录一条逻辑流,按 Ogg 规则交织(BOS 页置顶、数据页按粒度升序)
# 目录里没有子目录 → 整个目录一条逻辑流
moonmux mux ./packets/ output.ogg
# 链接:把多个 Ogg 文件首尾相接成一个物理流
# 流号不冲突时逐页原样透传(字节级无损);冲突时把后一个文件相撞的流换新流号
moonmux cat a.ogg b.ogg c.ogg output.ogg
# 拆分:把链接流按链接点切回各自独立的 Ogg 文件(输出 part1.ogg、part2.ogg……)
# 页原样沿用,字节与 CRC 一字节不改 —— 非链接流得到的 part1 与输入完全相同
moonmux split chained.ogg ./parts/
# 抽流:把第 n 条逻辑流单独取出来(页级原样,可与输入逐字节对账)
moonmux extract input.ogg 2 single.ogg
# 页级转储:偏移 / 流号 / 页序 / 粒度 / 标志 / 段数 / 负载
moonmux dump input.ogg
moonmux dump input.ogg --hex # xxd 兼容,可 `| xxd -r` 还原
# 注释:读取与改写(KEY= 表示删除该键)
moonmux tags input.ogg
moonmux tag input.ogg tagged.ogg TITLE=月光 ARTIST=王轶凡
# 定位:按毫秒找到不晚于该时刻的页(打印页下标、字节偏移与该页起始时间)
# 链接流可用第 3 个参数指定第几段(默认第 1 段)
moonmux seek input.ogg 2500
moonmux seek chained.ogg 500 2
# 转码:Ogg(Opus / Vorbis)→ WAV;默认 16 位,可选 24 位
moonmux to-wav input.ogg output.wav
moonmux to-wav input.ogg output24.wav 24
# 裁剪:按毫秒区间裁剪(页精度,头页保留,时间轴归零)
moonmux chop input.ogg clip.ogg 1000 3000moon build --target nativemoonmux/
├── moon.mod 模块配置
├── moon.pkg 根包
├── moonmux.mbt 模块级描述
├── ogg/ Ogg 容器
│ ├── crc.mbt CRC-32(RFC 3533 参数)与页校验
│ ├── page.mbt 页的解析与序列化
│ ├── packet.mbt 包重组与页切分
│ ├── mux.mbt 多逻辑流的分组与交织
│ ├── chain.mbt 物理流链接与拆分(chained bitstream)
│ ├── verify.mbt 结构体检(段表 / 页序号 / BOS·EOS)
│ └── stream.mbt 字节流 ↔ 页序列
├── wav/ WAV 容器
├── pipeline/ 转码管线(唯一引入三方解码器的包)
├── cli/ 命令行参数解析(纯逻辑)
├── cmd/main/ 命令行入口
└── testdata/ 真实音频样本source scripts/moonmux.bash # 子命令与文件路径补全| 项目 | 参考了什么 | 没有照搬什么 |
|---|---|---|
| Xiph oggz / liboggz | 子命令的语义(rip/dump/validate/chop 的职责划分)、多流合并按呈现时间 | 不做 Skeleton,不解析 Theora/FLAC 等头;dump 不可逆 |
| libogg | 页大小与 flush 时机(4096 阈值、首页/EOS 强制刷出) | 不把 BOS 顺序交给调用方;写侧自己维护不变量 |
| mutagen(Python) | 注释改写时用 padding 保持旧包等长、复用旧页布局 | 不做 high/low 区间公式 |
| ffmpeg | 作为行为对照(转码产物用独立工具回读验证) | 不用时间驱动的分页策略 |
| libopusfile | seek 在 granule 上插值二分、80 ms pre-roll | 只定位到页,不解码 |
Install
Download zipAudio container toolkit in pure MoonBit: Ogg page/packet read and write, CRC-32 verification, WAV parsing and encoding, and an Ogg-to-WAV transcoding pipeline