HTML5 视频音频标签完全指南

小飞兽 HTML/CSS 81 次阅读 2026-05-06

一、Introduction(引言)

在 HTML5 出现之前,在网页中嵌入音频和视频几乎是一场噩梦。开发者不得不依赖 Flash(需要安装插件、安全漏洞频出、性能糟糕),或者使用各种第三方播放器(如 Windows Media Player、QuickTime)的 embed/object 标签,不仅语法复杂,而且跨浏览器兼容性极差,不同浏览器支持不同的音频视频格式,用户经常看到"您需要安装 Flash 播放器"的提示。

HTML5 的出现彻底改变了这一局面。<video><audio> 是 HTML5 规范中最具革命性的两个标签,它们将音视频播放带入了"原生支持"时代——无需任何插件,直接在浏览器中播放,移动端和桌面端行为一致,JavaScript API 完善,功能强大。

本文将深入讲解这两个标签的完整用法,包括基础语法、多格式兼容、CSS 样式定制、JavaScript 控制,以及在生产环境中经常会遇到的兼容性问题与解决方案。

二、基础语法

2.1 <video> 标签

<video> 标签用于在页面中嵌入视频内容。其核心属性如下:

    • src:视频文件的 URL 地址
    • width / height:视频播放器的宽高(单位为像素,不带单位)
    • controls:显示浏览器自带的控制条(播放/暂停按钮、进度条、音量等),如果省略则视频不会显示控制条,需要通过 JavaScript 自定义控制
    • autoplay:页面加载后自动播放(现代浏览器大多要求配合 muted 才能自动播放)
    • muted:静音播放
    • loop:循环播放
    • poster:视频加载前/未播放时显示的封面图片 URL
    • preload:预加载策略,可选值 auto(页面加载时完整下载视频)、metadata(仅加载元数据)、none(不预加载)

    2.2 <audio> 标签

    <audio> 标签用于嵌入音频内容,用法与 <video> 类似,但没有画面相关的属性:

    • src:音频文件的 URL 地址
    • controls:显示控制条
    • autoplay:自动播放(同样常需配合 muted
    • muted:静音
    • loop:循环
    • preload:预加载策略

    2.3 多格式兼容:<source> 标签

    这是最关键、最容易出错的地方。不同浏览器对音视频格式的支持情况各不相同:

    • 视频:MP4 (H.264+AAC) 是兼容性最好的格式,几乎所有浏览器都支持;WebM (VP8/VP9+Opus/Vorbis) 在现代浏览器中支持良好;OGV (Ogg Theora) 已过时,基本不再使用。
    • 音频:MP3 所有浏览器都支持;WAV (PCM) 所有浏览器支持;OGG (Ogg Vorbis) Firefox/Chrome 支持,Safari 不支持;AAC IE9+ 和所有现代浏览器支持;FLAC 所有现代浏览器支持。

    因此,最佳实践是使用 <source> 标签提供多种格式,浏览器会按顺序尝试,直到找到自己能播放的格式:

    <video width="640" height="360" controls>
        <source src="video.mp4" type="video/mp4">
        <source src="video.webm" type="video/webm">
        您的浏览器不支持 HTML5 视频播放。
    </video>
    

    <audio controls>
    <source src="music.mp3" type="audio/mpeg">
    <source src="music.ogg" type="audio/ogg">
    您的浏览器不支持 HTML5 音频播放。
    </audio>


    注意 type 属性必须准确填写,它帮助浏览器快速判断自己是否能播放该格式,避免下载了不支持的格式浪费流量。

    2.4 <track> 标签(字幕与章节)

    <track> 标签用于为视频添加字幕、标题、章节描述等文本轨道,必须放在 <video> 内部、<source> 之后:

    <video src="movie.mp4" controls>
        <track kind="subtitles" srclang="zh-CN" label="中文" src="subtitle_zh.vtt" default>
        <track kind="subtitles" srclang="en" label="English" src="subtitle_en.vtt">
        <track kind="captions" srclang="zh-CN" label="音频描述" src="captions_zh.vtt">
    </video>

    kind 属性可取值:subtitles(字幕)、captions(聋哑人字幕,包含音效描述)、descriptions(音频描述)、chapters(章节标题)、metadata(供 JavaScript 读取的元数据)。

    三、代码示例

    3.1 最基础的 video 播放器

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>HTML5 视频播放示例</title>
        <style>
            body { font-family: 'Microsoft YaHei', sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
            .video-container { background: #000; border-radius: 8px; overflow: hidden; margin: 20px 0; }
            video { width: 100%; height: auto; display: block; }
            .controls-demo { margin: 30px 0; }
            button { padding: 10px 20px; font-size: 16px; cursor: pointer; margin: 5px; border-radius: 5px; border: none; background: #007bff; color: white; }
            button:hover { background: #0056b3; }
            .custom-controls { display: flex; align-items: center; gap: 10px; background: #333; padding: 10px 15px; border-radius: 6px; }
            .progress-bar { flex: 1; height: 6px; background: #555; border-radius: 3px; cursor: pointer; position: relative; }
            .progress-filled { height: 100%; background: #ff4757; border-radius: 3px; width: 0%; transition: width 0.1s; }
            .time-display { color: #fff; font-size: 13px; font-family: monospace; min-width: 90px; text-align: center; }
        </style>
    </head>
    <body>
        <h1>HTML5 Video 标签完全指南</h1>
    

    <!-- 示例1:带封面图的自动播放(静音) -->
    <div class="video-container">
    <video id="video1" width="800" height="450"
    poster="https://picsum.photos/800/450"
    controls autoplay muted loop>
    <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
    您的浏览器不支持 HTML5 视频。
    </video>
    </div>

    <!-- 示例2:JavaScript 自定义控制条 -->
    <div class="controls-demo">
    <div class="video-container">
    <video id="video2" width="800" src="https://www.w3schools.com/html/mov_bbb.mp4"></video>
    </div>
    <div class="custom-controls">
    <button id="playBtn">▶ 播放</button>
    <span class="time-display" id="timeDisplay">00:00 / 00:00</span>
    <div class="progress-bar" id="progressBar">
    <div class="progress-filled" id="progressFilled"></div>
    </div>
    <button id="muteBtn">🔊 静音</button>
    <input type="range" id="volumeSlider" min="0" max="1" step="0.1" value="1" style="width:80px">
    </div>
    </div>

    <!-- 示例3:带字幕的视频 -->
    <div class="video-container">
    <video id="video3" width="800" controls>
    <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
    <track kind="subtitles" srclang="zh" label="中文字幕"
    src="data:text/vtt,WEBVTT\n\n00:00:00.000 --> 00:00:05.000\n这是第一条字幕示例\n\n00:00:05.000 --> 00:00:10.000\nHTML5 视频播放测试" default>
    </video>
    </div>

    <script>
    const video = document.getElementById('video2');
    const playBtn = document.getElementById('playBtn');
    const muteBtn = document.getElementById('muteBtn');
    const volumeSlider = document.getElementById('volumeSlider');
    const progressBar = document.getElementById('progressBar');
    const progressFilled = document.getElementById('progressFilled');
    const timeDisplay = document.getElementById('timeDisplay');

    // 播放/暂停
    playBtn.addEventListener('click', () => {
    if (video.paused) {
    video.play();
    playBtn.textContent = '⏸ 暂停';
    } else {
    video.pause();
    playBtn.textContent = '▶ 播放';
    }
    });

    // 静音切换
    muteBtn.addEventListener('click', () => {
    video.muted = !video.muted;
    muteBtn.textContent = video.muted ? '🔇 已静音' : '🔊 静音';
    });

    // 音量控制
    volumeSlider.addEventListener('input', (e) => {
    video.volume = e.target.value;
    });

    // 格式化时间
    function formatTime(seconds) {
    const m = Math.floor(seconds / 60);
    const s = Math.floor(seconds % 60);
    return ${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')};
    }

    // 更新进度条和时间
    video.addEventListener('timeupdate', () => {
    const pct = (video.currentTime / video.duration) * 100;
    progressFilled.style.width = pct + '%';
    timeDisplay.textContent = ${formatTime(video.currentTime)} / ${formatTime(video.duration)};
    });

    // 点击进度条跳转
    progressBar.addEventListener('click', (e) => {
    const rect = progressBar.getBoundingClientRect();
    const pct = (e.clientX - rect.left) / rect.width;
    video.currentTime = pct * video.duration;
    });

    // 元数据加载完成后显示时长
    video.addEventListener('loadedmetadata', () => {
    timeDisplay.textContent = 00:00 / ${formatTime(video.duration)};
    });
    </script>
    </body>
    </html>

    3.2 最基础的 audio 播放器

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>HTML5 音频播放示例</title>
        <style>
            body { font-family: 'Microsoft YaHei', sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; }
            .audio-card { background: #f8f9fa; border-radius: 12px; padding: 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
            .audio-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #333; }
            audio { width: 100%; margin-bottom: 15px; }
            .audio-wave { height: 40px; background: #e9ecef; border-radius: 20px; display: flex; align-items: center; padding: 0 15px; gap: 3px; }
            .bar { width: 3px; background: #007bff; border-radius: 2px; animation: wave 1s ease-in-out infinite; }
            .bar:nth-child(odd) { animation-duration: 0.8s; }
            .bar:nth-child(even) { animation-duration: 1.2s; }
            @keyframes wave { 0%, 100% { height: 10px; } 50% { height: 30px; } }
            .playing .bar { animation-play-state: running; }
            .paused .bar { animation-play-state: paused; }
        </style>
    </head>
    <body>
        <h1>HTML5 Audio 标签完全指南</h1>
    

    <div class="audio-card">
    <div class="audio-title">背景音乐示例</div>
    <audio id="bgm" controls>
    <source src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3" type="audio/mpeg">
    <source src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.ogg" type="audio/ogg">
    您的浏览器不支持 HTML5 音频。
    </audio>
    <div class="audio-wave paused" id="waveContainer">
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div><div class="bar"></div>
    <div class="bar"></div>
    </div>
    </div>

    <div class="audio-card" style="margin-top: 20px;">
    <div class="audio-title">事件绑定示例</div>
    <audio id="sfx" src="data:audio/wav;base64,UklGRl9vT19XQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YU" controls></audio>
    <p style="font-size:13px;color:#666;margin-top:10px">提示:上方音频URL为示例,请替换为真实音频文件。</p>
    </div>

    <script>
    const audio = document.getElementById('bgm');
    const wave = document.getElementById('waveContainer');

    audio.addEventListener('play', () => wave.className = 'audio-wave playing');
    audio.addEventListener('pause', () => wave.className = 'audio-wave paused');

    // 显示加载状态
    audio.addEventListener('waiting', () => console.log('音频缓冲中...'));
    audio.addEventListener('canplay', () => console.log('音频可以开始播放了'));

    // 播放速率控制(0.5x - 2x)
    audio.playbackRate = 1.0;
    </script>
    </body>
    </html>

    3.3 在 PHP 中使用 video/audio 标签渲染数据库内容

    <?php
    $pdo = new PDO('mysql:host=127.0.0.1;dbname=shaoda_tech;charset=utf8mb4', 'root', 'Admin@2026!');
    

    // 假设从数据库读取文章数据
    $stmt = $pdo->prepare("SELECT * FROM articles WHERE id = 170");
    $stmt->execute();
    $article = $stmt->fetch(PDO::FETCH_ASSOC);

    // 输出 HTML 模板
    echo '<article class="video-article">';
    echo '<h1>' . htmlspecialchars($article['title'], ENT_QUOTES, 'UTF-8') . '</h1>';

    // 假设有 video_url 和 audio_url 字段
    if (!empty($article['video_url'])) {
    $videoUrl = htmlspecialchars($article['video_url'], ENT_QUOTES, 'UTF-8');
    echo <<<HTML
    <div class="video-wrapper">
    <video width="800" controls preload="metadata">
    <source src="{$videoUrl}" type="video/mp4">
    您的浏览器不支持 HTML5 视频播放。
    </video>
    </div>
    HTML;
    }

    // 动态生成带多格式的 audio 标签
    if (!empty($article['audio_url'])) {
    $audioUrl = htmlspecialchars($article['audio_url'], ENT_QUOTES, 'UTF-8');
    echo <<<HTML
    <div class="audio-wrapper">
    <audio controls>
    <source src="{$audioUrl}" type="audio/mpeg">
    <source src="" . str_replace('.mp3', '.ogg', $audioUrl) . "" type="audio/ogg">
    您的浏览器不支持 HTML5 音频播放。
    </audio>
    </div>
    HTML;
    }

    echo '</article>';
    ?>

    四、运行效果

    在浏览器中打开上述示例,你将体验到 HTML5 音视频标签的完整能力:

    • 视频示例1:页面加载后自动静音播放视频(符合现代浏览器自动播放策略),封面图 poster 属性在视频加载前显示,进度条、音量控制、全屏按钮等原生控制条完整可用
    • 视频示例2:自定义 JavaScript 控制条,点击"播放"按钮启动视频,下方进度条实时反映播放位置,点击进度条可跳转到指定位置,音量滑块实时调节音量,"静音"按钮切换静音状态
    • 视频示例3:视频下方显示字幕轨道选择器,用户可以在中文和其他语言字幕之间切换,内联 VTT 数据在无外部字幕文件时也能演示字幕功能
    • 音频示例:带有 CSS 动画波形可视化效果,播放时波形跳动,暂停时波形静止;显示加载状态,控制条包含播放进度条

    兼容性说明:现代浏览器(Chrome 90+、Firefox 88+、Safari 14+、Edge 90+)对 HTML5 video/audio 的支持度已经非常完善。但请注意,<track> 标签的样式目前无法直接通过 CSS 修改(字幕样式受浏览器控制),如果需要深度定制字幕样式,需要使用 JavaScript 库如 dash.jshls.js 来实现。

    五、常见问题(FAQ)

    Q1: 为什么加了 autoplay 视频没有自动播放?

    这是 HTML5 媒体标签最常见的问题之一。现代浏览器(Chrome、Safari、Firefox)都有"自动播放策略":带声音的媒体不允许自动播放,除非用户之前与页面有过交互(点击、触摸等)。解决方案有两个:

    • <video> 标签同时加上 autoplaymuted 属性,浏览器允许静音自动播放
    • 使用 JavaScript 在用户点击后调用 video.play() 来触发播放

    Q2: 视频格式不兼容,应该提供哪些格式?

    最安全的方案是同时提供 MP4 (H.264+AAC) 和 WebM (VP9+Opus) 两种格式,顺序无所谓,但 type 属性必须准确。MP4 是兼容性兜底,WebM 可以提供更小的文件体积和更好的质量。如果使用 HLS 流媒体(.m3u8 播放列表),需要借助 hls.js 或原生 HLS 支持(Safari)。

    Q3: 如何让视频在移动端也自适应宽度?

    在 CSS 中设置:video { width: 100%; height: auto; max-width: 100%; }。不要同时设置固定的 width 和 height 属性,而应该在 HTML 属性中用 CSS 来控制宽高比,或者使用 CSS 的 aspect-ratio 属性(如 aspect-ratio: 16/9)来保持宽高比。

    Q4: 视频加载太慢,如何实现渐进式加载/流式播放?

    <video> 添加 preload="metadata",这样页面加载时只下载视频的元数据(时长、尺寸等),不下载视频内容,用户点击播放后才开始加载实际数据。对于更高级的流媒体需求,推荐使用 HLS (HTTP Live Streaming) 或 DASH 协议,它们将视频切分为小块,按需加载,支持自适应码率。

    Q5: 如何监听视频的缓冲和加载状态?

    HTML5 媒体元素提供了一系列事件:loadstart(开始加载)、loadedmetadata(元数据加载完成)、loadeddata(第一帧数据加载完成)、canplay(可以开始播放)、canplaythrough(预计可以流畅播放)、waiting(等待缓冲)、playing(正在播放)、pause(暂停)、ended(播放结束)、error(错误)。通过监听这些事件,可以实现进度条上的缓冲区域可视化等高级功能。

    Q6: 可以在视频上叠加自定义的 HTML 内容吗?

    当然可以!使用 CSS 的 position: relative/absolute 可以将任意 HTML 元素覆盖在视频上方:

    <div style="position: relative; display: inline-block;">
        <video src="..." controls></video>
        <div style="position: absolute; top: 20px; left: 20px; color: white; font-size: 24px; text-shadow: 2px 2px 4px rgba(0,0,0,0.8);">
            水印文字
        </div>
        <button style="position: absolute; bottom: 60px; right: 20px;">自定义按钮</button>
    </div>

    六、延伸阅读

    • MDN - <video> 元素https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/video — 完整的 video 标签属性、事件和方法文档
    • MDN - <audio> 元素https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/audio — audio 标签的完整参考
    • MDN - 媒体事件与 APIhttps://developer.mozilla.org/zh-CN/docs/Web/Guide/Events/Media_events — 所有媒体相关事件的完整列表
    • WebM 项目官网https://www.webmproject.org/ — 开放免费的视频格式,了解 VP8/VP9 编码
    • FFmpeg 官方文档https://ffmpeg.org/ — 强大的音视频格式转换工具,用于生成多格式视频文件
    • HLS.jshttps://github.com/video-dev/hls.js — 在浏览器中实现 HLS 流媒体播放,无需 Flash
    • Video.jshttps://videojs.com/ — 最流行的开源 HTML5 视频播放器框架,支持 HLS、DASH、自定义皮肤
  • Can I Use - video elementhttps://caniuse.com/video — 各浏览器对 HTML5 video 的支持情况一览表