Understanding the Picture-in-Picture web API with examples
Tags: javascript, webdev, html, codenewbie
Published: 2021-05-06 07:30:07

`Picture-in-Picture` is a feature supported by some smart televisions, devices to show the content(like videos) on a floating window(on the top of other windows) so that users can continue to see the content while interacting with the background page, other sites.

Have you noticed the mini-player option when you watch a video on Youtube? You can watch the video in the Picture-in-Picture-like mode while interacting with the other part of the application.

> ![youtube_miniplayer.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1620116387067/kqPOw_Eh5.png)
Figure 1: Example of a Youtube video playing in the mini-player

The Google Chrome browser started supporting the `Picture-in-Picture` mode. You can use [this extension](https://chrome.google.com/webstore/detail/picture-in-picture-extens/hkgfoiooedgoejojocmhlaklaeopbecg) to enable it in the chrome browser. Once enabled, you can see it appearing beside the browser's address bar.

> ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1620118256076/21DydHcLg.png)
Figure 2: Picture-In-Picture extension for Chrome browser

For Mozilla Firefox, you may have to enable it from the `about.config` page by setting the `media.videocontrols.picture-in-picture.enabled` property to `true`

> ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1620118477979/V2ZCA3a6u.png)
Figure 3: Enable picture-in-picture in the firefox browser.

# Picture-in-Picture using JavaScript
JavaScript provides you the `Picture-in-Picture` API to create and control the feature programmatically. Here goes the browser support information:
- Google Chrome version >= 70
- Microsoft Edge version >= 79
- Safari version >= 13.1
- Mozilla Firefox: Partial(Conditional) Support

You can find the other browser and device support details [from here](https://caniuse.com/?search=picture-in-picture).

The picture-in-picture API methods are available in the `HTMLVideoElement(<video>)` and `Document` interfaces to allow users to toggle between the standard presentation and picture-in-picture modes.

## Check Browser's Support
We can check the browser's support for this API using the following code,

```js
if (document.pictureInPictureEnabled) {
  // The picture-in-picture feature is supported
} else {
  // Ther is no Support for the picture-in-picture feature
}
```

## Picture-in-Picture Mode: Enter and Exit 
To enter into the `picture-in-picture` mode, you can call the method `requestPictureInPicture()` on the `<video>` element. When you call the method `exitPictureInPicture()` on the `document` object, the video exits from the picture-in-picture mode and enter the standard presentation mode.

Let's add a simple video element in the HTML file,

```html
<video 
   src="path_to_video_file" 
   id="video" muted autoplay loop>
</video>
```
Next, we will add a button to toggle between the modes. Then, finally, add a click handler to call the `toggle()` function.

```html
<button 
   id="actionBtnId" 
   class="action" 
   onclick="toggle()" 
   disabled>
     Enter Picture-in-Picture mode
</button>
```
In the JavaScript, we will define the `toggle()` function as,

```js
function toggle() {
  if (document.pictureInPictureElement) {
      document.exitPictureInPicture();
  } else if (document.pictureInPictureEnabled) {
      video.requestPictureInPicture();
  }
}
```
In the code above, we check if the picture-in-picture feature is enabled. If so, call the `requestPictureInPicture` on the video element to get into the picture-in-picture mode. Once the picture-in-picture mode is enabled, the document object will have the `pictureInPictureElement`. So, when the toggle function gets called next time, it checks the `pictureInPictureElement`. If found, it exits from the picture-in-picture mode.

Here is a `CodePen` to see it as an example. Try clicking on the button below the video and see the video getting into the picture-in-picture mode. Click on the same button again to exit from the mode.

{% codepen https://codepen.io/atapas/pen/abpKaBV %}

> Please note: As explained before, to see the picture-picture feature working in the Mozilla Firefox browser, you have to enable it first. Once enabled, you can right-click on the video and select the option `Watch in Picture-in-Picture`. 
 ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1620127851689/kSZnTAmLW.png)

## Picture-in-Picture API Events
The `Picture-in-Picture` API defines three events.
- `enterpictureinpicture`: Triggers when a video element enters the picture-in-picture mode.
- `leavepictureinpicture`: Triggers when the video element exits the picture-in-picture mode.
- `resize`: Triggers when the picture-in-picture windows resize.

These events can come in handy when you want to perform any custom actions based on a video enters or exit the picture-in-picture mode. Here is an example of changing a button text and color when a video toggles between the modes.

```js
video.addEventListener('enterpictureinpicture', () => {
  actionBtnId.textContent = 'Exit Picture-in-Picture mode';
  actionBtnId.classList.add("redBtn");
});

video.addEventListener('leavepictureinpicture', () => {
  actionBtnId.textContent = 'Enter Picture-in-Picture mode';
  actionBtnId.classList.remove("redBtn");
});
```
You must have noticed it working in the code pen example we have seen above.

## Picture-in-Picture API Properties
The `Picture-in-Picture` API provides properties in multiple JavaScript interfaces like, `HTMLVideoElement(<video>)`, `Document`, and `ShadowRoot`. 

- `pictureInPictureEnabled`: We have seen this property already. It tells us whether or not it is possible to engage in picture-in-picture mode.
 ```js
   if (document.pictureInPictureEnabled) {
      video.requestPictureInPicture();
  }
 ```
`autoPictureInPicture`: It is a video element property that automatically enables a video to get into the picture-in-picture mode and exits when the user switches the tab/application. For example, right-click on the video in the CodePen below and enter into the picture-in-picture mode. Then switch tabs and come back to the same pen to see it exiting automatically.

 {% codepen https://codepen.io/atapas/pen/wvJwWVX %}

- `disablePictureInPicture`: This video element property will disable the picture-in-picture feature. Here is a CodePen to try out this property.

 {% codepen https://codepen.io/atapas/pen/wvgVmxj %}

## How to Control Styling?
The CSS pseudo-class `:picture-in-picture` allows us to adjust the size, style, or layout of content when a video switches back and forth between picture-in-picture and standard modes.

```css
:picture-in-picture {
  box-shadow: 0 0 0 5px #0081ff;
  background-color: #565652;
}
```

## Stream Webcam Capture into the Picture-in-Picture mode
Let us do something a bit more fun now. How about capturing the video using your webcam and show it in the picture-in-picture mode.

First create a video element,

```html
<video id="videostreamId" autoplay="" controls></video>
```
Now we can start the webcam, and once we start receiving the stream, we can pass it to the video element to play it.

```js
 await navigator.mediaDevices.getUserMedia({ video: true })
 .then(stream => {
    window.localStream = stream;
    video.srcObject = stream;
    video.play();
  });
```
Next, we use the `Picture-in-Picture` API method when the video is fully loaded into the video element.

```js
 video.addEventListener('loadedmetadata', () => {
    video.requestPictureInPicture();
  });
```

You can try out the same in the CodePen below.

> Please note: You may have to open the pen in a new tab and see the webcam working. Also, feel free to fork and fix a bug I left unfixed in the code 🐞.

{% codepen https://codepen.io/atapas/pen/abpeYxd %}

<hr />
That's all for now. If you enjoyed this article or found it helpful, let's connect. You can find me on [Twitter(@tapasadhikary)](https://twitter.com/tapasadhikary) sharing thoughts, tips, and code practices.

You may also like,

- [10 lesser-known Web APIs you may want to use](https://blog.greenroots.info/10-lesser-known-web-apis-you-may-want-to-use-ckejv75cr012y70s158n85yhn)
- [10 VS Code emmet tips to make you more productive](https://blog.greenroots.info/10-vs-code-emmet-tips-to-make-you-more-productive-ckknjvxal028f1qs18w20e94t)
- [MDN Picture-in-Picture API](https://developer.mozilla.org/en-US/docs/Web/API/Picture-in-Picture_API)