JS实现播放音乐时歌词同步展示

效果如下:

实现过程:

监听音频播放时间,使用歌词的出现时间与其比较,展示对应时间歌词内容,代码如下

<audio id="audio-player" src="每个眼神都只身荒野.m4a" controls></audio>

<div class="lyrics-container">
    <div id="lyrics"></div>
</div>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var audio = document.getElementById('audio-player');
        var lyricsContainer = document.getElementById('lyrics');

        // 歌词内容与时间
        var lyrics = [
            { time: 3, text: "在每个眼神都只身荒野那瞬间" },
            { time: 10, text: "你和我面对面如此地安慰" },
            { time: 18, text: "如果我能发现" },
            { time: 22, text: "动情的灵魂终将在前夜告别" },
            { time: 26, text: "我也不愿停下仅有时间" },
            { time: 29, text: "让我忘了我是谁" },
            // 歌词时间和文本继续添加
        ];

        // 更新歌词
        function updateLyrics(currentTime) {
            for (var i = 0; i < lyrics.length; i++) {
                if (currentTime >= lyrics[i].time && (!lyrics[i + 1] || currentTime < lyrics[i + 1].time)) {
                    lyricsContainer.innerText = lyrics[i].text;
                    break;
                }
            }
        }

        // 监听频播放时间更新事件
        audio.addEventListener('timeupdate', function() {
            var currentTime = audio.currentTime;
            updateLyrics(currentTime);
        });
    });
</script>

这样将歌词在js里面固定了,可以将歌词抽出成一个Irc文件,将该文件放在服务器上面,使其能用http访问到。

同时在js中获取Irc文件的内容,并沿用上面的实现,整个html文件如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Music歌词同步展示</title>
    <style>
        .lyrics-container {
            text-align: left;
            height: 30px;
        }

        #lyrics {
            margin-top: 5px;
            font-size: 20px;
            line-height: 1.5;
        }
    </style>
</head>
<body>
<audio id="audio-player" src="http://服务器IP/每个眼神都只身荒野.m4a" controls></audio>

<div class="lyrics-container">
    <div id="lyrics" src="http://服务器IP/每个眼神都只身荒野.lrc"></div>
</div>

<script>
    let audio = document.getElementById('audio-player');
    let lyricsContainer = document.getElementById('lyrics');
    let lyricsPath = lyricsContainer.getAttribute('src');
    console.log(lyricsPath);

    // 创建一个空数组来存储歌词数据
    let ircArray = [];
    // 匹配时间和文本的正则表达式模式
    const pattern = /\[(\d+:\d+.\d+)\](.+)/g;

    document.addEventListener('DOMContentLoaded', function() {
        // 更新展示的歌词
        function updateLyrics(currentTime) {
            for (var i = 0; i < ircArray.length; i++) {
                if (currentTime >= ircArray[i].time && (!ircArray[i + 1] || currentTime < ircArray[i + 1].time)) {
                    lyricsContainer.innerText = ircArray[i].text;
                    break;
                }
            }
        }

        // 监听频播放时间更新事件
        audio.addEventListener('timeupdate', function() {
            var currentTime = audio.currentTime;
            updateLyrics(currentTime);
        });
    });

    const xhr = new XMLHttpRequest();
    xhr.open('GET', lyricsPath);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200) {
                console.log(xhr.responseText);
                // 在数据中匹配正则表达式模式并提取时间和文本
                let match;
                while ((match = pattern.exec(xhr.responseText)) !== null) {
                    let time = match[1]; // 获取时间
                    let text = match[2]; // 获取文本

                    // 将时间转换为秒数,格式为 mm:ss.xxxx
                    let [minutes, seconds] = time.split(':');
                    let [secondsPart, milliseconds] = seconds.split('.');
                    let timeInSeconds = parseInt(minutes) * 60 + parseInt(secondsPart) + parseFloat(`0.${milliseconds}`);

                    // 创建包含 time 和 text 属性的对象
                    let ircObject = {
                        time: timeInSeconds,
                        text: text
                    };

                    // 将对象添加到数组中
                    ircArray.push(ircObject);
                }
                console.log(ircArray); // 在请求成功且数据处理完毕后打印数组内容
            } else {
                // 处理错误
                console.error('请求出错:', xhr.status);
            }
        }
    };
    xhr.send();

</script>

</body>
</html>

 


 

拓展:展示前3行、当前行和后4行歌词

效果如下

 

    audio.addEventListener('timeupdate', function() {
        var currentTime = audio.currentTime;
        var currentLineIndex = 0;

        // 清空歌词容器
        lyricsContainer.innerHTML = '';

        // 遍历歌词数据,查找当前播放时间对应的歌词
        for (var i = 0; i < ircArray.length; i++) {
            if (ircArray[i].time <= currentTime) {
                currentLineIndex = i;
            }
        }

        // 显示当前行及前3行、后4行的歌词
        var startIndex = Math.max(0, currentLineIndex - 3);
        var endIndex = Math.min(ircArray.length - 1, currentLineIndex + 4);

        for (var j = startIndex; j <= endIndex; j++) {
            var line = ircArray[j];
            var lineElement = document.createElement('p');

            if (j === currentLineIndex) {
                lineElement.classList.add('currentLine');
            }

            lineElement.innerText = line.text;
            lyricsContainer.appendChild(lineElement);
        }

        // 滚动歌词容器
        var currentLineElement = lyricsContainer.querySelector('.currentLine');
        if (currentLineElement) {
            lyricsContainer.scrollTop = currentLineElement.offsetTop - lyricsContainer.offsetHeight / 2;
        }
    });
View Code

 

posted @ 2023-08-15 22:50  请叫我小马驹  阅读(387)  评论(0编辑  收藏  举报