Skip to content

音视频 ​

定义 ​

HTML5 通过原生 <video>、<audio> 及子元素 <source>、<track> 在页面嵌入多媒体,无需插件。浏览器提供内置控件(controls)与 JavaScript 媒体 API,可编程控制播放、音量、进度与字幕轨道。

核心概念 ​

概念说明
容器 vs 编解码MP4/WebM 是容器;H.264、VP9、AAC 是编码;需多格式 <source> 兼容
媒体元素HTMLMediaElement 共通接口;HTMLVideoElement 额外有 videoWidth 等
默认静音自动播放多数浏览器仅允许 muted + autoplay;有声 autoplay 常被拦截
文本轨道<track kind="subtitles"> 提供 WebVTT 字幕/说明
CORSCanvas 截取视频帧需服务器返回正确 CORS 头

<video> 属性速查 ​

属性说明常用值
src视频 URL(单源时).mp4, .webm
controls显示原生控件布尔属性
autoplay就绪后自动播放常配合 muted
loop循环
muted静音autoplay 场景常用
poster加载前占位图 URL预览帧
preload预加载策略none | metadata | auto
playsinlineiOS 内联播放非全屏移动端必需
width / height显示尺寸防 CLS
crossoriginCORS 模式anonymous
disablepictureinpicture禁用画中画
disableremoteplayback禁用远程播放(如 AirPlay)

<audio> 属性速查 ​

属性说明
与 video 共用src, controls, autoplay, loop, muted, preload, crossorigin
无poster, playsinline, width, height

<source> 属性 ​

属性说明
src媒体 URL
typeMIME,如 video/mp4; codecs="avc1.42E01E, mp4a.40.2",帮浏览器跳过不支持的源
media媒体查询,按条件选源(较少用)

<track> 属性 ​

属性说明
srcWebVTT (.vtt) 文件 URL
kindsubtitles | captions | descriptions | chapters | metadata
srclang语言,如 zh-CN
label用户可见轨道名
default默认选中该轨道

常见媒体事件 ​

事件触发时机典型用途
loadstart开始加载显示 loading
loadedmetadata时长、尺寸就绪初始化进度条最大值
loadeddata首帧可用
canplay可开始播放(可能缓冲)
canplaythrough预计可播放到结束隐藏缓冲提示
play播放开始/恢复切换 UI 为暂停图标
pause暂停
timeupdate播放位置变化更新进度条(节流)
ended播放结束下一首 / 重播提示
volumechange音量或 muted 变化同步音量 UI
waiting缓冲不足暂停显示 spinner
error加载/解码失败错误提示;查 media.error

JavaScript 控制 API(HTMLMediaElement) ​

属性 / 方法类型说明
play()Promise播放;可能被 autoplay 策略 reject
pause()void暂停
pausedboolean是否暂停
currentTimenumber(秒)读写播放位置
durationnumber总时长;未就绪时为 NaN
volume0–1音量
mutedboolean静音
playbackRatenumber倍速,如 1.5
endedboolean是否已结束
readyState0–4数据就绪程度
networkState0–3网络状态
seekableTimeRanges可 seek 范围
textTracksTextTrackList字幕轨道集合
captureStream()MediaStream录制/ WebRTC(进阶)

示例 ​

多格式 video + 字幕 ​

html
<video controls width="640" height="360" poster="/posters/intro.jpg" preload="metadata">
  <!-- type 帮助浏览器跳过不支持的编码 -->
  <source src="/video/intro.webm" type="video/webm">
  <source src="/video/intro.mp4" type="video/mp4">
  <track kind="subtitles" src="/subs/intro.zh.vtt" srclang="zh-CN" label="简体中文" default>
  <track kind="subtitles" src="/subs/intro.en.vtt" srclang="en" label="English">
  <!-- 回退:不支持 video 的浏览器 -->
  <p>您的浏览器不支持 HTML5 视频,可<a href="/video/intro.mp4">下载 MP4</a>。</p>
</video>

自定义控件(核心 API) ​

html
<audio id="player" src="/audio/demo.mp3" preload="metadata"></audio>
<button id="btn-play" type="button">播放</button>
<input id="seek" type="range" min="0" max="100" value="0">
<span id="time">0:00 / 0:00</span>

<script>
  const audio = document.getElementById("player");
  const btnPlay = document.getElementById("btn-play");
  const seek = document.getElementById("seek");
  const timeEl = document.getElementById("time");

  /** 秒数格式化为 m:ss */
  function formatTime(sec) {
    if (!Number.isFinite(sec)) return "0:00";
    const m = Math.floor(sec / 60);
    const s = Math.floor(sec % 60).toString().padStart(2, "0");
    return `${m}:${s}`;
  }

  /** 更新进度条与时间文本 */
  function syncUI() {
    const pct = audio.duration ? (audio.currentTime / audio.duration) * 100 : 0;
    seek.value = String(pct);
    timeEl.textContent = `${formatTime(audio.currentTime)} / ${formatTime(audio.duration)}`;
  }

  btnPlay.addEventListener("click", async () => {
    try {
      if (audio.paused) {
        await audio.play(); // 用户手势触发,避免 autoplay 限制
        btnPlay.textContent = "暂停";
      } else {
        audio.pause();
        btnPlay.textContent = "播放";
      }
    } catch (err) {
      console.error("播放失败:", err);
    }
  });

  audio.addEventListener("loadedmetadata", syncUI);
  audio.addEventListener("timeupdate", syncUI);

  seek.addEventListener("input", () => {
    if (audio.duration) {
      audio.currentTime = (Number(seek.value) / 100) * audio.duration;
    }
  });
</script>

监听事件与错误 ​

javascript
const video = document.querySelector("video");

video.addEventListener("waiting", () => {
  // 缓冲中:显示 loading
});

video.addEventListener("error", () => {
  const code = video.error?.code; // 1=ABORTED, 2=NETWORK, 3=DECODE, 4=SRC_NOT_SUPPORTED
  console.error("媒体错误码:", code);
});

常见陷阱 ​

问题建议
仅有 MP4 在旧 Firefox 失败提供 WebM 或确认目标浏览器
有声 autoplay 被拦首次播放需用户手势,或 muted autoplay
iOS 全屏而非内联加 playsinline(及必要时 webkit-playsinline 旧版)
timeupdate 过频卡 UI用 requestAnimationFrame 节流或仅更新关键节点
未设 poster / 尺寸加载前空白或 CLS;设 poster 与 width/height
play() 不 awaitPromise reject 未捕获会在控制台报错
字幕不显示检查 .vtt MIME(text/vtt)、路径、CORS

延伸阅读(MDN) ​