[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;
}
2 Likes

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

As per the related issue I raised on the github issue tracker, I believe this proposal would enable useful functionality for my end users by facilitating a canvas overlayed atop a video element for displaying supplementary information in the PIP in a manner a simple solution like webvtts would simply be incapable of, such as animated sliding comments a la Nicovideo, or a webassembly of libass rendering SSA formatted subtitles.

I hope this moves forward.

This was extensively discussed at ‘http://github.com/w3c/picture-in-picture/issues/113#issuecomment-1047201076’, so consider observation of some of the useful suggestion that was provided.