配了三年视频会议,每次切出去再回来画面就丢了——今天 Document PiP 把这件事彻底变了

你用过视频会议软件的画中画吗?切换标签页回去,视频还在,但控制条没了、字幕停了——因为浏览器把那个标签页当成”后台”冻住了。三年了,我们用各种 hack 绕过这个问题。今天,Document Picture-in-Picture API 把这件事从浏览器底层原生修了。


问题的根子在哪

传统的 requestPictureInPicture() 只能把单个 <video> 元素塞进一个小窗口。浏览器给你的是一个孤立的视频播放器——它有自己的窗口,但它不知道你的页面上还有配套的聊天面板、字幕输入框、举手按钮。

你切到别的标签页,浏览器把整个页面(包括 PiP 窗口里的那个 <video>)都暂停了。等你回来,播放器状态是乱的:视频在播,但你的 UI 已经完全失控。

这本质上是浏览器不知道 PiP 窗口里的内容和主页面是一套系统。它们之间没有文档上下文,没有共享的 DOM,所以浏览器把它们当两个完全无关的东西处理。


Document PiP 是什么

Document Picture-in-Picture API(Chrome 116+ / Firefox 151+)换了一套思路:不是把单个元素扔出去,而是打开一个全新的空白窗口,塞进任意 HTML 内容

这个窗口是真正独立的浏览器窗口,有完整的 document,可以执行 JavaScript,可以加载 CSS,和主页面之间通过 postMessage 通信。

// 打开一个 PiP 窗口
const pipWindow = await documentPictureInPicture.requestWindow({
  initialAspectRatio: 16 / 9,
  copyStyleSheets: true,  // 把当前页面的样式复制过去
});

// 把整个组件移进去
const playerPanel = document.querySelector('#player-panel');
pipWindow.document.body.append(playerPanel);

// 监听关闭事件,把组件移回来
pipWindow.addEventListener('unload', () => {
  const mainContainer = document.querySelector('#main-container');
  mainContainer.append(playerPanel);
});

copyStyleSheets: true 是关键——浏览器帮你把主页面渲染好的 CSS 样式原样复制到 PiP 窗口里。你不需要在 PiP 窗口里重新引入样式表,它长的和主页面一模一样。


视频会议场景:三个真实痛点

痛点一:切换标签页回来状态全乱

视频会议里,点击”画中画”按钮,完整的会议控制面板(静音、摄像头、共享、举手)全部进入浮窗。主页面可以继续做笔记、翻文档,PiP 窗口永远置顶,不会被浏览器冻结。因为它是独立窗口,浏览器只冻结主标签页。

痛点二:多流视频拼接不再靠截图 hack

以前想把多个参会者视频拼成一个网格放到 PiP 窗口,需要用 <canvas> 截图再渲染,性能差、文字不可选中。现在直接往 PiP 窗口里 append 多个 <video> 元素,是真正的 DOM 节点,文字可复制、布局用 CSS Grid。

痛点三:关闭 PiP 后状态无缝接续

传统 PiP 关闭窗口,视频流直接断了,你需要重新 play()。Document PiP 关闭时触发 unload 事件,你在这个事件里把 DOM 节点移回主页面——用户看到的体验是:窗口关了,但控制条、视频、字幕全部原样回到主页面,无缝衔接。


浏览器支持现状

  • Chrome/Edge:116+ 完全支持
  • Firefox:151+ 完全支持
  • Safari:不支持(Apple 标准立场是”不反对”但无计划)
  • 74.5% 全球覆盖率

Feature detection 只能靠 JavaScript,因为 CSS @supports at-rule() 目前无法检测 display-mode: picture-in-picture

// Feature detection
if (!('documentPictureInPicture' in window)) {
  // 不支持,降级到传统 requestPictureInPicture()
}

下一步:怎么落地

第一步,盘点你的产品里哪些场景真正需要”永远置顶的多控件浮窗”——视频会议、直播监控、文档对照翻译、股票行情,都是天然适合 Document PiP 的场景。

第二步,用上面那段 15 行代码做一个最小可用的 demo:把一个 <div> 带完整 CSS 样式塞进 PiP 窗口,关闭后再移回来。跑通这个流程,你就掌握了核心机制。

第三步,注意 preferInitialWindowPlacement 参数——如果你的产品会反复打开/关闭 PiP(比如每次视频会议开始都新建 PiP 窗口),设为 true 可以让浏览器每次都把窗口放在默认位置,而不是复用上次用户手动拖拽过的位置。

浏览器正在变成真正的应用平台。Document PiP 是标志之一:它让 Web 应用第一次有了真正意义上的”多窗口”能力,而不是在同一个标签页里用 position: fixed 模拟浮层。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 15 阅读