使用Twilio Gather动词在同一通话中获取多语音回复问题排查
问题原因分析
你的问题出在Twilio <Gather> 的工作机制上——当用户完成语音输入后,Twilio会把请求发送到你指定的action地址,默认情况下,这个请求处理完后通话就会结束,不会继续执行后续的Twiml指令。你现在是一次性把三个问题的<Gather>都塞进初始Twiml里,但第一个<Gather>触发后就跳去webhook,后续的指令根本没机会执行,所以通话直接结束,只收到一条回复。
解决方案
要实现多问题的连续调查,你需要通过webhook的状态流转来逐步返回每个问题的Twiml,而不是一次性生成所有内容。具体做法如下:
1. 修改初始呼叫的Twiml生成逻辑
初始发起呼叫时,只播放第一个问题的音频和提示,并在<Gather>的action参数里带上当前问题的索引(用来标记进度):
const makeCalls = async () => { let callCount = 0; for (const phoneNumber of phoneNumberList) { if (callCount >= 40) { await new Promise(resolve => setTimeout(resolve, 60000)); callCount = 0; } const response = new twilio.twiml.VoiceResponse(); // 只处理第一个问题 const firstAudio = audioFiles[0]; response.play(firstAudio.url); response.say(firstAudio.question, { voice: 'alice', language: 'es-MX' }); // action带上问题索引,方便webhook判断进度 response.gather({ input: 'speech', language: 'es-MX', action: `${webhookEndpoint}?questionIndex=0`, speechtimeout: 1, method: 'POST', }); const twiml = response.toString(); await client.calls.create({ twiml: twiml, from: fromPhoneNumber, to: `+52${phoneNumber}`, record: true, transcribe: true, language: 'es-MX', }) .then(call => { console.log('Call initiated:', call.sid); callCount++; }) .catch(error => { console.error('Failed to make the call:', error); }); } };
2. 编写Webhook的处理逻辑
webhook需要接收用户的转录内容(通过SpeechResult参数),保存当前回复,然后根据questionIndex判断是否还有下一个问题:
// 假设用Express实现webhook,示例代码如下 app.post('/webhook', (req, res) => { const questionIndex = parseInt(req.query.questionIndex); const speechResult = req.body.SpeechResult; const callSid = req.body.CallSid; // 这里将用户回复保存到数据库/文件,关联通话ID和问题索引 console.log(`Call ${callSid} - Q${questionIndex+1}: ${speechResult}`); const response = new twilio.twiml.VoiceResponse(); const nextIndex = questionIndex + 1; if (nextIndex < audioFiles.length) { // 还有下一个问题,生成对应Twiml const nextAudio = audioFiles[nextIndex]; response.play(nextAudio.url); response.say(nextAudio.question, { voice: 'alice', language: 'es-MX' }); // action带上下一个问题的索引 response.gather({ input: 'speech', language: 'es-MX', action: `${webhookEndpoint}?questionIndex=${nextIndex}`, speechtimeout: 1, method: 'POST', }); } else { // 所有问题完成,结束通话 response.say('感谢你的回答,通话即将结束。', { voice: 'alice', language: 'es-MX' }); response.hangup(); } res.type('text/xml'); res.send(response.toString()); });
关键要点
- 每次
<Gather>的action必须带上当前问题索引,让webhook明确处理进度 - webhook处理完当前回复后,必须返回新的Twiml才能继续通话,否则Twilio会默认结束流程
- 需自行实现回复存储逻辑,关联通话ID与问题索引,确保每个回复对应正确的问题
内容的提问来源于stack exchange,提问作者Art N Werk Studio
相关产品推荐
相关产品推荐

