You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何渲染数组内的歌曲列表并自动获取对应音频时长

问题描述

需要将数组中存储的所有歌曲展示为列表形式,同时获取每个列表项对应的音频时长,咨询该功能是否支持自动实现,还是必须手动将duration字段添加到数组中。当前已编写的初始代码如下:

let tracks = [
  {
    name: "Song 1",
    artist: "Monica",
    path: "..song1.mp3",
  },
  {
    name: "Song 2",
    artist: "Carol",
    path: "..song2.mp3"
  },
  {
    name: "Song 3",
    artist: "Sam",
    path: "..song3.mp3"
  }
];

let list = "<ul>";
for (let i = 0; i < tracks.length; i++) {
    list += '<li>';
    list += '<div class="name">' + tracks[i].name + '</div>';
    list += '<div class="artist">' + tracks[i].artist + '</div>';
    list += '<div class="duration">XX:XX</div>';
    list += '<a href="' + tracks[i].path + '">Download</a>';
    list += '</li>';
}
// 此处存在语法错误:同一作用域重复用let声明list变量
let list = "</ul>";

playlist.innerHTML = list;
解答
  • 不需要手动提前给数组硬编码duration字段,可通过浏览器原生HTMLAudioElement API自动读取音频元数据获取时长。
  • 音频元数据加载是异步过程,无法通过同步拼接字符串的方式直接在初始渲染时拿到时长,可先渲染带占位符的列表,等元数据加载完成后再更新对应DOM节点的时长内容。
  • 原代码存在语法问题:拼接闭合</ul>标签时直接对已有list变量做追加赋值即可,不需要重复声明变量。

修正后可运行实现代码

const tracks = [
  {
    name: "Song 1",
    artist: "Monica",
    path: "../song1.mp3",
  },
  {
    name: "Song 2",
    artist: "Carol",
    path: "../song2.mp3"
  },
  {
    name: "Song 3",
    artist: "Sam",
    path: "../song3.mp3"
  }
];

// 时长格式化工具:秒转MM:SS格式,不足两位自动补零
const formatDuration = (seconds) => {
  const min = Math.floor(seconds / 60);
  const sec = Math.floor(seconds % 60);
  return `${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
};

// 先渲染基础列表结构
let listStr = "<ul>";
tracks.forEach((track, index) => {
  listStr += `<li data-index="${index}">`;
  listStr += `<div class="name">${track.name}</div>`;
  listStr += `<div class="artist">${track.artist}</div>`;
  // 给时长节点加专属标识,方便后续异步更新内容
  listStr += `<div class="duration" data-duration-role="${index}">加载中...</div>`;
  listStr += `<a href="${track.path}" download>Download</a>`;
  listStr += `</li>`;

  // 异步加载音频元数据获取时长
  const audio = new Audio(track.path);
  // 配置为仅加载元数据,不拉取完整音频,节省流量
  audio.preload = 'metadata';
  audio.addEventListener('loadedmetadata', () => {
    const durationEl = document.querySelector(`[data-duration-role="${index}"]`);
    if (durationEl) {
      durationEl.textContent = formatDuration(audio.duration);
    }
    // 加载完成后释放音频实例占用的资源
    audio.remove();
  });
  // 处理音频加载失败场景
  audio.addEventListener('error', () => {
    const durationEl = document.querySelector(`[data-duration-role="${index}"]`);
    if (durationEl) {
      durationEl.textContent = "--:--";
    }
  });
});
listStr += "</ul>";
playlist.innerHTML = listStr;

注意:如果音频资源和页面不同源,需要目标资源配置CORS允许跨域访问,否则无法读取元数据获取时长,本地同目录下的音频文件无此限制。

内容的提问来源于stack exchange,提问作者Avigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:54:24