问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

JS实现歌词与歌曲同步的完整指南

创作时间:
作者:
@小白创作中心

JS实现歌词与歌曲同步的完整指南

引用
1
来源
1.
https://docs.pingcode.com/baike/3766358

本文将详细介绍如何使用JavaScript实现歌词与歌曲的同步显示。通过使用时间戳、解析歌词文件、借助定时器和更新UI,可以确保歌词与歌曲保持同步。

一、JS将歌词和歌同步的方法

JS将歌词和歌同步的方法包括:使用时间戳、解析歌词文件、借助定时器、更新UI。其中,使用时间戳是最关键的一步,因为时间戳能够精确地标记歌词出现的时间点,确保歌词与歌曲的同步。

为了实现歌词和歌的同步,首先需要获取歌词文件并解析,将歌词与对应的时间点进行关联。然后,利用JavaScript的定时器功能,根据当前播放时间动态更新歌词显示。最后,需要处理UI更新,确保歌词在播放过程中能够实时显示并滚动。

二、解析歌词文件

解析歌词文件是实现歌词同步的第一步。通常,歌词文件以LRC格式存储,每一行歌词都有相应的时间戳。解析歌词文件时,需要将时间戳与歌词内容分离,并存储在数据结构中。这样,在播放歌曲时,可以根据当前时间查找对应的歌词。

1. LRC格式简介

LRC文件是一种常见的歌词文件格式,它将歌词与时间戳结合在一起,使歌词能够与歌曲同步显示。LRC文件中的每一行歌词都带有一个时间戳,表示歌词在歌曲中出现的时间点。时间戳通常以“[mm:ss]”格式出现,表示歌词在歌曲中出现的具体时间。例如,[00:30]表示歌词在30秒时出现。

2. 解析LRC文件

解析LRC文件时,需要将时间戳与歌词内容分离,并存储在数据结构中。可以使用JavaScript的正则表达式来提取时间戳和歌词内容。以下是一个简单的LRC文件解析示例:

function parseLRC(lrcContent) {
    const lines = lrcContent.split('n');
    const lyrics = [];
    for (const line of lines) {
        const match = line.match(/[(d{2}):(d{2}).(d{2})](.*)/);
        if (match) {
            const minutes = parseInt(match[1], 10);
            const seconds = parseInt(match[2], 10);
            const millis = parseInt(match[3], 10);
            const time = minutes * 60 + seconds + millis / 100;
            const text = match[4].trim();
            lyrics.push({ time, text });
        }
    }
    return lyrics;
}

在这个示例中,parseLRC函数接收一个LRC文件内容的字符串,并返回一个包含时间戳和歌词内容的数组。每一行歌词都被解析成一个对象,包含时间戳和歌词文本。

三、使用时间戳同步歌词

使用时间戳是实现歌词同步的核心。通过给每一行歌词加上时间戳,能够精确标记歌词出现的时间点,确保歌词与歌曲的同步。

1. 获取当前播放时间

为了实现歌词同步,需要获取歌曲的当前播放时间。HTML5的audio元素提供了丰富的API,可以用来控制和获取音频播放状态。以下是获取当前播放时间的示例:

const audio = document.getElementById('audio');
const currentTime = audio.currentTime;

在这个示例中,通过audio.currentTime属性可以获取音频的当前播放时间,以秒为单位。

2. 查找对应的歌词

根据当前播放时间,可以查找对应的歌词。可以使用二分查找算法来提高查找效率。以下是一个查找对应歌词的示例:

function findCurrentLyric(lyrics, currentTime) {
    let low = 0;
    let high = lyrics.length - 1;
    while (low <= high) {
        const mid = Math.floor((low + high) / 2);
        if (lyrics[mid].time < currentTime) {
            low = mid + 1;
        } else if (lyrics[mid].time > currentTime) {
            high = mid - 1;
        } else {
            return lyrics[mid];
        }
    }
    return lyrics[low - 1];
}

在这个示例中,findCurrentLyric函数接收一个包含歌词的数组和当前播放时间,并返回当前时间对应的歌词。

四、借助定时器更新歌词

借助定时器是实现歌词实时更新的关键。JavaScript提供了多种定时器方法,如setIntervalrequestAnimationFrame,可以用来定期检查歌曲的播放时间,并更新歌词显示。通过不断更新歌词,可以确保歌词与歌曲保持同步。

1. 使用setInterval定时器

可以使用setInterval定时器来定期检查歌曲的播放时间,并更新歌词显示。以下是一个示例:

const lyrics = parseLRC(lrcContent);
const audio = document.getElementById('audio');
const lyricsContainer = document.getElementById('lyrics');
function updateLyrics() {
    const currentTime = audio.currentTime;
    const currentLyric = findCurrentLyric(lyrics, currentTime);
    lyricsContainer.textContent = currentLyric.text;
}
setInterval(updateLyrics, 100);

在这个示例中,每隔100毫秒调用一次updateLyrics函数,获取当前播放时间,并查找对应的歌词,然后更新歌词显示。

2. 使用requestAnimationFrame定时器

requestAnimationFrame是浏览器提供的一种更高效的定时器方法,通常用于动画和UI更新。可以使用requestAnimationFrame来实现更平滑的歌词更新。以下是一个示例:

const lyrics = parseLRC(lrcContent);
const audio = document.getElementById('audio');
const lyricsContainer = document.getElementById('lyrics');
function updateLyrics() {
    const currentTime = audio.currentTime;
    const currentLyric = findCurrentLyric(lyrics, currentTime);
    lyricsContainer.textContent = currentLyric.text;
    requestAnimationFrame(updateLyrics);
}
requestAnimationFrame(updateLyrics);

在这个示例中,使用requestAnimationFrame来实现歌词更新,使歌词显示更加平滑。

五、更新UI显示

更新UI是歌词同步的最后一步。根据当前播放时间,查找对应的歌词,并更新显示。为了提高用户体验,通常需要实现歌词滚动效果,使当前歌词始终保持在视野中。

1. 实现歌词滚动效果

为了实现歌词滚动效果,可以使用CSS和JavaScript结合的方法。以下是一个示例:

<style>
    #lyrics {
        height: 200px;
        overflow: hidden;
        position: relative;
    }
    .lyric-line {
        position: absolute;
        width: 100%;
        text-align: center;
    }
</style>
<div id="lyrics">
    <div class="lyric-line" id="lyric-line-0">...</div>
    <div class="lyric-line" id="lyric-line-1">...</div>
    <!-- more lines -->
</div>
const lyrics = parseLRC(lrcContent);
const audio = document.getElementById('audio');
const lyricsContainer = document.getElementById('lyrics');
const lyricLines = document.querySelectorAll('.lyric-line');
function updateLyrics() {
    const currentTime = audio.currentTime;
    const currentLyric = findCurrentLyric(lyrics, currentTime);
    const index = lyrics.indexOf(currentLyric);
    lyricLines.forEach((line, i) => {
        if (i === index) {
            line.style.top = '50%';
            line.style.transform = 'translateY(-50%)';
        } else {
            line.style.top = `${50 + (i - index) * 100}%`;
            line.style.transform = 'translateY(-50%)';
        }
    });
    requestAnimationFrame(updateLyrics);
}
requestAnimationFrame(updateLyrics);

在这个示例中,通过调整歌词行的位置和样式,实现歌词滚动效果。当前歌词始终保持在视野中,而其他歌词根据位置进行调整。

六、优化歌词同步

为了提高歌词同步的效果,可以进行一些优化,如处理歌词延迟、支持多种歌词格式等。

1. 处理歌词延迟

在实际使用中,可能会遇到歌词延迟的问题。可以通过调整时间戳来处理歌词延迟。以下是一个示例:

function adjustLyricsDelay(lyrics, delay) {
    return lyrics.map(lyric => ({
        ...lyric,
        time: lyric.time + delay
    }));
}
const adjustedLyrics = adjustLyricsDelay(lyrics, -0.5);

在这个示例中,通过adjustLyricsDelay函数调整歌词的时间戳,处理歌词延迟问题。

2. 支持多种歌词格式

除了LRC格式,还可以支持其他格式的歌词文件,如SRT格式。可以编写不同的解析函数,支持多种格式的歌词文件。以下是解析SRT格式的示例:

function parseSRT(srtContent) {
    const lines = srtContent.split('nn');
    const lyrics = [];
    for (const line of lines) {
        const parts = line.split('n');
        if (parts.length >= 3) {
            const timeMatch = parts[1].match(/(d{2}):(d{2}):(d{2}),(d{3}) --> (d{2}):(d{2}):(d{2}),(d{3})/);
            if (timeMatch) {
                const startTime = parseInt(timeMatch[1], 10) * 3600 + parseInt(timeMatch[2], 10) * 60 + parseInt(timeMatch[3], 10) + parseInt(timeMatch[4], 10) / 1000;
                const text = parts.slice(2).join('n').trim();
                lyrics.push({ time: startTime, text });
            }
        }
    }
    return lyrics;
}

在这个示例中,通过parseSRT函数解析SRT格式的歌词文件,将时间戳和歌词内容分离,并存储在数组中。

总结

通过使用时间戳、解析歌词文件、借助定时器和更新UI,可以实现歌词和歌曲的同步显示。使用时间戳是实现歌词同步的核心,通过解析歌词文件和时间戳,将歌词与歌曲的播放时间关联起来。借助定时器,可以定期检查歌曲的播放时间,并更新歌词显示。最后,通过更新UI,实现歌词的滚动效果,确保歌词与歌曲保持同步。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号