La función pantalla en pantalla (PIP) permite que los usuarios miren videos en una ventana flotante (siempre encima de otras ventanas) para que puedan vigilar lo que están mirar mientras interactúa con otros sitios o aplicaciones.
Con la API web de pantalla en pantalla, puedes iniciar y controlar Pantalla en pantalla para los elementos de video de tu sitio web. Pruébala en nuestro Ejemplo de pantalla en pantalla oficial.
Información general
En septiembre de 2016, Safari agregó compatibilidad con pantalla en pantalla a través de una API de WebKit. en macOS Sierra. Seis meses después, Chrome reprodujo automáticamente Video pantalla en pantalla en un dispositivo móvil con el lanzamiento de Android O con un API nativa de Android. Seis meses después, anunciamos nuestra intención de crear y una API web, una función compatible con Safari, que le permitiría desarrolladores para crear y controlar la experiencia completa en torno a la función pantalla en pantalla. ¡Y aquí estamos!
Ingresar al código
Ingresa al modo de pantalla en pantalla
Empecemos simplemente con un elemento de video y una forma para que el usuario interactúe con él, como un elemento de botón.
<video id="videoElement" src="https://example.com/file.mp4"></video>
<button id="pipButtonElement"></button>
Solo debes solicitar la función Pantalla en pantalla en respuesta a un gesto del usuario, y nunca en el
Promise que muestra videoElement.play()
. Esto se debe a que las promesas no
aún propagan gestos del usuario. En su lugar, llama a requestPictureInPicture()
en un
y haz clic en el controlador en pipButtonElement
, como se muestra a continuación. Es tu responsabilidad
para controlar lo que ocurre
si un usuario hace dos clics.
pipButtonElement.addEventListener('click', async function () {
pipButtonElement.disabled = true;
await videoElement.requestPictureInPicture();
pipButtonElement.disabled = false;
});
Cuando se resuelve la promesa, Chrome reduce el video a una ventana pequeña que el usuario puede desplazarse y colocarse sobre otras ventanas.
Eso es todo. ¡Bien hecho! Puedes dejar de leer y llevarte tu merecido contenido vacaciones. Lamentablemente, no siempre es así. La promesa puede rechazar por cualquier por los siguientes motivos:
- El sistema no admite la función de pantalla en pantalla.
- No se permite usar la función Pantalla en pantalla en el documento debido a una restricción política de permisos.
- Aún no se cargaron los metadatos del video (
videoElement.readyState === 0
). - El archivo de video es solo de audio.
- El nuevo atributo
disablePictureInPicture
está presente en el elemento de video. - La llamada no se realizó en un controlador de eventos de gestos del usuario (p.ej., un clic en un botón). A partir de Chrome 74, esto solo se aplica si no hay un elemento en Ya se habilitó la función pantalla en pantalla.
La sección Compatibilidad con funciones que aparece a continuación muestra cómo habilitar o inhabilitar un botón según las estas restricciones.
Agreguemos un bloque try...catch
para capturar estos posibles errores y dejar que la
el usuario sepa lo que está sucediendo.
pipButtonElement.addEventListener('click', async function () {
pipButtonElement.disabled = true;
try {
await videoElement.requestPictureInPicture();
} catch (error) {
// TODO: Show error message to user.
} finally {
pipButtonElement.disabled = false;
}
});
El elemento de video se comporta de la misma manera ya sea en pantalla en pantalla o no: se activan los eventos y funcionan los métodos de llamada. Refleja los cambios de estado en la ventana de Pantalla en pantalla (como reproducir, pausar, saltar, etc.), y también posible cambiar el estado de forma programática en JavaScript.
Salir del modo de pantalla en pantalla
Ahora, hagamos que nuestro botón entre y salga del modo de pantalla en pantalla. Mié
primero debes comprobar si el objeto de solo lectura document.pictureInPictureElement
es nuestro elemento de video. Si no es así, enviaremos una solicitud para ingresar
Pantalla en pantalla como se muestra arriba. De lo contrario, te pediremos que te vayas llamando
document.exitPictureInPicture()
, lo que significa que el video volverá a aparecer en
la pestaña original. Ten en cuenta que este método también muestra una promesa.
...
try {
if (videoElement !== document.pictureInPictureElement) {
await videoElement.requestPictureInPicture();
} else {
await document.exitPictureInPicture();
}
}
...
Escucha eventos de pantalla en pantalla
Los sistemas operativos suelen restringir la función pantalla en pantalla a una sola ventana, por La implementación de Chrome sigue este patrón. Esto significa que los usuarios solo pueden jugar un video de pantalla en pantalla a la vez. Los usuarios deberían cerrar Pantalla en pantalla, incluso cuando no la habías solicitado.
Los nuevos controladores de eventos enterpictureinpicture
y leavepictureinpicture
permiten
personalizar la experiencia de los usuarios. Podría ser cualquier cosa, desde explorar un
hasta un catálogo de videos o un chat en vivo.
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.
});
Personaliza la ventana de pantalla en pantalla
Chrome 74 admite los botones de reproducción/pausa, pista anterior y pista siguiente en el Ventana de pantalla en pantalla que puedes controlar mediante la API de Media Session.
De forma predeterminada, siempre se muestra un botón de reproducción/pausa en la función Pantalla en pantalla
a menos que el video reproduzca objetos MediaStream (por ejemplo, getUserMedia()
,
getDisplayMedia()
, canvas.captureStream()
) o el video tiene una MediaSource
la duración establecida en +Infinity
(p.ej., feed en vivo). Para asegurarse de que haya un botón de reproducción/pausa
siempre está visible, configura somesee controladores de acción de sesiones multimedia para "Play". y
"Pausa" eventos multimedia como se muestra a continuación.
// 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.
});
Se muestra "Pista anterior" y “Siguiente pista” controles de ventana es similar. Parámetro de configuración Los controladores de acciones de la sesión multimedia para esos controladores los mostrarán en el modo de pantalla en pantalla. y podrás controlar estas acciones.
navigator.mediaSession.setActionHandler('previoustrack', function () {
// User clicked "Previous Track" button.
});
navigator.mediaSession.setActionHandler('nexttrack', function () {
// User clicked "Next Track" button.
});
Para ver esto en acción, prueba el ejemplo oficial de las sesiones multimedia.
Obtén el tamaño de la ventana de pantalla en pantalla
Si quieres ajustar la calidad del video cuando este entra y sale Pantalla en pantalla, debes conocer el tamaño de la ventana de pantalla en pantalla y notificaciones si un usuario cambia manualmente el tamaño de la ventana.
En el siguiente ejemplo, se muestra cómo obtener el ancho y la altura de la Ventana de pantalla en pantalla cuando se crea o se cambia su tamaño.
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.
}
Te sugiero que no te encajes directamente con el evento de cambio de tamaño, ya que se realiza cada pequeño cambio. al tamaño de la ventana de Pantalla en pantalla activará un evento independiente que podría problemas de rendimiento si realizas una operación costosa en cada cambio de tamaño. En otras palabras, la operación de cambio de tamaño activará los eventos una y otra vez, con rapidez. Recomendaría utilizar técnicas comunes, como regulación y de rebote para solucionar este problema.
Compatibilidad de características
Es posible que la API web de pantalla en pantalla no sea compatible, por lo que debes detectar esta
para proporcionar una mejora progresiva. Incluso cuando es compatible, puede ser
desactivados por el usuario o inhabilitados por una política de permisos Por suerte, puedes usar
el nuevo valor booleano document.pictureInPictureEnabled
para determinar esto.
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.');
}
Aplicado a un elemento de botón específico de un video, así es como te recomendamos controlar la visibilidad del botón de pantalla en pantalla.
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;
}
Compatibilidad con videos de MediaStream
Objetos MediaStream que se reproducen de video (p.ej., getUserMedia()
, getDisplayMedia()
,
canvas.captureStream()
) también admiten la función Pantalla en pantalla en Chrome 71. Esta
significa que puedes mostrar una ventana de pantalla en pantalla que contenga la cámara web del usuario
transmisión de video por Internet en pantalla, transmisión de video por Internet en pantalla o, incluso, un elemento de lienzo. Ten en cuenta que
no es necesario adjuntar un elemento de video al DOM para ingresar
Pantalla en pantalla como se muestra a continuación.
Mostrar la cámara web del usuario en la ventana de pantalla en pantalla
const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
video.play();
// Later on, video.requestPictureInPicture();
Mostrar la pantalla en la ventana de pantalla en pantalla
const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getDisplayMedia({video: true});
video.play();
// Later on, video.requestPictureInPicture();
Mostrar el elemento de lienzo en la ventana de pantalla en pantalla
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();
Si combinas canvas.captureStream()
con la API de Media Session, podrás
crear una ventana de playlist de audio en Chrome 74. Mira el video oficial
Muestra de una playlist de audio.
Ejemplos, demostraciones y codelabs
Consulta nuestra muestra oficial de pantalla en pantalla para probar la función pantalla en pantalla API web.
A continuación, se presentan demostraciones y codelabs.
¿Qué sigue?
Primero, consulta la página de estado de implementación para saber qué partes de Actualmente, la API está implementada en Chrome y otros navegadores.
Esto es lo que puedes esperar próximamente:
- Los desarrolladores web podrán agregar controles de pantalla en pantalla personalizados.
- Se proporcionará una nueva API web para mostrar objetos
HTMLElement
arbitrarios en una ventana flotante.
Navegadores compatibles
La API web de pantalla en pantalla es compatible con Chrome, Edge, Opera y Safari. Consulta MDN para obtener más detalles.
Recursos
- Estado de las funciones de Chrome: https://www.chromestatus.com/feature/5729206566649856
- Errores de implementación de Chrome: https://crbug.com/?q=component:Blink>Media>PictureInPicture
- Especificaciones de la API web de pantalla en pantalla: https://wicg.github.io/picture-in-picture
- Problemas de especificaciones: https://github.com/WICG/picture-in-picture/issues
- Muestra: https://googlechrome.github.io/samples/picture-in-picture/
- Polyfill de pantalla en pantalla no oficial: https://github.com/gbentaieb/pip-polyfill/
Muchas gracias a Mounir Lamouri y Jennifer Apacible por su trabajo en pantalla en pantalla y ayúdanos con este artículo. Muchas gracias a todos que participan en el esfuerzo de estandarización.