Skip to content

HTML5 Audio

概述

HTML5 的 <audio> 元素提供了在网页中嵌入音频的标准方式,无需依赖第三方插件。

基本语法

html
<audio src="music.mp3" controls>
    您的浏览器不支持 audio 标签。
</audio>

音频属性

controls

显示音频控件:

html
<audio src="music.mp3" controls></audio>

autoplay

自动播放(注意:大多数浏览器限制自动播放):

html
<audio src="music.mp3" autoplay></audio>

loop

循环播放:

html
<audio src="music.mp3" loop controls></audio>

muted

静音:

html
<audio src="music.mp3" muted controls></audio>

preload

预加载策略:

html
<!-- none: 不预加载 -->
<audio src="music.mp3" preload="none" controls></audio>

<!-- metadata: 只预加载元数据 -->
<audio src="music.mp3" preload="metadata" controls></audio>

<!-- auto: 预加载整个音频 -->
<audio src="music.mp3" preload="auto" controls></audio>

多格式支持

为了确保跨浏览器兼容性,提供多种音频格式:

html
<audio controls>
    <source src="music.mp3" type="audio/mpeg">
    <source src="music.ogg" type="audio/ogg">
    <source src="music.wav" type="audio/wav">
    您的浏览器不支持 audio 标签。
</audio>

音频格式

格式MIME 类型文件扩展名浏览器支持
MP3audio/mpeg.mp3广泛支持
Ogg Vorbisaudio/ogg.oggFirefox, Opera, Chrome
WAVaudio/wav.wav广泛支持
AACaudio/aac.aacSafari, Chrome

完整属性示例

html
<audio 
    src="music.mp3"
    controls
    autoplay
    loop
    muted
    preload="auto">
    您的浏览器不支持 audio 标签。
</audio>

JavaScript 控制

基本控制

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

<button onclick="playAudio()">播放</button>
<button onclick="pauseAudio()">暂停</button>
<button onclick="stopAudio()">停止</button>

<script>
    var audio = document.getElementById("myAudio");
    
    function playAudio() {
        audio.play();
    }
    
    function pauseAudio() {
        audio.pause();
    }
    
    function stopAudio() {
        audio.pause();
        audio.currentTime = 0;
    }
</script>

音量控制

html
<audio id="myAudio" src="music.mp3"></audio>

<button onclick="setVolume(0.1)">10%</button>
<button onclick="setVolume(0.5)">50%</button>
<button onclick="setVolume(1.0)">100%</button>

<script>
    var audio = document.getElementById("myAudio");
    
    function setVolume(volume) {
        audio.volume = volume;
    }
</script>

播放速度控制

html
<audio id="myAudio" src="music.mp3" controls></audio>

<button onclick="changeSpeed(0.5)">0.5x</button>
<button onclick="changeSpeed(1.0)">1.0x</button>
<button onclick="changeSpeed(1.5)">1.5x</button>
<button onclick="changeSpeed(2.0)">2.0x</button>

<script>
    var audio = document.getElementById("myAudio");
    
    function changeSpeed(speed) {
        audio.playbackRate = speed;
    }
</script>

音频事件

html
<audio id="myAudio" src="music.mp3" controls></audio>
<p id="status"></p>

<script>
    var audio = document.getElementById("myAudio");
    var status = document.getElementById("status");
    
    audio.addEventListener("play", function() {
        status.textContent = "音频正在播放";
    });
    
    audio.addEventListener("pause", function() {
        status.textContent = "音频已暂停";
    });
    
    audio.addEventListener("ended", function() {
        status.textContent = "音频播放结束";
    });
    
    audio.addEventListener("timeupdate", function() {
        var current = Math.floor(audio.currentTime);
        var duration = Math.floor(audio.duration);
        status.textContent = `播放进度: ${current}秒 / ${duration}秒`;
    });
    
    audio.addEventListener("volumechange", function() {
        status.textContent = `音量: ${Math.floor(audio.volume * 100)}%`;
    });
</script>

自定义音频播放器

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义音频播放器</title>
    <style>
        .audio-player {
            max-width: 500px;
            margin: 50px auto;
            background-color: #f0f0f0;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }
        
        .song-info {
            text-align: center;
            margin-bottom: 20px;
        }
        
        .song-title {
            font-size: 20px;
            font-weight: bold;
            margin-bottom: 5px;
        }
        
        .song-artist {
            color: #666;
        }
        
        .progress-container {
            background-color: #ddd;
            height: 8px;
            border-radius: 4px;
            cursor: pointer;
            margin-bottom: 15px;
        }
        
        .progress {
            background-color: #4CAF50;
            height: 100%;
            border-radius: 4px;
            width: 0%;
            transition: width 0.1s;
        }
        
        .time-info {
            display: flex;
            justify-content: space-between;
            font-size: 12px;
            color: #666;
            margin-bottom: 15px;
        }
        
        .controls {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 15px;
        }
        
        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
        }
        
        button:hover {
            background-color: #45a049;
        }
        
        .volume-control {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-top: 15px;
        }
        
        input[type="range"] {
            flex-grow: 1;
        }
    </style>
</head>
<body>
    <div class="audio-player">
        <audio id="audio">
            <source src="music.mp3" type="audio/mpeg">
        </audio>
        
        <div class="song-info">
            <div class="song-title">歌曲名称</div>
            <div class="song-artist">艺术家</div>
        </div>
        
        <div class="progress-container" id="progressContainer">
            <div class="progress" id="progress"></div>
        </div>
        
        <div class="time-info">
            <span id="currentTime">0:00</span>
            <span id="duration">0:00</span>
        </div>
        
        <div class="controls">
            <button id="prev">上一首</button>
            <button id="playPause">播放</button>
            <button id="next">下一首</button>
        </div>
        
        <div class="volume-control">
            <span>🔊</span>
            <input type="range" id="volume" min="0" max="100" value="100">
            <span id="volumeValue">100%</span>
        </div>
    </div>
    
    <script>
        const audio = document.getElementById('audio');
        const playPause = document.getElementById('playPause');
        const progressContainer = document.getElementById('progressContainer');
        const progress = document.getElementById('progress');
        const currentTimeEl = document.getElementById('currentTime');
        const durationEl = document.getElementById('duration');
        const volumeSlider = document.getElementById('volume');
        const volumeValue = document.getElementById('volumeValue');
        
        // 播放/暂停
        playPause.addEventListener('click', () => {
            if (audio.paused) {
                audio.play();
                playPause.textContent = '暂停';
            } else {
                audio.pause();
                playPause.textContent = '播放';
            }
        });
        
        // 更新进度
        audio.addEventListener('timeupdate', () => {
            const percent = (audio.currentTime / audio.duration) * 100;
            progress.style.width = percent + '%';
            
            currentTimeEl.textContent = formatTime(audio.currentTime);
        });
        
        // 加载元数据
        audio.addEventListener('loadedmetadata', () => {
            durationEl.textContent = formatTime(audio.duration);
        });
        
        // 点击进度条
        progressContainer.addEventListener('click', (e) => {
            const rect = progressContainer.getBoundingClientRect();
            const percent = (e.clientX - rect.left) / rect.width;
            audio.currentTime = percent * audio.duration;
        });
        
        // 音量控制
        volumeSlider.addEventListener('input', (e) => {
            const volume = e.target.value / 100;
            audio.volume = volume;
            volumeValue.textContent = e.target.value + '%';
        });
        
        // 格式化时间
        function formatTime(seconds) {
            const min = Math.floor(seconds / 60);
            const sec = Math.floor(seconds % 60);
            return `${min}:${sec.toString().padStart(2, '0')}`;
        }
        
        // 播放结束
        audio.addEventListener('ended', () => {
            playPause.textContent = '播放';
        });
    </script>
</body>
</html>

播放列表

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>音频播放列表</title>
    <style>
        .playlist {
            max-width: 400px;
            margin: 20px auto;
        }
        
        .playlist-item {
            padding: 10px;
            border-bottom: 1px solid #ddd;
            cursor: pointer;
        }
        
        .playlist-item:hover {
            background-color: #f0f0f0;
        }
        
        .playlist-item.active {
            background-color: #4CAF50;
            color: white;
        }
    </style>
</head>
<body>
    <audio id="audio" controls></audio>
    
    <div class="playlist">
        <div class="playlist-item" data-src="song1.mp3">歌曲 1</div>
        <div class="playlist-item" data-src="song2.mp3">歌曲 2</div>
        <div class="playlist-item" data-src="song3.mp3">歌曲 3</div>
    </div>
    
    <script>
        const audio = document.getElementById('audio');
        const items = document.querySelectorAll('.playlist-item');
        
        items.forEach(item => {
            item.addEventListener('click', function() {
                // 移除所有 active 类
                items.forEach(i => i.classList.remove('active'));
                
                // 添加 active 类到当前项
                this.classList.add('active');
                
                // 播放选中的音频
                audio.src = this.dataset.src;
                audio.play();
            });
        });
        
        // 自动播放下一首
        audio.addEventListener('ended', () => {
            const current = document.querySelector('.playlist-item.active');
            const next = current.nextElementSibling;
            
            if (next && next.classList.contains('playlist-item')) {
                next.click();
            }
        });
    </script>
</body>
</html>

音频可视化

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>音频可视化</title>
    <style>
        canvas {
            display: block;
            margin: 20px auto;
            background-color: #000;
        }
    </style>
</head>
<body>
    <audio id="audio" src="music.mp3" controls></audio>
    <canvas id="canvas" width="800" height="200"></canvas>
    
    <script>
        const audio = document.getElementById('audio');
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        
        const audioContext = new (window.AudioContext || window.webkitAudioContext)();
        const analyser = audioContext.createAnalyser();
        const source = audioContext.createMediaElementSource(audio);
        
        source.connect(analyser);
        analyser.connect(audioContext.destination);
        
        analyser.fftSize = 256;
        const bufferLength = analyser.frequencyBinCount;
        const dataArray = new Uint8Array(bufferLength);
        
        function draw() {
            requestAnimationFrame(draw);
            
            analyser.getByteFrequencyData(dataArray);
            
            ctx.fillStyle = 'rgb(0, 0, 0)';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            const barWidth = (canvas.width / bufferLength) * 2.5;
            let x = 0;
            
            for (let i = 0; i < bufferLength; i++) {
                const barHeight = dataArray[i] / 2;
                
                ctx.fillStyle = `rgb(${barHeight + 100}, 50, 50)`;
                ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
                
                x += barWidth + 1;
            }
        }
        
        audio.addEventListener('play', () => {
            audioContext.resume();
            draw();
        });
    </script>
</body>
</html>

最佳实践

  1. 提供多种格式:确保跨浏览器兼容性
  2. 避免自动播放:尊重用户体验
  3. 优化文件大小:压缩音频文件
  4. 提供控件:让用户控制播放
  5. 考虑移动设备:注意带宽和电池消耗
  6. 提供替代内容:为不支持的浏览器提供说明
  7. 使用适当的预加载策略:平衡性能和用户体验

总结

HTML5 Audio 元素为网页音频播放提供了强大的功能。通过合理使用其属性和 JavaScript API,可以创建功能丰富的音频播放体验,从简单的背景音乐到复杂的音频播放器和可视化效果。