Guardare il video utilizzando Picture in picture

François Beaufort
François Beaufort

Picture in picture (PIP) consente agli utenti di guardare i video in una finestra mobile (sempre sopra le altre finestre) per poter tenere d'occhio ciò che si sta guardare i video mentre interagisci con altri siti o applicazioni.

Con l'API Web Picture in picture, puoi avviare e controllare Picture in picture per gli elementi video sul tuo sito web. Provalo sul nostro esempio Picture in picture ufficiale.

Sfondo

A settembre 2016, Safari ha aggiunto il supporto di Picture in picture tramite un'API WebKit. in macOS Sierra. Sei mesi dopo, Chrome si è riprodotto automaticamente Video Picture in picture su dispositivi mobili con il rilascio di Android O tramite un API nativa di Android. Sei mesi dopo, abbiamo annunciato la nostra intenzione di creare e standardizzare un'API web, funzione compatibile con Safari, che consentirebbe agli sviluppatori di creare e controllare l'esperienza completa di Picture in picture. Ed eccoci qui!

Impara a conoscere il codice

Attiva Picture in picture

Iniziamo semplicemente con un elemento video e un modo in cui l'utente può interagire ad esempio un elemento pulsante.

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

Richiedi Picture in picture soltanto in risposta a un gesto dell'utente, mai nella promise restituito da videoElement.play(). Questo perché le promesse non propagare ancora i gesti dell'utente. Invece, chiama requestPictureInPicture() in un gestore dei clic su pipButtonElement, come mostrato di seguito. È tua responsabilità per gestire ciò che accade se un utente fa clic due volte.

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

  await videoElement.requestPictureInPicture();

  pipButtonElement.disabled = false;
});

Quando la promessa viene risolta, Chrome riduce il video in una piccola finestra che l'utente può spostarsi e posizionare su altre finestre.

Hai finito. Ottimo lavoro. Puoi smettere di leggere e andare a prendere il tuo meritato riposo per le vacanze. Purtroppo, non è sempre così. La promessa può rifiutare qualsiasi dei seguenti motivi:

  • La funzionalità Picture in picture non è supportata dal sistema.
  • Picture in picture non consentita nel documento a causa di restrizioni criteri relativi alle autorizzazioni.
  • I metadati del video non sono stati ancora caricati (videoElement.readyState === 0).
  • Il file video è in modalità solo audio.
  • Il nuovo attributo disablePictureInPicture è presente nell'elemento video.
  • La chiamata non è stata effettuata in un gestore di eventi di gesti dell'utente (ad es. un clic su un pulsante). A partire da Chrome 74, questa opzione è applicabile solo se non è presente un elemento in Già Picture in picture.

La sezione Supporto delle funzionalità di seguito mostra come attivare/disattivare un pulsante in base a: queste restrizioni.

Aggiungiamo un blocco try...catch per acquisire questi potenziali errori e lasciamo che l'utente sappia cosa sta succedendo.

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

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

Il comportamento dell'elemento video è lo stesso indipendentemente dal fatto che si trovi in modalità Picture in picture not: gli eventi vengono attivati e i metodi di chiamata funzionano. Riflette i cambiamenti di stato finestra Picture in picture (come riproduzione, pausa, ricerca e così via) ed è anche è possibile modificare lo stato in modo programmatico in JavaScript.

Esci da Picture in picture

Ora facciamo in modo che il pulsante di attivazione/disattivazione uscisca da Picture in picture. Me devi prima verificare se l'oggetto di sola lettura document.pictureInPictureElement è l'elemento video. In caso contrario, inviamo una richiesta di inserimento Picture in picture come sopra. In caso contrario, ti chiediamo di uscire chiamando document.exitPictureInPicture(), il che significa che il video verrà visualizzato di nuovo la scheda originale. Tieni presente che anche questo metodo restituisce una promessa.

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

Ascoltare eventi Picture in picture

In genere, i sistemi operativi limitano Picture in picture a una sola finestra, L'implementazione di Chrome segue questo schema. Ciò significa che gli utenti possono giocare un video Picture in picture alla volta. Gli utenti dovrebbero uscire Picture in picture anche quando non l'hai chiesto tu.

I nuovi gestori di eventi enterpictureinpicture e leavepictureinpicture consentono a personalizzare l'esperienza per gli utenti. Può trattarsi di qualsiasi cosa, dalla navigazione un catalogo di video, alla presentazione di una chat in live streaming.

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.
});

Personalizzare la finestra Picture in picture

Chrome 74 supporta i pulsanti Riproduci/Metti in pausa, Traccia precedente e Traccia successiva nella La finestra Picture in picture che puoi controllare utilizzando l'API Media Session.

Controlli di riproduzione dei contenuti multimediali in una finestra Picture in picture
Figura 1. Controlli di riproduzione dei contenuti multimediali in una finestra Picture in picture
di Gemini Advanced.
.

Per impostazione predefinita, nella modalità Picture in picture viene sempre mostrato un pulsante di riproduzione/pausa. a meno che il video non stia riproducendo oggetti MediaStream (ad es. getUserMedia(), getDisplayMedia(), canvas.captureStream()) o il video ha un oggetto MediaSource durata impostata su +Infinity (ad es. feed live). Per assicurarsi che un pulsante di riproduzione/pausa è sempre visibile, imposta i gestori di azioni della sessione multimediale per "Riproduci" e "Metti in pausa" eventi multimediali come mostrato di seguito.

// 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.
});

Visualizzazione di "Traccia precedente" e "Traccia successiva" controlli delle finestre è simile. Impostazione I gestori delle azioni della sessione multimediale per questi elementi li mostreranno nella modalità Picture in picture e potrai gestire queste azioni.

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

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

Per vedere come funziona, prova l'esempio di sessione multimediale ufficiale.

Visualizzare le dimensioni della finestra Picture in picture

Se vuoi regolare la qualità del video quando il video entra ed esce Picture in picture, devi conoscere le dimensioni della finestra Picture in picture una notifica se un utente ridimensiona manualmente la finestra.

L'esempio seguente mostra come ottenere la larghezza e l'altezza del Finestra Picture in picture quando viene creata o ridimensionata.

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.
}

Suggerirei di non eseguire il collegamento direttamente all'evento di ridimensionamento perché ogni piccola modifica apportata alle dimensioni della finestra Picture in picture, attiverà un evento separato che potrebbe se esegui un'operazione costosa a ogni ridimensionamento. Nella altre parole, l'operazione di ridimensionamento attiverà gli eventi più volte, rapidamente. Consiglio di usare tecniche comuni, come la limitazione e debouncing per risolvere questo problema.

Supporto delle funzionalità

L'API Web Picture in picture potrebbe non essere supportata, quindi devi rilevarla per apportare miglioramenti progressivi. Anche se è supportata, disattivata dall'utente o disattivata da un criterio di autorizzazione. Fortunatamente, puoi usare il nuovo valore booleano document.pictureInPictureEnabled per determinarlo.

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.');
}

Applicato a un elemento pulsante specifico per un video, questo è come potresti volere gestire la visibilità del pulsante Picture in picture.

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;
}

Supporto video MediaStream

Video che riproduce oggetti MediaStream (ad es. getUserMedia(), getDisplayMedia(), canvas.captureStream()) supportano anche Picture in picture in Chrome 71. Questo indica che puoi mostrare una finestra Picture in picture contenente la webcam dell'utente stream video, stream video display o persino un elemento canvas. Tieni presente che l'elemento video non deve essere necessariamente collegato al DOM per poter Picture in picture come mostrato di seguito.

Mostra la webcam dell'utente nella finestra Picture in picture

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

// Later on, video.requestPictureInPicture();

Mostra finestra Picture in picture

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

// Later on, video.requestPictureInPicture();

Mostra l'elemento canvas nella finestra Picture in picture

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();

Combinando canvas.captureStream() con l'API Media Session, puoi creare una finestra playlist audio in Chrome 74. Dai un'occhiata al Esempio di playlist audio.

Playlist audio in una finestra Picture in picture
Figura 2. Playlist audio in una finestra Picture in picture
di Gemini Advanced.
.

Esempi, demo e codelab

Guarda l'esempio ufficiale di Picture in picture per provare la funzionalità Picture in picture API Web.

Seguiranno demo e codelab.

Passaggi successivi

Innanzitutto, consulta la pagina relativa allo stato dell'implementazione per sapere quali parti delle Le API sono attualmente implementate in Chrome e in altri browser.

Ecco cosa puoi aspettarti di vedere nel prossimo futuro:

Supporto browser

L'API Web Picture in picture è supportata in Chrome, Edge, Opera e Safari. Vedi MDN per i dettagli.

Risorse

Grazie mille a Mounir Lamouri e Jennifer Apacible per il loro lavoro Picture in picture e guida per questo articolo. E grazie mille a tutti coinvolti nella standardizzazione.