video.loop仅检测属性存在性,ios safari需muted+autoplay+loop三者共存,ended事件是跨平台兜底方案,首尾帧对齐才是消除卡顿的关键。

video.loop 属性本身不认值,只看是否存在
写成 loop="true"、loop="" 甚至 loop="loop" 都无效。浏览器只检测该属性是否在标签中「存在」,只有 <video loop></video> 或 <video loop src="x.mp4"></video> 才真正启用原生循环逻辑。JS 动态设置也一样:video.loop = true 有效,但 video.setAttribute('loop', 'true') 或 video.loop = "true" 都不会触发行为。
iOS Safari 必须三者共存:muted + autoplay + loop
哪怕页面已加载完成、用户点过屏幕、视频也解码好了,iOS Safari(含微信、QQ 内置浏览器)仍会忽略 loop,除非同时满足以下条件:
-
muted—— 强制初始静音,绕过自动播放策略 -
autoplay—— 没它,视频根本不会启动,loop 自然无从谈起 -
loop—— 原生循环开关
漏掉任意一个,大概率出现“图标静音+暂停状态+不循环”;实测还建议加上 playsinline 和 preload="auto",避免 iOS 强制全屏或首帧加载延迟。
ended 事件监听是跨平台兜底方案,但得处理 play() 拒绝
原生 loop 在旧版 Safari、部分 Android WebView、或 JS 动态换 src 后不可靠。用 ended 事件手动重播更可控,但必须注意:
-
video.currentTime = 0要在ended触发后立刻执行,不能依赖load()或pause()/play()组合(会重加载,断流) -
video.play()返回 Promise,iOS 和部分安卓环境会在非用户手势上下文中直接 reject,必须加.catch() - 如果视频是 JS 动态设置的,建议等
loadeddata事件后再绑定ended,否则可能错过首次结束
首尾帧不对齐才是“卡顿”的真正原因
很多人以为加了 loop 就万事大吉,结果循环时一闪黑、一跳帧、一声“咔哒”。这不是代码问题,而是视频源本身缺陷:
- 最后一帧和第一帧画面亮度/构图/运动状态不一致 → 视觉跳变
- 音频结尾有空白或爆音 → 听觉断点
- 关键帧间隔过大(如 5 秒一帧)→
currentTime = 0实际跳到最近 I 帧,产生延迟
导出视频时务必让结尾淡出并冻结在起始画面,用 FFmpeg 控制关键帧密度(如 -g 30 对应 1 秒@30fps),再配合 loop 才算真正落地。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











