Picture In Picture

Editor’s Draft,

This version:
https://wicg.github.io/picture-in-picture
Issue Tracking:
GitHub
Editors:
(Google)
(Google)

Abstract

This specification intends to provide APIs to allow websites to create a floating video window over other windows so that users may continue consuming media while they interact with other content, sites, or applications on their device.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction

This section is non-normative.

Many users want to continue consuming media while they interact with other content, sites, or applications on their device. A common UI affordance for this type of activity is Picture in Picture (PiP), where the video is contained in a separate miniature window that is viewable above all other activities. Picture In Picture is a common platform-level feature among desktop and mobile OSs.

This specification aims to allow websites to initiate and control this behavior by exposing the following sets of properties to the API:

The proposed Picture In Picture API is very similar to [Fullscreen] as they have similar properties. The API only applies on HTMLVideoElement at the moment but is meant to be extensible.

2. Examples

2.1. Add a custom picture in picture button

<video id="video" src="https://example.com/file.mp4"></video>

<button id="pipButton"></button>

<script>
  // Hide button if Picture In Picture is not supported.
  pipButton.hidden = !document.pictureInPictureEnabled;

  pipButton.addEventListener('click', function() {
    // If there is no element in Picture In Picture yet, let’s request Picture
    // In Picture for the video, otherwise leave it.
    if (!document.pictureInPictureElement) {
      video.requestPictureInPicture()
      .catch(error => {
        // Video failed to enter Picture In Picture mode.
      });
    } else {
      document.exitPictureInPicture()
      .catch(error => {
        // Video failed to leave Picture In Picture mode.
      });
    }
  });
</script>

2.2. Monitor video picture in picture changes

<video id="video" src="https://example.com/file.mp4"></video>

<script>
  video.addEventListener('enterpictureinpicture', function() {
    // Video entered Picture In Picture mode.
  });

  video.addEventListener('leavepictureinpicture', function() {
    // Video left Picture In Picture mode.
  });
</script>

3. Concepts

3.1. Request picture in picture

When the request picture in picture algorithm with video and options is invoked, the user agent MUST run the following steps:

  1. If the algorithm is not triggered by user activation, throw a SecurityError and abort these steps.

  2. Let pipWindow be the Picture In Picture window that consistently stays above most other windows.

  3. Let pipVideo be the video contained in the pipWindow.

  4. If a pipWindow is not already created, create one.

  5. If one can’t be created, throw a UnknownError and abort these steps.

  6. Apply options width, height, top, and start to the pipWindow dimensions and position. If some options can’t be applied, it SHOULD apply latest ones that were successfully set if any.

  7. Render video frames in the pipVideo.

It is RECOMMENDED that the video frames are not rendered in the page and in the pipVideo at the same time but if they are, they MUST be kept in sync.

When a video is played in Picture in Picture, the states SHOULD transition as if it was played inline. That means that the events SHOULD fire at the same time, calling methods SHOULD have the same behaviour, etc. However, the user agent MAY transition out of Picture in Picture when the video element enters a state that is considered not compatible with Picture in Picture.

3.2. Exit picture in picture

When the exit picture in picture algorithm is invoked, the user agent MUST run the following steps:

  1. Let pipWindow be the current Picture In Picture window.

  2. Let pipVideo be the video contained in the pipWindow.

  3. Let video be the source video of pipVideo frames.

  4. Close pipWindow.

  5. If pipWindow can’t be closed, throw a UnknownError and abort these steps.

  6. Render pipVideo frames in the video.

3.3. Interaction with Remote Playback

The [Remote-Playback] specification defines a local playback device and a local playback state. For the purpose of Picture in Picture, the playback is local and regardless of whether it is played in page or in Picture in Picture.

3.4. One Picture in Picture window

Operating systems with a Picture In Picture API usually restricts Picture In Picture to only one window. Whether only one window is allowed in Picture In Picture will be left to the implementation and the platform. However, because of the one Picture In Picture window limitation, the specification assumes that a given Document can only have one Picture In Picture window.

What happens when there is a Picture In Picture request while a window is already in Picture In Picture will be left as an implementation details: the current Picture In Picture window could be closed, the Picture In Picture request could be rejected or even two Picture In Picture windows can be created. Regardless, the User Agent will have to fire the appropriate events in order to notify the website of the Picture In Picture status changes.

4. API

4.1. Extensions to HTMLVideoElement

dictionary PictureInPictureOptions {
    unsigned long width;
    unsigned long height;
    unsigned long top;
    unsigned long start;
};
partial interface HTMLVideoElement {
    Promise<void> requestPictureInPicture(optional PictureInPictureOptions options);

    attribute EventHandler onenterpictureinpicture;
    attribute EventHandler onleavepictureinpicture;
};

The requestPictureInPicture() method, when invoked, MUST return a new promise promise and run the following steps in parallel:

  1. If pictureInPictureEnabled is false, reject promise with a NotSupportedError and abort these steps.

  2. If options is not valid, reject promise with a TypeError and abort these steps.

  3. Let video be the requested video.

  4. Run the request picture in picture algorithm with video and options.

  5. If the previous step threw an exception, reject promise with that exception and abort these steps.

  6. Set pictureInPictureElement to video.

  7. Queue a task to fire a simple event with the name enterpictureinpicture at the video. The event MUST not bubble, MUST not be cancelable, and has no default action.

  8. Return promise.

4.2. Extensions to Document

partial interface Document {
  readonly attribute boolean pictureInPictureEnabled;

  Promise<void> exitPictureInPicture();
};

The pictureInPictureEnabled attribute’s getter must return true if the context object is allowed to use the feature indicated by attribute name allowpictureinpicture and Picture In Picture is supported, and false otherwise.

Picture In Picture is supported if there is no previously-established user preference, security risk, or platform limitation.

The exitPictureInPicture() method, when invoked, MUST return a new promise promise and run the following steps in parallel:

  1. If pictureInPictureEnabled is false, reject promise with a NotSupportedError and abort these steps.

  2. Run the exit picture in picture algorithm.

  3. If the previous step threw an exception, reject promise with that exception and abort these steps.

  4. Unset pictureInPictureElement.

  5. Queue a task to fire a simple event with the name leavepictureinpicture at the video. The event MUST not bubble, MUST not be cancelable, and has no default action.

  6. Return promise.

4.3. Extension to DocumentOrShadowRoot

partial interface DocumentOrShadowRoot {
  readonly attribute Element? pictureInPictureElement;
};

The pictureInPictureElement attribute’s getter must run these steps:

  1. If the context object is a shadow root and its host is not connected, then return null.

  2. Return the picture in picture element

4.4. Event types

enterpictureinpicture

Fired on a HTMLVideoElement when it enters Picture In Picture.

leavepictureinpicture

Fired on a HTMLVideoElement when it leaves Picture In Picture.

5. Security considerations

5.1. Feature Policy

This specification defines a feature that controls whether pictureInPictureEnabled is true or false.

The feature name for this feature is "picture-in-picture".

The default allowlist for this feature is ["self"].

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[PROMISES-GUIDE]
Domenic Denicola. Writing Promise-Using Specifications. 16 February 2016. Finding of the W3C TAG. URL: https://www.w3.org/2001/tag/doc/promises-guide
[Remote-Playback]
Anton Vayvod; Mounir Lamouri. Remote Playback API. URL: https://www.w3.org/TR/remote-playback/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WebIDL]
Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. URL: https://heycam.github.io/webidl/

Informative References

[Fullscreen]
Anne van Kesteren. Fullscreen API Standard. Living Standard. URL: https://fullscreen.spec.whatwg.org/

IDL Index

dictionary PictureInPictureOptions {
    unsigned long width;
    unsigned long height;
    unsigned long top;
    unsigned long start;
};

partial interface HTMLVideoElement {
    Promise<void> requestPictureInPicture(optional PictureInPictureOptions options);

    attribute EventHandler onenterpictureinpicture;
    attribute EventHandler onleavepictureinpicture;
};

partial interface Document {
  readonly attribute boolean pictureInPictureEnabled;

  Promise<void> exitPictureInPicture();
};

partial interface DocumentOrShadowRoot {
  readonly attribute Element? pictureInPictureElement;
};