3

I'm getting a binary audio file when I call the api tts.speech.microsoft.com and I would like to transform this binary into a base64 string.

I've been trying a lot of things, for example:

Buffer.from(body, "binary").toString("base64");

does not work.

I'm not sure 'binary' is the exact word, but it's not a readable format.

Thank you for your help.

GuillaumeC
  • 535
  • 1
  • 8
  • 18
  • Can you clarify "does not work"? The code looks correct. Also where does the binary data come from? Some things such as fs.readFile has shortcuts to convert to base64. – Dominic Jan 29 '19 at 14:50
  • I call this endpoint from a phone, and try to play the sound. When I try to do it with another base64 string it works so I know the code on this part is ok. @Dominic – GuillaumeC Jan 29 '19 at 14:54
  • Where does the other base64 string come from? My hunch is that your original binary content is not correct/the same format as the working one – Dominic Jan 29 '19 at 14:58
  • it comes from google cloud. – GuillaumeC Jan 29 '19 at 15:03
  • when I try to save the file from my computer and read it with: require("fs").writeFile("out.mp3", content, "base64", function(err) { console.log(err); }); – GuillaumeC Jan 29 '19 at 15:03
  • the file is not readable... – GuillaumeC Jan 29 '19 at 15:03
  • 1
    You can see here there is nothing wrong with the conversion code - https://repl.it/@DominicTobias/WorstUtilizedComputers (converting binary "apple" to base64 and back). So the issue is in code you haven't posted, most likely your binary data is incorrect compared to the working one – Dominic Jan 29 '19 at 15:04
  • Yeah I can see this part is correct, but when I try to save the file and read it locally from my computer, the file is not readable: const content = Buffer.from(body, "binary").toString("base64"); require("fs").writeFile("out.wav", content, "base64", function(err) { console.log(err); }); Maybe the response is not in binary ? – GuillaumeC Jan 29 '19 at 15:18
  • 1
    What format is `body` in? Is it just incoming as a buffer/byte array? – Alex Jan 29 '19 at 16:34
  • @Alex body is a string. The only solution I found is to save the file with createwritestream , and then read the file in base64 and send it. This is not ideal of course, but I've been playing with it for hours... – GuillaumeC Jan 30 '19 at 09:16

1 Answers1

6

I guess you were following the section Make a request and save the response of the offical document Quickstart: Convert text-to-speech using Node.js to write your code, as below.

var request = require('request');

let options = {
    method: 'POST',
    baseUrl: 'https://westus.tts.speech.microsoft.com/',
    url: 'cognitiveservices/v1',
    headers: {
        'Authorization': 'Bearer ' + accessToken,
        'cache-control': 'no-cache',
        'User-Agent': 'YOUR_RESOURCE_NAME',
        'X-Microsoft-OutputFormat': 'riff-24khz-16bit-mono-pcm',
        'Content-Type': 'application/ssml+xml'
    },
    body: body
};

function convertText(error, response, body){
  if (!error && response.statusCode == 200) {
    console.log("Converting text-to-speech. Please hold...\n")
  }
  else {
    throw new Error(error);
  }
  console.log("Your file is ready.\n")
}
// Pipe the response to file.
request(options, convertText).pipe(fs.createWriteStream('sample.wav'));

So I change the offical code above to create a function encodeWithBase64 to encode body with Base64.

function encodeWithBase64(error, response, body){
  if (!error && response.statusCode == 200) {
    var strBase64 = Buffer.from(body).toString('base64');
    console.log(strBase64);
  }
  else {
    throw new Error(error);
  }
  console.log("Your file is encoded with Base64.\n")
}
// Pipe the response to file.
request(options, convertText);

Or you can use the npm packages base64-stream and get-stream to get the string with Base64 from body.

var base64 = require('base64-stream');
const getStream = require('get-stream');
(async () => {
    var encoder = new base64.Base64Encode();
    var b64s = request(options).pipe(encoder);
    var strBase64 = await getStream(b64s);
    console.log(strBase64);
})();

Otherwise, stream-string also can do it.

var base64 = require('base64-stream');
const ss = require('stream-string');
var encoder = new base64.Base64Encode();
var b64s = request(options).pipe(encoder);
ss(b64s).then(data => {
  console.log(data);
})
Peter Pan
  • 23,476
  • 4
  • 25
  • 43