最近在做一个歌词组件,分享一下中间踩到的坑。
这个歌词组件简单来说就是读入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,请远离它。