做者:杰里米
阅读时间:5~10minjavascript
以前在腾讯视频刷剧时,偶然看到有一个画中画的功能很是好用,不懂就问:什么是“画中画”?提及画中画,就不得不提起咱们常常干的一件事儿,咱们想在PC浏览器上看电视的同时逛淘宝、刷微博、玩知乎...... 只有你想不到的,没有我玩不顺的!奈何咱们只有一块屏幕(ps: 用扩展屏的大佬打扰了),这个时候就须要一个辅助英雄——画中画,来提升咱们桌面利用率并提升时间效率。java
首先请容许我介绍下“画中画”:画中画(英文Picture-in-picture,缩写PiP)是指将一个电视节目(或其余画面)显示在整个画面上,同时将另外一个或多个其余画面显示在角落中,一般只播放主窗口的声音 —— from wikigit
早在1976年蒙特利尔奥运会的电视报道中就出现了近似的画中画效果,其使用Quantel数字帧存储设备在开幕式期间插入奥林匹克圣火的特写照片。github
随着咱们平常社交生活的丰富,咱们但愿在浏览器上也用到画中画的功能。web
近两年,浏览器厂商开始陆续支持画中画的功能,咱们先来看下浏览器中画中画的效果:chrome
下面介绍目前主流浏览器上画中画的实现状态canvas
详情请查看Implementation Statuspromise
早在2016年9月,Safari经过macOS Sierra中的WebKit API添加了Picture-in-Picture支持。相比chrome,safari在自带的播放控件内加入了画中画模式的按钮。浏览器
2017年4月,Chrome经过使用原生Android API发布Android O,能够自动在移动设备上播放画中画视频。 2018年10月,Chrome在PC 客户端69版本加入画中画的特性,但在该版本中画中画是默认关闭的,若是想开启该特性,须要在浏览器执行如下操做:bash
chrome://flags
并按下回车键enable-experimental-web-platform-features
(启用正在开发的实验性Web平台功能)、enable-Surfaces-for-videos
(启用合成到Surface而不是视频的VideoLayer)、enable-picture-in-picture
(为video开启画中画特性)并将选项值置为Enabled
。到了70版本已默认开启该特性,安装chrome扩展插件可进入画中画,进入画中画后,页面选项卡会出现一个蓝色的图标,以提醒用户该页面正在播放视频。
Chrome 71中的画中画支持播放MediaStream对象的视频(例如getUserMedia(),getDisplayMedia(),canvas.captureStream())。这意味着能够显示包含用户网络摄像头视频流的画中画窗口,便可以 显示webRTC的视频流。
目前Firefox的画中画功能还在测试之中,须要Firefox超前测试版Nightly才能开启画中画模式,具体步骤以下:
about:config
设置页media.videocontrols.picture-in-picture.enabled
点击切换,让其置为true
须要注意的是,Chrome 与 Firefox 的画中画模式略有不一样,Chrome 开启画中画后,浏览器内的视频将再也不播放,而 Firefox 则至关于启用了双屏播放,画中画和原标签页同步播放,并且目前的画中画功能甚至没有关闭画中画视频的选项,所以必须再次鼠标右键单击才能关闭画中画功能。
对于开发者而言,让用户体验到画中画模式带来的效果是最使人兴奋的,感谢浏览器爸爸提供了相应的API供咱们开发者调用。因为safari实现的时间太早,而谷歌又用本身的一套API,致使API目前还没有标准化(好消息是画中画Web API的规范 已经在WICG草案阶段中了,大致上和chrome的API规范一致,具体可猛戳此处),我将对目前已支持的浏览器(chrome和safari)分别介绍其Web API:
先来看一个示例(示例中的视频源来自腾讯):
咱们来看上述示例中用到的属性和方法:
该属性用来判断当前文档是否支持使用画中画所示的功能。(不能理解为浏览器是否支持,由于即使浏览器支持的状况下,用户禁用画中画功能也会返回false)
该属性返回当前文档内存在的画中画元素对象,若是不存在返回null,不然返回video element
这个API是真正去请求视频进入画中画模式的,结果会返回一个promise,在promise成功回调中拿到一个pipWindow对象,这个对象包含:
{ width, height, resize }
复制代码
width和height分别是视频进入画中画窗口的宽高,resize能够监听一个事件回调,在画中画窗口发生变化时触发。
① 为什么API挂载到video上而不是document上?
由于一个页面可能会存在多个video,因此须要指定触发画中画的video元素。
② 那么什么状况下API会调用失败?
disablePictureInPicture
新属性mouseover
、mouseenter
、mousemove
、mouseleave
、scroll
、onload
等事件都不算用户手势事件。当咱们想主动退出画中画,能够调用这个API,其结果也会返回一个promise。
① 为什么API挂载到document而不是video上?
由于目前一个页面最多仅容许一个video显示在画中画窗口上。对于开发者而言,不须要退出画中画的是哪一个video,所以只须要挂载到document上就能够了。
当咱们想监听video是否真正进入/退出画中画时,有时候进入/退出画中画并非咱们经过调用requestPictureInPicture/exitPictureInPicture来触发的,好比用户经过chrome插件让视频进入画中画,这个时候须要监听这两个事件,来获取一些有用的信息并进行上报之类的行为。
因为safari早在2016年就原生支持了画中画,所以API和chrome是彻底不一致的。在safari里咱们能够把“画中画”理解为播放模式的概念,safari中的播放模式只有三种,分别是inline
、picture-in-picture
、fullscreen
。
咱们先来看一个简单的示例:
从上面示例能够看出,画中画相关属性和方法都是挂载到具体的视频元素上。
咱们来看上述示例中用到的属性和方法:
该方法是检测video元素所支持的“演示模式”(通常理解为播放模式),这里传参mode支持三个有效值:picture-in-picture
、inline
、fullscreen
。
通常有两种方式来判断是否支持画中画。第一种就是上述示例所介绍的,第二种即:
let supportsPiP = false;
try {
supportsPiP = video.webkitSupportsPresentationMode('picture-in-picture');
} catch(e) {
supportsPiP = false;
}
复制代码
若是webkitSupportsPresentationMode传入无效值,会抛出error,以下所示:
这个属性值返回的其实就是上面播放模式的三个有效值之一。能够用该属性判断当前video所处的模式是否为画中画。
这个方法能够设置当前模式,当mode='picture-in-picture',就等效于chrome中的video.requestPictureInPicture()。当mode='inline',就等效于chrome中的document.exitPictureInPicture()。须要注意的是,在safari里调用此方法进入/退出画中画,都没有返回值,固然也不会报错。
当前播放模式发生变化时能够经过这个事件监听,不管是进入/退出画中画,都会触发此事件的监听回调。须要注意的是这里不会返回画中画窗口下的对象信息(包括窗口width、height等)
不管在safari/chrome,若是画中画内播放的是实时音视频流,浏览器会在退出画中画时暂停掉视频的播放,须要在退出画中画后手动触发视频流继续播放。
根据目前画中画的支持状况,这里有一个画中画polyfill库能够兼容到chrome和safari
在WICG Picture-in-Picture草案中提到了自动画中画的特性:
“ 某些页面的video元素想要自动进入/退出画中画,例如,当用户在Web应用程序与其余应用tab之间来回切换时,视频Web应用程序将受益于一些自动画中画行为。但很遗憾,用户手势目前是作不到的,因此就须要Auto Picture-in-Picture了!”
咱们只须要给video元素加入一个新属性autopictureinpicture
:
<video autopictureinpicture></video>
复制代码
这意味着不须要开发者手动调用方法来执行画中画的行为,当页面文档隐藏时,最近设置了autopictureinpicture属性的video元素就会自动进入Picture-in-Picture(若是容许画中画的话),当页面文档可见时,画中画中的视频元素会自动离开。
让 Chrome 与 Firefox 实现系统级视频画中画效果
developers.google.com/web/updates…
关注【IVWEB社区】公众号获取每周最新文章,通往人生之巅!