最简可用音频播放需加controls属性,用标签提供多格式备用,src路径需正确且通过本地服务器访问;autoplay仅muted时可能生效,但应监听用户手势调用play();推荐单audio实例动态切换src,配合preload="none"和load()方法确保兼容性。

只用 <audio></audio> 标签就能跑起来,但必须加 controls
不加 controls 属性,页面上就看不到任何按钮或进度条——它会静默加载,用户完全无法操作。这是新手最常卡住的地方。
最简可用写法就是:
<audio controls><source src="music.mp3" type="audio/mpeg"><source src="music.ogg" type="audio/ogg"> 你的浏览器不支持 audio 元素。 </source></source></audio>
-
src直接写在<audio></audio>上也行,但用<source></source>更稳妥:浏览器按顺序尝试,第一个能解码的就用 -
type必须写对,audio/mpeg对应 MP3,audio/ogg对应 OGG,错一个就跳过该源 - 路径出错时,控制台报
net::ERR_FILE_NOT_FOUND或 404,不是代码问题,是文件根本没放对位置 - 本地双击打开 HTML(
file://协议)时,Chrome 会拒绝加载音频——必须起本地服务,比如python3 -m http.server
autoplay 和 muted 组合才可能生效,但别依赖它
单独写 autoplay 基本无效。现代浏览器强制要求:首次播放必须由用户手势触发,否则直接抛 DOMException: play() failed because the user didn't interact with the document。
唯一勉强可行的组合是 autoplay muted,但它只在部分桌面 Chrome 中“可能”响,且:
- iOS Safari 完全无视
autoplay,无论是否muted - 安卓微信内置浏览器连
muted autoplay都大概率静音 - 即使成功,刷新后策略重置,还得等用户点一下才能再播
真正可靠的方案,是监听一次 click 或 touchstart,然后调 audio.play()。例如:
document.body.addEventListener('click', () => {
document.querySelector('audio').play().catch(e => console.warn(e));
}, { once: true });
音乐列表别堆多个 <audio></audio>,用一个实例动态换 src
把每首歌都写一个带 controls 的 <audio></audio>,页面会变慢、内存飙升、切换卡顿。正确做法是只留一个隐藏的 <audio></audio> 实例,列表项用 <li> 或 <button></button>,通过 data-src 存路径。
- 列表项加
、data-title="夜曲"等属性 -
<audio preload="none"></audio>,避免页面一开就预加载所有音频 - 点击时先
audio.pause(),再audio.src = clickedEl.dataset.src,然后audio.load(),最后audio.play() - 必须调
load():Safari iOS 不调这个,play()会失败 - 播放前清空
audio.currentTime = 0,否则连续点同一首会从上次位置继续播
移动端和 iOS 的坑比桌面多,别硬刚自动播放
移动端几乎不认 autoplay,iOS 尤其严格。你写的 autoplay muted 在 iPhone 上基本等于没写。
更现实的做法是:
- 默认隐藏播放控件,列表项用文字或图标引导用户“点击播放”
- 播放按钮文案实时切换:
audio.paused ? '播放' : '暂停',靠监听play和pause事件更新 - 进度条用
<input type="range">,拖动时设audio.currentTime,别自己画<div> 进度条——兼容性和拖动手感差太多 <li>高亮当前播放项靠加 <code>class="playing",CSS 控制样式;切换前先移除旧的playing类
真正的难点不在写代码,而在处理各种浏览器策略差异和用户交互时机——比如 iOS 要求第一次 play() 必须紧贴用户点击,中间插个 setTimeout 就失效。











