Understanding the Picture-in-Picture web API with examples

JavaScript Web APIs provide many helpful features. The picture-in-Picture feature is one you should know to use and control videos in better ways.

Featured on Hashnode

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

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 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 to enable it in the chrome browser. Once enabled, you can see it appearing beside the browser's address bar.

image.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 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.

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,

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,

<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.

<button 
   id="actionBtnId" 
   class="action" 
   onclick="toggle()" 
   disabled>
     Enter Picture-in-Picture mode
</button>

In the JavaScript, we will define the toggle() function as,

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.

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

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.

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.

     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.

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

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.

: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,

<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.

 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.

 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 ğŸž.


That's all for now. If you enjoyed this article or found it helpful, let's connect. You can find me on Twitter(@tapasadhikary) sharing thoughts, tips, and code practices. Please hit the Subscribe button at the top of the page to get an email notification on my latest posts.

You may also like,

Interested in reading more such articles from Tapas Adhikary?

Support the author by donating an amount of your choice.

Recent sponsors
Victoria Lo's photo

Another amazing article Tapas! I love it ❤️❤️

Tapas Adhikary's photo

Thank you very much, Victoria.

Edidiong Asikpo's photo

I really love the picture-in-picture feature. Thanks for sharing a detailed guide about it with examples, Tapas Adhikary.

Pratik Sharma's photo

Nice introduction to picture-in-picture api. Same feature with the Hashnode audio/podcast embed would be great.

Tapas Adhikary's photo

Super Idea Pratik Sharma. I'll try doing a codepen with audio soon Pratik Sharma

Yogesh Chavan's photo

Awesome. Loved it.❤️

Tapas Adhikary's photo

Thanks Yogesh Chavan. Glad you liked it.

Gerardo Cardenas's photo

I can not find the bug. Where is it?