Start · Sprachen · JavaScript · Referenz · HTMLVideoElement: enterpictureinpicture

HTMLVideoElement: enterpictureinpicture

Ereignis

Wird ausgelöst, sobald ein <code>&lt;video&gt;</code>-Element erfolgreich in den Bild-im-Bild-Modus wechselt. Das Ereignisobjekt ist ein <code>PictureInPictureEvent</code>.

seit JavaScript Chrome 70+, Edge 79+, Safari 13.1+; Firefox: nicht Kategorie: webapi

Signatur

videoElement.addEventListener("enterpictureinpicture", handler)

Beschreibung

Das Ereignis enterpictureinpicture gehört zur Picture-in-Picture-API. Es wird am HTMLVideoElement ausgelöst, sobald das Video tatsächlich im schwebenden Bild-im-Bild-Fenster läuft. Dabei spielt es keine Rolle, ob der Wechsel per video.requestPictureInPicture() aus dem eigenen Code kam oder über die Bedienelemente des Browsers.

Das Ereignisobjekt ist ein PictureInPictureEvent. Seine Eigenschaft pictureInPictureWindow verweist auf das zugehörige PictureInPictureWindow. Darüber lassen sich die aktuelle Breite und Höhe (width, height) auslesen und mit dem Ereignis resize Größenänderungen des Fensters verfolgen, etwa um die Auflösung des Videostreams anzupassen.

Typische Einsätze sind: den Zustand der Oberfläche umschalten (z. B. einen Button von „Bild-im-Bild“ auf „Zurück zum Tab“ ändern), einen Platzhalter an der ursprünglichen Stelle des Videos anzeigen oder Analyse-Ereignisse erfassen. Als Gegenstück dient leavepictureinpicture. Den Handler kannst du mit addEventListener() registrieren oder über die Eigenschaft video.onenterpictureinpicture zuweisen.

Das Ereignis steigt im DOM auf (bubbles: true) und lässt sich nicht abbrechen. Du kannst den Moduswechsel damit also nicht verhindern, sondern nur darauf reagieren.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname, immer "enterpictureinpicture".
$handler Pflicht (event: PictureInPictureEvent) => void Callback-Funktion. Sie erhält ein PictureInPictureEvent mit der Eigenschaft pictureInPictureWindow.
$options boolean | AddEventListenerOptions false Optionen wie once, passive, signal oder capture.

Rückgabewert

Typ
void
Beschreibung
addEventListener() gibt nichts zurück. Der Handler erhält ein PictureInPictureEvent.

Beispiele

Oberfläche beim Wechsel in den Bild-im-Bild-Modus anpassen

const video = document.querySelector('#player');
const pipButton = document.querySelector('#pip-toggle');

pipButton.addEventListener('click', async () => {
  try {
    if (document.pictureInPictureElement === video) {
      await document.exitPictureInPicture();
    } else {
      await video.requestPictureInPicture();
    }
  } catch (err) {
    console.error('Bild-im-Bild fehlgeschlagen:', err.name);
  }
});

video.addEventListener('enterpictureinpicture', (event) => {
  pipButton.textContent = 'Zurück zum Tab';
  video.classList.add('is-pip');
  const { width, height } = event.pictureInPictureWindow;
  console.log(`PiP-Fenster: ${width}×${height}`);
});

video.addEventListener('leavepictureinpicture', () => {
  pipButton.textContent = 'Bild-im-Bild';
  video.classList.remove('is-pip');
});
PiP-Fenster: 400×225

Größe des PiP-Fensters verfolgen

const video = document.querySelector('video');

const onResize = (e) => {
  const { width, height } = e.target;
  console.log(`Neue PiP-Größe: ${width}×${height}`);
};

video.addEventListener('enterpictureinpicture', (event) => {
  const pipWindow = event.pictureInPictureWindow;
  pipWindow.addEventListener('resize', onResize);

  // Listener beim Verlassen wieder aufräumen
  video.addEventListener('leavepictureinpicture', () => {
    pipWindow.removeEventListener('resize', onResize);
  }, { once: true });
});
Neue PiP-Größe: 512×288

Handler über die on-Property setzen und wieder entfernen

const video = document.querySelector('video');

video.onenterpictureinpicture = () => {
  console.log('Video läuft jetzt im Bild-im-Bild-Fenster');
};

// Später: Handler entfernen
video.onenterpictureinpicture = null;

// Alternative mit addEventListener und AbortController
const controller = new AbortController();
video.addEventListener('enterpictureinpicture', () => {
  console.log('PiP aktiv');
}, { signal: controller.signal });

controller.abort(); // entfernt den Listener

Funktionsprüfung vor der Registrierung

const video = document.querySelector('video');
const pipButton = document.querySelector('#pip-toggle');

const pipSupported = 'pictureInPictureEnabled' in document
  && document.pictureInPictureEnabled
  && !video.disablePictureInPicture;

if (pipSupported) {
  video.addEventListener('enterpictureinpicture', () => {
    console.log('PiP gestartet');
  });
} else {
  pipButton.hidden = true;
  console.log('Bild-im-Bild wird nicht unterstützt');
}
Bild-im-Bild wird nicht unterstützt

// Wichtig · Fallstricke

  • Browser-Unterstützung: Chromium-Browser (Chrome, Edge, Opera) und Safari unterstützen die API. Firefox hat zwar eine eigene Bild-im-Bild-Funktion, setzt aber die Picture-in-Picture-API nicht um. Dort wird dieses Ereignis nie ausgelöst. Prüfe die Unterstützung daher immer mit document.pictureInPictureEnabled.
  • requestPictureInPicture() braucht eine Nutzeraktion (transiente Aktivierung, z. B. einen Klick). Ohne sie wird das Promise mit NotAllowedError abgelehnt und kein enterpictureinpicture ausgelöst.
  • Ist video.disablePictureInPicture gesetzt, das Video noch nicht geladen (readyState === 0) oder hat es keine Videospur, schlägt der Wechsel fehl (InvalidStateError).
  • Es kann immer nur ein Element im Bild-im-Bild-Modus sein. Wechselt ein anderes Video hinein, erhält das vorherige zuerst leavepictureinpicture.
  • Das Ereignis lässt sich nicht abbrechen. preventDefault() hat keine Wirkung.
  • Die Picture-in-Picture-API für Videos ist nicht dasselbe wie die neuere Document Picture-in-Picture API (documentPictureInPicture.requestWindow(), nur in Chromium). Diese löst andere Ereignisse aus.
  • Über die Permissions-Policy picture-in-picture kann die Funktion in iframes gesperrt sein.