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

如何通过PHP/Symfony+Twilio JS Voice SDK将排队呼叫转至会议室实现监控辅导

解决方案:基于Twilio TaskRouter实现排队呼叫转会议室+主管监控

核心思路:通过自定义Dequeue回调URL将入队呼叫接入动态专属会议室,再单独呼叫坐席、主管进入该会议室,全程保留TaskRouter的任务队列路由逻辑。


步骤1:服务器端新增会议室TwiML路由(PHP/Symfony)

创建控制器方法,生成将呼叫接入指定会议室的TwiML,用Reservation SID作为会议室名称后缀保证唯一性:

// src/Controller/VoiceController.php
use Twilio\TwiML\VoiceResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * @Route("/voice/conference", name="voice_conference")
 */
public function conferenceAction(Request $request)
{
    $reservationSid = $request->query->get('reservationSid');
    $conferenceName = 'support-call-' . $reservationSid;

    $voiceResponse = new VoiceResponse();
    $voiceResponse->conference($conferenceName, [
        'startConferenceOnEnter' => true,
        'endConferenceOnExit' => false,
        'record' => 'record-from-answer',
        'statusCallback' => 'https://your-domain.com/anon/voice/status',
        'statusCallbackEvent' => 'initiated,ringing,answered,completed'
    ]);

    return new Response($voiceResponse->asXml(), Response::HTTP_OK, ['Content-Type' => 'text/xml']);
}

步骤2:修改客户端Dequeue逻辑

不再直接将呼叫转接到坐席,而是先将排队呼叫导入会议室,再主动呼叫坐席进入该会议室:

this.dequeueReservation = function(data) {
    let reservation = self.getReservation(data.phone_number);
    if(!reservation) return;

    const conferenceName = 'support-call-' + reservation.sid;
    const dequeueUrl = `https://your-domain.com/voice/conference?reservationSid=${reservation.sid}`;

    // 1. 将排队呼叫转接到专属会议室
    reservation.dequeue(
        dequeueUrl,
        null,
        'record-from-answer',
        30,
        'https://your-domain.com/anon/voice/status',
        'initiated,ringing,answered,completed',
        null, // 取消原contactUri参数,由dequeueUrl返回的TwiML处理路由
        (error, newReservation) => {
            if(!error) {
                // 2. 呼叫坐席进入同一会议室
                self.joinConference(conferenceName);
            }
            onDequeue(data, error, newReservation);
        }
    );
}

// 新增方法:让坐席接入指定会议室
this.joinConference = function(conferenceName) {
    let contactUri = self.getContactUri();
    if(!contactUri) return;

    self.twilioDevice.connect({
        To: `conference:${conferenceName}`,
        AgentId: self.agent.id
    });
}

步骤3:实现主管监控/辅导功能

支持三种监控模式:监听(仅听不说)、耳语(仅和坐席对话)、辅导(三方通话),通过服务器端路由控制会议权限:

服务器端主管接入路由

/**
 * @Route("/voice/supervisor-conference", name="voice_supervisor_conference")
 */
public function supervisorConferenceAction(Request $request)
{
    $conferenceName = $request->query->get('conferenceName');
    $mode = $request->query->get('mode', 'listen');
    $agentClientId = $request->query->get('agentClientId'); // 坐席的Twilio Client标识

    $voiceResponse = new VoiceResponse();
    $dial = $voiceResponse->dial();
    
    $confParams = [
        'startConferenceOnEnter' => true,
        'endConferenceOnExit' => false,
        'beep' => 'true'
    ];

    switch($mode) {
        case 'listen':
            $confParams['muted'] = true;
            break;
        case 'whisper':
            $confParams['whisper'] = $agentClientId;
            break;
        case 'coach':
            $confParams['coach'] = $agentClientId;
            break;
    }

    $dial->conference($conferenceName, $confParams);
    return new Response($voiceResponse->asXml(), Response::HTTP_OK, ['Content-Type' => 'text/xml']);
}

客户端主管接入逻辑

// 主管后台调用此方法接入指定会议
function supervisorJoinConference(conferenceName, mode = 'listen', agentClientId) {
    const supervisorUri = `client:${self.supervisor.username}`;
    const connectUrl = `https://your-domain.com/voice/supervisor-conference?conferenceName=${conferenceName}&mode=${mode}&agentClientId=${agentClientId}`;

    self.supervisorDevice.connect({
        To: supervisorUri,
        Url: connectUrl
    });
}

关键注意事项

  • 会议室唯一性:用Reservation SID作为会议室名称后缀,避免不同呼叫的会议室冲突
  • TaskRouter状态同步:Dequeue操作完成后,TaskRouter会自动更新任务状态,保留原队列路由逻辑
  • 权限控制:主管接入功能需添加身份验证,仅授权用户可触发监控操作
  • 会议参数调整:可根据业务需求修改startConferenceOnEnter、endConferenceOnExit等参数,比如设置客户等待坐席接入时不启动会议

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:40:28