Introducción a la API web Picture-in-Picture | Programar Plus

Picture-in-Picture hizo su primera aparición en la web en el navegador Safari con el lanzamiento de macOS Sierra en 2016. Hizo posible que un usuario mostrara un video en una pequeña ventana flotante que permanece sobre todos los demás, de modo que pueden seguir mirando mientras hacen otras cosas. Es una idea que surgió de la televisión, donde, por ejemplo, es posible que desee seguir viendo su Evento deportivo popular incluso mientras navega por la guía o incluso por otros canales.

No mucho después de eso, se lanzó Android 8.0, que incluía soporte de imagen en imagen a través de API nativas. Chrome para Android pudo reproducir videos en modo de imagen en imagen a través de esta API, aunque su contraparte de escritorio no pudo hacerlo.

Esto condujo a la redacción de una API web Picture-in-Picture estándar que hace posible que los sitios web inicien y controlen este comportamiento.

En el momento de escribir este artículo, solo Chrome (versión 70+) y Edge (versión 76+) admiten esta función. Firefox, Safari y Opera utilizan API patentadas para sus implementaciones.

Estos datos de soporte del navegador son de Caniuse, que tiene más detalles. Un número indica que el navegador admite la función en esa versión y en adelante.

Escritorio

Cromo Firefox ES DECIR Borde Safari
70 97 No 79 13.1

Móvil / Tableta

Android cromo android firefox Androide iOSSafari
96 95 No 14,0-14,4

Cómo utilizar la API de imagen en imagen

Comencemos agregando un video a una página web.

<video controls src="https://css-tricks.com/an-introduction-to-the-picture-in-picture-web-api/video.mp4"></video>

En Chrome, ya habrá un interruptor para entrar y salir del modo Picture-in-Picture.

Mostrando un video con la opción de imagen en imagen en la parte inferior derecha de la pantalla.

Para probar la implementación de Firefox, deberá habilitar el media.videocontrols.picture-in-picture.enabled bandera en about:config primero, luego haga clic derecho en el video para encontrar la opción de imagen en imagen.

Mostrando la configuración de Firefox que habilita la imagen en imagen.
Habilitación de imagen en imagen en Firefox

Si bien esto funciona, en muchos casos, desea que sus controles de video sean consistentes en todos los navegadores y es posible que desee controlar qué videos se pueden ingresar en el modo de imagen en imagen y cuáles no.

Podemos reemplazar el método predeterminado de ingresar al modo de imagen en imagen en el navegador con nuestro propio método utilizando la API web de imagen en imagen. Por ejemplo, agreguemos un botón que, al hacer clic, lo habilite:

<button id="pipButton" class="hidden" disabled>Enter Picture-in-Picture mode</button>

Luego seleccione tanto el video como el botón en JavaScript:

const video = document.getElementById('video');
const pipButton = document.getElementById('pipButton');

El botón está oculto y deshabilitado de forma predeterminada porque necesitamos saber si la API Picture-in-Picture es compatible y está habilitada en el navegador del usuario antes de mostrarla. Esta es una forma de mejora progresiva que ayuda a evitar una experiencia rota en los navegadores que no admiten la función.

Podemos verificar que la API sea compatible y habilitar el botón como se muestra a continuación:

if ('pictureInPictureEnabled' in document) {
  pipButton.classList.remove('hidden')
  pipButton.disabled = false;
}

Entrar en el modo de imagen en imagen

Digamos que nuestro JavaScript ha determinado que el navegador tiene habilitado el soporte de imagen en imagen. Llamemos requestPictureInPicture() en el elemento de video cuando el botón con #pipButton se hace clic. Este método devuelve una promesa que coloca el video en una mini ventana en el lado inferior derecho de la pantalla de forma predeterminada cuando se resuelve, aunque el usuario puede moverlo.

if ('pictureInPictureEnabled' in document) {
  pipButton.classList.remove('hidden')
  pipButton.disabled = false;

  pipButton.addEventListener('click', () => {
    video.requestPictureInPicture();
  });
}

No podemos dejar el código de arriba como está porque requestPictureInPicture() devuelve una promesa y es posible que la promesa se rechace si, por ejemplo, los metadatos del video aún no están cargados o si el disablePictureInPicture El atributo está presente en el video.

Agreguemos un catch block para capturar este error potencial y hacerle saber al usuario lo que está pasando:

pipButton.addEventListener('click', () => {
  video
    .requestPictureInPicture()
    .catch(error => {
      // Error handling
    });
});

Salir del modo de imagen en imagen

El navegador proporciona de manera útil un botón de cierre en la ventana de imagen en imagen, que permite que la ventana se cierre cuando se hace clic en ella. Sin embargo, también podemos proporcionar otra forma de salir del modo de imagen en imagen. Por ejemplo, podemos hacer clic en nuestro #pipButton cerrar cualquier ventana de imagen en imagen activa.

pipButton.addEventListener('click', () => {
  if (document.pictureInPictureElement) {
    document
      .exitPictureInPicture()
      .catch(error => {
      // Error handling
    })
  } else {
    // Request Picture-in-Picture
  }
});

Otra situación en la que es posible que desee cerrar la ventana de imagen en imagen es cuando el video ingresa al modo de pantalla completa. Chrome ya hace esto automáticamente sin tener que escribir ningún código.

Eventos de imagen en imagen

El navegador nos permite detectar cuando un video entra o sale del modo de imagen en imagen. Dado que hay muchas formas de ingresar o salir del modo de imagen en imagen, es mejor confiar en la detección de eventos para actualizar los controles de medios.

los eventos son enterpictureinpicture y leavepictureinpicture que, como sus nombres lo indican, se activan cuando un video ingresa o sale del modo de imagen en imagen, respectivamente.

En nuestro ejemplo, necesitamos actualizar el #pipButton etiqueta dependiendo de si el video está o no actualmente en modo de imagen en imagen.

Aquí está el código que nos ayuda a lograrlo:

video.addEventListener('enterpictureinpicture', () => {
  pipButton.textContent="Exit Picture-in-Picture mode";
});

video.addEventListener('leavepictureinpicture', () => {
  pipButton.textContent="Enter Picture-in-Picture mode";
});

Aquí hay una demostración de eso:

Personalización de la ventana de imagen en imagen

El navegador muestra un botón de reproducción/pausa en la ventana de imagen en imagen de manera predeterminada, excepto cuando el video se está reproduciendo en un objeto MediaStream (producido por una fuente de video virtual, como una cámara, un dispositivo de grabación de video, un servicio de pantalla compartida u otro hardware). fuentes).

También es posible agregar controles que vayan a la pista anterior o siguiente directamente desde la ventana de imagen en imagen:

navigator.mediaSession.setActionHandler('previoustrack', () => {
  // Go to previous track
});

navigator.mediaSession.setActionHandler('nexttrack', () => {
  // Go to next track
});

Visualización de la transmisión de una cámara web en una ventana de imagen en imagen

Las aplicaciones web de reuniones de video podrían beneficiarse al colocar una transmisión de cámara web en modo de imagen en imagen cuando un usuario alterna entre la aplicación y otras pestañas o ventanas del navegador.

Aquí hay un ejemplo:

Deshabilitar imagen en imagen en un video

Si no desea que un video aparezca en una ventana de imagen en imagen, puede agregar el disablePictureInPicture atribuirle, así:

<video disablePictureInPicture controls src="https://css-tricks.com/an-introduction-to-the-picture-in-picture-web-api/video.mp4"></video>

Terminando

¡Eso es prácticamente todo lo que necesita sobre la API web Picture-in-Picture en este momento! Actualmente, la API solo admite la <video> pero está destinado a ser extensible a otros elementos también.

Aunque el soporte del navegador es irregular en este momento, aún puede usarlo como una forma de mejorar progresivamente la experiencia de video en su sitio web.

Otras lecturas

  • Especificación de API de imagen en imagen
  • Ver video usando Picture-in-Picture
  • Ejemplo de imagen en imagen (Google Chrome en GitHub)