JsSIP的基本使用

本文详细介绍了如何使用JsSIP库在WebRTC环境中通过WebSocket建立连接,开启和注册,以及进行呼叫、接听、挂断和注销操作,包括设置超时时间、媒体约束等关键步骤。

1、建立连接

webrtc的连接就是一个webscoket,遵循的是tcp协议

在jssip中,jssip定义了一个JsSIP对象,其包含一个WebSocketInterface方法用来使用webscoket

WebSocketInterface(url)

  • url:websocket连接地址
JsSIP.C.SESSION_EXPIRES=120 //websocket超时时间,默认值60
JsSIP.C.MIN_SESSION_EXPIRES=120 //websocket最小超时时间,默认值60

let url = '' //websocket地址(包含端口)

let socket = new JsSIP.WebSocketInterface('wss://' + url + '/ws')

scoket.via_transport = 'WS'

2、开启/注册

JsSIP.UA(option)

option参数

  • sockets:创建的websocket连接,是一个数组
  • uri:sip的注册地址,例如:sip:1001@example.com
  • password:分机的注册密码
  • register:是否开启自动注册,默认值是false,如果使用默认值或者指定了false,那么需要单独去掉用register()函数进行注册

以上三个参数的必填的参数,其他非必填参数请参考JsSIP官网文档:https://jssip.net/

let configuration = {
    sockets: [ socket ],
    uri: 'sip:'+sip+'@'+host+':'+port,
    password : password,
    authorization_user:sip,
    display_name:sip,
    register: true, //是否启用自动注册,默认值是false
    registrar_server:'sip:'+ host,
    session_timers: false,
    pcConfig:{url:'stun:1.1.1.1:3478'},//示例地址,无效,请更换自己的stun服务器地址
    user_agent:'jssip'
}

let sip_scoket = JsSIP.UA(configuration)

如果设置了register参数为true,同时会触发registered事件,如果设置为false,或者没有传递register参数,使用了默认值,那么就不会触发registered事件,需要等到调用了register()方法后才会触发registered事件

sip_scoket.on('registered',(data) => {
    console.log('======注册完成======', data)
})

3、注册

register()

上面说的是通信的开启,如果设置了register参数为true,那么就会自动进行注册,不需要手动执行了,但是设置了false或者说没有传递register参数,那么默认会使用false,这时就需要手动进行注册了。

sip_scoket.register()

在执行该方法后会触发registered事件

sip_scoket.on('registered',(data) => {
    console.log('======注册完成======', data)
})

4、呼叫

call(target, option)

  • target:呼叫的对象

  • option:其他额外的参数(这里主要说明一下mediaConstraints,这个是必须要传递的,不然会没有声音)

    mediaConstraints是一个对象,包含2个参数,一个是audio,一个是video,表明指定当前通话是使用音频还是视频,也可以指定一个,也可以全部都指定,默认值为true,就是即使用音频也使用视频

sip_socket.call(
	'1001',
    mediaConstraints:{audio:true}
)

呼叫成功后会触发newRTCSession事件,需要在这里进行音频流的处理(我这里以音频流为例),newRTCSession事件的返回值中有一个originator参数,如果值为remote那么表明这是一个呼入,如果是local那么表明这是一个外呼,呼入和外呼对于音频流的处理 位置也是不一样的,如果是外呼直接在newRTCSession的返回值的

sip_socket.on("newRTCSession", (e) => {
    console.log("===========newRTCSession==========", e)
    session = e.session
    if(e.originator == 'remote'){
        session.on("peerconnection", (data) => {
            addTrack(data,'incomming')
        })
    } else {
        addTrack(e.session._connection,'outcomming')
    }
}
              
//添加音频流函数
function addTrack(data, type) {
	console.log("========addTrack==============")
     if (type == "incomming") {
          data.peerconnection.ontrack = () => {
            let remoteStream = new MediaStream();
            let receivers = session._connection.getReceivers();
            receivers.forEach((recevier) => {
              if (recevier.track.kind == "audio") {
                remoteStream.addTrack(recevier.track);
                document.getElementById("remoteAudio").srcObject = remoteStream;
              }
            });
          };
        } else {
            data.ontrack = () => {
                let remoteStream = new MediaStream()
                let receivers = session._connection.getReceivers()
                receivers.forEach((recevier) => {
                    if (recevier.track.kind == "audio") {
                        remoteStream.addTrack(recevier.track)
                        document.getElementById("remoteAudio").srcObject = remoteStream
                    }
                })
            }
        }
      }

5、挂断

terminate()

挂断调用terminate()方法,挂断后会触发ended事件。在ended事件中,可以通过返回值的originator获得是本地挂断还是被叫挂断,如果originator的值为local那么就是本地挂断或者叫主叫挂断,如果originator的值为remote,那么就是被叫挂断。同时,返回值的cause会返回挂断的原因。

session.terminate()

session.on('ended', (data) => {
    if(data.originator == 'local') {
        console.log('主叫挂断')
    }
    
    if(data.originator == 'remote') {
        console.log('被叫挂断')
    }
})

6、接听

answer(option)

option的参数主要说明一下mediaConstraints

mediaConstraints是一个对象,包含2个参数,一个是audio,一个是video,表明指定当前通话是使用音频还是视频,也可以指定一个,也可以全部都指定,默认值为true,就是及使用音频也使用视频

session.answer({
    mediaConstraints: { audio: true }
})

接听完成后会触发accepted事件,可以根据事件返回值的originator参数来获得是主叫接听还是被叫接听,如果值为remote那么就是被叫接听,如果是local那么就是主叫接听。

session.on('accepted', (data) => {
    if(data.originator == 'remote') {
        consloe.log('被叫接听')
    }
    
    if(data.originator == 'local') {
        consloe.log('主叫接听')
    }
})

7、注销

注销实际上就是直接关闭当前连接就可以了,使用stop()方法

sip_scoket.stop()

注销后会触发unregistered事件,整个注销过程为固定的2秒钟,如果在注销后又其他逻辑运行,建议2秒钟后再执行其他逻辑。

sip_socket.on('unregistered', (e) => {
    consloe.log('======注销======', e)
})

以上内容是JsSIP的基本使用,后续会逐渐的汇总每一个步骤所涉及到的具体细节性的内容。

<think>好的,我现在需要帮助用户找到Vue3和JsSIP结合的示例代码或使用案例。首先,我得回顾一下用户提供的引用内容,看看是否有相关信息。引用[2]提到了Vue组件的数据监视,这可能与集成JsSIP时的状态管理有关。用户需要的是Vue3的具体实现,所以我要考虑Vue3的Composition API和Options API的区别。 首先,JsSIP是一个JavaScript的SIP协议库,用于实现WebRTC通信。在Vue3中集成它,通常需要创建SIP客户端实例,并管理其生命周期。用户可能需要处理通话状态、事件监听等,所以使用Vue的响应式系统会很合适。 接下来,我应该考虑如何结构化的示例代码。可能需要安装JsSIP库,然后在Vue组件中引入。在setup函数中使用ref或reactive来创建响应式变量,比如通话状态、远程流等。然后,在挂载时初始化JsSIP实例,注册事件监听器,比如来电事件、通话建立、结束等。 用户提供的引用[1]提到使用container.setState或container.extendState来动态设置状态,这可能对应于Vue3中使用reactive或ref来管理状态。需要将JsSIP的事件处理与Vue的状态更新结合起来,比如当来电时更新状态,触发UI重新渲染。 另外,引用[3]指出JsSIP支持多平台,所以需要确保示例代码的兼容性,但主要关注Web环境。可能的案例包括一个简单的语音通话界面,显示通话状态,并有接听、挂断按钮。 需要注意的事项包括:在Vue组件销毁时清理JsSIP实例,避免内存泄漏;正确处理异步操作,比如连接SIP服务器;错误处理等。此外,使用Vue3的Composition API会更简洁,但也要提供Options API的示例,如果用户需要的话。 现在需要整合这些思路,编写一个基本的示例代码,展示如何初始化JsSIP客户端,处理来电,管理通话状态。同时,确保代码符合用户的要求,使用正确的中文注释,并引用相关的引用内容。最后生成相关问题,帮助用户进一步探索。</think>以下为Vue3与JsSIP集成的基础实现方案,包含核心代码示例和状态管理要点: ### 一、基础集成框架 ```vue <template> <div> <p>通话状态:{{ callStatus }}</p> <button @click="makeCall">拨打电话</button> <button @click="endCall" :disabled="!activeCall">挂断</button> </div> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue'; import JsSIP from 'jssip'; const socket = new JsSIP.WebSocketInterface('wss://sip.example.com'); const configuration = { sockets: [socket], uri: 'sip:user@domain.com', password: 'your_password' }; const ua = ref(null); const callStatus = ref('空闲'); const activeCall = ref(null); // 初始化SIP客户端 [^3] onMounted(() => { ua.value = new JsSIP.UA(configuration); ua.value.start(); // 监听来电事件 ua.value.on('newRTCSession', ({ originator, session }) => { if (originator === 'remote') { callStatus.value = '来电中...'; activeCall.value = session; session.on('accepted', () => callStatus.value = '通话中'); session.on('ended', () => { callStatus.value = '空闲'; activeCall.value = null; }); } }); }); // 发起呼叫 const makeCall = () => { const options = { extraHeaders: ['X-Custom-Header: value'], mediaConstraints: { audio: true, video: false } }; activeCall.value = ua.value.call('sip:target@domain.com', options); callStatus.value = '拨号中...'; activeCall.value.on('accepted', () => callStatus.value = '通话中'); activeCall.value.on('ended', () => { callStatus.value = '空闲'; activeCall.value = null; }); }; // 结束通话 const endCall = () => { if (activeCall.value) { activeCall.value.terminate(); } }; // 组件卸载时清理 [^1] onUnmounted(() => { if (ua.value) { ua.value.stop(); ua.value = null; } }); </script> ``` ### 二、关键实现要点 1. **状态管理**:使用Vue3的`ref`响应式变量跟踪通话状态和SIP会话对象[^2] 2. **生命周期**:通过`onMounted/onUnmounted`管理SIP客户端的初始化/销毁 3. **事件监听**:处理SIP协议层的`newRTCSession`、`accepted`等核心事件 4. **媒体控制**:通过`mediaConstraints`配置音视频传输参数 ### 三、典型应用场景 1. WebRTC语音通话系统 2. 浏览器端SIP软电话 3. 视频会议前端接入层 4. 即时通讯应用的音视频模块
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值