Send Recorded Twilio Audio To Lex

安稳与你 提交于 2019-12-10 19:04:54

问题


Currently I am able to record user input, pass the recording URL to the needed function, and download the audio file locally. What I am trying to do with the audio file is either get a buffer of it to send to Lex or convert it to the format Lex needs.

Per AWS Documentation the following values are accepted for the input stream param value:

var params = {
  botAlias: 'STRING_VALUE', /* required */
  botName: 'STRING_VALUE', /* required */
  contentType: 'STRING_VALUE', /* required */
  inputStream: new Buffer('...') || 'STRING_VALUE' || streamObject, /*required */
  userId: 'STRING_VALUE', /* required */
  accept: 'STRING_VALUE',
  requestAttributes: any /* This value will be JSON encoded on your behalf with JSON.stringify() */,
  sessionAttributes: any /* This value will be JSON encoded on your behalf with JSON.stringify() */
};
lexruntime.postContent(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
});

Per the twilio documentation it looks like the audio file is pretty flexible...

A request to the RecordingUrl will return a recording in binary WAV audio format by default. To request the recording in MP3 format, append ".mp3" to the RecordingUrl.

What do I need to do to get the twilio recorded audio in the right format for Lex? Is it just a matter of building the correct Lex param set or do I need to do some audio conversion before hand? I am writing this application in node js if that helps and I can add more code if it will help.


回答1:


I was able to figure this out by downloading the file from Twilio as a PCM and changing my parameters a bit. Also, due to the way that Twilio handles the record verb, I needed to transfer the call to a hold state while waiting for the recordingStatusCallback to POST out. I also send a text to the caller with the final status from Lex.

The code I used to download the file:

app.post('/processRecording', (request, response) => {   
    var https = require('https');
    var fs = require('fs');

    let callSID = request.body.CallSid;
    let url = request.body.RecordingUrl;

    var saveFile = new Promise(function(resolve, reject) {
       let fileName = callSID+ ".pcm";
       var file = fs.createWriteStream(fileName);
       var request = https.get(url, function(response) {
       response.pipe(file);
       resolve();
      });
    });

});

const accountSid = 'YOUR ACCOUNT SID';
const authToken = 'YOUR AUTH TOKEN';
const client = require('twilio')(accountSid, authToken);
//Once the file is downloaded, I then fetch the call from the hold state using this code:
saveFile.then(function(){
client.calls(callSID)
    .update({method: 'POST', url: '/updateCall'})
    .then(call => console.log(call.to))
    .done();
  });

And my updateCall endpoint looks like this:

app.post('/updateCall', (request, response) => {
    let lexruntime = new AWS.LexRuntime();
    let recordedFileName = request.body.CallSid + '.pcm';
    let toNumber = request.body.To;
    let fromNumber = request.body.From;
    let twiml = new Twilio.twiml.VoiceResponse();
    let lexFileStream = fs.createReadStream(recordedFileName);
    let sid = request.body.CallSid;
    var params = {
        botAlias: 'prod', /* required */
        botName: 'OrderFlowers', /* required */
        contentType: 'audio/lpcm; sample-rate=8000; sample-size-bits=16; channel-count=1; is-big-endian=false',
        accept: 'text/plain; charset=utf-8',
        userId: sid /* required */

    };

params.inputStream = lexFileStream;

lexruntime.postContent(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(data);           // successful response



    if (data.dialogState == "ElicitSlot" || data.dialogState == "ConfirmIntent" || data.dialogState == "ElicitIntent" ){
        twiml.say(data.message);
        twiml.redirect({
                        method: 'POST'
                        }, '/recordVoice');

            response.type('text/xml');
            response.send(twiml.toString());

    }
    else if (data.dialogState == "Fulfilled" ){
      twiml.say(data.message);
      response.type('text/xml');
      response.send(twiml.toString());
        client.messages.create({
           to: toNumber,
           from: fromNumber,
           body: data.message
        }).then(msg => {
        }).catch(err => console.log(err));
     }
    else{
        twiml.say(data.message);
        response.type('text/xml');
        response.send(twiml.toString());
    }

    });
});

The recordVoice endpoint is actually a Twilio Serverless Function But I think this is what it would look like as an express endpoint:

 app.post('/recordVoice', (request, response) => {
    let twiml = new Twilio.twiml.VoiceResponse();
    twiml.record({
        action: '/deadAir',
        recordingStatusCallback: '/processRecording',
        trim: true,
        maxLength: 10,
        finishOnKey: '*'
    });
    twiml.say('I did not receive a recording');
    response.type('text/xml');
    response.send(twiml.toString());
});

The /deadAir endpoint is also a Twilio Serverless Function but this is what it would look like:

app.post('/deadAir', (request, response) => {
    let twiml = new Twilio.twiml.VoiceResponse();
    twiml.pause({
        length: 60
    });
    response.type('text/xml');
    response.send(twiml.toString());
});


来源:https://stackoverflow.com/questions/51898951/send-recorded-twilio-audio-to-lex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!