问题发生在“选择文件”这一步
最初的上传入口把文件选择器限制为常见音频 MIME 类型。在桌面浏览器中这通常有效,但部分安卓系统会把 M4A 报告为 video/mp4、application/mp4,甚至给出不完整类型。文件实际包含音频,系统选择器却只根据类型标签判断,于是用户还没上传就无法点选。
这次问题提醒我们:浏览器显示的 MIME 是设备和文件管理器提供的描述,不是对文件内容的最终鉴定。把它当成绝对事实,会在移动端制造兼容断点。
扩展名、MIME、容器和编码不是一回事
.m4a 是常见扩展名;MIME 是系统传给网页的类型标签;MP4 是容器;容器内部通常还装着 AAC 等实际音频编码。四者相关,却不能互相替代。改个扩展名不会转换编码,MIME 写错也不代表文件一定损坏。
| 线索 | 能说明什么 | 不能说明什么 |
|---|---|---|
| 扩展名 | 用户和应用预期怎样打开文件 | 不能证明内部编码真实有效 |
| MIME | 设备如何描述这次选择 | 不同安卓系统可能给出不同值 |
| 容器 | 音频流和元数据怎样封装 | 同一种容器可以包含不同编码 |
| 解码结果 | 服务端是否真的能读出音频 | 仍不能证明内容适合声音分析 |
CVoice 采用的修复方式
上传入口改成通用文件选择器,让安卓系统不再提前屏蔽 M4A;文件被选中后,再由网页执行白名单校验,只接受 WAV、MP3、M4A、WebM、OGG 和 AMR。对于可可靠识别但缺少标准扩展名的文件,页面补全名称;audio/mp4、audio/x-m4a、video/mp4 和 application/mp4 都进入 M4A 兼容分支。
这不是“接受所有文件”。选择器负责让用户选得到,前端白名单负责第一层安全检查,服务端解码负责验证真实内容,声音质量门槛再判断它是否足以生成报告。修复时完整服务测试共 79 项通过,并加入安卓 M4A MIME 别名的专项检查。
从这次修复得到的通用检查顺序
- 确认文件是否在系统选择器中可见,而不是先怀疑分析算法。
- 记录设备提供的扩展名与 MIME,不只收集一句“上传失败”。
- 把“允许选择”和“允许处理”拆成两层,避免为了兼容而放弃校验。
- 让解码错误、时长不足、静音过多和格式不支持显示不同提示。
- 用真实移动设备复查,不只依赖桌面浏览器模拟。
适用边界这套映射解决的是“有效音频被错误拦截”。它不能修复内部数据损坏、编码器异常或伪装成音频的其他文件;最终仍以实际解码结果为准。