HTML5 Video 标签全攻略:属性、事件与 API

💡 前言

你是否在开发视频功能时遇到过这些问题:

  • "为什么视频在手机上不能自动播放?"
  • "如何知道用户点击了暂停,还是视频自然播放结束?"
  • "我想做一个自定义的进度条,该怎么获取当前播放时间?"

<video> 标签不仅仅是一个播放器,它是一个拥有丰富 属性(Properties)事件(Events)API(Methods) 的强大 DOM 元素。

今天,我们就来拆解这个"多媒体瑞士军刀",让你能够完全掌控视频的行为。

1. 基础配置:常用属性详解 ⚙️

属性决定了视频的初始状态基本行为。我们可以把它们分为"展示类"和"控制类"。

📋 核心属性表

属性名 类型 说明 示例/备注
src String 视频资源的 URL <video src="movie.mp4">
controls Boolean 是否显示浏览器默认控制条 <video controls>
autoplay Boolean 页面加载后是否自动播放 注意:现代浏览器通常要求静音才能自动播放
muted Boolean 是否默认静音 <video muted> (配合 autoplay 使用)
loop Boolean 播放结束后是否循环 <video loop>
poster String 视频加载前显示的封面图 <video poster="cover.jpg">
preload Enum 预加载策略 none (不预加载), metadata (仅元数据), auto (预加载全部)
width/height Number 播放器的显示尺寸 建议通过 CSS 控制,保持宽高比

⚠️ 关于自动播放(Autoplay)的陷阱

为了防止打扰用户,Chrome、Safari 等现代浏览器制定了严格的自动播放策略:

  1. 必须静音 :如果设置 autoplay,通常必须同时设置 muted,否则浏览器会阻止播放。
  2. 用户交互:如果用户之前与域名有过交互(点击、触摸等),后续可能允许有声自动播放。
  3. 最佳实践:始终提供明显的"播放"按钮,不要依赖自动播放。

2. 状态感知:关键事件监听 👂

事件是视频与用户、浏览器之间沟通的桥梁。通过监听事件,你可以知道视频"正在发生什么"。

🔄 生命周期关键事件

我们可以将事件分为几个阶段:

A. 加载阶段
  • loadstart: 浏览器开始寻找媒体数据。
  • loadedmetadata : 元数据(时长、尺寸)已加载。这是获取视频总时长 duration 的最佳时机。
  • canplay: 浏览器估计可以开始播放,但可能需要缓冲。
  • canplaythrough: 浏览器估计可以在不停顿的情况下播放完整个视频。
B. 播放控制阶段
  • play : 调用 play() 方法或用户点击播放时触发。注意:此时视频不一定已经开始渲染帧。
  • playing: 视频真正开始播放(第一帧渲染后)时触发。
  • pause : 调用 pause() 方法或用户点击暂停时触发。
  • ended : 视频播放完毕时触发。常用于实现"播放结束后推荐下一个视频"。
C. 进度与状态阶段
  • timeupdate : 当前播放位置 currentTime 改变时触发。频率很高(约 250ms 一次),用于更新自定义进度条。
  • seeking: 用户开始拖动进度条时触发。
  • seeked: 用户拖动进度条结束时触发。
  • waiting: 视频因缓冲不足而暂停时触发(显示加载圈)。
  • error: 加载或播放发生错误时触发。

💡 实例演练:监听播放状态

javascript 复制代码
const video = document.getElementById("myVideo");

// 监听真正的播放开始
video.addEventListener("playing", () => {
  console.log("视频正在播放中...");
  // 这里可以隐藏封面图,显示播放界面
});

// 监听播放结束
video.addEventListener("ended", () => {
  console.log("视频播放完毕");
  // 这里可以重置进度条,或加载下一个视频
});

// 监听错误
video.addEventListener("error", (e) => {
  console.error("视频加载失败", e);
  // 这里可以显示错误提示给用户
});

3. 程序化控制:核心 API 方法 🕹️

除了属性和事件,JavaScript 提供了强大的 API 来主动控制视频的行为。

🛠️ 常用方法与属性读写

成员 类型 说明 用法示例
play() Method 开始播放 video.play().catch(...)
pause() Method 暂停播放 video.pause()
currentTime Property 获取/设置当前播放时间(秒) video.currentTime = 10; // 跳转到第10秒
duration Property 获取视频总时长(秒) console.log(video.duration);
volume Property 获取/设置音量 (0.0 - 1.0) video.volume = 0.5;
playbackRate Property 获取/设置播放速度 video.playbackRate = 2.0; // 倍速播放
paused Property 判断是否处于暂停状态 if (video.paused) { ... }
requestFullscreen() Method 全屏播放 video.requestFullscreen();

⚠️ 注意 play() 返回 Promise

在现代浏览器中,video.play() 返回一个 Promise。如果自动播放被浏览器策略阻止,Promise 会被 reject。

javascript 复制代码
var playPromise = video.play();

if (playPromise !== undefined) {
  playPromise
    .then((_) => {
      // 自动播放成功
    })
    .catch((error) => {
      // 自动播放被阻止,显示播放按钮让用户手动点击
      showPlayButton();
    });
}

4. 实战场景:构建一个简单的自定义控制器 🛠️

光说不练假把式。让我们结合属性、事件和 API,实现一个最简单的"播放/暂停"切换功能。

HTML 结构

html 复制代码
<div class="video-container">
  <video id="myVideo" src="sample.mp4" poster="cover.jpg"></video>
  <button id="playBtn">播放</button>
  <div id="progressBar">
    <div id="progressFill"></div>
  </div>
</div>

JavaScript 逻辑

javascript 复制代码
const video = document.getElementById("myVideo");
const playBtn = document.getElementById("playBtn");
const progressFill = document.getElementById("progressFill");

// 1. 切换播放/暂停
playBtn.addEventListener("click", () => {
  if (video.paused) {
    video
      .play()
      .then(() => {
        playBtn.textContent = "暂停";
      })
      .catch((err) => console.error("播放失败:", err));
  } else {
    video.pause();
    playBtn.textContent = "播放";
  }
});

// 2. 同步进度条
video.addEventListener("timeupdate", () => {
  if (video.duration) {
    const percent = (video.currentTime / video.duration) * 100;
    progressFill.style.width = `${percent}%`;
  }
});

// 3. 播放结束后重置按钮
video.addEventListener("ended", () => {
  playBtn.textContent = "重播";
  progressFill.style.width = "0%";
});

5. 常见误区与最佳实践 ❌ vs ✅

  1. 误区 :"autoplay 加了就一定能自动播放。"

    • 真相 :受浏览器策略限制,务必处理 play() 的 Promise rejection,并提供 fallback UI(如播放按钮)。
  2. 误区 :"timeupdate 事件非常精确。"

    • 真相timeupdate 的触发频率由浏览器决定,并不保证每帧触发。如果需要高精度的帧同步,建议使用 requestAnimationFrame 轮询 currentTime
  3. 最佳实践移动端优化

    • 在移动端,视频全屏播放行为可能不同(iOS 默认 inline 播放需加 playsinline 属性)。
    • <video playsinline webkit-playsinline ...> 确保视频在页面内播放,而不是强制全屏。
  4. 最佳实践资源加载策略

    • 对于非首屏视频,设置 preload="none"preload="metadata",避免浪费用户流量和带宽。
    • 提供多种格式(.mp4, .webm)以兼容不同浏览器。

6. 总结记忆口诀 🧠

Video 标签功能强,属性事件 API 忙。

自动播放需静音,Promise 捕获防报错。

LoadedMetadata 取时长,TimeUpdate 刷进度。

Play Pause 控启停,Ended 之后做跳转。

移动端加 PlaysInline,预加载策略省流量。

自定义控件灵活配,用户体验最至上。


希望这篇文档能帮你彻底理清 HTML5 Video 标签的使用!如果觉得有用,欢迎点赞收藏~ 🌟