play()本身不决定格式支持,真正取决于浏览器对音视频编码格式的解码能力;需用canPlayType()检测兼容性,并确保用户手势触发、元数据加载完成且未静音。
HTML5 的 play() 函数本身不决定支持哪些格式,它只是触发播放;真正决定能否播放的,是浏览器对 或 元素内嵌音视频编码格式的支持程度。
不同浏览器对容器(.mp4、.webm、.ogg)和内部编码(H.264、VP9、AAC、Opus)的支持不一致。关键不是“play() 支持什么”,而是“你传给 的文件能否被当前浏览器解码”。
.mp4 容器 + H.264 视频 + AAC 音频:Chrome、Firefox、Safari、Edge 均广泛支持(Safari 对 MP4 最友好).webm 容器 + VP9 视频 + Opus 音频:Chrome、Firefox、Edge 支持好;Safari 16.4+ 才开始支持 VP9,旧版仅支持 VP8.ogg / .oga 容器 + Theora 视频 / Vorbis 音频:Firefox、Chrome 支持,Safari 和 Edge 基本不支持.mp4 或 .mkv 容器):Chrome 109+、Firefox 107+、Edge 110+ 支持;Safari 16.4+ 仅支持 AV1 解码但不支持 直接加载 .mp4 封装的 AV1(需用 MediaSource Extensions)play() 前必须检查的三件事即使格式正确,play() 也可能静默失败或抛出 NotAllowedError —— 这和格式无关,而是浏览器策略限制。
click、touchstart)触发,不能在页面加载后自动调用readyState 至少为 1(HAVE_METADATA),建议监听 loadedmetadata 事件后再调用muted 属性:部分浏览器(如 Chrome)要求自动播放的视频必须带 muted,否则拒绝 play()
canPlayType() 是判断格式兼容性的唯一可靠方法不要靠文件扩展名或服务端 MIME 类型猜测;用元素原生方法实测:
const audio = new Audio();
console.log(audio.canPlayType('audio/mp4; codecs="aac"')); // "probably" / "maybe" / ""
console.log(audio.canPlayType('audio/webm; codecs="opus"'));
注意: canPlayType() 返回值只有三个可能:"probably"(高置信度支持)、"maybe(容器匹配但无法确认编码)、
""(不支持)。它不发起网络请求,也不解码,只查本地能力表。
iOS 上几乎所有非用户手势触发的 play() 都会失败,且对格式更苛刻:
playsinline 属性必须显式设置,否则视频会跳全屏(影响 UI 控制流)真正要解决“播不出”问题,得先分清是格式不支持、策略拦截、还是资源加载失败——play() 只是最后一环,它不会告诉你前面哪一步断了。