当前位置:首页 > JavaScript

js实现歌词同步

2026-03-01 04:45:56JavaScript

实现歌词同步的基本思路

歌词同步通常需要将歌词文本与音频时间轴对齐,根据当前播放时间动态高亮显示对应歌词。核心步骤包括解析歌词格式、监听音频时间更新、匹配并渲染当前歌词。

解析歌词格式

常见歌词格式为LRC,每行包含时间标签和歌词文本。例如:

[00:00.00]歌曲名
[00:01.00]第一句歌词
[00:03.50]第二句歌词

解析时需要将时间转换为秒数:

function parseLRC(lrcText) {
  const lines = lrcText.split('\n');
  const result = [];
  const timeRegex = /\[(\d{2}):(\d{2})\.(\d{2})\]/;

  lines.forEach(line => {
    const matches = timeRegex.exec(line);
    if (matches) {
      const min = parseInt(matches[1]);
      const sec = parseInt(matches[2]);
      const ms = parseInt(matches[3]) / 100;
      const time = min * 60 + sec + ms;
      const text = line.replace(timeRegex, '').trim();
      result.push({ time, text });
    }
  });

  return result;
}

监听音频播放进度

通过<audio>元素或Web Audio API获取当前播放时间:

const audio = document.querySelector('audio');
const lyrics = parseLRC(lrcText);

audio.addEventListener('timeupdate', () => {
  const currentTime = audio.currentTime;
  updateLyrics(currentTime);
});

匹配并高亮当前歌词

根据当前时间查找应显示的歌词行:

function updateLyrics(currentTime) {
  let activeIndex = 0;
  for (let i = 0; i < lyrics.length; i++) {
    if (lyrics[i].time <= currentTime) {
      activeIndex = i;
    } else {
      break;
    }
  }

  // 渲染逻辑
  const lyricsContainer = document.getElementById('lyrics');
  lyricsContainer.innerHTML = lyrics.map((line, index) => 
    `<div class="${index === activeIndex ? 'active' : ''}">${line.text}</div>`
  ).join('');
}

滚动定位优化

确保当前歌词始终在可视区域:

const activeLine = document.querySelector('.active');
if (activeLine) {
  activeLine.scrollIntoView({ behavior: 'smooth', block: 'center' });
}

样式增强

通过CSS实现视觉反馈:

#lyrics {
  height: 300px;
  overflow-y: auto;
}
#lyrics div {
  padding: 8px;
  transition: all 0.3s;
}
#lyrics div.active {
  color: #1db954;
  font-weight: bold;
  transform: scale(1.05);
}

处理空白歌词行

过滤无意义的空行:

result = result.filter(item => item.text);

性能优化建议

对于长音频,避免频繁DOM操作:

let lastActiveIndex = -1;

function updateLyrics(currentTime) {
  let activeIndex = -1;
  // ...查找逻辑...

  if (activeIndex !== lastActiveIndex) {
    renderLyrics(activeIndex);
    lastActiveIndex = activeIndex;
  }
}

扩展功能

支持双语歌词显示:

function parseBilingualLRC(lrcText1, lrcText2) {
  const lyrics1 = parseLRC(lrcText1);
  const lyrics2 = parseLRC(lrcText2);
  return lyrics1.map((item, index) => ({
    ...item,
    text2: lyrics2[index]?.text || ''
  }));
}

错误处理

增加格式校验:

if (!timeRegex.test(line)) {
  console.warn(`Invalid LRC format: ${line}`);
  continue;
}

完整示例

HTML结构:

<audio src="song.mp3" controls></audio>
<div id="lyrics-container">
  <div id="lyrics"></div>
</div>

整合后的JavaScript:

document.addEventListener('DOMContentLoaded', () => {
  const audio = document.querySelector('audio');
  const lyricsData = parseLRC(lrcText);
  let lastActiveIndex = -1;

  audio.addEventListener('timeupdate', () => {
    const currentTime = audio.currentTime;
    const activeIndex = findActiveLyric(currentTime);

    if (activeIndex !== lastActiveIndex) {
      renderLyrics(activeIndex);
      lastActiveIndex = activeIndex;
    }
  });

  function findActiveLyric(currentTime) {
    for (let i = lyricsData.length - 1; i >= 0; i--) {
      if (lyricsData[i].time <= currentTime) {
        return i;
      }
    }
    return 0;
  }

  function renderLyrics(activeIndex) {
    const lyricsElement = document.getElementById('lyrics');
    lyricsElement.innerHTML = lyricsData.map((line, index) => `
      <div class="${index === activeIndex ? 'active' : ''}">
        ${line.text}
      </div>
    `).join('');

    const activeLine = document.querySelector('.active');
    if (activeLine) {
      activeLine.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  }
});

js实现歌词同步

标签: 歌词同步js
分享给朋友:

相关文章

css3结合js制作

css3结合js制作

CSS3 结合 JavaScript 制作动态效果 CSS3 和 JavaScript 结合可以实现丰富的动态效果,包括动画、交互和响应式设计。以下是几种常见的实现方式: CSS3 动画与 Java…

js实现图片放大缩小

js实现图片放大缩小

实现图片放大缩小的基础方法 使用CSS的transform: scale()属性可以快速实现图片的放大缩小效果。通过JavaScript动态修改该属性值: const img = document…

js实现二叉树

js实现二叉树

二叉树的基本概念 二叉树是一种树形数据结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的常见操作包括插入、删除、遍历等。 二叉树的节点定义 在JavaScript中,二叉树的节点…

js实现dh

js实现dh

JavaScript 实现 DH(Diffie-Hellman)密钥交换 Diffie-Hellman(DH)密钥交换是一种安全协议,允许双方在不安全的通信信道上建立一个共享密钥。以下是如何在 Jav…

js实现选题

js实现选题

实现选题功能的JavaScript方法 基础实现方案 使用数组存储选项,通过随机索引选取: const options = ['选项A', '选项B', '选项C', '选项D']; const…

js树实现

js树实现

树的基本概念 树是一种非线性的数据结构,由节点和边组成。每个节点包含一个值和指向子节点的引用。树的顶部节点称为根节点,没有子节点的节点称为叶节点。 树的实现方式 在JavaScript中,树可以通…