HTML DOM Audio played 属性(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3700+ 小伙伴加入学习 ,欢迎点击围观

在现代 Web 开发中,音频控制功能是许多项目的核心需求,无论是在线音乐平台、视频网站还是交互式游戏,开发者都需要精准控制音频的播放状态。本文将深入探讨 HTML DOM Audio played 属性,这一属性能够帮助开发者获取音频已播放的时间范围,从而实现进度条同步、播放进度记录等功能。通过结合实例代码和实用技巧,我们将会从基础概念逐步深入,帮助读者掌握这一属性的使用场景与技术细节。


一、基础概念:HTML Audio 元素与 DOM 属性

在讲解 played 属性 之前,我们需要先了解 HTML 中音频元素的基本知识。

1.1 HTML Audio 元素

HTML 的 <audio> 标签用于在网页中嵌入音频文件。通过结合 JavaScript 的 DOM(文档对象模型),我们可以动态控制音频的播放、暂停、音量调整等行为。例如:

<audio id="myAudio">
  <source src="example.mp3" type="audio/mpeg">
</audio>

通过 JavaScript,可以获取该元素并操作其属性:

const audio = document.getElementById("myAudio");
audio.play(); // 播放音频

1.2 TimeRanges 对象与播放范围

played 属性 返回一个 TimeRanges 对象,该对象描述了音频中已被播放的时间范围。例如,如果用户在音频播放到第 3 秒时暂停,然后跳转到第 5 秒继续播放,played 将记录两个时间段:0-3秒5秒之后播放的部分

比喻:可以将 TimeRanges 想象为一张地图,标记出音频已“探索”过的区域。


二、核心知识点:深入理解 played 属性

2.1 属性的基本用法

played 属性 是只读属性,直接通过 audioElement.played 获取。例如:

const playedRanges = audio.played;
console.log(playedRanges); // 输出 TimeRanges 对象

2.2 TimeRanges 对象的结构

TimeRanges 对象包含以下关键属性和方法:

  • length:表示时间段的数量。
  • start(index):返回第 index 个时间段的起始时间(秒)。
  • end(index):返回第 index 个时间段的结束时间(秒)。

示例代码

const audio = document.getElementById("myAudio");
const played = audio.played;

if (played.length > 0) {
  const firstSegmentStart = played.start(0);
  const firstSegmentEnd = played.end(0);
  console.log(`已播放的第一个时间段:${firstSegmentStart} 秒到 ${firstSegmentEnd} 秒`);
}

2.3 典型场景:音频进度条同步

在实际开发中,最常见的用途是同步音频播放进度条。例如,当用户拖动进度条时,需要根据已播放的时间范围更新 UI。

实现步骤

  1. 监听音频的 timeupdate 事件,实时获取播放进度。
  2. 通过 played 属性计算已播放的总时长。
  3. 更新进度条的样式或数值。

完整代码示例

<!-- HTML 结构 -->
<audio id="audioPlayer" src="song.mp3"></audio>
<div id="progressBar">
  <div id="playedBar"></div>
</div>

<script>
  const audio = document.getElementById("audioPlayer");
  const progressBar = document.getElementById("progressBar");
  const playedBar = document.getElementById("playedBar");

  // 更新进度条
  const updateProgress = () => {
    const duration = audio.duration;
    const played = audio.played;

    if (played.length > 0) {
      const endTime = played.end(played.length - 1);
      const percentage = (endTime / duration) * 100;
      playedBar.style.width = `${percentage}%`;
    }
  };

  // 监听时间更新事件
  audio.addEventListener("timeupdate", updateProgress);
</script>

三、进阶技巧与注意事项

3.1 处理不连续的播放记录

当用户暂停、跳转或重复播放时,played 可能包含多个时间段。例如:

  • 用户播放到第 5 秒后暂停。
  • 重新播放到第 8 秒后再次暂停。
    此时,played 将记录两个时间段:0-5秒8秒之后播放的部分

计算总已播放时长

若需获取总已播放时长(非连续时间段的总和),可通过循环遍历 TimeRanges

const calculateTotalPlayed = (timeRanges) => {
  let total = 0;
  for (let i = 0; i < timeRanges.length; i++) {
    total += timeRanges.end(i) - timeRanges.start(i);
  }
  return total;
};

const totalPlayedTime = calculateTotalPlayed(audio.played);

3.2 处理跨域音频资源

如果音频文件来自不同域,浏览器的安全策略可能导致 played 属性无法正确返回数据。此时需确保服务器配置了正确的 CORS(跨源资源共享)头。

3.3 性能优化建议

频繁读取 played 属性可能影响性能,建议结合 requestAnimationFramesetTimeout 降低更新频率:

let rafID;

const updateProgress = () => {
  // 更新逻辑
  rafID = requestAnimationFrame(updateProgress);
};

// 在需要停止更新时调用
cancelAnimationFrame(rafID);

四、实际案例:实现带跳转功能的音频控制器

以下是一个综合案例,展示如何结合 played 属性实现以下功能:

  • 显示当前播放进度和总时长。
  • 拖动进度条跳转到指定时间点。
  • 高亮显示已播放的部分。

HTML 结构

<audio id="audioPlayer" src="song.mp3"></audio>
<div class="control-container">
  <button id="playPause">播放</button>
  <div class="progress-bar">
    <div class="progress-played"></div>
    <div class="progress-buffered"></div>
    <div class="progress-handle"></div>
  </div>
  <div class="time-display">
    <span id="currentTime">00:00</span> / <span id="duration">00:00</span>
  </div>
</div>

JavaScript 实现

const audio = document.getElementById("audioPlayer");
const playPauseBtn = document.getElementById("playPause");
const progressBar = document.querySelector(".progress-bar");
const progressPlayed = document.querySelector(".progress-played");
const progressHandle = document.querySelector(".progress-handle");
const currentTimeDisplay = document.getElementById("currentTime");
const durationDisplay = document.getElementById("duration");

// 初始化总时长
audio.addEventListener("loadedmetadata", () => {
  durationDisplay.textContent = formatTime(audio.duration);
});

// 格式化时间(如将 123 秒转为 "02:03")
const formatTime = (seconds) => {
  const minutes = Math.floor(seconds / 60);
  const secs = Math.floor(seconds % 60);
  return `${String(minutes).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
};

// 更新进度条和时间
const updateProgress = () => {
  const duration = audio.duration;
  const played = audio.played;

  if (played.length > 0) {
    const endTime = played.end(played.length - 1);
    const percentage = (endTime / duration) * 100;
    progressPlayed.style.width = `${percentage}%`;
    currentTimeDisplay.textContent = formatTime(endTime);
  }
};

// 播放/暂停切换
playPauseBtn.addEventListener("click", () => {
  if (audio.paused) {
    audio.play();
    playPauseBtn.textContent = "暂停";
  } else {
    audio.pause();
    playPauseBtn.textContent = "播放";
  }
});

// 拖动进度条跳转
progressBar.addEventListener("click", (e) => {
  const rect = progressBar.getBoundingClientRect();
  const clickX = e.clientX - rect.left;
  const percentage = clickX / progressBar.offsetWidth;
  const time = percentage * audio.duration;
  audio.currentTime = time;
});

// 监听事件
audio.addEventListener("timeupdate", updateProgress);

五、常见问题与解决方案

5.1 为什么 played.length 始终为 0?

  • 可能原因:音频未加载完成或未开始播放。
  • 解决方案:在 loadedmetadatacanplay 事件后操作 played 属性。

5.2 如何区分已缓冲与已播放的区域?

  • 使用 audio.buffered 属性获取已缓冲的时间范围,与 played 结合使用:
    const buffered = audio.buffered;
    // 绘制缓冲进度条的逻辑
    

5.3 如何避免因网络延迟导致的播放中断?

  • 结合 playedbuffered 属性,当已播放区域接近缓冲末尾时,可提示用户加载更多数据。

六、结论

通过本文的学习,读者应已掌握 HTML DOM Audio played 属性 的核心功能与使用技巧。这一属性不仅是实现音频进度控制的基础,还能与 bufferedseeked 等属性结合,构建更复杂的交互逻辑。在实际开发中,建议结合代码示例逐步调试,并关注浏览器兼容性与性能优化。掌握 played 属性 的开发者,能够更灵活地应对音频播放相关的 Web 开发需求,为用户提供流畅的交互体验。

延伸思考:尝试将 played 属性与 Web Storage 结合,记录用户的播放进度,实现“断点续播”功能。

最新发布