文档首页/ 云客服/ 用户接入——网页版客户端集成 (RESTful)/ 代码使用示例-用户发起点击通话
更新时间:2023-02-28 GMT+08:00
分享

代码使用示例-用户发起点击通话

发起点击通话的前提,是在接收用户消息时,通过了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中的:

在通话建立时,sdk会调用callConfirmed方法
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 方法。
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();
}

在视频通话中

  1. 挂断方法在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)
}

相关文档