I'm using Twilio's example of Google Cloud Speech to transcribe the audio stream of Twilio in real time (because twilio model doesn't support my language). But I wanted to response to user after I heard some keyword from them. But the gather function only works with Twilio's speech model.
app.post("/", (req, res) => {
res.set("Content-Type", "text/xml");
res.send(`
<Response>
<Start>
<Stream url="wss://${req.headers.host}/"/>
</Start>
<Say>Hello?</Say>
<Gather/>
</Response>
`);
});
I would like to know how to response to user after I catch the keyword, I tried to response in the stream but it doesn't work:
recognizeStream = client
.streamingRecognize(request)
.on("error", console.error)
.on("data", (data) => {
console.log("result: " + data.results[0].alternatives[0].transcript);
if (data.results[0].alternatives[0].transcript.toLowerCase() == "xin chào"){
console.log("got xin chao")
app.post("/", (req, res) => {
res.set("Content-Type", "text/xml");
res.send(`
<Response>
<Say>Hello there</Say>
</Response>
`);
});
}
Please help me out, thanks!
Twilio developer evangelist here.
When you use <Start><Stream> Twilio forks the audio and starts sending the audio from the call to your websocket. The call then carries on with the next TwiML instruction. If you want to interrupt the user once they say a keyword there are two approaches you can take.
Instead of using <Start><Stream> you can use <Connect><Stream>. <Connect> sets up a bidirectional stream, allowing you to receive the audio over the web socket connection and send audio back over the web socket. This way you could use the Google Cloud Speech API to generate your responses and stream them into the call. <Connect> doesn't fork the stream, so it won't carry out the TwiML instructions after it until the connection is ended.
Alternatively, you can continue using <Start><Stream> but once you get the keyword you are looking for you can redirect the call to new TwiML. Note that you need to use the REST API to update the call rather than returning TwiML within the web socket stream, like you are attempting.
Related
I have a small Twilio app that calls a real phone number (e.g. +3333333) whenever my Twilio number (e.g. +22222222) is called using my personal number (e.g. +1111111). I implement this using the following Twilio function:
exports.handler = (context, event, callback) => {
const twiml = new Twilio.twiml.VoiceResponse();
twiml.dial("+3333333");
return callback(null, twiml);
};
Now when the owner of +3333333 picks up his phone, a call connection is established between the caller (+1111111) and the target (+3333333).
How can I intercept speeches in this call, in real-time, by running a function whenever either the caller (+1111111) or the target (+3333333) speaks, to do things such as changing voice, filtering profanity, etc?
I have tried using <Gather> and <Say> TwiML verbs in my Twilio function but these will only get triggered after the call has ended or hung up.
You can actually achieve this with Twilio now. You can receive and send audio streams using the <Connect><Stream> TwiML. <Stream> allows you to receive and send audio to the call over a websocket connection in real time.
To change the audio in between, you would want to connect the callers just to the <Stream>, not to each other, and relay the audio from one call, through the websocket and whatever processing you want to do to it, and then out through the websocket connected to the other call (and vice versa).
I don't have more information on how to do that, as I've not seen it done. But it's possible in theory.
I've been following the https://github.com/TwilioDevEd/browser-calls-node project code, and I have it successfully making calls from a browser to a cellular phone, but I can't for the life of me figure out if Twilio's supports DTMF inside that call from the Cell phone.
Calling their sales department just had them create a support ticket and I haven't gotten a response.
Has anyone successfully done this? And if so, how?
This is the code I've added is to call.js, in the /connect endpoint I added:
const gather = twiml.gather({
input: 'dtmf',
finishOnKey: 9,
timeout: 1,
action: '/call/completed'
});
gather.say('Welcome to Twilio, please tell us why you\'re calling');
console.log(twiml.toString())
As well as added the route:
router.post('/completed', twilio.webhook({ validate: false }), function (req, res, next) {
console.log(req.toString());
});
Their support team replied saying (tl;dr) they only support sendDigits(digits) in the SDK, and do not support recognizing DTMF in incoming audio stream.
Their response:
The Twilio Client SDK's sendDigits(digits) parameter can used to pass dtmf tones.
The SDK only supports sending DTMF digits. It does not raise events if DTMF digits are present in the incoming audio stream.
Ref:https://www.twilio.com/docs/voice/client/javascript/connection#sendDigits```
So i'm trying to make it so an outbound call gets redirected to my Autopilot system, but my Twiml does seem to recognize the connect function built into the voice response method
I've tried to have the account sid be provided, call, and even load the link in a browser, it just gives the same error
Heres the code im using
exports.handler = function(context, event, callback) {
let res = new Twilio.twiml.VoiceResponse();
console.log(res.toString());
res.connect().autopilot(context.AI_SID);
console.log(res.toString());
callback(null, res);
};
It should return the code below, but seems like this doc is not accurate: https://www.twilio.com/docs/voice/twiml/connect
<Response>
<Connect>
<Autopilot>#####</Autopilot>
</Connect>
</Response>
Update the Twilio helper libraries under your Twilio Functions, Configure, to use a release that added this verb.
https://github.com/twilio/twilio-node/blob/master/CHANGES.md
I know how to send an SMS via Twilio to a phone number specified in the request body, however I need a way for this route to wait for the user to respond with a text message. I need to capture that messages body and send it as a response.
router.post('/', function(req, res){
var customerNumber = req.body.mobileNumber;
var twilioNumber = process.env.TWILIO_NUMBER;
client.messages
.create({
to: '+1' + customerNumber,
from: twilioNumber,
body: 'message to user',
provideFeedback: 'true',
}, function(err, message){
if(err) res.send('message err: ' + err);
else{
// wait 10-20 seconds for user to respond
res.send("A response from the user");
}
})
});
I also know how to listen to responses with Twilio, but this doesn't work because I need the above route to respond with the message I get from the user in the route below.
router.post('/sms-response', function(req, res){
var twilio = require('twilio');
var twiml = new twilio.twiml.MessagingResponse();
twiml.message('thanks for your feedback');
res.writeHead(200, {'Content-Type':'text/xml'});
res.end(twiml.toString());
});
I've been looking for a way to do this all day with no success at all. I appreciate your help!
I dont know if that is possible yet, I went through their documentation and didnt see that feature yet. I would suggest using a web socket like socket.io. When message comes in you can just pass the response in through the socket to the user.
Twilio developer evangelist here.
While this could technically be possible I strongly recommend against it. You mention that you might be waiting for 10-20 seconds, but users are much more fickle than that, as are mobile networks. So getting a response may take much longer that that or even never happen. Then you'd be left with a long running connection to your server waiting for a response that might never come.
As Hammer suggested, it would be better to return a response to the user straight away, saying something like "We're waiting for your response", then connecting that user's browser to your server via a websocket or server sent event stream. When you receive the incoming message on your webhook endpoint, you can then send the information down the websocket or event source and react to that in the front end.
Let me know if that helps at all.
When a user texts my number, I would like to respond with a message using TwiML. I'd also like to know whether my response message sends or fails. I'm creating my TwiML response using the Twilio library for Node.js.
Here is my code:
const response = new twilio.TwimlResponse();
response.message(Response, {
statusCallback: '/sms/status/'
});
Here is the code for the route. Please note that the router is mounted upon the "/sms/" router:
router.post('/status/', acceptRequestsOnlyFromTwilio, (req, res) => {
const Event = require('./../models/schemas/event');
const event = new Event({
description:
`MessageSid = ${req.body.MessageSid}
MessageStatus = ${req.body.MessageStatus}`
});
event.save();
console.log(
`MessageSid = ${req.body.MessageSid}
MessageStatus = ${req.body.MessageStatus}`
);
res.sendStatus(200);
});
When I check my logs using the Heroku CLI, I don't log nor do I see a record when I check MongoDB.
Anyone have any ideas or tips on how I can go about debugging this or if I'm implementing this incorrectly?
Thanks for you time!
Twilio developer evangelist here.
Firstly, have you set your Messaging request URL for the Twilio phone number you are using? Is it pointing at the correct route for your Message TwiML response?
Also, your first code block should also be within a router.post endpoint for your server. Do you correctly return the TwiML response as the server response?
As a tip, it might be better to develop this application locally and test your webhook endpoints using a tool like ngrok. I love using ngrok to test webhooks.