uni-app的组件不支持原生倍速控制,需分端处理:小程序须用uni.createVideoContext在onReady后设playbackRate;H5可操作DOM但需用户手势触发;App端暂不支持。

uni-app 的 <video></video> 组件不支持原生倍速控制
uni-app 的 <video></video> 是跨端封装组件,iOS 和 Android 原生 video 元素虽支持 playbackRate,但 uni-app 未透出该能力;H5 端虽可操作 DOM,但小程序端(微信、支付宝等)完全不可控。直接写 playbackRate = 1.5 在真机上无效是常态,不是你代码写错了。
实操建议:
- 小程序平台必须用原生组件
<cover-view></cover-view>+<cover-image></cover-image>自定义 UI,并通过uni.createVideoContext获取上下文后调用playbackRate(仅微信基础库 2.25.0+ 支持,且需在onReady后设置) - H5 端可绕过 uni-app 封装,用
document.querySelector('video')拿到原生元素再设playbackRate,但要注意v-if或动态渲染时 DOM 可能未就绪 - App 端(iOS/Android)目前无公开 API 支持倍速,
plus.video.Player不提供该参数,只能降级为「不显示倍速选项」或提示「暂不支持」
微信小程序中设置 playbackRate 的正确时机和限制
微信小程序的 video 原生组件虽支持 playbackRate 属性,但 uni-app 的 <video></video> 并未将其作为 prop 暴露。你得手动用 uni.createVideoContext 操作,而且有硬性前提:必须在 onReady 生命周期之后、且视频已加载元数据(canplay 或 loadedmetadata 触发后)才能生效,否则设了也白设,控制台无报错但毫无反应。
实操建议:
- 在
<video></video>上绑定@loadedmetadata事件,内部调用videoContext.playbackRate(1.5) - 不要在
mounted或onLoad就设,此时 context 可能拿不到真实节点,或节点还没加载完成 - 微信开发者工具可能表现正常,但真机(尤其 iOS 微信)对非 0.5/1.0/1.25/1.5/2.0 的值会自动向下取整,比如设 1.3 → 实际按 1.25 跑
- 记得在倍速切换时重新调用
playbackRate(),暂停再播放不是必须的,但部分机型需要seek一下才刷新渲染
自定义控制器里如何安全绑定倍速按钮并同步状态
自定义控制器本质是盖在 <video></video> 上的 <cover-view></cover-view>(小程序)或普通 <view></view>(H5/App),按钮点击后要触发倍速变更,同时保证 UI 状态(如高亮当前倍速)与实际播放速率一致。难点在于:不同平台响应延迟不同、playbackRate 获取值不一定实时可读(微信小程序 videoContext.getPlayBackRate 返回的是 Promise,且只在真机有效)。
实操建议:
- 维护一个响应式变量
currentRate,所有倍速操作先更新它,再调用videoContext.playbackRate() - 不要依赖
videoContext.getPlayBackRate()来同步 UI —— 它异步、可能失败、H5 不支持;UI 状态应以你的currentRate为准 - 倍速按钮建议固定为 [0.5, 0.75, 1.0, 1.25, 1.5, 2.0],避免小数精度问题(如 1.33)导致平台兼容异常
- 在 App 端,检测到
uni.getSystemInfoSync().platform === 'app'时,直接隐藏倍速区域或置灰禁用,别留个点不动的按钮
为什么 H5 端用原生 DOM 操作仍可能失效
H5 端看似最自由,但 uni-app 的 <video></video> 在编译后可能被包裹多层,或者使用了 v-show(display: none)而非 v-if(DOM 销毁),导致 querySelector('video') 拿到的是隐藏元素或占位符。更隐蔽的问题是:Chrome 对 playbackRate 修改有策略限制 —— 必须由用户手势(click/tap)触发,不能在自动播放、autoplay 或定时器里调用,否则静默失败。
实操建议:
- 给视频容器加唯一
id(如id="my-video"),用document.getElementById('my-video').children[0]更稳妥地拿到<video></video>元素 - 倍速按钮的
@click必须是直接用户触发,不能套在setTimeout或watch里间接调用videoEl.playbackRate = 1.5 - 设完倍速后,检查
videoEl.playbackRate的返回值是否等于设定值,不等就说明被拦截了,可 fallback 到提示“浏览器不支持此倍速” - 避免在
onShow或页面切回来时自动恢复倍速,这属于非用户手势,大概率失败
事情说清了就结束。倍速这事,核心不是“怎么写代码”,而是“在哪一端、什么时机、用什么方式去触达原生能力”。跨端差异比想象中更硬,别指望一套逻辑跑通三端。










