vue实现歌词同步
实现歌词同步的基本思路
歌词同步的核心是将歌词文本与音频时间轴匹配,通过解析歌词文件(如LRC格式)获取时间戳和歌词内容,在播放时根据当前时间动态高亮显示对应歌词。
解析歌词文件
LRC格式的歌词文件通常包含时间戳和歌词文本,例如:
[00:00.00] 歌曲名
[00:01.00] 第一句歌词
[00:03.50] 第二句歌词
解析方法:

function parseLrc(lrcText) {
const lines = lrcText.split('\n')
const result = []
for (let line of lines) {
const parts = line.split(']')
const timeStr = parts[0].substring(1)
const obj = {
time: parseTime(timeStr),
words: parts[1]
}
result.push(obj)
}
return result
}
function parseTime(timeStr) {
const parts = timeStr.split(':')
return +parts[0] * 60 + +parts[1]
}
歌词组件实现
创建Lyric.vue组件:
<template>
<div class="lyric-container">
<ul ref="lyricList">
<li
v-for="(line, index) in lyricLines"
:key="index"
:class="{ active: currentLine === index }"
>
{{ line.words }}
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
lrcText: String,
currentTime: Number
},
data() {
return {
lyricLines: [],
currentLine: 0
}
},
watch: {
lrcText: {
immediate: true,
handler(val) {
this.lyricLines = this.parseLrc(val)
}
},
currentTime(newTime) {
this.findCurrentLine(newTime)
}
},
methods: {
parseLrc(lrcText) {
// 使用上面的解析函数
},
findCurrentLine(time) {
for (let i = 0; i < this.lyricLines.length; i++) {
if (time < this.lyricLines[i].time) {
this.currentLine = i - 1
this.scrollToCurrentLine()
return
}
}
},
scrollToCurrentLine() {
const container = this.$refs.lyricList
const activeItem = container.children[this.currentLine]
if (activeItem) {
container.scrollTop = activeItem.offsetTop - container.offsetHeight / 2
}
}
}
}
</script>
<style>
.lyric-container {
height: 300px;
overflow-y: auto;
}
.active {
color: #ff0000;
font-weight: bold;
}
</style>
与音频播放器集成
在父组件中使用:

<template>
<div>
<audio
ref="audioPlayer"
:src="audioSrc"
@timeupdate="handleTimeUpdate"
></audio>
<Lyric :lrc-text="lrcText" :current-time="currentTime" />
</div>
</template>
<script>
import Lyric from './Lyric.vue'
export default {
components: { Lyric },
data() {
return {
audioSrc: 'your-audio-file.mp3',
lrcText: '', // 从API或文件加载歌词
currentTime: 0
}
},
methods: {
handleTimeUpdate() {
this.currentTime = this.$refs.audioPlayer.currentTime
}
}
}
</script>
性能优化
对于长歌词列表,考虑虚拟滚动技术减少DOM渲染压力。可使用vue-virtual-scroller等库实现:
<template>
<RecycleScroller
class="lyric-container"
:items="lyricLines"
:item-size="50"
key-field="time"
v-slot="{ item, index }"
>
<li :class="{ active: currentLine === index }">
{{ item.words }}
</li>
</RecycleScroller>
</template>
处理复杂歌词格式
对于双语歌词或带翻译的歌词,解析时需要额外处理:
[00:01.00] 原文歌词
[00:01.00](trans) 翻译歌词
解析时可创建多语言支持的数据结构:
{
time: 1.00,
original: "原文歌词",
translation: "翻译歌词"
}






