You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Twilio可编程语音、Function及TWIML实现IVR多语音输入交互

实现基于Twilio可编程语音的IVR系统(结合Twilio Function与TwiML)

看起来你已经搞定了Twilio呼叫的基础流程,接下来咱们把这个IVR系统打磨得更实用——让它能根据用户的语音/按键输入返回对应业务回复,结合你已有的Webhook和Twilio Function,一步步完善如下:

一、先理清楚现有逻辑的作用

你当前的C# Webhook负责初始化呼叫流程:通过<Gather>组件触发语音/按键收集,设置超时时间,并指定把用户输入结果发送到你的Twilio Function地址;而Twilio Function则接收语音识别结果,返回对应的TwiML回复。

你的现有Webhook代码(C#)

[HttpPost] 
public TwiMLResult Index(string message) { 
    var response = new VoiceResponse(); 
    var gather = new Gather(
        input: new List<Gather.InputEnum>() { Gather.InputEnum.Speech } , 
        timeout: 5, 
        action:new Uri("https://url-sample/GatherSample")
    ); 
    gather.Say("Please press 1 or say sales for sales."); 
    response.Append(gather); 
    LogWriter.Debug($"Message : {response.ToString()}"); 
    return new TwiMLResult(response); 
}

你的现有Twilio Function代码

exports.handler = function(context, event, callback) { 
    const twiml = new Twilio.twiml.VoiceResponse(); 
    const command = event.SpeechResult.toLowerCase(); 
    twiml.say(`You said ${command}. I'll give you a ${command} fact.`); 
    callback(null, twiml); 
};

二、完善IVR核心功能的关键调整

1. 给Function添加分支逻辑,匹配不同指令

现在的Function只是简单重复用户输入,咱们可以加条件判断,针对不同的语音/按键指令返回不同的业务回复,同时处理无法识别的情况:

调整后的Twilio Function代码:

exports.handler = function(context, event, callback) { 
    const twiml = new Twilio.twiml.VoiceResponse(); 
    // 兼容语音识别结果为空或按键输入的情况
    const command = event.SpeechResult?.toLowerCase() || event.Digits || '';

    // 匹配销售相关指令(支持语音说sales/按1)
    if (command.includes('sales') || command === '1') {
        twiml.say("Thank you for choosing our sales team. We're available Monday to Friday, 9 AM to 5 PM. You'll be connected to a representative in just a moment.");
        // 如果需要直接转接电话,添加<Dial>组件即可
        // twiml.dial('+1234567890');
    } 
    // 新增支持客服分支(语音说support/按2)
    else if (command.includes('support') || command === '2') {
        twiml.say("Welcome to customer support. Please briefly describe your issue, and we'll help you resolve it right away.");
        // 如果需要再次收集用户问题,可以在这里嵌套<Gather>跳转到另一个Function
        // const gather = twiml.gather({input: 'speech', timeout: 10, action: '/support-handler'});
        // gather.say("Please describe your issue now.");
    }
    // 处理无法识别的输入,引导重试
    else {
        twiml.say("Sorry, I didn't catch that. Please say 'sales' or press 1 for sales, or say 'support' or press 2 for customer service.");
        // 跳回初始的Webhook,让用户重新输入
        twiml.redirect('https://url-sample/'); // 替换成你初始Webhook的公网地址
    }

    callback(null, twiml); 
};

2. 优化Webhook的配置,提升体验

咱们可以让<Gather>同时支持语音和按键输入,添加针对电话场景的语音模型提升识别准确率,还要加上超时后的 fallback 提示:

调整后的Webhook代码:

[HttpPost] 
public TwiMLResult Index(string message) { 
    var response = new VoiceResponse(); 
    var gather = new Gather(
        input: new List<Gather.InputEnum>() { Gather.InputEnum.Speech, Gather.InputEnum.Dtmf }, 
        timeout: 5,
        numDigits: 1, // 按键只收集1位,适合IVR快捷选择
        action: new Uri("https://url-sample/GatherSample"),
        speechModel: Gather.SpeechModelEnum.PhoneCall // 专门优化电话场景的语音识别模型
    ); 
    // 把提示语说得更清晰,引导用户操作
    gather.Say("Welcome to our IVR system. Please press 1 or say 'sales' to reach the sales team, or press 2 or say 'support' for customer service."); 
    response.Append(gather); 

    // 如果用户超时未输入,播放 fallback 提示
    response.Say("Sorry, I didn't receive any input. Thank you for calling, goodbye.");

    LogWriter.Debug($"Message : {response.ToString()}"); 
    return new TwiMLResult(response); 
}

3. 必要的配置检查

  • 确保你的Twilio Function已经绑定了正确的Twilio账号,并且地址能被Twilio访问到(本地开发的话,用ngrok之类的工具暴露公网地址)。
  • 检查Webhook和Function的action地址是否正确,避免拼写错误导致无法回调。

三、测试验证流程

  1. 用你的Twilio号码发起呼叫,听IVR提示语。
  2. 测试正常路径:说sales或者按1,确认返回销售相关回复;说support或者按2,确认客服分支生效。
  3. 测试异常路径:说无关关键词,确认引导重试的提示正常播放;不做任何操作等超时,确认fallback提示生效。

内容的提问来源于stack exchange,提问作者Ayyappan Subramanian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:49:53