JSFiddle - React, Tailwind, and code Playground

by ibcaliax

HTML

"Unfortunatelly" it seems that this issue just happens with WebRTC audio tracks (so it does not happen here). And I don't have time to modify it...

JavaScript

const AUDIO_URL = 'https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3';

let audioElement;

async function run() {
	const speakers = (await navigator.mediaDevices.enumerateDevices())
	  .filter((device) => device.kind === 'audiooutput');

	addTitle('SUCCESS: setSinkId() *after* audio element was in the DOM:');

	for (const speaker of speakers) {
		addButton(speaker, true);
	}

	addTitle('ERROR: setSinkId() *before* audio element was in the DOM:');

	for (const speaker of speakers) {
		addButton(speaker, false);
	}
}


function addTitle(text) {
	const title = document.createElement('h1');

	title.textContent = text;
	document.body.appendChild(title);
}

function addButton(speaker, success) {
  const button = document.createElement('input');
  
  button.type = 'button';
  button.value = speaker.label;
  button.onclick = () => {
  	if (success) {
  		onButtonClickSuccess(speaker);
  	} else {
  		onButtonClickError(speaker);
  	}
  };

  document.body.appendChild(button);
}

async function onButtonClickSuccess(speaker) {
	if (audioElement) {
		audioElement.remove();
	}

	audioElement = document.createElement('audio');
	audioElement.src = AUDIO_URL;

	document.body.appendChild(audioElement);

	await audioElement.setSinkId(speaker.deviceId);	
	await audioElement.play();	
}

async function onButtonClickError(speaker) {
	if (audioElement) {
		audioElement.remove();
	}

	audioElement = document.createElement('audio');
	audioElement.src = AUDIO_URL;

	await audioElement.setSinkId(speaker.deviceId);
	await audioElement.play();		

	document.body.appendChild(audioElement);
}

run();