How to capture generated audio from window.speechSynthesis.speak() call?

Viewed 9482

Previous questions have presented this same or similar inquiry

yet no workarounds appear to be have been created using window.speechSynthesis(). Though there are workarounds using epeak , meSpeak How to create or convert text to audio at chromium browser? or making requests to external servers.

How to capture and record audio output of window.speechSynthesis.speak() call and return result as a Blob, ArrayBuffer, AudioBuffer or other object type?

2 Answers

This is an updated code from previous answer which works in Chrome 96:

  • make sure to select "Share system audio" checkbox in "Choose what to share" window
  • won't run via SO code snippet (save to demo.html)

<script>
(async () => {
const text = "The revolution will not be televised";

const blob = await new Promise(async resolve => {
    console.log("picking system audio");
    const stream = await navigator.mediaDevices.getDisplayMedia({video:true, audio:true});
    const track = stream.getAudioTracks()[0];
    if(!track)
        throw "System audio not available";
    
    stream.getVideoTracks().forEach(track => track.stop());
    
    const mediaStream = new MediaStream();
    mediaStream.addTrack(track);
    
    const chunks = [];
    const mediaRecorder = new MediaRecorder(mediaStream, {bitsPerSecond:128000});
    mediaRecorder.ondataavailable = event => {
        if (event.data.size > 0)
            chunks.push(event.data);
    }
    mediaRecorder.onstop = () => {
        stream.getTracks().forEach(track => track.stop());
        mediaStream.removeTrack(track);
        resolve(new Blob(chunks));
    }
    mediaRecorder.start();
    
    const utterance = new SpeechSynthesisUtterance(text);
    utterance.onend = () => mediaRecorder.stop();
    window.speechSynthesis.speak(utterance);
    console.log("speaking...");
});
console.log("audio available", blob);

const player = new Audio();
player.src = URL.createObjectURL(blob);
player.autoplay = true;
player.controls = true;

})()
</script>

Related