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,请联系我们。

声网 SIP-PSTN 网关