浏览器中的画中画(Picture-in-Picture)模式及其 API

简介:

想边刷微博边追剧?想边聊微信边看球赛?从浏览器支持扩展功能开始,人们就一直有这样的需求:

Chrome看视频,有没有可以弹出视频窗口的插件?

各个国产壳子浏览器也争相内置“视频弹窗播放”的功能,比如当年的火狐中国版

2700061cbfe5f04bc6812c6d370d967c92eaeadc

这么多年过去了,正统浏览器们终于要内置这个功能了,而且还有配套的 API 给开发者使用。

WICG,全名为 Web Incubator Community Group(Web 孵化器社区小组),主要成员为 Chrome 的工程师们,他们从一年前开始标准化这个能让视频弹窗播放的特性,起名为 Picture-in-Picture(画中画),缩写为 PiP。

Chrome 从今年年初开始着手实现,到本文撰稿时,已经实现的差不多了。这篇文章将主要讲两方面:Chrome 当前实现的 PiP 交互是怎么样的,以及有哪些 API 让我们开发者使用。

Chrome 中的 PiP 交互

Chrome 官方提供了一个 demo 页面 Picture-in-Picture Sample,我用这个 demo 录了一个简单的演示视频:


从视频中可以看到,Chrome 在原生的 video 控件中提供了开启画中画模式的菜单项,一旦开启画中画模式,原本页面中内联(inline)展现的那个 video 还占据着原来的位置,各种控件也都在,但最重要的视频画面已经被无缝的转移到了新的弹出窗口中了,只剩下一张 poster 图片和一层灰色的遮罩。

我们把弹出的那个视频窗口叫做 PiP 窗口,PiP 窗口只有视频画面,没有标题栏和地址栏(chrome-less),这一点和用 window.open()打开的弹窗不一样。同时,PiP 窗口也没有完整的视频控件,只有开始/暂停/关闭按钮三个,时间、进度条、音量这些控件都没有。PiP 窗口还支持拖拽改变大小(不能大于一个象限),以及支持拖拽到任意位置(录屏里没有体现,因为在本文撰写时还不支持)。还有最重要的一点是,PiP 窗口在所有窗口中是置顶的(always on top),正如我在录屏里演示的,当焦点切换到 Safari 后,Chrome 中打开的 PiP 窗口仍然是在最上层的。

另外一个没有在录屏里体现出来的交互是,“同一时刻只能有一个 PiP 窗口”。同一个页面里如果为多个视频开启画中画模式,前面开启的那个会自动退出画中画模式,同一个浏览器窗口下的多个 Tab 里的视频亦如此,同一个浏览器打开的多个浏览器窗口亦如此(在本文撰稿时,Chrome 还没有实现最后一种情况,即多个浏览器窗口可以同时开启多个 PiP 窗口,已确认是 bug 不是 feature)。

PiP 相关 API

1. video 元素新增的方法 requestPictureInPicture()

请求让该 video 元素进入画中画模式,返回一个 promise,如果没有异常,这个 promise 包的值会是一个 PictureInPictureWindow对象,这个对象就代表弹出的那个 PiP 窗口,后面会单独讲它的 API。


async function openPiP(video) {
  try {
    const pipWindow = await video.requestPictureInPicture() // 进入画中画模式
    ...
  } catch (e) {
    console.error(e) // 处理异常
  }
})

哪些情况下进入画中画模式会失败?一共有 5 种情况:

  1. 操作系统不支持、或者用户通过浏览器选项禁用了此功能,此时 document.pictureInPictureEnabled 属性会返回 false
  2. 视频文件错误、或者没有视频流只有音频流
  3. 此次请求不是由用户操作触发的,比如用户没有点击任何按钮,页面自动执行该方法,会被当做恶意行为拦截掉
  4. 当前页面通过 feature-policy 禁用了画中画特性,此时 document.pictureInPictureEnabled属性也会返回 false
  5. 当前 video 元素通过 disablePictureInPicture 属性(HTML 属性和 DOM 属性均可)禁用了画中画特性

2. video 元素新增的属性 disablePictureInPicture

通过该属性可以禁用 video 元素的画中画特性,右键菜单中的“画中画”选项会被禁用。

通过 HTML 属性:

<video src="..." disablePictureInPicture>

通过 DOM 属性:

video.disablePictureInPicture = true

3. video 元素新增的事件 enterpictureinpicture 和 leavepictureinpicture


video.addEventListener('enterpictureinpicture', function(pipWindow) {
  // 进入了画中画模式,可以拿到 pipWindow 对象
})

video.addEventListener('leavepictureinpicture', function() {
  // 退出了画中画模式
})

4. document 上新增的方法 exitPictureInPicture()

因为一个页面只能打开一个 PiP 窗口,所以让 video 元素退出画中画模式的方法不在 video 元素自己身上,而在 document 上。

这个方法也返回一个 promise,不过 promise 包的值是个 undefined

5. document 上新增的属性 pictureInPictureElement和 pictureInPictureEnabled

类似于document.pointerLockElement和 document.fullscreenElement, document.pictureInPictureElement 会返回当前页面中处于画中画模式的 video 元素,如果没有的话,返回 null

document.pictureInPictureEnabled上面已经提到过了,在当前页面不支持或被禁用画中画模式的情况下会返回 false,否则返回 true

这两个属性都是只读的。

6. PictureInPictureWindow对象的 API

requestPictureInPicture()方法的返回值和 enterpictureinpicture事件的回调参数中可以拿到 pipWindow 对象,该对象有两个属性 widthheight,还支持一个resize事件,在用户改变 PiP 窗口大小时会触发。


async function openPiP(video) {
  const pipWindow = await video.requestPictureInPicture()
  console.log(pipWindow.width, pipWindow.height) // 打印了默认的窗口大小

  pipWindow.addEventListener('resize', function() {
    console.log(pipWindow.width, pipWindow.height) // 用户改变 PiP 窗口大小时触发
  })
}

注意这里的 widthheight是只读的,你不能通过给他们赋值来改变窗口大小。

杂项

1. Safari 中已有的画中画 API

Safari 在两年前就支持了画中画模式,还有一套带前缀的配套 API,叫 Presentation Mode。好消息是这个新规范也有 Safari 的人参与了制定,事实上目前为止四大浏览器厂商只剩 Edge 还没表示支持。

2. 画中画这个名字的由来

“画中画”这东西是十几年前电视机上的一个功能,我自己去年看到这个规范的时候也觉的它这个名字比较误导人,现在规范 issue 里也有个人在问,希望你没把它理解成是嵌套的 <img>

3. Chrome 哪个版本支持

现在的 Chrome Canary(69)还没有默认打开这个特性,需要你手动开启

chrome://flags/#enable-experimental-web-platform-features

chrome://flags/#disable-background-video-track

chrome://flags/#enable-picture-in-picture

这三个开关,不用 Canary 的同学老实等两个月。

4. 可不可能弹出 video 以外的元素

规范制定者表示未来有可能


原文发布时间为:2018年06月21日
原文作者: 掘金

本文来源: 掘金 如需转载请联系原作者

相关文章
|
8月前
|
Web App开发 Windows
让网页自动调用双核浏览器的极速模式
让网页自动调用双核浏览器的极速模式
67 0
|
2月前
|
XML JSON 安全
借助API接口实现自营商城上货采集,无货源模式采集商品
在无货源模式的自营商城中,通过API接口实现商品采集是一个高效且灵活的方式。这种方式允许商家直接从供应商或其他电商平台的API接口中获取商品信息,然后将这些信息导入到自己的商城中,无需自己拥有实际的库存。
|
2月前
|
Web App开发 数据可视化 测试技术
Selenium Headless模式:无头浏览器的使用与优势
Selenium Headless模式是无界面的自动化测试方式,适用于Chrome和Firefox等浏览器,提供更快的速度、更高的隐秘性和资源节省。在Python中启用该模式,需导入Options并设置相关参数。示例代码展示了如何在无头模式下访问网站、执行点击和输入操作。这种模式提升了测试效率和稳定性,尤其适合大规模测试和CI环境。
47 1
|
2月前
|
缓存 中间件 API
|
8月前
|
API
api一键自动合约跟单模式 | 程序化交易系统开发讲解【附样板源码实例分析】
“量化交易”有着两层含义:一是从狭义上来讲,是指量化交易的内容,将交易条件转变成为程序,自动下单;二是从广义上来讲,是指系统交易方法,就是一个整合的交易系统。
|
4月前
|
JavaScript 前端开发 API
探索前端BOM API:解锁浏览器的潜力
探索前端BOM API:解锁浏览器的潜力
46 0
|
4月前
|
API Windows
介绍一款API浏览器--Dash
介绍一款API浏览器--Dash
35 0
|
5月前
|
Web App开发 Windows
Windows【Chrome浏览器 02】Auto Dark Mode for Web Contents 无需安装插件开启chrome浏览器黑暗模式
Windows【Chrome浏览器 02】Auto Dark Mode for Web Contents 无需安装插件开启chrome浏览器黑暗模式
78 0
|
5月前
|
JavaScript
sgSpeedMode.js判断360浏览器是“兼容模式”,提示使用“极速模式”
sgSpeedMode.js判断360浏览器是“兼容模式”,提示使用“极速模式”
|
5月前
|
Web App开发 前端开发 安全
File System Access API 让浏览器拥有操作本地文件的能力
File System Access API 让浏览器拥有操作本地文件的能力
93 0