node.jsamazon-polly

AWS Polly v3: SynthesizeSpeech 'mp3', AudioStream not instanceOf Buffer


I am converting AWS Polly code in Javascript (node) from v2 to v3.

When using AWS Polly v3 synthesizeSpeech(), how can I convert the returned data.AudioStream to an instance of Buffer?

The following JavaScript code works using v2, and returned audio.AudioStream is an instance of Buffer:

const { Polly } = require('aws-sdk');

// Create an Polly client
const polly = new Polly({
    signatureVersion: 'v4',
    region: process.env.AWS_DEFAULT_REGION
});

const params = {
    OutputFormat: 'mp3',
    VoiceId: voiceId,
    TextType: 'ssml',
    Text: '<speak><prosody rate="85%">Hello World</prosody></speak>'
};

// ***

return await polly
    .synthesizeSpeech(params)
    .promise()
    .then(data => {
         if (data.AudioStream instanceof Buffer) {
             return data.AudioStream
         } else {
             console.error('AudioStream not instanceof Buffer');
             return null;
         }
     })

The following JavaScript code using v3, its response from synthesizeSpeech() contains audio.AudioStream is not an instance of Buffer, but begins with IncomingMessage:

const {
    Polly
} = require("@aws-sdk/client-polly");

// Create an Polly client
const polly = new Polly({
    signatureVersion: 'v4',
    region: process.env.AWS_DEFAULT_REGION
});

// ***

const params = {
    OutputFormat: 'mp3',
    VoiceId: voiceId,
    TextType: 'ssml',
    Text: '<speak><prosody rate="85%">Hello World</prosody></speak>'
};

return await polly
    .synthesizeSpeech(params)
    .then(data => {
         if (data.AudioStream instanceof Buffer) {
             return data.AudioStream
         } else {
             console.error('AudioStream not instanceof Buffer');
             return null;
         }
     })

I have all tried the following v3 using PollyClient and SynthesizeSpeechCommand, same results

const {
    PollyClient,
    SynthesizeSpeechCommand
} = require("@aws-sdk/client-polly");

const client = new PollyClient({
    region: process.env.AWS_DEFAULT_REGION
});

// ***

const command = new SynthesizeSpeechCommand({
    OutputFormat: 'mp3',
    Text:'hello world, this is alex',
    VoiceId: 'Kimberly',
    TextType: 'text'
});

return client
    .send(command)
    .then((data) => {
        if (data.AudioStream instanceof Buffer) {
            return data.AudioStream
        } else {
            console.error('AudioStream not instanceof Buffer');
            console.log('data.AudioStream:', data.AudioStream);
            return null;
        }
    })
    .catch((error) => {
        console.error(error);
    });

Contents of v3 data.AudioStream is:

IncomingMessage {
  _readableState:
   ReadableState {
     objectMode: false,
     highWaterMark: 16384,
     buffer: BufferList { head: null, tail: null, length: 0 },
     length: 0,
     pipes: null,
     ***

Thank you for reading, any feedback appreciated.


Solution

  • Now is a ReadableStream object.

       import { Readable } from "stream";
        //...
        if (data.AudioStream instanceof Readable) {
          console.log("Readable");
          data.AudioStream.pipe(fs.createWriteStream("fileName.mp3"));
        } else {
          console.log("no Readable");
        }
        //...
    

    You can find details about this change here: https://github.com/aws/aws-sdk-js-v3/issues/1096#issuecomment-620900466