不能直接跨平台通用——仅H5(Chrome70+/Edge79+/Safari14.1+)、App(需原生支持及权限)有限支持,微信小程序不开放API;须用户手势触发、视频就绪、H5启用HTTPS,并按平台条件编译分别处理。

uni-app 的 requestPictureInPicture 能不能直接用?
不能直接跨平台通用——它只在特定环境生效,且必须满足硬性前提。H5 端依赖浏览器支持(Chrome 70+、Edge 79+、Safari 14.1+),App 端需原生层透出能力,小程序端(如微信)压根不开放该 API。
常见错误现象:videoElement.requestPictureInPicture is not a function 或调用后静默失败,往往是因为:
- 没加用户手势触发(必须由
@click等用户操作发起,不能自动调用) - 视频未加载完成(
canplay事件后才稳妥) - H5 页面未启用 HTTPS(非本地开发时,HTTP 下 PiP 被禁用)
- App 端未启用 Picture-in-Picture 权限(Android 需
android.permission.USE_PICTURE_IN_PICTURE)
条件编译下如何安全调用 requestPictureInPicture
得按平台拆开处理,不能一股脑写在一起。关键不是“能不能调”,而是“在哪调、谁来调、失败了怎么兜住”。
实操建议:
-
#ifdef H5块里检查document.pictureInPictureEnabled,再调video.requestPictureInPicture(),并用.catch()捕获拒绝或不支持的错误 -
#ifdef APP-PLUS块里不能只靠 JS,得走原生桥接:要么用uni.requireNativePlugin('xxx-pip')调第三方插件(如wrs-videoplayer),要么自己写原生模块暴露enterPip()方法 - 微信小程序完全绕过 PiP,改用「自定义小窗样式 + 固定定位」模拟(即切换
videoStyle),这是唯一可行路径
示例片段(仅 H5):
enterPiP() {
const video = this.$refs.videoPlayer;
if (!document.pictureInPictureEnabled) return;
video.requestPictureInPicture().catch(e => {
console.warn('PiP failed:', e.name); // 常见 e.name: 'NotAllowedError' / 'SecurityError'
});
}
为什么别信“一键支持画中画”的插件?
像 Ba-VideoPip、KJ-PlayerAndroid 这类插件,表面封装了 PiP,实际在 Android 上依赖 PictureInPictureMode Activity 生命周期管理,在 iOS 上则要 hook 系统播放器——而 uni-app 的 WebView 容器本身不具备这些控制权。
踩坑点很实在:
-
Ba-VideoPip在小窗后视频黑屏/不同步,本质是没接管音视频解码线程,只是“截图式悬浮” -
wrs-videoplayer不支持rtmp,因为底层用的是 ExoPlayer(Android)和 AVPlayer(iOS),两者对流协议支持差异大 - 所有插件在小程序里都退化成“伪小窗”,靠 CSS 定位 +
z-index层级强行浮起,无法真正脱离当前页面
真要上线,推荐分三层策略落地
别追求“一套代码全平台 PiP”,而是按终端能力分级交付:
- H5:用原生
requestPictureInPicture+enterpictureinpicture/leavepictureinpicture事件监听,做状态同步 - App:放弃 Web Video 标签,改用原生视频组件(如
uni-appx的<video-player></video-player>或封装好的wrs-videoplayer),它才能真正调系统 PiP - 小程序:纯 CSS 小窗(固定定位 + 手势拖拽 +
transform优化渲染),配合uni.createVideoContext控制播放状态,接受它是“模拟”而非“系统 PiP”
最易被忽略的一点:画中画退出后,H5 页面的 document.exitPictureInPicture() 不会自动恢复视频 DOM 位置,得手动监听 leavepictureinpicture 事件重置 video 样式或重新挂载。

















