需求
最近接手的vue项目需要使用jssip通话,jssip官网是全英文,所有看起来比较费劲。完成项目后记录一下jssip。
这一章节主要记录了jssip的安装、配置以及一些状态信息传递,包括二次拨号函数、来电铃声开关函数、通话添加媒体流函数、接听挂断函数、初始化函数等
安装
npm install jssip
jssip文件
在src/utils下创建jssip.js文件
import JsSIP from 'jssip'
import bus from '@/utils/bus'
var ua = null
var currentSession // 当前会话
var peer
var stream // 流媒体
// 初始化配置
function initConfig(data) {
// Create our JsSIP instance and run it:
const socket = new JsSIP.WebSocketInterface(`wss://${data.url}:${data.port}`)
const configuration = {
sockets: [socket],
uri: `sip:${data.username}@${data.url}`, // 分机号注册 格式 sip: + 分机号码 + @ + FS注册地址
authorization_user: data.username, // 授权用户
password: data.password, // 密码
register: true, // 自动注册
connection_recovery_max_interval: 60, // 链接恢复的最大间隔
connection_recovery_min_interval: 5 // 链接恢复的最小间隔
}
return configuration
}
// 初始化jssip
function jssipInit(data) {
JsSIP.C.SESSION_EXPIRES = 120 // FreeSWITCH 默认设置要求 Session Expires 不低于120 低于120打不出电话
JsSIP.C.MIN_SESSION_EXPIRES = 120
const configuration = initConfig(data) // 配置参数
ua = new JsSIP.UA(configuration) // 创建对象
addRegisterMethod(ua) // 添加监听方法
ua.start() // 链接
return ua
}
// 打电话
function call(data) {
// 这一步也是添加监听,不过已经使用在addRegisterMethod方法中添加了这里为空就行
const eventHandlers = {
// 呼叫中
// progress: function (e) {
// console.log('call is in progress')
// },
// 失败
// failed: function (e) {
// console.log('call failed: ', e)
// },
// 结束
// ended: function (e) {
// console.log('call ended : ', e)
// }
// 呼叫确认
// confirmed: function (e) {
// console.log('call confirmed')
// }
}
const options = {
eventHandlers: eventHandlers,
mediaConstraints: {
audio: true,
video: false
}
}
// console.log('呼叫:' + data.phone)
ua.call(`sip:${data.phone}@${data.url}`, options)
}
// jssip监听方法
function addRegisterMethod(ua) {
// 接线中
ua.on('connecting', (res) => {
// console.log('接线中', res)
})
// 连线中
ua.on('connected', (res) => {
// console.log('连线中', res)
})
// 取消连线
ua.on('disconnected', (res) => {
console.log('取消连线', res)
})
// 注册成功
ua.on('registered', (res) => {
console.log('注册成功', res)
bus.$emit('sessionData', { state: 'registered' }) // 这里使用bus将数据传递到对应的监听文件进行处理
})
// 注册失败
ua.on('registrationFailed', (res) => {
// console.log('注册失败', res)
})
// 注册即将失效(重新注册)
ua.on('registrationExpiring', (res) => {
console.log('重新注册', res)
})
// 注销回调
ua.on('unregistered', (res) => {
console.log('解除注册', res)
bus.$emit('sessionData', { state: 'unregistered' }) // 这里使用bus将数据传递到对应的监听文件进行处理
})
// 会话
ua.on('newRTCSession', function (data) {
const { session, request, originator } = data
currentSession = session
// 呼叫中 打电话与接电话的呼叫都走这里
currentSession.on('progress', (res) => {
if (originator === 'remote') {
console.log('电话过来拉~~~~~~~~~··', res)
// console.log('我接听了', res)
bus.$emit('sessionData', { state: 'progress-remote', data: request })
playRingMedia() // 这里可以加一个判断,如果是监听的时候不需要播放音乐
} else {
console.log('接听事件在progress中触发', res)
bus.$emit('sessionData', { state: 'progress' })
streamingMediaPlayer() // 添加媒体流 这时候开启音频
}
})
// 对等连接事件触发
currentSession.on('peerconnection', (data) => {
console.log('对等连接事件触发,peerconnection', data)
bus.$emit('sessionData', { state: 'peerconnection' })
})
// 交换sdp信令事件触发
currentSession.on('sdp', (res) => {
console.log('交换sdp信令事件触发,sdp', res)
bus.$emit('sessionData', { state: 'sdp' })
})
// 对等连接建立(通话连线时候触发)
currentSession.on('connecting', (data) => {
peer = currentSession._connection
console.log('对等连接建立,connecting', peer, data)
bus.$emit('sessionData', { state: 'connecting' })
})
// 通话接受时候触发
currentSession.on('accepted', (res) => {
console.log('通话接受时候触发', res)
bus.$emit('sessionData', { state: 'accepted' })
})
// 通话失败事件触发
currentSession.on('failed', (res) => {
console.log('通话失败事件触发--- failed', res)
stopPlayRingMedia() // 关闭来电振铃
bus.$emit('sessionData', { state: 'failed' })
})
currentSession.on('reinvite', (res) => {
// openLocalCamera()
console.log('重新协商事件触发', res)
if (currentSession._connection.getLocalStreams().length > 0) {
// 接听后,判断localStream
}
if (currentSession?._connection.getRemoteStreams().length > 0) {
}
})
// 呼叫确认
currentSession.on('confirmed', (res) => {
console.log('呼叫确认--设置媒体流到音视频中,confirmed', res)
bus.$emit('sessionData', { state: 'confirmed' })
if (originator === 'remote') {
streamingMediaPlayer() // 呼入时没有添加媒体流,这时候添加媒体流
}
})
// 通话结束
currentSession.on('ended', (res) => {
console.log('通话结束--- ended', res)
bus.$emit('sessionData', { state: 'ended' })
})
})
}
// 挂断
function hangUp() {
stopPlayRingMedia() // 关闭放来电振铃
ua.terminateSessions()
}
// 接听
function answer() {
var options = {
mediaConstraints: { audio: true, video: false, mandatory: { maxWidth: 640, maxHeight: 360 } }
}
currentSession.answer(options) // 接听来电
}
// 添加媒体流
function streamingMediaPlayer() {
stopstreamingMediaPlayer() // 先关闭媒体流
stream = new MediaStream()
const receivers = currentSession.connection?.getReceivers()
if (receivers) {
receivers.forEach((receiver) => stream.addTrack(receiver.track))
}
// 这里创建一个audio标签隐藏,添加媒体流,添加到界面id为ringMediaAudioId的标签中
var ringAudio = document.getElementById('ringMediaAudioId')
ringAudio = document.createElement('audio')
ringAudio.id = 'ringMediaAudioId'
ringAudio.hidden = true
ringAudio.srcObject = stream // 添加媒体流
var box = document.getElementById('ringMediaAudioBox')
box.appendChild(ringAudio) // 添加到box中
ringAudio.play() // 播放
}
// 停止播放媒体流
function stopstreamingMediaPlayer() {
var ringAudio = document.getElementById('ringMediaAudioId')
if (ringAudio) {
var box = document.getElementById('ringMediaAudioBox')
box.removeChild(ringAudio)
}
}
// 播放来电振铃
function playRingMedia() {
stopPlayRingMedia()
var ringAudio = document.getElementById('cheerMusic') // 这是界面存在的audio标签,隐藏了的,里面的音乐可以自己找,主要用于呼入时响铃
ringAudio.play()
}
// 停止播放来电振铃
function stopPlayRingMedia() {
var cheerMusic = document.getElementById('cheerMusic')
cheerMusic.load()
}
/**
* 二次拨号
* @param dtmfNumber 二次拨号号码
* 注意功能是打通电话后,在按键时对方可接收到
*/
function dtmf(dtmfNumber) {
console.log(dtmfNumber)
const options = {
transportType: 'RFC2833' // dtmf类型,默认是info
}
currentSession.sendDTMF(dtmfNumber, options)
}
const sip = {
jssipInit: jssipInit, // 初始化
call: call, // 拨号
answer: answer, // 接听
hangUp: hangUp, // 挂断
dtmf: dtmf // 二次拨号
}
export default sip
bus.js文件
在src/utils文件下创建bus.js文件(在需要跨文件触发时引入)
// @/utils/bus.js
import Vue from 'vue'
const bus = new Vue()
export default bus
使用
由于内容过多,具体使用请看jssip(二)——使用
https://blog.csdn.net/xuelong5201314/article/details/132623288