jssip介绍系列-分机注册与接听
虽不是专业前端,但基本完成了关于基于jssip的注册,接听,挂断 ,视频接听、屏幕分享、摄像头切换,实时拍照,视频录像、虚拟摄像头等功能。 一路踩了很多坑,虽然jssip官网对这些功能说了可以实现,但jssip本事主要专注于底层webrtc和sip协议等。 这些上层的应用文档确实写得不是很友好。 因此应qq群友邀请,我贡献一下自己对这些基础功能的实现
首先本系列jssip基于版本3.6.1, freeswitch 1.10.5-release~64bit, 浏览器最新chrome
第一步检测
浏览器系统音频、视频是否支持
navigator.getUserMedia(
// constraints
{
video: true,
audio: true
},
// successCallback
function (localMediaStream) {
// video.src = window.URL.createObjectURL(localMediaStream);
// video.onloadedmetadata = function(e) {
// // Do something with the video here.
// };
},
// errorCallback
function (err) {
console.log(err);
}
);
第二步:jssip基本简介
jssip 使用webrtc形式与freeswitch进行连通,这里有个注意事项,webrtc必须使用https域名等才可以使用,否则浏览器不允许(细节重点)
jssip.UA 所谓UA即为一个连接客户端,而客户端需要注册分机到freeswitch,因此初始化UA十分关键,直接影响你是否能收到来电等信息。
注册成功的UA,将监听重点事件,由此完成电话的接听,挂断等事件。
很多网友虽然注册成功,仍无法接听电话等,是因为 UA注册信息缺失。
var configuration = {
sockets: [socket],
uri: 'sip:' + username + '@**.com;transport=wss',
password: password,
contact_uri: 'sip:' + username + '@**.com;transport=wss',
outbound_proxy_set: 'wss://**.com:7443',
display_name: username
};
contact_uri 非常重要
准备工作
我们使用创建一个全局变量来存储UA信息, 创建两个video标签用来展示来电视频、接听者视频信息。
<video width="300" height="200" id="my-video" autoplay> </video>
<video width="200" height="150" id="peer-video" autoplay> </video>
window.remoteView = document.getElementById(remoteVideoTag);
window.selfView = document.getElementById(selfVideoTag);
window.sipSession = undefined; // 当前电话session
window.ua = undefined; // 当前注册UA
window.comingPhone = undefined; // 来电号码
事件绑定
向freeswitch注册完成分机后,需要监听newRTCSession 事件,用来判断来电信息。通过来电的事件的‘accepte’,‘progress’, ‘end’ 来确定电话是来电,接听,和挂断
处理接听时候,判断e.session._connection的LocalStreams,和remoteStreams流,将流绑定到video标签中,从而在页面展示来电视频。
function sipEventBind(e, callbacks){
e.session.on("accepted", function () {
if (e.session._connection.getLocalStreams().length > 0) {
// 接听后,判断localStream
window.selfView.srcObject = e.session._connection.getLocalStreams()[0];
window.selfView.volume = 0;
}
if (e.session._connection.getRemoteStreams().length > 0) {
window.remoteView.srcObject = e.session._connection.getRemoteStreams()[0];
}
});
// 来电 振铃
e.session.on("progress", function(data){
try{
var player = document.createElement('audio');
player.setAttribute("id", "ringId");
player.setAttribute("src", "https://cdn-obs-question.aegis-info.com/mall/newspaper/20210220_467c8bfd-7474-447a-8028-2c198659da7e.mp3");
player.setAttribute('autoplay', 'autoplay');
player.play();
}catch(err){
console.log(err);
}
if (callbacks != undefined) {
if (typeof callbacks === "function") {
window.comingPhone = e.session.remote_identity.display_name;
callbacks(e.session.remote_identity.display_name);
}
}
});
// 挂断处理
e.session.on("ended", function(data){
var stream1 = window.selfView.srcObject;
if(stream1 != undefined){
var tracks = stream1.getTracks();
if(tracks != undefined){
tracks.forEach(track => {
track.stop();
});
}
}
console.log('call ended with cause: ' + e.cause);
});
}
具体封装代码如下:
function login(account, password, callbacks, loginCallback) {
var username = account;
var socket = new JsSIP.WebSocketInterface('wss://**.com:7443');
var configuration = {
sockets: [socket],
uri: 'sip:' + username + '@**.com;transport=wss',
password: password,
contact_uri: 'sip:' + username + '@**.com;transport=wss',
outbound_proxy_set: 'wss://**.com:7443',
display_name: username
};
var ua = new JsSIP.UA(configuration);
ua.start();
window.ua = ua;
window.ua.on('registered', function(e){
// 注册成功回调方法
if (loginCallback != undefined) {
if (typeof loginCallback === "function") {
loginCallback();
}
}
});
window.ua.on('newRTCSession', function (e) {
if (e.session._direction == "outgoing") {
console.log("打电话");
} else {
console.log("来电话啦");
// 绑定session
window.sipSession = e.session;
sipEventBind(e)
}
});
window.ua.on('sipEvent', function (e) {
console.log(e);
});
}
调用时候,login(user, password, incommingCallback, loginCallback)
第三个参数为来电对调。
login(username, "password", function(calledNumber){
alert("来电话啦"+ calledNumber);
},
function(){
alert("注册freeswitch成功");
}
);
由此我们完成了,电话的注册,来电振铃,接听等事件监听处理。
注意!!
a、chrome在使用振铃、视频接听等操作时候,需要用户主动触发。 因此注册操作login方法必须由用户主动点击页面进行!!
b、出现问题:handshake failure
解决方法: 升级chrome 对 dtls有要求,需要更新 openssl 版本,使得fs进行支持,dtls 版本
解决办法一:a、升级openssl,重新生成证书,7443端口指定的证书
b、删除 dtls-srtp.pem (fs自动生成的)
c、重新编译freeswitch
解决方法二: 升级freeswtich, 或者降低chrome版本
下一节我们继续jssip的其他应用处理。