使用Twilio实现呼叫转接未接通后的语音留言功能

admin 百科 15

使用Twilio实现呼叫转接未接通后的语音留言功能-第1张图片-佛山资讯网

本文详细介绍了如何利用Twilio的TwiML功能,为基于掩码号码的呼叫转接系统添加语音留言功能。当用户的主号码因无人接听、忙线或无法接通时,系统将引导呼叫方录制语音留言。教程涵盖了通过`twiml.dial`设置呼叫超时、使用`twiml.record`进行留言录制,以及配置`recordingStatusCallback`处理录音文件并集成语音转文本及邮件通知的实现细节。

在构建基于掩码号码(Masked Number)的通信应用时,实现呼叫转接是核心功能之一。用户通过购买的掩码号码接收客户来电,系统将这些来电转接到用户的真实号码上。然而,当用户的真实号码无法接通、忙线或无人应答时,提供一个语音留言机制将极大提升用户体验,确保重要信息不丢失。本文将指导您如何利用Twilio的TwiML指令,为您的应用集成这一关键功能。

1. 呼叫转接与未接通处理

首先,我们需要确保呼叫能够正确地从掩码号码转接到用户的真实号码。在您的Twilio语音Webhook中,当接到来自客户的来电时,您会获取到呼叫信息,并通过查询数据库获取掩码号码对应的用户真实号码(primaryPhoneNumber)。

在现有的代码逻辑中,router.post("/webhook/voice", ...) 负责处理入站语音呼叫。当CallStatus为"ringing"时,我们通过twiml.dial(primaryPhoneNumber)将呼叫转接出去。为了处理未接通的情况,我们需要为dial动词添加timeout属性。

设置呼叫转接超时:

timeout属性定义了Twilio在放弃尝试连接被叫方之前等待的秒数。一旦达到超时,如果呼叫未成功建立,Twilio将继续执行TwiML响应中的下一个动词。

const twilio = require("twilio");
const express = require("express");
const router = express.Router();
// ... (其他引入和数据库操作函数)

router.post("/webhook/voice", async (req, res) => {
  const { To, From, CallStatus } = req.body;

  const [numbers] = await getNumberWithoutUser(To);
  if (!numbers) return res.status(400).send("User does not own this number");

  const type = numbers.numbers.subscriptions.find(
    (subscription) => subscription.active
  ).type;
  const isToPrimaryPhone =
    numbers?.numbers?.settings?.forwarding?.toPrimaryPhone;
  const primaryPhoneNumber =
    numbers?.numbers?.settings?.forwarding?.primaryPhoneNumber;

  if (isToPrimaryPhone) {
    switch (CallStatus) {
      case "ringing":
        const twiml = new twilio.twiml.VoiceResponse();

        // 1. 尝试呼叫用户的真实号码,设置超时为7秒
        // 如果在7秒内未接通,Twilio将继续执行TwiML中的下一个指令
        const dial = twiml.dial({
          timeout: 7 // 设置呼叫超时时间,单位:秒
        });
        dial.number(primaryPhoneNumber); // 拨打用户的真实号码

        // ... (后续的语音留言逻辑将在此处添加)

        await updateQuota(numbers._id, To, "callForwarding", type);
        res.type("text/xml");
        return res.send(twiml.toString());

      case "completed":
        await appendCall(numbers._id, To, From, req.body);
        return res.send("success");
    }
  }
  res.send("Call Forwarding is disabled or package has finished");
});

登录后复制

2. 实现语音留言录制

在dial动词超时或失败后,我们可以使用twiml.record动词来提示呼叫方录制语音留言。

twiml.record的关键属性:

  • recordingStatusCallback: 这是最重要的属性。当录音完成后,Twilio会向这个URL发送一个POST请求,其中包含录音文件的URL (RecordingUrl)、录音时长 (RecordingDuration) 等详细信息。您需要在此回调URL对应的端点处理录音文件。
  • maxLength: 设置录音的最大时长(秒)。
  • finishOnKey: 允许呼叫方按下指定按键(如*或#)提前结束录音。
  • playBeep: 是否在录音开始前播放提示音(蜂鸣声)。

集成语音留言功能:

在上述case "ringing"的代码块中,紧跟在twiml.dial之后添加twiml.say和twiml.record动词。

      case "ringing":
        const twiml = new twilio.twiml.VoiceResponse();

        const dial = twiml.dial({
          timeout: 7
        });
        dial.number(primaryPhoneNumber);

        // 如果主号码未接通(超时、忙线、无人接听),则执行以下语音留言逻辑
        twiml.say({ voice: 'Polly.Zhiyu', language: 'zh-CN' }, "您好,您拨打的用户暂时无法接听,请在滴声后留言。"); // 语音提示
        twiml.record({
          recordingStatusCallback: "https://your-ngrok-url/webhook/voice/voicemail-callback", // 替换为您的实际回调URL
          maxLength: 60, // 最大录音时长60秒
          finishOnKey: '*' // 呼叫方按*号结束录音
        });
        twiml.say({ voice: 'Polly.Zhiyu', language: 'zh-CN' }, "感谢您的留言,再见。"); // 录音结束后的提示

        await updateQuota(numbers._id, To, "callForwarding", type);
        res.type("text/xml");
        return res.send(twiml.toString());

登录后复制

注意事项:

标签: go app ai switch 路由 google 邮箱

发布评论 0条评论)

还木有评论哦,快来抢沙发吧~