JavaScript使用Audio构造器获取音频时长返回NaN如何解决
问题根因
你拿到NaN的核心原因是 音频元数据的加载是异步操作:调用new Audio(element)只是创建了音频实例、触发了资源加载请求,此时音频的时长、编码等元数据还没有完成拉取解析,直接读取duration属性就会返回NaN。
解决方案
可以监听音频的loadedmetadata事件,等元数据加载完成后再读取时长属性即可。如果需要批量拿到所有音频的时长,可以用Promise包装做批量异步处理:
基础事件监听写法
const audioArray = [ '1.mp3', '2.mp3', '3.mp3', '4.mp3' ] audioArray.forEach((element)=>{ const audioElement = new Audio(element); // 元数据加载完成后触发回调 audioElement.addEventListener('loadedmetadata', () => { console.log(`${element} 时长:`, audioElement.duration); }) // 加载失败的异常兜底 audioElement.addEventListener('error', (err) => { console.error(`${element} 加载失败:`, err) }) })
批量收集时长写法
如果需要把所有音频时长汇总后统一处理,可以用Promise.allSettled实现:
const audioArray = [ '1.mp3', '2.mp3', '3.mp3', '4.mp3' ] // 封装单个音频时长获取方法 const getAudioDuration = (audioSrc) => { return new Promise((resolve, reject) => { const audio = new Audio(audioSrc); audio.addEventListener('loadedmetadata', () => resolve({ src: audioSrc, duration: audio.duration })) audio.addEventListener('error', (err) => reject({ src: audioSrc, error: err })) }) } // 批量获取所有音频时长 Promise.allSettled(audioArray.map(item => getAudioDuration(item))) .then(results => { results.forEach(res => { if(res.status === 'fulfilled') { console.log(`${res.value.src} 时长:`, res.value.duration) } else { console.error(`${res.reason.src} 加载失败:`, res.reason.error) } }) })
注意事项
- 本地调试如果直接用
file://协议打开页面,部分浏览器会因为跨域限制无法正常加载本地音频资源,建议用本地服务启动调试 - 返回的时长单位为秒,若需要转换为分秒格式可自行做数值换算
内容的提问来源于stack exchange,提问作者Harshu Prasad Shukla
相关产品推荐
相关产品推荐

