图片画中画 Web API 简介

Avatar of Ayooluwa Isaiah
Ayooluwa Isaiah 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

图片画中画于 2016 年 macOS Sierra 发布时首次出现在 Safari 浏览器中。它使用户能够将视频弹出到一个小的浮动窗口中,该窗口始终位于其他窗口之上,以便他们在执行其他操作时可以继续观看。这个想法来自电视,例如,您可能希望在浏览节目指南或其他频道时继续观看您喜欢的体育赛事。

不久之后,Android 8.0 发布,其中包含通过原生 API 支持的图片画中画功能。Android 版 Chrome 能够通过此 API 以图片画中画模式播放视频,尽管其桌面版本无法做到这一点。

这导致了 标准图片画中画 Web API 的起草,它使网站能够启动和控制此行为。

在撰写本文时,只有 Chrome(70 版及以上)和 Edge(76 版及以上)支持此功能。Firefox、Safari 和 Opera 都使用专有 API 来实现其功能。

此浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器在该版本及更高版本中支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
701327913.1

移动/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712714.0-14.4

如何使用图片画中画 API

让我们从在网页中添加视频开始。

<video controls src="video.mp4"></video>

在 Chrome 中,已经有一个切换按钮可以进入和退出图片画中画模式。

Showing a video with the picture-in-picture option in the bottom right of the screen.

要测试 Firefox 的实现,您需要先在 about:config 中启用 media.videocontrols.picture-in-picture.enabled 标志,然后右键单击视频以查找图片画中画选项。

Showing the Firefox settings that enable picture-in-picture.
在 Firefox 中启用图片画中画

虽然这可以工作,但在许多情况下,您希望您的视频控件在不同浏览器之间保持一致,并且您可能希望控制哪些视频可以进入图片画中画模式,哪些视频不能。

我们可以使用 图片画中画 Web API 将浏览器中进入图片画中画模式的默认方法替换为我们自己的方法。例如,让我们添加一个按钮,当单击时,启用它

<button id="pipButton" class="hidden" disabled>Enter Picture-in-Picture mode</button>

然后在 JavaScript 中选择视频和按钮

const video = document.getElementById('video');
const pipButton = document.getElementById('pipButton');

默认情况下,按钮是隐藏和禁用的,因为我们需要知道在用户的浏览器中是否支持和启用了图片画中画 API,然后再显示它。这是一种渐进增强形式,有助于避免在不支持此功能的浏览器中出现错误体验。

我们可以检查 API 是否受支持并启用按钮,如下所示

if ('pictureInPictureEnabled' in document) {
  pipButton.classList.remove('hidden')
  pipButton.disabled = false;
}

进入图片画中画模式

假设我们的 JavaScript 确定浏览器启用了图片画中画支持。当单击带有 #pipButton 的按钮时,让我们在视频元素上调用 requestPictureInPicture()。此方法返回一个 Promise,该 Promise 默认情况下将视频放置在屏幕右下角的一个迷你窗口中,尽管用户可以将其移动到其他位置。

if ('pictureInPictureEnabled' in document) {
  pipButton.classList.remove('hidden')
  pipButton.disabled = false;

  pipButton.addEventListener('click', () => {
    video.requestPictureInPicture();
  });
}

我们不能照原样保留上面的代码,因为 requestPictureInPicture() 返回一个 Promise,并且如果例如视频元数据尚未加载或视频上存在 disablePictureInPicture 属性,则该 Promise 可能被拒绝。

让我们添加一个 catch 块来捕获此潜在错误并让用户知道发生了什么

pipButton.addEventListener('click', () => {
  video
    .requestPictureInPicture()
    .catch(error => {
      // Error handling
    });
});

退出图片画中画模式

浏览器会在图片画中画窗口中提供一个关闭按钮,单击该按钮可以关闭窗口。但是,我们也可以提供另一种退出图片画中画模式的方法。例如,我们可以使单击我们的 #pipButton 关闭任何活动的图片画中画窗口。

pipButton.addEventListener('click', () => {
  if (document.pictureInPictureElement) {
    document
      .exitPictureInPicture()
      .catch(error => {
      // Error handling
    })
  } else {
    // Request Picture-in-Picture
  }
});

当视频进入全屏模式时,您可能还需要关闭图片画中画窗口。Chrome 已经自动执行此操作,无需编写任何代码。

图片画中画事件

浏览器允许我们检测视频何时进入或离开图片画中画模式。由于图片画中画模式的进入或退出方式有很多种,因此最好依靠事件检测来更新媒体控件。

这些事件是 enterpictureinpictureleavepictureinpicture,顾名思义,它们分别在视频进入或退出图片画中画模式时触发。

在我们的示例中,我们需要根据视频当前是否处于图片画中画模式来更新 #pipButton 标签。

以下代码可帮助我们实现此目标

video.addEventListener('enterpictureinpicture', () => {
  pipButton.textContent = 'Exit Picture-in-Picture mode';
});

video.addEventListener('leavepictureinpicture', () => {
  pipButton.textContent = 'Enter Picture-in-Picture mode';
});

这是一个演示

自定义图片画中画窗口

浏览器默认情况下会在图片画中画窗口中显示播放/暂停按钮,除非视频正在播放 MediaStream 对象(由虚拟视频源(如摄像头、视频录制设备、屏幕共享服务或其他硬件源)生成)。

还可以添加控件,直接从图片画中画窗口转到上一曲目或下一曲目

navigator.mediaSession.setActionHandler('previoustrack', () => {
  // Go to previous track
});

navigator.mediaSession.setActionHandler('nexttrack', () => {
  // Go to next track
});

在图片画中画窗口中显示网络摄像头画面

视频会议 Web 应用程序可以在用户在应用程序和其他浏览器选项卡或窗口之间切换时,将网络摄像头画面置于图片画中画模式,从而从中受益。

这是一个示例

禁用视频上的图片画中画

如果您不希望视频在图片画中画窗口中弹出,可以向其添加 disablePictureInPicture 属性,如下所示

<video disablePictureInPicture controls src="video.mp4"></video>

总结

目前,这就是您需要了解的关于图片画中画 Web API 的所有内容!目前,该 API 仅支持 <video> 元素,但它也旨在扩展到其他元素。

尽管目前浏览器支持参差不齐,但您仍然可以将其用作逐步增强网站上视频体验的一种方式。

进一步阅读