浏览器读取标签分三步:先建dom节点、再加载元数据、最后准备播放;需等loadedmetadata事件后才能安全读取duration等属性,preload="metadata"可预加载头信息,autoplay需muted+playsinline+页面聚焦才生效。

浏览器怎么读取 <video></video> 标签
它不是“解析完就播”,而是分三步走:先建 DOM 节点,再加载元数据,最后准备播放状态。DOM 构建阶段只认属性名(如 src、autoplay),但此时不会发起网络请求;真正触发加载的是 load() 方法或首次访问 videoWidth 这类只读属性,或者用户点了播放按钮。
常见错误现象:video.duration 一开始是 NaN,video.readyState 是 0(HAVE_NOTHING)。这不是代码写错了,是还没走到加载那步。别急着读时长、设时间点,得等 loadedmetadata 事件。
-
preload="metadata"会让浏览器在 DOM 就绪后主动加载视频头信息(宽高、时长、编码格式),适合需要预知尺寸或做封面展示的场景 -
preload="none"完全不加载,直到调用play()才开始拉流,省流量但首帧延迟明显 -
autoplay不是“立刻播”,它只是个提示;浏览器最终是否执行,取决于当前上下文是否满足静音、用户交互、页面可见性等策略
autoplay 失效时该查哪几个条件
现代浏览器(Chrome ≥70、Safari iOS ≥10、Firefox ≥66)对自动播放有明确限制:带声音的视频必须由用户手势触发。所以 autoplay 单独存在基本等于摆设。
真机调试时最常漏掉的三个硬性条件:
- 必须同时设置
muted属性——这是自动播放的“准入证”,不是可选项 - iOS Safari 必须加
playsinline,否则即使静音也会强制全屏,而全屏模式下自动播放被禁用 - 页面必须已获得焦点(
document.hasFocus() === true),比如从后台切回来的 Tab 可能还没激活,play()会抛NotAllowedError
建议用 video.play().catch(e => console.warn('Autoplay blocked:', e)) 主动捕获失败原因,比靠猜靠谱得多。
为什么 width/height 和 CSS 尺寸经常对不上
<video></video> 元素有两个独立的尺寸系统:一个是渲染框(由 width/height 属性或 CSS 控制),另一个是视频画面本身(由 videoWidth/videoHeight 只读属性反映,取决于原始文件分辨率和 object-fit 行为)。
典型踩坑场景:做竖屏短视频流,CSS 设了 height: 100vh,结果画面被拉伸变形。这是因为没管 object-fit,默认是 fill,强行撑满容器。
- 想保持原始宽高比且居中显示,用
object-fit: contain+width: 100%; height: 100% - 想铺满容器不露黑边,用
object-fit: cover,但注意可能裁剪画面 -
width/height属性值单位只能是像素,不支持百分比;CSS 中则完全自由 - 移动端尤其要注意:iOS Safari 对
object-fit的支持从 iOS 9.0 开始,旧版本需降级处理
用 JavaScript 控制播放前必须确认的状态
play()、pause()、currentTime = x 这些方法不是随时都能调。调早了会静默失败或抛错,调晚了又卡顿。关键要看 readyState 和 networkState。
安全调用 play() 的最小前提:
-
video.readyState >= HTMLMediaElement.HAVE_METADATA(至少拿到宽高、时长) -
video.networkState === HTMLMediaElement.NETWORK_LOADED或NETWORK_IDLE(没在加载出错) - 如果之前调过
load(),要等loadeddata事件;如果是自动加载,等canplay更稳妥
特别容易忽略的一点:video.paused 是只读布尔值,但它反映的是“当前是否暂停”,不是“能否暂停”。哪怕 paused 是 true,如果 readyState 还是 0,play() 依然会失败。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











