Skip to main content
Version: 6.0

Document Picture-in-Picture

The Document Picture-in-Picture (Document PiP) API lets you move the entire call UI into a separate browser window that always stays on top of other windows. The application can render custom HTML in the PiP window with multiple video elements and controls arranged in the desired layout, allowing users to keep the call UI visible while working in another tab or window.

Supported call typeMinimum SDK version
1-to-1 call, group call (conference)WebPlanetKit 6.0

Overview

WebPlanetKit opens the Document PiP window and provides an empty container element inside it. Drawing the call UI (video elements, control elements, and layout) inside this container is the responsibility of the application.

Check browser support

The Document PiP API is only available on Chromium-based desktop browsers such as Chrome and Edge. Therefore, before exposing a PiP entry point in your UI, you must check whether the current browser supports it.

To check whether the current browser supports the Document PiP API, call the static method isDocumentPipSupported(). You can use it without creating a Call or Conference object, and you can call it before starting a call. Call.isDocumentPipSupported() and Conference.isDocumentPipSupported() always return the same value.

Use Document PiP

Open a Document PiP window

Calling openDocumentPip(options) opens a PiP window. This method returns a DocumentPipResult that contains the newly opened PiP window and the empty container element created inside it. The application draws the call UI directly inside this container. The same DocumentPipResult is also passed to the evtPipOpened event. You can use the return value (Promise) of openDocumentPip() with await, or receive it in the evtPipOpened event. Choose whichever is more convenient for your application.

Field of DocumentPipOptionsTypeDescription
widthnumber(Optional) The initial width of the PiP window in pixels.
heightnumber(Optional) The initial height of the PiP window in pixels.
disallowReturnToOpenerboolean(Optional) If true, hides the control element for returning from the PiP window to the original tab.
preferInitialWindowPlacementboolean(Optional) If true, does not remember the position of the previously opened PiP window and positions it fresh from the default location.
Field of DocumentPipResultTypeDescription
pipWindowWindowThe separate browser window where the PiP is rendered.
containerHTMLDivElementThe empty container element created inside pipWindow, where you draw the video and UI.
Note
  • openDocumentPip() cannot be called before a call starts. You must start a call first; after calling one of makeCall(), verifyCall(), or joinConference(), you can open a PiP window in any call state.
  • Only one Document PiP window can exist per page. If you call openDocumentPip() while another instance already has a PiP window, the browser rejects the request.

Close a Document PiP window

The PiP window closes automatically when the user closes it directly, the call ends, or the connection is lost. In these cases, the browser or SDK handles the cleanup, so the application does not need to perform any additional action.

To close the PiP window explicitly from the application, call closeDocumentPip(). This triggers the evtPipClosed event. If you call it when there is no open PiP window, nothing happens, the method returns normally, and evtPipClosed is not triggered.

Handle when a Document PiP window opens or closes

If the application has logic to run when the PiP window opens or closes, register evtPipOpened and evtPipClosed on the call delegate. evtPipOpened receives the same DocumentPipResult that openDocumentPip() returns. Through the evtPipClosed event, you can check why the PiP window was closed, and a DocumentPipClosedInfo is passed.

Value of DocumentPipClosedInfo.reasonMeaning
'user'The user closed the PiP window.
'disconnect'The call ended or the connection was lost.
'api'The application called closeDocumentPip().

Get the current Document PiP window and container

When you want to obtain the Window or container element of the currently open PiP window, use getDocumentPipWindow() and getDocumentPipContainer(). If there is no open PiP window, both methods return null.

Example: Implement automatic Document PiP when switching tabs

Chromium-based browsers (Chrome 120 and later) have a feature that automatically opens a PiP window when the user switches to another tab or minimizes the window from a tab where a call is in progress. When the application registers a handler for the browser's enterpictureinpicture action, Chrome calls this handler whenever the user leaves the tab. Calling openDocumentPip() inside the handler opens a PiP window. When the user returns to the original tab, Chrome closes the PiP window for you, so the application does not need to manage opening and closing the window every time.

Note
  • Automatic PiP (auto-PiP) cannot be used in a call that uses neither the microphone nor the camera.
  • The enterpictureinpicture action and the Document PiP API are only available on Chromium-based browsers (Chrome 120 and later).

How to implement

The following code shows the entire flow: checking browser support, registering the action handler, drawing the local user's video when the PiP window opens, and cleaning up the handler when the call ends.

if (!PlanetKit.Call.isDocumentPipSupported()) {
// Unsupported browser.
return;
}

// When the user leaves the tab, Chrome calls this handler, which opens the PiP window.
navigator.mediaSession.setActionHandler('enterpictureinpicture', () => {
planetKit.openDocumentPip({ width: 480, height: 360 });
});

planetKit.makeCall({
...,
delegate: {
evtPipOpened: ({ pipWindow, container }) => {
// Draw the local user's video in the container inside the PiP window.
const video = pipWindow.document.createElement('video');
video.srcObject = planetKit.getMyMediaStream();
container.appendChild(video);
video.play();
},
evtDisconnected: () => {
// When the call ends, clean up the registered action handler.
navigator.mediaSession.setActionHandler('enterpictureinpicture', null);
}
}
});

Conditions for automatic PiP to work

For Chrome to call the enterpictureinpicture action, both of the following conditions must be met.

  1. The application must register the enterpictureinpicture action handler in advance.
  2. At the moment the user leaves the tab, that tab must actually be using the microphone or camera. Here, "in use" means that the browser has actually opened the microphone and camera streams, so the microphone and camera usage indicator is lit next to the browser tab or address bar.

Let's look at a few things to keep in mind regarding the second condition above.

First, to avoid requesting permission that the user does not immediately need, WebPlanetKit does not access the microphone and camera at the start of a call in the following two cases.

  • An audio call started with micOn: false
  • A video call started with micOn: false and cameraOn: false

Therefore, if you start a call in either of the two cases above, the browser does not recognize that the microphone and camera are in use, so the enterpictureinpicture action does not occur, and as a result automatic PiP does not work. In other cases, that is, when you start a call actually using either the microphone or the camera, the SDK opens the corresponding media stream, so automatic PiP works normally.

Second, when you mute or pause during a call, the microphone and camera behave differently.

  • Microphone: Muting the microphone only temporarily blocks the data flow, so even when muted, the SDK does not close the microphone stream and keeps it as is. Therefore, in a call where the microphone was turned on at least once at the start, automatic PiP keeps working even after switching to the background in a muted state.
  • Camera: When you pause, the SDK completely closes the camera stream to turn off the camera LED. Therefore, if you turned the camera on and then paused it and the microphone is not in use, automatic PiP does not work.

Third, when you create a media stream through MediaStreamManager and use it for a call, MediaStreamManager opens the microphone and camera streams internally, so automatic PiP works regardless of the micOn or cameraOn values.

The APIs related to Document PiP are as follows.

Common

1-to-1 call

Group call