Oglądanie filmu w trybie obrazu w obrazie

François Beaufort
François Beaufort

Funkcja obraz w obrazie (PIP) umożliwia użytkownikom oglądanie filmów w pływającym oknie. (zawsze nad innymi oknami), dzięki czemu dziecko może dokładnie śledzić, oglądać treści podczas interakcji z innymi witrynami lub aplikacjami.

Za pomocą interfejsu Picture-in-Picture Web API możesz Obraz w obrazie w elementach wideo w witrynie. Wypróbuj na oficjalną próbkę obrazu w obrazie.

Tło

We wrześniu 2016 roku w Safari dodaliśmy obsługę obrazu w obrazie za pomocą interfejsu API WebKit. w systemie macOS Sierra. Pół roku później Chrome automatycznie Funkcja obrazu w obrazie na urządzeniach mobilnych z Androidem O wykorzystującym natywnym Android API. Pół roku później ogłosiliśmy zamiar stworzenia ustandaryzować interfejs Web API, funkcję zgodną z przeglądarką Safari, która umożliwiłaby deweloperom aplikacji do tworzenia i kontrolowania wszystkich funkcji obrazu w obrazie. I o to chodzi!

Zapoznaj się z kodem

Włącz tryb obraz w obrazie

Zacznijmy od elementu wideo i sposobu interakcji użytkownika np. przycisk.

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

Żądaj funkcji obraz w obrazie tylko w odpowiedzi na gest użytkownika i nigdy Metoda promise zwracana przez funkcję videoElement.play(). To dlatego, że obietnice nie są jeszcze rozpowszechnić gesty użytkowników. Zamiast tego zadzwoń do requestPictureInPicture() w moduł obsługi kliknięć w systemie pipButtonElement, jak pokazano poniżej. To Ty odpowiadasz na to, co się stanie, gdy użytkownik kliknie go 2 razy.

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  await videoElement.requestPictureInPicture();

  pipButtonElement.disabled = false;
});

Po spełnieniu obietnicy Chrome zmniejsza film do małego okna, użytkownik może się poruszać i przesuwać nad inne okna.

Gotowe. Brawo! Możesz przestać czytać i zająć się urlop. Niestety nie zawsze tak jest. Obietnica może zostać odrzucona w przypadku dowolnego z następujących powodów:

  • System nie obsługuje trybu obraz w obrazie.
  • Dokument nie może korzystać z funkcji obraz w obrazie z powodu ograniczeń zasadami uprawnień.
  • Metadane filmu nie zostały jeszcze wczytane (videoElement.readyState === 0).
  • Plik wideo zawiera tylko dźwięk.
  • W elemencie wideo znajduje się nowy atrybut disablePictureInPicture.
  • Połączenie nie zostało wykonane w ramach modułu obsługi zdarzeń gestów (np. kliknięcia przycisku). Od Chrome 74 dotyczy to tylko wtedy, gdy nie ma elementu w Tryb obraz w obrazie jest już włączony.

W sekcji Obsługa funkcji poniżej dowiesz się, jak włączyć lub wyłączyć przycisk na podstawie tych ograniczeń.

Dodajmy blok try...catch, aby rejestrować te potencjalne błędy i pozwolić użytkownicy wiedzą, co się dzieje.

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  try {
    await videoElement.requestPictureInPicture();
  } catch (error) {
    // TODO: Show error message to user.
  } finally {
    pipButtonElement.disabled = false;
  }
});

Element wideo działa tak samo niezależnie od tego, czy jest w obrazie w obrazie, czy nie: zdarzenia są wywoływane, a metody wywoływania działają. Odzwierciedla on zmiany stanu okna obrazu w obrazie (takiego jak odtwarzanie, wstrzymywanie, przewijanie itp.), a także w JavaScripcie możesz automatycznie zmienić stan.

Wyłącz obraz w obrazie

Teraz zajmijmy się włączaniem i wyłączaniem obrazu w obrazie za pomocą przełącznika. Śr najpierw sprawdź, czy obiekt tylko do odczytu document.pictureInPictureElement czyli elementu wideo. W przeciwnym razie wyślemy prośbę o podanie Obraz w obrazie jak powyżej. W przeciwnym razie poprosimy Cię o opuszczenie spotkania, dzwoniąc pod numer document.exitPictureInPicture(), co oznacza, że film powróci za oryginalnej karty. Pamiętaj, że ta metoda zwraca też obietnicę.

    ...
    try {
      if (videoElement !== document.pictureInPictureElement) {
        await videoElement.requestPictureInPicture();
      } else {
        await document.exitPictureInPicture();
      }
    }
    ...

Słuchanie zdarzeń z funkcją obraz w obrazie

Systemy operacyjne zwykle ograniczają obraz w obrazie do jednego okna, Implementacja Chrome opiera się na tym wzorcu. Oznacza to, że użytkownicy mogą grać tylko jeden film w trybie obraz w obrazie jednocześnie. Użytkownicy powinni wyjść Funkcja obraz w obrazie nawet wtedy, gdy o to nie prosisz.

Nowe moduły obsługi zdarzeń enterpictureinpicture i leavepictureinpicture pozwalają aby dostosować je do potrzeb użytkowników. Może to być wszystko, od przeglądania katalog filmów, aby wyświetlić czat na żywo.

videoElement.addEventListener('enterpictureinpicture', function (event) {
  // Video entered Picture-in-Picture.
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  // Video left Picture-in-Picture.
  // User may have played a Picture-in-Picture video from a different page.
});

Dostosowywanie okna obrazu w obrazie

Chrome 74 obsługuje przyciski odtwarzania/wstrzymywania, poprzedniego utworu i następnego utworu Okno obrazu w obrazie, którym możesz sterować za pomocą interfejsu Media Session API.

Sterowanie odtwarzaniem multimediów w oknie obrazu w obrazie
Rysunek 1. Sterowanie odtwarzaniem multimediów w oknie obrazu w obrazie
.
.

Domyślnie w obrazie w obrazie jest zawsze widoczny przycisk odtwarzania/wstrzymywania chyba że w filmie są odtwarzane obiekty MediaStream (np. getUserMedia(), getDisplayMedia(), canvas.captureStream()) lub film ma MediaSource czas trwania ustawiony na +Infinity (np. kanał na żywo). Aby przycisk odtwarzania/wstrzymywania jest zawsze widoczny, ustaw moduły obsługi działań sesji multimedialnej dla obydwu parametrów „Odtwarzanie” oraz „Wstrzymaj” zdarzeń związanych z multimediami.

// Show a play/pause button in the Picture-in-Picture window
navigator.mediaSession.setActionHandler('play', function () {
  // User clicked "Play" button.
});
navigator.mediaSession.setActionHandler('pause', function () {
  // User clicked "Pause" button.
});

Wyświetlam „Poprzedni utwór” i „Następny utwór” są podobne. Ustawienie Moduły obsługi działań związanych z sesją multimediów będą wyświetlać je w obrazie w obrazie możesz wykonać te działania.

navigator.mediaSession.setActionHandler('previoustrack', function () {
  // User clicked "Previous Track" button.
});

navigator.mediaSession.setActionHandler('nexttrack', function () {
  // User clicked "Next Track" button.
});

Aby przekonać się, jak to działa, wypróbuj oficjalną próbkę sesji multimedialnej.

Określanie rozmiaru okna obrazu w obrazie

Jeśli chcesz dostosować jakość odtwarzania filmu przed jego rozpoczęciem i po jego zakończeniu. w przypadku funkcji obraz w obrazie należy znać rozmiar okna obrazu w obrazie powiadomienia, gdy użytkownik ręcznie zmieni rozmiar okna.

Poniższy przykład pokazuje, jak obliczyć szerokość i wysokość Okno obraz w obrazie po utworzeniu lub zmianie rozmiaru.

let pipWindow;

videoElement.addEventListener('enterpictureinpicture', function (event) {
  pipWindow = event.pictureInPictureWindow;
  console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`);
  pipWindow.addEventListener('resize', onPipWindowResize);
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  pipWindow.removeEventListener('resize', onPipWindowResize);
});

function onPipWindowResize(event) {
  console.log(
    `> Window size changed to ${pipWindow.width}x${pipWindow.height}`
  );
  // TODO: Change video quality based on Picture-in-Picture window size.
}

Nie łącz się bezpośrednio ze zdarzeniem zmiany rozmiaru po wprowadzeniu każdej drobnej zmiany. na rozmiar okna obrazu w obrazie spowoduje uruchomienie osobnego zdarzenia, które może jeśli wykonujesz kosztowne operacje przy każdej zmianie rozmiaru. W Innymi słowy, operacja zmiany rozmiaru spowoduje ciągłe uruchamianie zdarzeń bardzo szybko. Polecam użycie popularnych technik, takich jak ograniczanie

Obsługa funkcji

Interfejs Picture-in-Picture Web API może nie być obsługiwany, więc musisz to wykryć i wprowadzaj kolejne usprawnienia. Nawet jeśli jest obsługiwana, może wyłączone przez użytkownika lub wyłączone przez zasadę uprawnień. Na szczęście nową wartość logiczną document.pictureInPictureEnabled.

if (!('pictureInPictureEnabled' in document)) {
  console.log('The Picture-in-Picture Web API is not available.');
} else if (!document.pictureInPictureEnabled) {
  console.log('The Picture-in-Picture Web API is disabled.');
}

Zastosowanie do konkretnego elementu przycisku w filmie. określić widoczność przycisku obrazu w obrazie.

if ('pictureInPictureEnabled' in document) {
  // Set button ability depending on whether Picture-in-Picture can be used.
  setPipButton();
  videoElement.addEventListener('loadedmetadata', setPipButton);
  videoElement.addEventListener('emptied', setPipButton);
} else {
  // Hide button if Picture-in-Picture is not supported.
  pipButtonElement.hidden = true;
}

function setPipButton() {
  pipButtonElement.disabled =
    videoElement.readyState === 0 ||
    !document.pictureInPictureEnabled ||
    videoElement.disablePictureInPicture;
}

Obsługa wideo MediaStream

Film odtwarza obiekty MediaStream (np. getUserMedia(), getDisplayMedia(), canvas.captureStream()) obsługują też funkcję obraz w obrazie w Chrome 71. Ten Oznacza to, że możesz pokazać okno z obrazem w obrazie, na którym znajduje się kamera internetowa użytkownika strumienia wideo, strumienia wideo w sieci reklamowej, a nawet elementu canvas. Pamiętaj, że parametr Element wideo nie musi być dołączony do DOM, aby można go było otworzyć. Obraz w obrazie, jak pokazano poniżej.

Pokazuj kamerę internetową użytkownika w oknie obrazu w obrazie

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

Pokaż wyświetlacz w oknie obrazu w obrazie

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getDisplayMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

Pokaż element canvas w oknie obrazu w obrazie

const canvas = document.createElement('canvas');
// Draw something to canvas.
canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);

const video = document.createElement('video');
video.muted = true;
video.srcObject = canvas.captureStream();
video.play();

// Later on, video.requestPictureInPicture();

Dzięki połączeniu canvas.captureStream() z Media Session API możesz może utworzyć okno playlisty audio w Chrome 74. Poznaj oficjalnego Próbka playlisty audio.

Playlista audio w oknie obrazu w obrazie
Rysunek 2. Playlista audio w oknie obrazu w obrazie
.
.

Przykłady, wersje demonstracyjne i ćwiczenia z programowania

Wypróbuj naszą oficjalną próbkę obrazu w obrazie i wypróbuj ją. Web API.

Później będą dostępne prezentacje i ćwiczenia z programowania.

Co dalej?

Najpierw na stronie Stan implementacji dowiesz się, które fragmenty kodu Interfejs API jest obecnie zaimplementowany w Chrome i innych przeglądarkach.

Oto, czego możesz się spodziewać w najbliższej przyszłości:

Obsługa przeglądarek

Interfejs Picture-in-Picture Web API jest obsługiwany w przeglądarkach Chrome, Edge, Opera i Safari. Szczegółowe informacje znajdziesz w MDN.

Zasoby

Dziękujemy Mounir Lamouri i Jennifer Apacible za pracę obraz w obrazie i pomoc w tym artykule. Dziękuję wszystkim w procesy standaryzacyjne.