代码使用示例-用户发起点击通话
发起点击通话的前提,是在接收用户消息时,通过了webRTC环境的校验。
当demo中出现了以下按钮,代表可以发起点击通话。
发起的方法,可以参考Footer.vue中的createCall方法。
/音视频通话 createCall(callType) { this.mode = callType === '0' ? 'audio' : 'video'; let callbacks = function () { EventBus.$emit("startCallPoll"); } this.$Chat.createClickToCall(callType, callbacks); this.isTalking = true; this.callType = callType; }
该方法会调用createClickToCall接口,当方法得到成功返回后,会调用callbacks回调函数,回调函数中的方法EventBus.$emit("startCallPoll")意为发送一个startCallPoll事件。
事件的监听方法如下:
//轮询座席消息 EventBus.$on("startCallPoll", () => { this.getCallEvent(); });
会开始调用getClickToCallEvents接口,开始轮询点击通话事件。
//轮询获取通话事件 getCallEvent() { setTimeout(() => { this.$Chat.getClickToCallEvents(this.callbacks); }, 100); }
这里面的callbacks方法如下,其中new AudioCodesUA()来自奥科的SDK
//音视频相关回调函数 callbacks(data) { if (data && data['resultCode'] === '0') { let eventId = data['eventId']; if (eventId) { if (eventId === 168101) { //已接入到座席 const msgContent = data['content']; // eslint-disable-next-line no-undef this.webRtcConfig.phone = new AudioCodesUA(); this.webRtcConfig.callTo = msgContent['accessCode'] this.webRtcConfig.serverConfig.domain = msgContent['domain'] this.webRtcConfig.serverConfig.addresses = msgContent['gwAddresses'] this.webRtcConfig.account.user = msgContent['clickToCallCaller'] this.webRtcConfig.account.displayName = msgContent['clickToCallCaller'] this.initSipStack(); } else if (eventId === 168102) { //that.$Chat.guiInfo('排队中....') } else if (eventId === 168106) { // 呼叫转移 //that.$Chat.guiInfo('呼叫转移中') } else if (eventId === 168110) { // 呼叫释放 this.isTalking = false } else if (eventId === 168103) { // 呼叫排队超时 this.isTalking = false } else if (eventId === 168105) { // 呼叫失败 this.isTalking = false this.$message({ message: '建立通话失败!', type: 'warning' }); }else { this.$message({ message: '建立通话失败!失败原因码为:' + eventId, type: 'warning' }); if (this.callType === '1'){ EventBus.$emit("videoDrop"); }else { EventBus.$emit("audioDrop"); } } } } else { this.isTalking = false; } if (this.isTalking) { EventBus.$emit("startCallPoll"); } }
在收到168101事件代表已成功接入到座席,这时候会调用initSipStack方法参考如下。
initSipStack() { let phone = this.webRtcConfig.phone phone.setServerConfig(this.webRtcConfig.serverConfig.addresses, this.webRtcConfig.serverConfig.domain, this.webRtcConfig.serverConfig.iceServers) phone.setAccount(this.webRtcConfig.account.user, this.webRtcConfig.account.displayName, this.webRtcConfig.account.password) // Set phone API listeners let that = this phone.setListeners({ loginStateChanged: function (isLogin, cause) { switch (cause) { case 'connected': that.ac_log('phone>>> loginStateChanged: connected') if (that.webRtcConfig.activeCall !== null) { that.ac_log('Already exists active call') } else { if (that.mode === 'video') { that.webRtcConfig.activeCall = phone.call(phone.VIDEO, that.webRtcConfig.callTo) } else { that.webRtcConfig.activeCall = phone.call(phone.AUDIO, that.webRtcConfig.callTo) } EventBus.$emit("showAudio"); } break case 'disconnected': that.ac_log('phone>>> loginStateChanged: disconnected') if (phone.isInitialized()) { that.ac_log('Cannot connect to SBC server') } if (that.callType === '1'){ EventBus.$emit("videoDrop"); }else { EventBus.$emit("audioDrop"); } that.ac_log('service disconnected') break case 'login failed': that.ac_log('phone>>> loginStateChanged: login failed') break case 'login': that.ac_log('phone>>> loginStateChanged: login') break case 'logout': that.ac_log('phone>>> loginStateChanged: logout') break } }, // eslint-disable-next-line no-unused-vars outgoingCallProgress: function (call, response) { that.ac_log('phone>>> outgoing call progress') EventBus.$emit("callMessage", "呼叫中"); }, // eslint-disable-next-line no-unused-vars callTerminated: function (call, message, cause, redirectTo) { that.ac_log('phone>>> call terminated callback, cause=%o', cause) if (call !== that.webRtcConfig.activeCall) { that.ac_log('terminated no active call') return } that.webRtcConfig.activeCall = null that.ac_log('Call terminated: ', cause) phone.deinit() // Disconnect from SBC server. that.isTalking = false // 轮询结束 console.log('Stop polling, drop existing ClickToCall, reset CallDurationTimer and enable ClickToCall') that.guiClearVideoView() }, // eslint-disable-next-line no-unused-vars callConfirmed: function (call, message, cause) { that.ac_log('phone>>> callConfirmed') // Show or hide video controls, according call property 'video' let hasVideo = call.hasVideo() that.guiToggleLocalVideo() // set local video according current check box setting. if (hasVideo) { EventBus.$emit("showVideo"); EventBus.$emit("hideAudioImmediately"); } else { EventBus.$emit("callMessage", "time"); } }, callShowStreams: function (call, localStream, remoteStream) { console.log('phone>>> callShowStreams') let remoteVideo = document.getElementById('remote_video') remoteVideo.srcObject = remoteStream // to play audio and optional video }, // eslint-disable-next-line no-unused-vars incomingCall: function (call, invite) { console.log('phone>>> incomingCall') call.reject() }, // eslint-disable-next-line no-unused-vars callHoldStateChanged: function (call, isHold, isRemote) { console.log('phone>>> callHoldStateChanged ' + isHold ? 'hold' : 'unhold') } }) phone.init(false) }
上述的方法来自奥科文档,具体使用方式可以参考奥科官网,搜索webrtc-web-browser-client-sdk-api-reference-guide了解。本处提示几个地方:
本方和对方的音视频展示,需要有一个video标签,可以参考VideoWindow.vue中的:
callConfirmed: function (call, message, cause) { that.ac_log('phone>>> callConfirmed') // Show or hide video controls, according call property 'video' let hasVideo = call.hasVideo() that.guiToggleLocalVideo() // set local video according current check box setting. if (hasVideo) { EventBus.$emit("showVideo"); EventBus.$emit("hideAudioImmediately"); } else { EventBus.$emit("callMessage", "time"); } }
会展示本方的音视频媒体。
存在对方媒体时会调用callShowStreams展示对方媒体。
callShowStreams: function (call, localStream, remoteStream) { console.log('phone>>> callShowStreams') let remoteVideo = document.getElementById('remote_video') remoteVideo.srcObject = remoteStream // to play audio and optional video }
callTerminated: function (call, message, cause, redirectTo) { that.ac_log('phone>>> call terminated callback, cause=%o', cause) if (call !== that.webRtcConfig.activeCall) { that.ac_log('terminated no active call') return } that.webRtcConfig.activeCall = null that.ac_log('Call terminated: ', cause) phone.deinit() // Disconnect from SBC server. that.isTalking = false // 轮询结束 console.log('Stop polling, drop existing ClickToCall, reset CallDurationTimer and enable ClickToCall') that.guiClearVideoView() }
因其他情况结束了通话流程会触发disconnected事件。
case 'disconnected': that.ac_log('phone>>> loginStateChanged: disconnected') if (phone.isInitialized()) { that.ac_log('Cannot connect to SBC server') } if (that.callType === '1'){ EventBus.$emit("videoDrop"); }else { EventBus.$emit("audioDrop"); } that.ac_log('service disconnected') break
语音通话的结束按键方法可以参考MainContent.vue中的HangUp方法。
/** * 挂断点击通话 */ hangUp() { if (this.hangUpButton) { EventBus.$emit("hangUp"); clearInterval(this.talkTimeTask); this.hangUpButton = false; this.audioIn = "0"; this.sec = 0; this.min = 0; let msg = { avatar: "zph", text: `<img src="` + audioPng + `" class="footer-image" alt="" style="height: 16px;margin-right: 5px;vertical-align: middle;margin-bottom: 2px">` + "通话时长" + this.infos, type: 0, time: this.$Utils.getDateString(), float: "right", }; if (this.infos!=='呼叫中'){ EventBus.$emit("pushInRecords", JSON.stringify(msg)); } this.infos = "00:00"; } }
该方法会发送hangUp事件:EventBus.$emit("hangUp");在Footer.vue中有该事件的监听,会调用cancel方法。
//音视频挂断 EventBus.$on("hangUp", () => { this.cancel(); });
其中dropClickToCall会调用dropClickToCall接口。
cancel() { if (this.webRtcConfig.activeCall != null) { this.webRtcConfig.activeCall.terminate() this.webRtcConfig.activeCall = null } this.$Chat.dropClickToCall(); }
在视频通话中
- 挂断方法在VideoWindow.vue中的hangUpVideoCall。
2. hangUpVideoCall(){ if (this.videoView){ EventBus.$emit("hangUp"); this.videoView = false; let msg = { avatar: "zph", text: `<img src="`+videoPng+`" class="footer-image" alt="" style="height: 16px;margin-right: 5px;vertical-align: middle;margin-bottom: 2px">`+"通话时长"+this.infos, type: 0, time: this.$Utils.getDateString(), float: "right", }; if (this.infos!=='呼叫中'){ EventBus.$emit("pushInRecords", JSON.stringify(msg)); } this.infos = "00:00"; this.sec = 0; this.min = 0; clearInterval(this.talkTimeTask); this.talkTimeTask = ""; } }
该方法同样会发送hangUp事件,同音频挂断。
2. 停止发送本地视频VideoWindow.vue中的hangUpVideoCall
/** * 视频画面停止 */ videoMuteEvent(){ this.videoIsOff = !this.videoIsOff; EventBus.$emit("videoMute"); }
该方法会发送videoMute事件,在Footer.vue中监听。
EventBus.$on("videoMute", () => { this.videoMute() });
videoMute() { let muted = this.webRtcConfig.activeCall.isVideoMuted() this.webRtcConfig.activeCall.muteVideo(!muted) }
3. 视频静音方法VideoWindow.vue中的audioMuteEvent。
/** * 视频语音静音 */ audioMuteEvent(){ this.voiceIsOff = !this.voiceIsOff; EventBus.$emit("audioMute"); }
该方法会发送audioMute事件,在Footer.vue中监听。
EventBus.$on("audioMute", () => { this.audioMute() })
audioMute() { let muted = this.webRtcConfig.activeCall.isAudioMuted() this.webRtcConfig.activeCall.muteAudio(!muted) }