HTML原生video标签需多格式<source>(MP4+WebM)、跨域配置、muted autoplay及用户手势触发才能稳定播放;默认控件难定制,建议隐藏后用JS监听事件实现自定义UI。
HTML 原生 <video> 标签就能直接播放视频,不需要额外写播放器逻辑——但默认控件简陋、样式难改、移动端兼容细节多,真要“能用+好看+稳定”,得手动干预几个关键点。
<video> 在所有浏览器里都正常加载常见错误是只提供一种格式,比如只传 .mp4,结果 Safari 或 Firefox 某些版本报 VIDEO_ERROR_DECODE 或静音黑屏。不同浏览器支持的编码(H.264 / VP9 / AV1)和容器(MP4 / WebM)不一样。
<source> 多个格式:优先 MP4(H.264+AAC),再加 WebM(VP9+Opus)作为后备Access-Control-Allow-Origin: *,否则 iOS Safari 会静音或拒绝加载./videos/demo.mp4,测试时没问题,上线后常因路由或打包路径错位导致 404<video controls> <source src="demo.mp4" type="video/mp4"> <source src="demo.webm" type="video/webm"></video>
controls 还没按钮,或者点击没反应不是所有属性都能“写了就生效”。controls 只是启用默认控件,但真正决定能否播放的是媒体加载状态和用户交互权限。
DOMContentLoaded 或 setTimeout 里自动 play(),否则被静音拦截muted)才允许自动播放;有声视频必须等用户点击后才能调 play()
controls 显示,建议显式加 playsinline 和 webkit-playsinline
原生 <video> 的控件不可 CSS 选择,但可以用 JS 监听事件 + 自己画 UI,再通过 API 控制行为——这是最轻量可控的做法。
立即学习“前端免费学习笔记(深入)”;
controls="false",然后监听 timeupdate、volumechange、loadedmetadata 等事件更新自定义进度条位置currentTime,先检查 video.readyState >= 2(至少已加载元数据),否则可能跳转失败video.requestFullscreen(),但注意:Firefox 需要 video.webkitRequestFullscreen() 兼容,且必须在用户手势回调内执行autoplay 为什么总失败,有没有绕过方法没有可靠绕过方法。所谓“绕过”基本是误判:比如用 setTimeout 延迟播放,或监听 visibilitychange,这些在新版 iOS/Android 上全部失效。
muted + autoplay + 用户首次点击触发 play()(哪怕只是点空白区域),之后再取消静音canplay 或 canplaythrough 事件自动播放——它们不等于用户授权,iOS 仍会拦截<video muted autoplay loop>,但务必加 playsinline,否则 iOS 强制全屏真正麻烦的不是写播放逻辑,而是不同设备对“用户手势”的定义差异:微信内置浏览器把 touchstart 当有效,但某些安卓 WebView 要求 click;iOS 15 后甚至要求手势必须落在 <video> 元素上才放行 play()。这些边界情况,光看文档很难覆盖,得靠真机日志反复验证。