Play Watson Text-to-Speech via XHR
Updated: 03 September 2023
Play the Audio
In order to play audio from the result of an XHR request we can make use of the following code (in this case using the IBM Watson Text to Speech Service), this will make the request, store the response audio as a Blob
, assign that to an Audio Element, and then play the audio.
We will need to have the following in our HTML
1<audio id="myAudioElement" />
And then the necessary Javascript to get the audio source set on the element
1var data = null2var xhr = new XMLHttpRequest()3xhr.withCredentials = true4xhr.responseType = 'blob'5xhr.addEventListener('readystatechange', function () {6 if (this.readyState === 4) {7 //console.log(this.responseText);8 }9})10xhr.onload = function (evt) {11 var binaryData = []12 binaryData.push(xhr.response)13 var blob = new Blob(binaryData, { type: 'audio/mp3' })14 var objectUrl = window.URL.createObjectURL(15 new Blob(binaryData, { type: 'application/zip' })16 )17 console.log(objectUrl)18 var audioElement = document.getElementById('myAudioElement')19 audioElement.src = objectUrl20 audioElement.play()21}22xhr.open(23 'GET',24 `speech/text-to-speech/api/v1/voices/en-GB_KateVoice/synthesize?text=${text}`25)26xhr.setRequestHeader('Accept', 'audio/mp3')27xhr.setRequestHeader('Authorization', 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXX')28xhr.setRequestHeader('cache-control', 'no-cache')29xhr.send(data)
Note that we may get blocked by CORS, in order to prevent this we can make use of an Express Proxy on the server side (or really any kind of proxy) which will serve our site files from a public
folder, and proxy requests to /speech
to https://stream.watsonplatform.net/
1const express = require('express')2var proxy = require('express-http-proxy')3
4const app = express()5
6app.use(express.static('public'))7app.use('/speech', proxy('https://stream.watsonplatform.net/'))
It may be possible to make the request on the server as well and simply pass the binary forward, however I have not gotten that to work as yet