duration初始为NaN是因元数据未加载完成,需监听loadedmetadata事件后读取,并用isNaN和isFinite判断容错;Infinity表示直播流或无确定时长,应避免直接计算百分比。

duration 不是随时能读的值,直接取大概率是 NaN。必须等元数据加载完成才能用。
为什么 duration 一开始是 NaN
浏览器不会一拿到 src 就立刻知道音频多长——它得先请求文件头、解析容器格式(比如 MP4 或 MP3 的 metadata box),这个过程叫“加载元数据”。没完成前 audio.duration 就是 NaN。
常见误操作:
- DOM 渲染完立即读
audio.duration - 在
load或canplay事件里读(这两个事件触发时元数据未必就绪) - 没检查
audio.readyState就算进度百分比
正确时机是监听 loadedmetadata 事件:
立即学习“前端免费学习笔记(深入)”;
const audio = document.getElementById('my-audio');
audio.addEventListener('loadedmetadata', () => {
console.log('总时长:', audio.duration); // 此时才可靠
});
loadedmetadata 之后还要防 Infinity
直播流、HLS/DASH 等动态流媒体的 duration 可能是 Infinity,这不是错误,是规范行为。硬除会得 NaN,界面卡死或进度条炸开。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
安全读取模式:
- 先判断
!isNaN(audio.duration) && isFinite(audio.duration) && audio.duration > 0 - 对
Infinity场景,改用audio.buffered.end(0)(如果缓冲区有数据)或服务端返回的预估时长 - 别依赖
duration做 UI 渲染逻辑,加 fallback:比如显示 “直播中” 而非 “0:00 / --:--”
currentTime 和 timeupdate 怎么配合用
想实时更新进度条?必须用 timeupdate,不是轮询 currentTime。
原因很实际:
-
timeupdate是浏览器原生同步播放引擎的事件,拖拽、跳转、倍速都会立刻触发 -
requestAnimationFrame或setInterval轮询会漏帧、白耗 CPU,且页面切后台时还在跑 -
currentTime可写,但写入超范围值(比如大于duration)会被自动截断,不报错也不提醒
示例(带边界保护):
audio.addEventListener('timeupdate', () => {
const d = audio.duration;
const c = audio.currentTime;
if (isFinite(d) && d > 0) {
const percent = Math.min(100, Math.round((c / d) * 1000) / 10);
progressBar.style.width = `${percent}%`;
}
});最常被忽略的一点:即使监听了 loadedmetadata,如果音频资源 404、跨域失败、MIME 类型不匹配,事件根本不会触发——务必加 error 监听并打印 audio.error 码排查。


















