Mudar o dispositivo de saída de destino no Web Audio

Francisco Beaufort
François Beaufort

Até agora, só era possível configurar o dispositivo de saída de áudio de destino para <video> e <audio> com HTMLMediaElement.setSinkId(). Em Web Audio, o AudioContext usou o dispositivo padrão, deixando o usuário mudar o dispositivo de saída de áudio do sistema manualmente.

No Chrome 110, é possível usar AudioContext.setSinkId() para direcionar programaticamente a saída de áudio no Áudio da Web para qualquer dispositivo permitido.

Isso é muito útil em diversas situações de comunicação em tempo real. Por exemplo, um aplicativo da Web pode usar esse recurso para direcionar a saída de forma programática para um dispositivo de saída de áudio específico, como um fone de ouvido Bluetooth ou viva-voz.

Encaminhar a saída de áudio para um dispositivo específico

Primeiro, você precisa do identificador do dispositivo de saída de áudio que quer usar como destino. Acesse a lista de dispositivos de mídia disponíveis com navigator.mediaDevices.enumerateDevices(), filtre apenas em dispositivos de saída de áudio e use o atributo deviceId do dispositivo de saída de áudio de sua preferência. O valor "" da string vazia também pode ser usado como dispositivo padrão para deviceId

Depois de ter o identificador do dispositivo de saída de áudio, crie uma AudioContext e chame audioContext.setSinkId(deviceId). Se for bem-sucedida, a promessa retornada vai ser resolvida quando o áudio for encaminhado para o dispositivo de saída conectado escolhido. Poderá falhar se o AudioContext for fechado.

O exemplo abaixo mostra como solicitar acesso ao microfone, se necessário, e direcionar a saída de áudio no Áudio da Web para o primeiro dispositivo de saída disponível.

const permission = await navigator.permissions.query({ name: "microphone" });
if (permission.state == "prompt") {
  // More audio outputs are available when user grants access to the mic.
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  stream.getTracks().forEach((track) => track.stop());
}

// Request a list of media devices and filter audio output devices.
const devices = await navigator.mediaDevices.enumerateDevices();
const audioOutputs = devices.filter(device => device.kind == "audiooutput");

const audioContext = new AudioContext();

// Pick the first available audio output.
const deviceId = audioOutputs[0].deviceId;
await audioContext.setSinkId(deviceId);

Também é possível transmitir o deviceId como um parâmetro sinkId ao criar um AudioContext.

const audioContext = new AudioContext({ sinkId: deviceId });

Renderizar áudio com um AudioContext silenciado

Agora você pode especificar um "dispositivo de saída silencioso" no Web Audio para minimizar o consumo de energia. Desta vez, em vez de um valor de string, transmita { type: "none" } para AudioContext.setSinkId().

O relógio de áudio acessível por audioContext.currentTime ainda avançará para renderizar o gráfico de áudio. O principal objetivo do AudioContext sem som é renderizar o gráfico de áudio sem produzir som audível. O principal caso de uso seria analisar a entrada do microfone sem emitir sons.

// Silent Web Audio output.
await audioContext.setSinkId({ type: "none" });

Detecção de recursos

Para conferir se AudioContext.setSinkId() é compatível, use:

if ("setSinkId" in AudioContext.prototype) {
  // AudioContext.setSinkId() is supported.
}

Exemplo

Uma demonstração está disponível em https://sinkid.glitch.me/ para jogar com AudioContext.setSinkId().

Suporte ao navegador

AudioContext.setSinkId() está disponível no Chrome 110 ou posterior.

Feedback

A equipe do Chrome e a comunidade de padrões da Web querem saber mais sobre suas experiências com o AudioContext.setSinkId(). Envie feedback comentando sobre problemas atuais ou registrando novos problemas do GitHub.

Agradecimentos

Agradecemos a Hongchan Choi e Michael Wilson pela análise deste artigo.

Foto da agenda de Steve Harvey no Unsplash (links em inglês).