我对 Twilio Media Stream 集成有一些疑问。我目前正在使用 Nest.js 和 socket.io 构建一个通信应用程序,该应用程序可以从我的应用程序拨打常规电话号码。在网络研究过程中,我发现了一个解决方案,建议结合使用 Twilio Media Streams 和 Twilio Voice 来实现我的目标。不过,在这个过程中我也遇到了一些挑战。
在这种情况下,当使用我的应用程序的用户 A 向用户 B 的常规电话号码发起呼叫时,我的应用程序利用 Twilio API 建立电话呼叫,并同时提供 URL 来启动流处理过程。
实际问题源于 Twilio 不支持我的应用程序使用的 socket.io。因此,我没有收到来自 Twilio 的任何事件。为了解决这个问题,我决定创建一个单独的 Node.js 应用程序,它使用 websockets 而不是 socket.io。这使我能够接收事件。
然而,新的问题又出现了。当用户发起呼叫时,我会收到呼叫 SSID,但该 SSID 不包含在 Twilio 通过 websockets 发出的事件中。相反,Twilio 会发出一个流 SSID,该 SSID 不存在于呼叫发起应用程序的后端中。因此,我无法确定哪个流对应于每个用户的呼叫。
此外,由于多个用户可以同时使用该应用程序并拨打电话,因此挑战变得更加复杂。我目前正在寻找更有效的方法来实现我的目标。
我想为您提供我的第一个和第二个应用程序的相关代码摘录。
第一个应用程序:发起呼叫
public async makeCall(to: string, from: string): Promise<TwilioCallResponse> {
/**
* This function hits when the user initiates call from my application
*/
try {
const call = await this.twilioClient.calls.create({
twiml: `<Response>
<Pause length="10000"/>
</Response>`,
url: `https://${this.DOMAIN_URL}/twilio-media-stream/startStream`,
statusCallback:`https://${this.DOMAIN_URL}/twilio-media-stream/status`,
statusCallbackEvent: ['initiated', 'answered','completed','ringing'],
statusCallbackMethod: 'POST',
to: to,
from: from,
});
return TwilioCallResponse.of(true, call.sid);
} catch (error) {
console.log(error.message);
return TwilioCallResponse.of(false, '', error.message);
}
}
第一个应用程序:监听回调以开始流媒体
public async startStream(res:Response,body:TwilioStatusCallbackRequest){
// This function is called when the call is answered. So we can start stream here.
const twiml = new VoiceResponse();
// In this functions context we get access to call SSID, Since twilio sends that via the callback
const callSid=body.CallSid
twiml.start().stream({ url: `wss://old-rings-trade.loca.lt` });
twiml.say('Hello, this call will be transcribed.');
twiml.pause({ length: 60000 });
console.log(twiml.toString())
res.writeHead(200, {'Content-Type': 'text/xml'});
return res.end(twiml.toString());
}
第二个应用程序:从 twilio 媒体流捕获事件并用它做一些事情
wss.on("connection", function connection(ws) {
console.log("New Connection Initiated");
ws.on("message", function incoming(message) {
const msg = JSON.parse(message);
//here the event doesnt have callSSID. So that i cant determine the event is for which call.
switch (msg.event) {
case "connected":
//i'll do some stuff
break;
case "start":
//i'll do some stuff
break;
case "media":
//i'll do some stuff
break;
case "stop":
//i'll do some stuff
break;
}
});
});
这里是 Twilio 技术支持工程师。正如您正确地提到的,我们的媒体流产品不支持 socket.io 协议,我们使用原始的 websockets。对于缺少呼叫 SID 的情况,我们在 Start Message 中将其作为
start.callSid
与您已经看到的 start.streamSid
一起发送。