当前位置:首页 > 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实现轮播

实现轮播图的基本思路 轮播图的核心逻辑是通过定时切换展示的图片或内容,通常结合左右滑动按钮和指示器(小圆点)增强交互性。以下是基于原生JavaScript的实现方法。 HTML结构 构建轮播图的HT…

js分组实现

js分组实现

分组实现方法 在JavaScript中,可以通过多种方式实现数组或对象的分组操作。以下是几种常见的方法: 使用Array.prototype.reduce() 通过reduce方法可以轻松实现数组分…

js jquery

js jquery

jQuery 简介 jQuery 是一个快速、简洁的 JavaScript 库,简化了 HTML 文档遍历、事件处理、动画设计和 Ajax 交互。它兼容多种浏览器,提供易于使用的 API,使开发者能够…

js实现授权

js实现授权

授权流程设计 授权流程通常涉及前端与后端的交互,常见方案包括OAuth2.0、JWT等。以JWT为例的典型流程: 用户提交凭证(如用户名密码)到认证服务 服务端验证通过后生成包含用户信息的JWT令牌…

js实现密码

js实现密码

密码强度验证 使用正则表达式验证密码强度是一种常见方法。以下代码检查密码是否包含大小写字母、数字和特殊字符,且长度至少为8位: function checkPasswordStrength(pass…

js实现吸色

js实现吸色

使用Canvas实现吸色功能 通过Canvas的getImageData方法获取像素颜色数据。创建一个Canvas元素,将目标图像绘制到Canvas上,通过鼠标事件获取坐标对应的颜色值。 c…