Signatur
Beschreibung
Mit requestPictureInPicture() wird ein <video>-Element aus der Seite gelöst und in einem kleinen, immer im Vordergrund liegenden Fenster abgespielt. So können Nutzer ein Video weiterschauen, während sie in anderen Tabs oder Anwendungen arbeiten – typisch für Videoplattformen, Webinare, Videokonferenzen oder Tutorials.
Die Methode gibt ein Promise zurück, das mit einem PictureInPictureWindow-Objekt erfüllt wird. Über dessen Eigenschaften width und height sowie das Ereignis resize lässt sich auf die Größe des Fensters reagieren. Am Element selbst werden die Ereignisse enterpictureinpicture und leavepictureinpicture ausgelöst; das aktuell schwebende Element steht in document.pictureInPictureElement.
Der Aufruf erfordert eine transiente Nutzeraktivierung (z. B. innerhalb eines click-Handlers). Vorher sollte man mit document.pictureInPictureEnabled prüfen, ob die Funktion verfügbar ist, und das Attribut disablePictureInPicture des Videos beachten. Beendet wird der Modus mit document.exitPictureInPicture().
Rückgabewert
PictureInPictureWindow erfüllt wird, sobald das Video im Bild-in-Bild-Modus ist. Es wird mit einer DOMException abgelehnt, wenn die Anfrage nicht erfüllt werden kann.Beispiele
Bild-in-Bild per Button umschalten
const video = document.querySelector('#player');
const button = document.querySelector('#pip-button');
// Button nur anzeigen, wenn PiP möglich ist
button.hidden = !document.pictureInPictureEnabled || video.disablePictureInPicture;
button.addEventListener('click', async () => {
try {
if (document.pictureInPictureElement === video) {
await document.exitPictureInPicture();
} else {
const pipWindow = await video.requestPictureInPicture();
console.log(`PiP-Fenster: ${pipWindow.width}×${pipWindow.height}`);
}
} catch (err) {
console.error('Bild-in-Bild fehlgeschlagen:', err.name, err.message);
}
});
Auf Ein-/Austritt und Größenänderung reagieren
const video = document.querySelector('video');
video.addEventListener('enterpictureinpicture', (event) => {
const pipWindow = event.pictureInPictureWindow;
document.body.classList.add('pip-aktiv');
const onResize = () => console.log('Neue Größe:', pipWindow.width, pipWindow.height);
pipWindow.addEventListener('resize', onResize);
video.addEventListener('leavepictureinpicture', () => {
pipWindow.removeEventListener('resize', onResize);
document.body.classList.remove('pip-aktiv');
console.log('Bild-in-Bild beendet');
}, { once: true });
});
Beim Tab-Wechsel automatisch in PiP (nur mit vorheriger Nutzeraktion)
const video = document.querySelector('video');
// Nutzer startet das Video per Klick – dadurch ist PiP im selben Handler erlaubt
document.querySelector('#play').addEventListener('click', async () => {
await video.play();
if (document.pictureInPictureEnabled && !document.pictureInPictureElement) {
await video.requestPictureInPicture().catch((err) => {
console.warn('PiP nicht möglich:', err.name);
});
}
});
// Wichtig · Fallstricke
- Nutzeraktivierung erforderlich: Ohne vorhergehende Nutzeraktion (Klick, Tastendruck) wird das Promise mit
NotAllowedErrorabgelehnt. Einawaitvor dem Aufruf (z. B. auffetch) kann die Aktivierung verbrauchen bzw. ablaufen lassen. - Weitere Fehler:
NotSupportedError, wenn die Funktion nicht unterstützt oder perdisablePictureInPicturedeaktiviert ist;InvalidStateError, wenn das Video noch keine Metadaten hat (readyState === HAVE_NOTHING) oder keine Videospur besitzt;SecurityError, wenn die Permissions Policypicture-in-pictureden Zugriff (z. B. im iframe) verbietet. - Es kann immer nur ein Element gleichzeitig im PiP-Modus sein; ein neuer Aufruf ersetzt das bisherige Element.
- Kompatibilität: Unterstützt in Chromium-Browsern und Safari. Firefox implementiert die API nicht, bietet aber eine eigene PiP-Schaltfläche an – daher stets per Feature-Erkennung (
'pictureInPictureEnabled' in document) prüfen. Safari kennt zusätzlich das älterewebkitSetPresentationMode('picture-in-picture'). - Für beliebige HTML-Inhalte (nicht nur Videos) gibt es die neuere Document Picture-in-Picture API (
documentPictureInPicture.requestWindow()), bislang nur in Chromium.