🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
随着 Chrome 116+ 支持 Document Picture-in-Picture API 的出现,我们终于可以把整个页面内容(不仅仅是 <video>)移入画中画小窗口中,并在小窗中实现自定义控件、播放进度操作等功能。
本文博主将带着小伙伴们实现一个主页面和小窗同步视频控制功能,例如在主窗口暂停、小窗也同步暂停;调节音量、跳转进度也保持一致,提升用户体验。
1. 前言
不知道小伙伴是否发现 B 站的视频播放中,有一个功能 画中画 ,当用户点击会展现一个小窗播放,即使将主窗口缩起来,小窗口依然保留在外面电脑桌面上,如下图:
开启画中画(小窗口)

收缩主窗口

2. 为什么要使用 Document PiP API
在当今多任务处理的时代,用户经常需要在观看视频的同时进行其他操作(如浏览信息、回复消息等)。小窗模式(画中画)解决了这一需求,让视频可以浮动在页面上方,同时用户可以自由浏览其他内容。
与传统 Picture-in-Picture 的区别

- 传统的画中画
API功能有限,无法带自定义控件与交互 - 新的
API可以让整个文档出现在独立的小窗口中,支持丰富交互,如播放、暂停、音量、进度条等 - 特别适用于视频会议、在线课程、弹幕播放器、以及需要自定义控制画中画的小应用
新
API优势
完整 HTML 支持:可包含按钮、进度条等交互元素
无缝集成:与原始页面共享 JavaScript 上下文
尺寸灵活:可自定义小窗尺寸
双向通信:主页面与小窗实时同步
3. 完整代码案例
代码中 1.mp4 为博主本地保存测试的视频,大家可以自行获取相应资源源,修改 video 的 src 即可
3.1 可直接复用运行代码
CSS 代码
*{margin: 0;padding: 0;box-sizing: border-box;}body{font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;line-height: 1.6;color: #333;background:linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);padding: 20px;min-height: 100vh;}.container{max-width: 1200px;margin: 0 auto;background-color:rgba(255, 255, 255, 0.95);border-radius: 15px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);overflow: hidden;}header{background:linear-gradient(to right, #1a2a6c, #b21f1f);color: white;padding: 25px 40px;text-align: center;}{: ;: ;: (, , , );}{: ;: ;: ;: auto;}{: flex;: ;: ;}{: ;: ;: ;: hidden;: (, , , );}{: relative;: ;: ;}{: absolute;: ;: ;: ;: ;: block;}{: flex;: ;: ;: ;}{: ;: white;: none;: ;: ;: pointer;: ;: all ease;: flex;: center;: ;}{: ;:(-);: (, , , );}{: ;: not-allowed;: none;: none;}{: ;: white;: ;: ;: (, , , );}{: ;: ;: ;: solid ;}{: ;}{: flex;: flex-start;: ;}{: ;: white;: ;: ;: ;: flex;: center;: center;: ;: ;}{: fixed;: ;: ;: ;: ;: black;: ;: hidden;: (, , , );: ;: none;} {: ;: ;: cover;}{: absolute;: ;: ;: ;: flex;: center;: ;: ;: opacity ;} {: ;}{: ;: ;: ;: ;: monospace;}{: ;: ;: ;: ;: solid ;}{: flex;: ;: ;: wrap;}{: flex;: center;: ;}{: ;}{: ;}(max-width: ){{: column;}}
HTML 代码
<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>视频小窗模式演示</title><linkhref="css/pip.css"rel="stylesheet"type="text/css"/></head><body><divclass="container"><header><h1>视频小窗模式演示</h1><pclass="subtitle">使用 Document Picture-in-Picture API 实现在其他内容上浮动播放视频</p></header><divclass="content"><divclass="video-section"><divclass="video-container"><videoid="mainVideo"src="1.mp4"controlsplaysinline></video></div><divclass="video-controls"><buttonid="pipButton"title="开启小窗模式"><svgwidth="20"height="20"fill="currentColor"viewBox="0 0 16 16"><pathd="M0 3.5A1.5 1.5 0 0 1 1.5 2h13A1.5 1.5 0 0 1 16 3.5v9a1.5 1.5 0 0 1-1.5 1.5h-13A1.5 1.5 0 0 1 0 12.5v-9zM1.5 3a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h13a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-13z"/><pathd="M8 8.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-3z"/></svg> 开启小窗模式 </button><buttonid="fullscreenButton"><svgwidth="20"height="20"fill="currentColor"viewBox="0 0 16 16"><pathd="M1.5 1a.5.5 0 0 0-.5.5v4a.5.5 0 0 1-1 0v-4A1.5 1.5 0 0 1 1.5 0h4a.5.5 0 0 1 0 1h-4zM10 .5a.5.5 0 0 1 .5-.5h4A1.5 1.5 0 0 1 16 1.5v4a.5.5 0 0 1-1 0v-4a.5.5 0 0 0-.5-.5h-4a.5.5 0 0 1-.5-.5zM.5 10a.5.5 0 0 1 .5.5v4a.5.5 0 0 0 .5.5h4a.5.5 0 0 1 0 1h-4A1.5 1.5 0 0 1 0 14.5v-4a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v4a1.5 1.5 0 0 1-1.5 1.5h-4a.5.5 0 0 1 0-1h4a.5.5 0 0 0 .5-.5v-4a.5.5 0 0 1 .5-.5z"/></svg> 全屏 </button></div></div><divclass="info-section"><h2>Document Picture-in-Picture API<divclass="feature-list"><divclass="feature"><divclass="feature-icon">1任意 HTML 内容可以在小窗中显示视频控件、字幕等任意 HTML 元素<divclass="feature"><divclass="feature-icon">2保持播放状态进入小窗模式时视频持续播放,不中断观看体验<divclass="feature"><divclass="feature-icon">3双向同步主页面和小窗中的视频状态实时同步<divclass="feature"><divclass="feature-icon">4自由调整用户可以调整小窗位置和大小,适应不同需求<divclass="status">当前状态:<spanid="statusText">等待操作小窗状态:<spanid="pipStatus">未激活<divclass="browser-support">浏览器支持情况<divclass="support-list"><divclass="browser"><svgwidth="24"height="24"fill="#4285F4"viewBox="0 0 24 24"><pathd="M12 15.6l-3.9 2.3 1-4.3-3.2-2.9 4.3-.4L12 6.5l1.8 4.1 4.3.4-3.2 2.9 1 4.3z"/><spanclass="supported">Chrome 108+<divclass="browser"><svgwidth="24"height="24"fill="#FF9500"viewBox="0 0 24 24"><pathd="M0 0h24v24H0V0z"fill="none"/><pathd="M17.2 3H6.8l-5.2 9 5.2 9h10.4l5.2-9-5.2-9zm-1.15 16h-8.1l-4.04-7 4.04-7h8.09l4.04 7-4.03 7z"/><spanclass="unsupported">Firefox<divclass="browser"><svgwidth="24"height="24"fill="#0078D7"viewBox="0 0 24 24"><pathd="M0 0v24h24V0H0zm22 22H2V2h20v20z"/><pathd="M12 12l-4 4 1.4 1.4 2.6-2.6 2.6 2.6 1.4-1.4z"/><spanclass="unsupported">Edge<divclass="browser"><svgwidth="24"height="24"fill="#000000"viewBox="0 0 24 24"><pathd="M18.7 4.3c-1.2-1.2-2.9-1.9-4.7-1.9H5C3.3 2.4 2 3.7 2 5.4v13.1c0 1.8 1.5 3.2 3.3 3.2H19c1.8 0 3.2-1.4 3.2-3.2V9c0-1.8-.7-3.5-1.9-4.7h-.6zM19 20.5H5.3c-.9 0-1.7-.7-1.7-1.7V5.4c0-.9.8-1.7 1.7-1.7h9c.9 0 1.7.7 1.7 1.7v3.9h3.9c.9 0 1.7.8 1.7 1.7v7.9c0 .9-.7 1.7-1.6 1.7z"/><spanclass="unsupported">Safari<divid="pipContainer"class="pip-window"><videoid="pipVideo"src="1.mp4"controls><divclass="pip-controls"><buttonid="closePipButton"title="关闭小窗">关闭
3.2 演示效果
小伙伴们可以根据以下 GIF 演示图,查看效果
4. 案例核心原理与流程
4.1 代码流程
- 用户点击按钮 → 调用
documentPictureInPicture.requestWindow({ width, height })创建PiP窗口 - 将包含
<video>的DOM节点移动到小窗口中 - 在两个窗口里同步播放、暂停、音量、当前时间等状态
- 窗口关闭时,通过监听
pagehide或按钮将DOM恢复到主窗口
4.2 状态同步机制

4.3 关键事件处理
- timeupdate:同步播放进度
- play/pause:同步播放状态
- volumechange:同步音量设置
- pagehide:检测小窗关闭
5. 结语
Document Picture-in-Picture API 为开发者提供了强大的工具来创建更灵活的视频观看体验。虽然目前浏览器支持有限(Chrome 116+),但随着标准的发展,相信它将成为视频播放页面的标配功能。
本文演示了如何使用 window.documentPictureInPicture.requestWindow() API 创建一个自定义画中画窗口,并实现主窗口与小窗之间同步播放、暂停、音量控制与关闭逻辑。该方案相比传统 PiP 能实现更强的可定制化,适用于自定义播放器场景。


