[Proposal] Document Picture-in-Picture

Summary

There currently exists a Web API for putting an HTMLVideoElement into a Picture-in-Picture window (HTMLVideoElement.requestPictureInPicture()). If a website wants to have something as simple as custom media controls icons or as complex as a full scrollable playlist in the PiP window, they can’t currently provide it in the existing HTMLVideoElement experience.

We want to expand upon that functionality with a new method on the Window object (window.requestPictureInPictureWindow()) which opens a picture-in-picture (i.e. always-on-top) window with a blank document that can be populated with arbitrary HTMLElements instead of only a single HTMLVideoElement.

Example code

HTML

<body>
  <div id="player-container">
    <div id="player">
      <video id="video" src="foo.webm"></video>
      <!-- more player elements here -->
    </div>
  </div>
  <input type="button" onclick="enterPiP();" value="Enter PiP" />
</body>

JavaScript

// Handle to the picture-in-picture window.
let pipWindow = null;

function enterPiP() {
  const player = document.getElementById('player');
  let pipOptions = { width: player.clientWidth, height: player.clientHeight,
                     constrainAspectRatio: true };
  window.requestPictureInPictureWindow(pipOptions).then(pipWin => {
    pipWindow = pipWin;

    // Style remaining container to imply the player is in PiP.
    playerContainer.classList.add('pip-mode');

    // Add styles to the PiP window.
    const styleLink = document.createElement('link');
    styleLink.href = 'pip.css';
    styleLink.rel = 'stylesheet';
    styleLink.type = 'text/css';
    pipWindow.document.body.appendChild(styleLink);

    // Add player to the PiP window.
    pipWindow.document.body.appendChild(player);

    // Listen for the PiP closing event to put the video back.
    window.addEventListener('exitpictureinpicture', onExitPiP,
        { once: true });
  });
}

// Called when the PiP window has closed.
function onExitPiP(event) {
    // Remove pip styling from the container.
    const playerContainer = document.getElementById('player-container');
    playerContainer.classList.remove('pip-mode');

    // Add the player back to the main window.
    const player = event.pictureInPictureWindow.document
                        .getElementById('player');
    playerContainer.appendChild(player);

    pipWindow = null;
}

This looks like it might be good for using with canvas. Perhaps small web games could go in PiP windows!

Also see Picture-in-Picture for arbitrary content - Chrome Platform Status where this has been proposed before.

Very happy to see this, we are interested in using this for video with custom player controls and caption rendering for accessibility. See also discussion in Picture-in-Picture for any Element · Issue #113 · w3c/picture-in-picture · GitHub