当我们在加载一个线上mp3地址或者获取audio的duration的时候,会发现有拿到duration是Infinity的情况,这时如果我们动态的展示录音时间时候就会有问题。首先明确一下这是chrome浏览器自己的存在的一个bug,因为我们拿到的录音数据流没有定义长度,所以浏览器无法解析出当前音频的时长。
一、发现问题
使用浏览器内置播放器<audio>无法显示时长
Chrome && Edge: 播放到一定时间后才能移动进度条与显示时长
Firefox
:直接可以看到进度条与时长
继续往下,解决Chrome中的问题
二、获取总时长为 NaN || Infinity
audio.ontimeupdate = () => { console.log(`currentTime: ${audio.currentTime} , duration: ${audio.duration}`) }
根据输出结果发现,只有播放一段时间,或者开始播放的时候才会拿到总时长,但这并不是我们想要的。初始化的时候就想拿到总时长
三、解决方案
预加载!直接先播放一遍获取时长!
// node为audio标签的dom元素 export const formatePlayerDuration = (node: any) => { node.onloadedmetadata = (e: any) => { const audio = e.target; const audioDuration = audio.duration; if (audioDuration === Infinity) { audio.currentTime = 1e101; audio.ontimeupdate = () => { audio.ontimeupdate = () => { return; }; // 不重新设置currtTime,会直接触发audio的ended事件,因为之前将currentTime设置成了一个比音频时长还大的值。所以要将currentTime重置为初始状态。 // 注: 这里有一个问题,直接设置为0 是不起作用的。需要重新设置一下audio.currentTime = 1e101;然后再设置为 audio.currentTime = 1e101; audio.currentTime = 0; } } } }
问题解决!!!!!!!
audio标签
<audio src='mp3地址' class="xxx" controls controlsList="nodownload noplaybackrate" preload="auto"></audio>
尝试了一种setTimeout的方法,也可以解决,但是页面时间部分会出现时间闪烁的情况,所以就不考虑了,代码贴出来
const audio = new Audio() audio.src = 'https://www.xx.com/audio/xx.mp3' const countAudioTime = async () => { while (isNaN(audio.duration) || audio.duration === Infinity) { await new Promise(resolve => setTimeout(resolve, 200)); // 设置随机播放时间 audio.currentTime = 10000000 * Math.random(); } console.log('音频的总时长:',audio.duration) } countAudioTime()