当前位置:首页 > 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:

js实现歌词同步

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实现复制到剪贴板

js实现复制到剪贴板

使用document.execCommand方法(传统方式,已废弃但部分浏览器仍支持) 该方法适用于旧版浏览器,但已被标记为废弃。执行前需确保文本已被选中: function copyToClipb…

js实现拷贝

js实现拷贝

实现文本拷贝 使用 document.execCommand 方法(已废弃但兼容性较好): function copyText(text) { const textarea = document…

js实现报表

js实现报表

使用JavaScript实现报表 在JavaScript中实现报表功能可以通过多种方式完成,常见的方法包括使用原生JavaScript、第三方库(如Chart.js、D3.js)或结合后端数据渲染。以…

js实现游标

js实现游标

使用JavaScript实现游标 在JavaScript中,可以通过操作DOM元素的cursor样式属性来实现自定义游标效果。以下是几种常见的实现方法: 修改默认鼠标指针样式 通过CSS的curso…

js实现求导

js实现求导

实现数值求导的方法 在JavaScript中实现求导通常采用数值方法,因为JavaScript不是符号计算语言。以下是常见的数值微分方法: 中心差分法 中心差分法提供较高精度的导数近似: func…

利用js实现

利用js实现

使用 JavaScript 实现 在 JavaScript 中,可以通过多种方式实现功能,具体取决于需求。以下是几种常见的方法: 方法一:使用原生 JavaScript // 示例代码…