必须同时写死 autoplay 和 muted 布尔属性,加 playsinline 及 webkit-playsinline,preload="metadata",play() 必须 catch 并兜底按钮,静音后延时 100ms 再开声。

autoplay + muted 必须同时写死在 HTML 里
单独写 autoplay 几乎必然失败,浏览器根本不执行;只靠 JS 后续设 video.muted = true 也无效——策略判断发生在元素插入 DOM 的瞬间。必须用布尔属性形式同步声明:<video autoplay muted></video>。写成 muted="false" 或 autoplay="autoplay" 都可能被误判为已静音,反而触发拦截。
移动端必加 playsinline,iOS 不加就全屏
iOS Safari 对内联播放极其敏感:哪怕 autoplay 和 muted 全对,缺了 playsinline,视频也会强制跳全屏,视觉上等于没播。Android Chrome 虽不强制,但加上无副作用,推荐统一加上。旧版 iOS 还需额外加 webkit-playsinline 兼容:
<video autoplay muted playsinline webkit-playsinline></video>
注意:若父容器有 transform: scale() 或 opacity: 0,部分 iOS 版本也会回退静音策略,导致黑屏。
preload="metadata" 不是可选项,是首帧速度关键
默认 preload="auto" 会尝试下载整个视频,弱网下白屏久、流量浪费;preload="none" 则元数据不加载,play() 直接被拒。固定用 preload="metadata" 只取时长、宽高、封面帧位置,首帧出得快,且不影响 autoplay 行为。
- 不要依赖
poster替代preload:没元数据,poster可能压根不显示 - 开发时 localhost 正常,上线后 CDN 或 Nginx 重写响应头(如删掉
Access-Control-Allow-Origin或覆盖Content-Type)会导致静默失败,控制台无报错,只黑屏
调用 play() 必须带 .catch(),失败后立刻给按钮
即使 HTML 属性全对,微信 Android X5 内核、后台标签页、低电量模式等仍可能拒绝播放。不能只信属性,必须主动调用并兜底:
video.play().catch(e => {
console.warn("自动播放被拒", e.name);
showPlayButton(); // 显示“点击观看演示”之类带价值的按钮
});
按钮点击后再调一次 video.play(),此时 100% 成功——因为发生在用户手势上下文中。别写“播放”,要写动词+价值,比如“立即查看效果”。
静音是起点不是终点,用户看几秒后想听讲解,这时再用 video.muted = false 开声才合理;但别在 play() 后立刻切,Safari 17+ 会中断播放,建议延迟 100ms 以上再执行。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











