HTMLAudioElement的onplay、ontimeupdate事件里timeStamp值的误差问题

Posted by 橙叶 on Thu, Sep 2, 2021

最近在做一个歌词组件,分享一下中间踩到的坑。

这个歌词组件简单来说就是读入lrc格式的歌词文件,把时间戳解析出来,在音乐播放时按时间戳显示。

这些都不重要,重要的是为了获取音乐的实时播放事件,让歌词滚动到相应的位置,监听了HTMLAudioElement的ontimeupdate事件。

const audioTag = this.$refs.audioTag as HTMLAudioElement
audioTag.ontimeupdate = async (evt) => {
    await this.scrollLyric(evt.timeStamp)
}

ontimeupdate里的事件的timeStamp的值是歌曲的播放进度。

但是后来发现,这个值和歌曲实际播放时间并不一样,会比实际播放进度快2~3秒甚至4秒。具体这个误差是哪儿来的我也不清楚。

实际上onplay里的timeStamp也一样会快,但比ontimeupdate的第一次调用早300ms左右。

因此实际使用的时候,可以在onplay里把时间误差记录一下,然后在ontimeupdate里再减掉这个误差,最终得到准确的播放进度:

audioTag.onplay = async (evt) => {
    this.play.startTime = evt.timeStamp
}
audioTag.ontimeupdate = async (evt) => {
    await this.scrollLyric(evt.timeStamp - this.play.startTime)
}

更新:正确的获取播放进度的办法是...

const audioTag = this.$refs.audioTag as HTMLAudioElement
audioTag.ontimeupdate = async (evt) => {
    await this.scrollLyric(evt.target.currentTime)
}

至于那个timestamp,请远离它。



comments powered by Disqus