XSwitch Cloud
WebRTC 呼叫
XSwitch Cloud 支持 WebRTC 呼叫。
通过 WebRTC 技术,可以在浏览器中直接发起通话,支持最新的 Chrome、Firefox、Safari、Edge 等浏览器。
WHIP
WHIP协议基于 HTTP 实现,比较简单,简单的呼叫只需要发送一个 HTTP POST 请求即可。
WHIP 本来是一个单向的协议,用于浏览器向服务端(即 XSwitch Cloud)推流;而 WHAP 则可以从服务端拉流。通过 WHIP 和 WHAP,可能通过两个连接实现双向通信。
XSwitch 扩展了 WHIP 协议,通过 WHXP,可以在一个流上实现双向通信。下面主要以 WHXP 为例。
推荐使用whip-whap-js库。
呼叫
下面是一个简单的使用说明:
// WHIP URL const url = "https://cloud.xswitch.cn/api/cloud/whip"; const token = "xxxx"; // XSwitch Cloud的Token
WHXP 呼叫,详见代码内注释。
let whxp_pc = null; // 全局变量,用于记住当前通话的PeerConnection,以便挂机时关闭相关媒体流 let whxp_location = null; // 记住呼叫返回的URL,用于挂机 let enable_video = false; // 不开视频 let dest = "10000203"; // 被叫号码 async function start_whxp() { let whipwhap = await import("./whip-whap-js.js"); // 导入JS库 let pc = (whxp_pc = new RTCPeerConnection({ iceServers: [] })); // 建立一个peer connection // 让whip库处理媒体流变化 pc.addEventListener( "iceconnectionstatechange", whipwhap.handleIceStateChange ); // 协商成功后,发起WHXP呼叫请求 pc.addEventListener("negotiationneeded", (ev) => { const headers = new Headers(); headers.append("X-XTRA-AUTH-ID", token); // 将Token加入HTTP头域 // 拼接URL,请求地址后面加上dest,即被叫号码 whipwhap .handleNegotiationNeeded(ev, url + "/" + dest, headers) .then((location) => { console.log("whxp_location", location); whxp_location = location; // 呼叫成功后,记住返回的URL,以便后面挂机 }); }); // 打开本地媒体设备,开启音频,不开视频 let gum = await navigator.mediaDevices.getUserMedia({ audio: true, video: enable_video, }); // 媒体流方向,sendrecv表示既能发送也能接收,sendonly表示只能发送,recvonly表示只能接收 pc.addTransceiver(gum.getAudioTracks()[0], { direction: "sendrecv" }); if (enable_video) { pc.addTransceiver(gum.getVideoTracks()[0], { direction: "sendrecv" }); } // 从HTML页面中获取本地视频标签,将本地视频流绑定到该标签 let localVideo = document.getElementById("localVideo"); localVideo.srcObject = gum; localVideo.play(); // 播放视频 // 远端视频标签 let remoteVideo = document.getElementById("remoteVideo"); pc.ontrack = (ev) => (remoteVideo.srcObject = ev.streams[0]); }
HTML 中的标签示例如下:
<video id="remoteVideo" autoplay controls width="640" allowfullscreen /> <video id="localVideo" autoplay controls muted width="360" allowfullscreen />
调用start_whxp()
即可发起呼叫。
挂机
async function stop_whxp() { if (whxp_pc) { console.log("closing whxp"); whxp_pc.close(); // 将 PeerConnection关掉 whxp_pc = null; } closeLocalStream(); // 关闭本地媒体流 closeRemoteStream(); // 关闭远端媒体流 if (whxp_location) { // 发送WHIP消息通知远端挂机 const headers = new Headers(); headers.append("X-XTRA-AUTH-ID", token); fetch(whxp_location, { method: "DELETE", headers }); } } function closeLocalStream() { if (localVideo.srcObject) { localVideo.srcObject.getTracks().forEach(function (track) { track.stop(); }); } } function closeRemoteStream() { if (remoteVideo.srcObject) { remoteVideo.srcObject.getTracks().forEach(function (track) { track.stop(); }); } }
选择音视频设备
Todo.
CORS
一般来说,由于安全性原因,浏览器不允许跨域进行 HTTP 访问。如:你的网页部署在https://example.com
,则无法直接在浏览器端访问https://cloud.xswitch.cn/
。为了解决跨域问题,建议使用 Nginx 进行反向代理。在你的网站后台,加入以下配置:
location /api/cloud/whip { proxy_pass https://cloud.xswitch.cn; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
如果/api/
路径跟你本地的 API 冲突,可以改成其他路径。如:
location /xapi/whip { proxy_pass https://cloud.xswitch.cn/api/cloud/whip/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
这样,可以在浏览器中请求你自己的域名,如https://example.com/xswitch-cloud/api/cloud/whip
,Nginx 会将请求转发到https://cloud.xswitch.cn/api/cloud/whip
。
Demo
登录后,可以通过如下 Demo 测试发起呼叫:https://cloud.xswitch.cn/demo/whip
示例代码参见:https://git.xswitch.cn/xswitch/xcc-examples/src/branch/master/whip
todo: 放到 https://git.xswitch.cn/xswitch/cloud-examples/ 中。
其他
通话结束后,最好调用stop_whxp()
挂机,以便释放资源,而不是直接关闭浏览器。如果直接关闭浏览器标签,则媒体超时(默认为5
秒)后会自动挂机释放资源(这意味着如果短暂断网也会断开通话)。
本系统不支持在呼叫中开关摄像头等媒体重协商,不支持 PATCH 请求和 SDP fragment。
通过 Websocket 发起呼叫
Websocket 是 HTTP 协议的升级版,允许双向通信。使用 Websocket 信令协议可以更好的知道呼叫的状态,方便控制呼叫挂机等。
可以支持媒体重协商。
Websocket 协议使用起来比较复杂,如果需要使用 Websocket,请联系我们。