当前位置:首页 > 前端开发 > 正文

lrc歌词如何引入html中

可通过` 标签嵌入音乐,配合JavaScript解析LRC歌词的时间戳与文本,动态高亮当前行,实现同步显示,需将LRC转为数组,通过定时器或timeupdate`事件匹配播放

LRC文件格式解析

LRC(Lyrics)是一种基于纯文本的歌词文件格式,其核心规则是通过[mm:ss.xx]的时间戳标记与对应歌词行的映射关系,典型结构如下:

[00:00.00]歌曲名 歌手
[00:01.50]第一句歌词
[00:04.20]第二句歌词
...

关键特征
每行仅包含一个有效时间戳+歌词的组合
时间精度支持到百分之一秒(.xx
空行会被忽略
特殊符号(如换行符n)需转义处理

要素 说明 示例
时间戳格式 [mm:ss.xx] [03:15.75]
标识符 可选的前缀(如ID3标签) [ar:张三][ti:歌名]
注释行 以开头 # 这是注释

三种主流实现方案对比

方案1:纯静态文本展示(适合简单需求)

适用场景:无需与音频同步,仅需展示固定歌词文本。
实现步骤
1️⃣ 手动去除时间戳:将LRC文件中的时间戳全部删除,保留纯文本
2️⃣ 使用<pre>标签保持格式:

<pre>
这里是去除了时间戳的纯净歌词文本
可以保留原有的换行和空格
</pre>

优点:零依赖,加载速度快;
缺点:无法实现逐句高亮/滚动效果。

方案2:JavaScript动态解析(推荐方案)

核心思路:通过JS读取LRC文件→解析时间轴→根据当前播放时间匹配对应歌词→动态更新DOM元素。

lrc歌词如何引入html中  第1张

完整实现流程

  1. 准备LRC文件:确保文件编码为UTF-8,建议命名为song.lrc
  2. 创建HTML结构
    <div id="lyrics-container">
    <ul id="lyrics-list"></ul>
    </div>
    <audio id="audio-player" src="music.mp3" controls></audio>
  3. 编写解析函数(关键代码):
    function parseLRC(lrcText) {
    const lines = lrcText.split('n'); // 按行分割
    const lyrics = [];

lines.forEach(line => {
const timeMatch = line.match(/[(d{2}):(d{2}).(d{2})](.)/);
if (timeMatch) {
const minutes = parseInt(timeMatch[1]);
const seconds = parseInt(timeMatch[2]);
const hundredths = parseInt(timeMatch[3]);
const totalSeconds = minutes
60 + seconds + hundredths / 100;
lyrics.push({
time: totalSeconds,
text: timeMatch[4].trim()
});
}
});
return lyrics;
}

绑定音频事件:
```javascript
const audio = document.getElementById('audio-player');
const lyricsList = document.getElementById('lyrics-list');
let currentIndex = -1;
// 初始化歌词列表
fetch('song.lrc')
  .then(response => response.text())
  .then(lrcText => {
    const lyrics = parseLRC(lrcText);
    lyrics.forEach((item, index) => {
      const li = document.createElement('li');
      li.textContent = item.text;
      li.dataset.time = item.time;
      lyricsList.appendChild(li);
    });
  });
// 实时更新当前歌词
audio.addEventListener('timeupdate', () => {
  const currentTime = audio.currentTime;
  const activeItem = Array.from(lyricsList.children)
    .find(li => parseFloat(li.dataset.time) <= currentTime);
  if (activeItem && activeItem !== lyricsList.children[currentIndex]) {
    currentIndex = Array.from(lyricsList.children).indexOf(activeItem);
    // 移除所有高亮
    document.querySelectorAll('#lyrics-list li').forEach(li => {
      li.classList.remove('active');
    });
    // 添加新高亮
    activeItem.classList.add('active');
    // 滚动到可视区域
    activeItem.scrollIntoView({ behavior: 'smooth', block: 'center' });
  }
});
  1. 配套CSS样式
    #lyrics-container {
    height: 300px;
    overflow-y: auto;
    border: 1px solid #ccc;
    padding: 10px;
    }

lyrics-list li {

padding: 8px;
transition: all 0.3s ease;
}

lyrics-list li.active {

background-color: #ffeb3b;
font-weight: bold;
transform: scale(1.05);
}


优势:
️ 精准的时间同步
️ 支持自动滚动和高亮效果
️ 可扩展性强(如添加点击跳转功能)
# 方案3:借助现成库快速实现(适合快速开发)
推荐使用轻量级库:lrc-parser(npm包)或CDN版本。
```html
<!-引入CDN -->
<script src="https://cdn.jsdelivr.net/npm/lrc-parser@latest/dist/lrc-parser.min.js"></script>
<script>
// 使用示例
LrcParser.load('song.lrc').then(lyrics => {
  console.log(lyrics); // 获取解析后的数组对象
});
</script>

关键注意事项

跨域问题:若LRC文件与网页不同源,需配置CORS头或改用本地存储
编码问题:务必使用UTF-8无BOM编码保存LRC文件,避免中文乱码
性能优化:对于长歌词建议虚拟滚动而非渲染全部DOM节点
兼容性处理:旧版浏览器可能需要polyfill Promise API
异常捕获:添加try-catch处理文件读取错误和解析异常


增强功能扩展建议

双语对照:创建双列布局,左右分别显示原文和译文
卡拉OK效果:通过Canvas绘制波形图配合歌词跳动动画
离线缓存:使用localStorage预存常用歌词数据
自适应排版:根据屏幕宽度自动调整字体大小和行间距
搜索定位:输入关键词快速跳转到对应歌词段落


相关问答FAQs

Q1: LRC文件中出现多个相同时间戳怎么办?

A: 根据规范,同一时间戳只能对应一行歌词,如果出现重复,后出现的歌词会覆盖前者,建议采用以下任一方案解决:
① 微调时间戳(如改为[01:23.45][01:23.46]
② 合并为多行文本(使用n换行符,需注意转义)
③ 使用扩展字段区分不同轨道(如[v1:01:23.45]表示第一声道)

Q2: 如何让歌词字体随音频音量变化?

A: 可通过Web Audio API获取实时音量数据,结合CSS变量动态调整字体大小/透明度,示例代码片段:

const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const analyser = audioContext.createAnalyser();
const source = audioContext.createMediaElementSource(document.getElementById('audio-player'));
source.connect(analyser);
analyser.connect(audioContext.destination);
function updateFontSize() {
  const dataArray = new Uint8Array(analyser.frequencyBinCount);
  analyser.getByteFrequencyData(dataArray);
  const avgVolume = dataArray.reduce((a, b) => a + b) / dataArray.length;
  document.documentElement.style.setProperty('--font-scale', avgVolume / 255  0.5 + 0.8); // 缩放范围0.8~1.3
}
setInterval(updateFontSize, 100);

配合CSS:

body {
  font-size: calc(16px  var(--font-scale, 
0