Como fazer a integração com teclas de mídia de hardware, personalizar notificações de mídia e muito mais.
Para permitir que os usuários saibam o que está tocando no navegador e controlem essa ação sem retornar à página que a iniciou, a API Media Session foi surgiu. Ele permite que os desenvolvedores Web personalizem essa experiência por meio de metadados em notificações de mídia personalizadas, eventos de mídia como reproduzir, pausar buscar, rastrear eventos de alteração e videoconferência, como ativar/desativar som microfone, ligar/desligar câmera e desligar. Essas personalizações são disponíveis em vários contextos, incluindo hubs de mídia em computadores, notificações de mídia em dispositivos móveis e wearables. Vou descrever essas personalizações neste artigo.
Sobre a API Media Session
A API Media session oferece vários benefícios e recursos:
- As teclas de mídia de hardware são compatíveis.
- As notificações de mídia são personalizadas em dispositivos móveis, computadores e dispositivos wearable pareados.
- O hub de mídia está disponível para computadores.
- Os controles de mídia da tela de bloqueio estão disponíveis no ChromeOS e em dispositivos móveis.
- Os controles de janela picture-in-picture estão disponíveis para reprodução de áudio, videoconferência e apresentação de slides.
- A integração com o Google Assistente em dispositivos móveis está disponível.
Alguns exemplos ilustrarão alguns desses pontos.
Exemplo 1:se os usuários pressionarem "Próxima faixa" a tecla de mídia do teclado, os desenvolvedores Web podem processar essa ação do usuário se o navegador estiver em primeiro plano. ou no plano de fundo.
Exemplo 2:se os usuários ouvem um podcast na Web enquanto o dispositivo a tela está bloqueada, ainda é possível pressionar o botão ícone do cadeado controles de mídia da tela para que os desenvolvedores web atrasem o tempo de reprodução em poucos segundos.
Exemplo 3:se os usuários tiverem guias que reproduzem áudio, é possível interromper facilmente a reprodução do hub de mídia no computador para que os desenvolvedores Web tenham a chance de limpar o estado.
Exemplo 4:se os usuários estiverem em uma videochamada, eles podem pressionar o botão "Alternar microfone" na janela picture-in-picture para impedir que o site recebendo dados do microfone.
Tudo isso é feito em duas interfaces diferentes: MediaSession
.
e a interface MediaMetadata
. A primeira permite que os usuários controlem
a reprodução. O segundo é como você informa a MediaSession
o que precisa ser controlado.
Para ilustrar, a imagem abaixo mostra como essas interfaces se relacionam com parâmetros controles de mídia. Neste caso, uma notificação de mídia em um dispositivo móvel.
Mostre aos usuários o que está tocando
Quando um site está tocando áudio ou vídeo, os usuários recebem mídia automaticamente. notificações na bandeja de notificações em dispositivos móveis ou no hub de mídia ativado computador. O navegador faz o possível para mostrar as informações adequadas usando o do título do documento e da maior imagem de ícone que ele encontrar. Com a sessão de mídia API, é possível personalizar a notificação de mídia com alguns recursos de mídia metadados, como título, nome do artista, nome do álbum e capa, conforme mostrado abaixo.
O Chrome solicita a versão "completa" a seleção de áudio para mostrar notificações de mídia somente quando o duração da mídia de pelo menos cinco segundos. Isso garante que sons incidentais como pings, não mostram notificações.
// After media (video or audio) starts playing
await document.querySelector("video").play();
if ("mediaSession" in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
artist: 'Rick Astley',
album: 'Whenever You Need Somebody',
artwork: [
{ src: 'https://via.placeholder.com/96', sizes: '96x96', type: 'image/png' },
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/192', sizes: '192x192', type: 'image/png' },
{ src: 'https://via.placeholder.com/256', sizes: '256x256', type: 'image/png' },
{ src: 'https://via.placeholder.com/384', sizes: '384x384', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
});
// TODO: Update playback state.
}
Quando a reprodução terminar, não será necessário "liberar" a sessão de mídia como
a notificação desaparecerá automaticamente. Lembre-se de que
O app navigator.mediaSession.metadata
será usado quando a próxima reprodução começar
No entanto, Por isso, é importante atualizá-lo quando a fonte de reprodução de mídia
para garantir que as informações relevantes sejam exibidas na notificação de mídia.
Há algumas coisas a serem observadas sobre os metadados de mídia.
- A matriz de arte de notificação é compatível com URLs de blob e de dados.
- Se nenhuma arte estiver definida e houver uma imagem de ícone (especificada usando
<link rel=icon>
) em um tamanho desejável, as notificações de mídia a usarão. - O tamanho do destino da arte da notificação no Google Chrome para Android é
512x512
. Para dispositivos mais simples, é256x256
. - O atributo
title
do elemento HTML de mídia é usado no jogo Widget do macOS. - Se o recurso de mídia estiver incorporado (por exemplo, em um iframe), a API Media Session informações precisam ser definidas a partir do contexto incorporado. Confira o snippet abaixo.
<iframe id="iframe">
<video>...</video>
</iframe>
<script>
iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
...
});
</script>
Você também pode adicionar informações de capítulos individuais aos metadados de mídia, como o título da seção, o carimbo de data/hora e uma captura de tela. Isso permite que os usuários naveguem pelo conteúdo da mídia.
navigator.mediaSession.metadata = new MediaMetadata({
// title, artist, album, artwork, ...
chapterInfo: [{
title: 'Chapter 1',
startTime: 0,
artwork: [
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
}, {
title: 'Chapter 2',
startTime: 42,
artwork: [
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
}]
});
Permitir que os usuários controlem o que está tocando
Uma ação de sessão de mídia é uma ação (por exemplo, "reproduzir" ou "pausar") que um site pode
para os usuários quando eles interagem com a reprodução de mídia atual. As ações são
análogos e funcionam de forma muito semelhante aos eventos. Assim como os eventos, as ações são
implementado pela definição de manipuladores em um objeto apropriado, uma instância de
MediaSession
, neste caso. Algumas ações são acionadas quando os usuários pressionam
de um fone de ouvido, de outro dispositivo remoto, de um teclado, ou interagir com um
notificação de mídia.
Como algumas ações da sessão de mídia podem não ser suportadas, é recomendado
use um bloco try…catch
ao configurá-las.
const actionHandlers = [
['play', () => { /* ... */ }],
['pause', () => { /* ... */ }],
['previoustrack', () => { /* ... */ }],
['nexttrack', () => { /* ... */ }],
['stop', () => { /* ... */ }],
['seekbackward', (details) => { /* ... */ }],
['seekforward', (details) => { /* ... */ }],
['seekto', (details) => { /* ... */ }],
/* Video conferencing actions */
['togglemicrophone', () => { /* ... */ }],
['togglecamera', () => { /* ... */ }],
['hangup', () => { /* ... */ }],
/* Presenting slides actions */
['previousslide', () => { /* ... */ }],
['nextslide', () => { /* ... */ }],
];
for (const [action, handler] of actionHandlers) {
try {
navigator.mediaSession.setActionHandler(action, handler);
} catch (error) {
console.log(`The media session action "${action}" is not supported yet.`);
}
}
Desativar um gerenciador de ações de sessão de mídia é tão fácil quanto configurá-lo como null
.
try {
// Unset the "nexttrack" action handler at the end of a playlist.
navigator.mediaSession.setActionHandler('nexttrack', null);
} catch (error) {
console.log(`The media session action "nexttrack" is not supported yet.`);
}
Depois de definidos, os gerenciadores de ação de sessão de mídia vão persistir nas reproduções de mídia. É semelhante ao padrão de listener de eventos, exceto pelo fato de que lidar com um evento significa que o navegador deixa de executar qualquer comportamento padrão e o usa como que indica que o site oferece suporte à ação de mídia. Portanto, os controles de ação de mídia não será exibido, a menos que o gerenciador de ações adequado esteja definido.
Reproduzir / pausar
A ação "play"
indica que o usuário quer retomar a reprodução de mídia.
enquanto "pause"
indica um desejo de interrompê-lo temporariamente.
A opção de reproduzir/pausar é sempre mostrado em uma notificação de mídia e os eventos eventos de mídia são manipulados automaticamente pelo navegador. Para substituir o padrão comportamento, trate de "reproduzir" e "pausar" ações de mídia, conforme mostrado abaixo.
O navegador pode considerar um site que não está reproduzindo mídia ao buscar ou
o carregamento, por exemplo. Nesse caso, modifique esse comportamento definindo
navigator.mediaSession.playbackState
para "playing"
ou "paused"
para garantir
a interface do site permanece sincronizada com os controles de notificação de mídia.
const video = document.querySelector('video');
navigator.mediaSession.setActionHandler('play', async () => {
// Resume playback
await video.play();
});
navigator.mediaSession.setActionHandler('pause', () => {
// Pause active playback
video.pause();
});
video.addEventListener('play', () => {
navigator.mediaSession.playbackState = 'playing';
});
video.addEventListener('pause', () => {
navigator.mediaSession.playbackState = 'paused';
});
Faixa anterior
A ação "previoustrack"
indica que o usuário quer iniciar o
a reprodução da mídia atual desde o início, se ela tiver uma noção de
ou voltar ao item anterior da playlist se a reprodução de mídia
tenha uma noção de playlist.
navigator.mediaSession.setActionHandler('previoustrack', () => {
// Play previous track.
});
Próxima faixa
A ação "nexttrack"
indica que o usuário quer mover a reprodução de mídia para
o próximo item na playlist se a reprodução de mídia tiver uma ideia de playlist.
navigator.mediaSession.setActionHandler('nexttrack', () => {
// Play next track.
});
Parar
A ação "stop"
indica que o usuário quer interromper a reprodução de mídia e
limpar o estado, se apropriado.
navigator.mediaSession.setActionHandler('stop', () => {
// Stop playback and clear state if appropriate.
});
Voltar / avançar
A ação "seekbackward"
indica que o usuário quer mover a mídia.
o tempo de reprodução é reduzido em um curto período, enquanto "seekforward"
indica um desejo
para avançar o tempo de reprodução da mídia por um curto período. Em ambos os casos, uma
um período curto significa alguns segundos.
O valor seekOffset
fornecido no gerenciador de ações é o tempo em segundos para
mudar o tempo de reprodução da mídia. Se ele não for informado (por exemplo, undefined
),
use um tempo adequado (por exemplo, de 10 a 30 segundos).
const video = document.querySelector('video');
const defaultSkipTime = 10; /* Time to skip in seconds by default */
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
const skipTime = details.seekOffset || defaultSkipTime;
video.currentTime = Math.max(video.currentTime - skipTime, 0);
// TODO: Update playback state.
});
navigator.mediaSession.setActionHandler('seekforward', (details) => {
const skipTime = details.seekOffset || defaultSkipTime;
video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
// TODO: Update playback state.
});
Procurar um horário específico
A ação "seekto"
indica que o usuário quer mover a reprodução de mídia.
em um horário específico.
O valor seekTime
fornecido no gerenciador de ações é o tempo em segundos para
para mudar o tempo de reprodução da mídia.
O booleano fastSeek
fornecido no gerenciador de ações será verdadeiro se a ação for
sendo chamado várias vezes como parte de uma sequência e essa não é a última chamada
nessa sequência.
const video = document.querySelector('video');
navigator.mediaSession.setActionHandler('seekto', (details) => {
if (details.fastSeek && 'fastSeek' in video) {
// Only use fast seek if supported.
video.fastSeek(details.seekTime);
return;
}
video.currentTime = details.seekTime;
// TODO: Update playback state.
});
Definir a posição da reprodução
A exibição precisa da posição de reprodução de mídia em uma notificação é tão simples definir o estado da posição em um momento apropriado, conforme mostrado abaixo. A o estado da posição é uma combinação da velocidade de reprodução de mídia, duração e no horário atual.
A duração precisa ser fornecida e positiva. A posição deve ser positiva e menor que a duração. A velocidade do vídeo precisa ser maior que 0.
const video = document.querySelector('video');
function updatePositionState() {
if ('setPositionState' in navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: video.duration,
playbackRate: video.playbackRate,
position: video.currentTime,
});
}
}
// When video starts playing, update duration.
await video.play();
updatePositionState();
// When user wants to seek backward, update position.
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
/* ... */
updatePositionState();
});
// When user wants to seek forward, update position.
navigator.mediaSession.setActionHandler('seekforward', (details) => {
/* ... */
updatePositionState();
});
// When user wants to seek to a specific time, update position.
navigator.mediaSession.setActionHandler('seekto', (details) => {
/* ... */
updatePositionState();
});
// When video playback rate changes, update position state.
video.addEventListener('ratechange', (event) => {
updatePositionState();
});
Redefinir o estado da posição é tão fácil quanto defini-lo como null
.
// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);
Ações de videoconferência
Quando o usuário coloca a vídeo chamada em uma janela picture-in-picture, o navegador pode exibir controles para o microfone e a câmera e para desligar. Quando o usuário clica nelas, o site trata delas pelo vídeo. de videoconferência abaixo. Confira este exemplo de videoconferência.
.Alternar microfone
A ação "togglemicrophone"
indica que o usuário quer desativar ou ativar o som.
o microfone. O método setMicrophoneActive(isActive)
informa ao navegador
se o site atualmente considera que o microfone está ativo.
let isMicrophoneActive = false;
navigator.mediaSession.setActionHandler('togglemicrophone', () => {
if (isMicrophoneActive) {
// Mute the microphone.
} else {
// Unmute the microphone.
}
isMicrophoneActive = !isMicrophoneActive;
navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});
Alternar câmera
A ação "togglecamera"
indica que o usuário quer ativar
câmera ligada ou desligada. O método setCameraActive(isActive)
indica se a
navegador considera o site ativo.
let isCameraActive = false;
navigator.mediaSession.setActionHandler('togglecamera', () => {
if (isCameraActive) {
// Disable the camera.
} else {
// Enable the camera.
}
isCameraActive = !isCameraActive;
navigator.mediaSession.setCameraActive(isCameraActive);
});
Desligar
A ação "hangup"
indica que o usuário quer encerrar uma chamada.
navigator.mediaSession.setActionHandler('hangup', () => {
// End the call.
});
Ações de apresentação de slides
Quando o usuário coloca a apresentação de slides em uma janela picture-in-picture, o navegador pode exibir controles para navegar pelos slides. Quando o usuário clicar neles, o site os tratará pela API Media Session. Para um exemplo, consulte o exemplo Apresentação de slides.
Slide anterior
A ação "previousslide"
indica que o usuário quer voltar para o
slide anterior durante a apresentação.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
Compatibilidade com navegadores
Próximo slide
A ação "nextslide"
indica que o usuário quer acessar o próximo slide.
durante a apresentação de slides.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
Compatibilidade com navegadores
Amostras
Confira alguns exemplos de Sessões de mídia com o Remixer Foundation (em inglês) e O trabalho de Jan Morgenstern.
Recursos
- Especificações da sessão de mídia: wicg.github.io/mediasession
- Problemas com especificações: github.com/WICG/mediasession/issues
- Bugs do Chrome: crbug.com