直接回答
WAV 是 RIFF 容器,不是一个固定 44 字节头后面必定紧跟 PCM 样本。常见 PCM 测试文件可能恰好是这种大小,但有效文件也能含可选元数据、额外格式字段或对齐填充。固定跳到字节 44,可能把元数据当样本,或跳过另一种布局的一部分。容器解析应和媒体解码、后续推理任务分开;先确认某个有界 profile 实际暴露了哪些字节范围。 对声明支持的 classic RIFF/WAVE profile,依次解析 RIFF 标识符、小端无符号 32 位长度、WAVE form type 和子 chunk 序列。父长度覆盖 form type 与子 chunk 内容,包括必须的对齐填充。子 chunk 由四字节 ID、四字节长度和数据构成;chunk size 不含 8 字节子头或填充字节。数据长度为奇数时,下一个 chunk 从补上的一个字节之后开始。这些都是容器长度,不是固定头长度。 用带边界检查的游标,并在每次加法前使用更宽整数运算。先算出 RIFF 声明的结尾并与真实源长度比较;如果尺寸溢出、越过父边界、超过应用设定的字节上限,或无法完整读取,就拒绝。对每个子 chunk,在 seek 或 skip 前校验头是否完整、数据结尾和补齐后的下一个偏移。未知 chunk 只能在相同已验证边界内跳过,不能按不可信 size 分配内存。还要限制 chunk 数量,防止许多极小 chunk 导致无界处理。 必须定义支持的 WAVE profile,不能承诺所有扩展名为 WAV 的文件都支持。profile 应写明如何寻找 fmt/data、如何处理重复或错序的必需 chunk,以及哪些 fmt 长度或压缩代码交给解码器。格式 chunk 并非固定 16 字节的 PCM 结构;extensible 和压缩格式需要各自声明。本文不解析采样率或判断音频适不适合模型。保留 chunk 范围,只把解码器明确支持的格式交给它。 RIFF/WAVE 的 32 位尺寸字段不能表示任意大文件。RF64/BW64 使用不同容器标识和 ds64 chunk 提供扩展长度。classic RIFF 解析器不得把 0xFFFFFFFF sentinel 当成普通超大长度、转换成负有符号数或按它分配内存。要么在读取 chunk 前明确拒绝 RF64/BW64,要么交给单独验证过、能处理 64 位长度表的实现。格式的大文件上限不是 Android RAM 估算。 生产环境优先考虑维护中的媒体/容器库,前提是它的支持 profile 与边界行为符合需求。若应用代码自己拥有一个小型结构探测器,也要把它视为不可信输入边界,独立测试并记录范围。解析器找到 fmt 和 data 只能说明所选结构检查通过;不能证明 codec 可解、可播放、模型兼容或离线 AI 任务完整。COVE-ASR-01 表明当前共享推理路径会把 PCM 包成 WAV 输出;不能据此说 Cove 已能读取任意导入 WAV。 测试使用合成字节夹具,不用用户录音。覆盖最小支持文件、在已知 chunk 前后的未知/元数据 chunk、奇数长度和填充字节、profile 允许的非典型 fmt 长度、重复 fmt/data、错误顺序、父长度错误、chunk 长度溢出、缺少 padding、chunk 内容截断和声明数据早于真实音频结束。逐项断言偏移和拒绝原因。解析本身要限制读取与循环,不公开由合成样例得出的设备兼容列表。
导入 WAV 在音频数据前包含元数据 chunk
用户选择一个 WAV,RIFF/WAVE 外层有效,含可选元数据 chunk,而 audio data 不从第 44 字节开始。固定偏移读取器把元数据传给下游解码器,任务失败后看起来像推理故障。
决策
依据声明且有边界的 chunk size 遍历 RIFF 序列并处理对齐,再只把已验证且被所选解码器支持的数据范围交出去。
预期结果
导入路径会识别可支持的数据范围,或以容器结构错误明确拒绝;不会猜偏移后把不明字节送入推理。
需要收集的证据
只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:
- ANDROID-AUDIO-01:音频格式与下游封装需要分别记录;不意味着 Cove 实现了任意 WAV 导入解析器。
- COVE-ASR-01:当前共享 InferenceEngine 会把 PCM 包为 WAV 交给 LiteRT-LM;这是生成侧代码事实,不是读取外部 WAV 的能力证明。
- AUDIO-RIFF-BOUNDS-2026-10:RIFF/WAVE chunk-size 与父容器边界、奇数填充和 RF64/BW64 扩展应按有界格式解析并单独验证。
发布结论只对所记录的配置和验收集有效;扩大适用范围需要更多记录。
实施流程
- 声明接受的容器 profile. 写明只接受 classic RIFF/WAVE 还是其他格式,识别哪些必需 chunk,以及如何处理重复或错序的 fmt/data 和格式扩展。将 RF64/BW64 交给独立解析器或明确拒绝。
- 安全解析父容器边界. 读取 RIFF 标识和小端无符号长度,不把值转换成有符号长度。用溢出检查计算父结尾,包含 WAVE form type 和 chunk/padding,并在遍历前确认声明范围不超过实际源长度。
- 不使用固定偏移遍历每个 chunk. 确保八字节子头完整,将数据结尾和奇数长度后的 padding 纳入父容器与文件边界检查。未知 chunk 只按已验证范围 seek 或 drain;不按其声明长度分配数组。
- 验证格式与数据范围. 按 profile 处理 fmt/data 的存在、重复与顺序。只把精确的 data 偏移和长度交给支持该格式的解码器;不推断所有 WAV 都是 PCM16,也不接受实现未声明的 extensible 或压缩格式。
- 明确拒绝扩展或损坏容器. 把 RF64/BW64 标识和 0xFFFFFFFF size sentinel 视为需 ds64 支持的独立格式。对截断数据、溢出、越界、缺失 padding 和超量 chunk 返回结构错误,而不是猜测后回退解码。
- 独立测试结构和解码边界. 用合成夹具断言 chunk 偏移、未知块跳过、边界和拒绝类别,再将解码器交接作为单独阶段验证。结构解析通过不证明 codec、播放、采样格式或模型兼容性。
让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。
验收标准
- 解析器不假设 44 字节头;它从经验证的 RIFF 边界寻找支持的 chunk,并处理每个 chunk 头和奇数填充字节。
- 所有尺寸加法对照声明父边界和实际源长度检查,并限制字节与 chunk 数量;不从不可信长度分配内存,早期 EOF 明确失败。
- 支持的 profile 明确必需/重复 chunk 和格式处理;不支持的压缩/extensible 格式与 RF64/BW64 会拒绝或交给单独验证过的解析器。
- 测试区分容器结构与解码/推理,不从结构通过推导音频格式普遍受支持或 Cove 支持导入。
决策对照表
| 维度 | 选择或证据 | 解读方式 |
|---|---|---|
| 固定 44 字节偏移读取器 | 假设最小 PCM 头,并从固定位置读取音频 | 窄夹具中也许可用,但可选 chunk、格式扩展或 padding 会改变数据位置。 |
| 有界 classic RIFF/WAVE 遍历 | 依次读声明 chunk 头并遵守已验证长度/对齐 | 可实现声明好的子集并跳过未知 chunk;每个偏移仍必须做边界检查。 |
| 支持 RF64/BW64 的读取器 | 通过指定 ds64 表解析 sentinel 和扩展尺寸 | 是独立的 64 位容器合同;classic 32 位 RIFF 解析器应拒绝而非猜大小。 |
| 媒体解码器或维护中的解析库 | 委托给版本固定、profile 明确的实现 | 其行为和错误边界仍需实测,不能仅凭库名声称它支持目标文件。 |
需要避免的失败模式
- 假设 WAV 一律是 44 字节头并从固定偏移读取。
- 把 32 位 chunk size 当作有符号长度,或在加 padding 时发生溢出。
- 遇到未知 chunk 就分配其声明长度,或忽略早期 EOF。
- 将 RF64/BW64 的 0xFFFFFFFF 当普通长度处理。
- 从找到 fmt 与 data 推断编解码器、模型输入或 Cove 功能已支持。
还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。
最小复现记录
| 层级 | 记录内容 |
|---|---|
| 设备 | 厂商、型号、芯片、内存档位、操作系统版本 |
| 软件 | 应用版本和 Git 提交号 |
| 模型 | 系列、变体、版本、格式、文件长度、摘要、量化方式 |
| 运行时 | 名称、版本、请求后端及实际后端证据 |
| 工作负载 | 样例版本、输入摘要、提示词摘要、输出策略 |
| 结果 | 完成、失败、取消、回退及保护隐私的诊断信息 |
发布检查表
- ☐ 主要搜索问题已回答,且没有未经支持的数字。
- ☐ 所有模型文件和运行时版本均已固定。
- ☐ 代表性任务和失败处理策略均有说明。
- ☐ 生命周期、取消、清理和回退均已测试。
- ☐ 用户内容与网络边界均有说明。
- ☐ 结论只适用于被记录的配置。
- ☐ 新增测试结果时链接到原始方法或证据。
来源与相关证据
- Cove Travel 语音翻译实现
- Microsoft Learn — Resource Interchange File Format (RIFF)
- Microsoft Learn — RIFF 格式服务与 chunk 遍历
- EBU — RF64 扩展音频文件格式
- EBU — Tech 3306 RF64 结构,1.1 版
- ITU-R — Recommendation BS.2088-2 BW64 格式
中文部署与排错专题见。奇连 AI 端侧专题。
常见问题
每个 WAV 的音频都从第 44 字节开始吗?
不是。该偏移只对应常见的最小 PCM 布局,不是通用 RIFF/WAVE 合同。可选 chunk、格式扩展和对齐填充都可能改变支持的数据 chunk 的起点。
未知 RIFF chunk 可以直接忽略吗?
有界读取器可以不解释未知内容而跳过它,但必须先验证长度、填充字节和父边界。不能按声明尺寸分配内存,也不能越过实际文件结尾。
classic RIFF 读取器可以接受 RF64 size sentinel 吗?
不可以。RF64/BW64 使用单独 ds64 尺寸合同。要么拒绝,要么交给经验证能读该表的实现;不能把 0xFFFFFFFF 当普通长度。
找到 fmt 和 data 就证明 WAV 可被 AI 模型读取吗?
不能。结构解析只证明声明 profile 下的 chunk 边界通过;解码器还需支持实际格式,且结构检查无法证明推理兼容或 Cove 已实现该功能。