原因
问题在于 AAC 是一种流式传输格式。这意味着没有像容器格式一样提供全局文件头(例如“mp4”),因此浏览器必须猜测基于初始加载的比特率的时间数据包 标头(ADTS)和服务器提供的文件长度。
由于浏览器在整个流被消耗之前不知道实际样本长度,因此结果将根据浏览器(或底层系统)尝试预测持续时间的方式而有所不同。
AAC 也可以使用 可变比特率 (VBR) 进行编码,这使得很难正确预测持续时间,因为在开始时找到的比特率可能不是用于稍后会提供其他示例数据包。
当然也有文件/编码损坏或错误的可能性。
顺便说一句,这些相同的挑战也适用于 MP3 文件。这就是为什么它们有时也会显示不正确的持续时间。
解决方法
首先是使用恒定比特率 (CBR) 对 AAC 进行编码。这将允许浏览器更可靠地预测时间,因为如果变化很明显,VBR 可以在任何时候抛出计算。这很可能会影响文件大小。
如果 CBR 不是一个选项,一种解决方法是为 AAC 流(例如 MP4)提供 容器格式,它可以将持续时间存储在开头加载的全局标头中 - MP4 可以由 Audio 元素作为缓冲音频使用。执行此操作时,您将获得正确的时间(可能会有一些次要数字的舍入误差):
AAC 在 Firefox 的 MP4 容器中加载:
AAC 在 Chrome 的 MP4 容器中加载
要为 AAC 生成 MP4 容器,您可以使用例如免费的 ffmpeg 和这些参数,它将按原样复制 AAC(不进行重新编码,因此结果将具有相同的质量和位-率和以前一样):
ffmpeg.exe -i "Lesson+53-A.aac" -c:a copy "Lesson+53-A.mp4"
你也会看到 ffmpeg 指出这个问题:
[aac @ 0000000001c624a0] 根据比特率估计持续时间,这可能不准确 [...]
另一个可能不太方便的解决方法是将持续时间作为元数据提供,例如文件名本身(类似于“myfile_MMSS.aac”)或作为 url 中的哈希标签/参数,或单独加载元数据。
虽然我们不能覆盖原生播放器的持续时间字段(以跨浏览器友好的方式),但后者会产生一定的影响,这可能需要您构建自定义播放器界面,以便您可以将元数据显示为持续时间而不是浏览器预测一个。