已经在家办公两个星期了,领导虽然不能再像以前一样,以十分钟一次的频率出现在我眼前询问进度,但微信,钉钉群里时不时的问候,还是少不了。。。苦啊!
因为疫情的原因,产品要在项目中增加视频通话功能,项目分为微信小程序端(以下简称小程序)和web端两部分,人手有限,所以两个部分都是我负责。
下面我先简单介绍一下业务场景:
1、我们的业务上只涉及1v1的视频模式,使用的是腾讯云提供的实时音视频服务。
2、视频通话是由web端用户发起,小程序端接收。这个功能是放在IM社交聊天里面的,所以接收与挂断等功能都是通过ws实现的。
3、web端框架为vue,小程序端框架为mpvue(坑多,一直想用原生重构,苦于没时间,只能继续填坑)
下面先来聊聊web端的部分吧。
SDK与demo下载与解析
首先,我们先从官网上下载一分钟跑通demo(web)的相关代码(地址:cloud.tencent.com/document/pr… 的方式不安全,容易被反向破解,建议大家将 UserSig 的计算代码集成到服务端,然后通过接口的方式获取,具体的实现方式官网也有相关文档。(我们公司是后端大大负责这块,所以我也没深入研究,有兴趣的小伙伴可以自己看看)
下载好代码后我们可以看到以下内容:
官网提供的demo功能比较全的,但是有些用不上,所以我们要精简代码,将需要的部分用vue重写。
先来分析下demo里的目录结构:
css就不讲了,js中debug文件夹的GenerateTestUserSig是用来生成SDKAppID和SECRETKEY的,后期会被后端提供的相关接口替代;
lib-generate-test-usersig.min.js同上,用来生成SDKAppID和SECRETKEY的,准确来讲,GenerateTestUserSig.js是封装了一下lib-generate-test-usersig.min.js,所以这俩后面都会被删掉;
bootstrap和jqery也不讲了,大家都知道。popper.js和toastify.js就是俩提示类的插件,我们项目上用elementUI,所以这俩也用不到,后面会删掉
trtc.js是腾讯云视频通话的源码部分,复制到vue项目中去,不做改动。
rtc-client.js对trtc.js的封装,暴露出部分API,详细的API文档详见官网(地址:cloud.tencent.com/document/pr…
utils.js里主要做了几个工作,获取用户的摄像头与话筒设备,然后提供了几个添加元素,删除元素的方法,供rtc-client使用,还有定义Toast对象,封装了一下toastify.js,对有使用UI库的我们来说,没用。还有个jqery在chrome M76中的polyfill,大家看自己需求重写或延用。
index.js就是我们的入口文件了,稍后会用vue重写。
初始化RtcClient实例
按产品的原型图,页面会在用户点击视频通话时弹出一个弹框,里面放视频的画面,大概长这个样子:
所以我封装了个video-chat.vue组件,下面讲一下代码实现:
首先要在项目里的index.html中引入以上用到的几个js文件:
然后新建一个vue文件,并从rtc-client.js中引入RtcClient类;
this.rtc = new RtcClient({
userId,// 用户id
roomId,// 房间id,我们项目中涉及订单概念,所以我用订单id作为roomID
sdkAppId, // sdkAppId,调后端接口获取
userSig, // userSig,调后端接口获取
streamSubscribedCallback: this.connectSuccess, // 有用户接入成功的回调
streamRemovedCallback: this.connectEnd // 用户断开连接的回调
});
要实现接通后页面由等待接收邀请,变为视频中,任何一方挂断视频后弹窗关闭。
我们就必须要监听到远端流订阅成功事件(即stream-subscribed)和远端流删除事件(stream-removed),所以我为RtcClient类增加了两个回调函数作为入参:streamSubscribedCallback和streamRemovedCallback,如上图;
ret-client.js也要做些改动:
class RtcClient {
constructor(options) {
this.sdkAppId_ = options.sdkAppId;
this.userId_ = options.userId;
this.userSig_ = options.userSig;
this.roomId_ = options.roomId;
this.isJoined_ = false;
this.isPublished_ = false;
this.localStream_ = null;
this.remoteStreams_ = [];
// NOTE: 以下为新增的两个回调
this.streamSubscribedCallback = options.streamSubscribedCallback;
this.streamRemovedCallback = options.streamRemovedCallback
}
...
// 在事件处理函数中的两个事件回调中增加以下代码
handleEvents() {
// 远端流订阅成功事件
this.client_.on('stream-subscribed', evt => {
...
// NOTE: 调用自己的业务逻辑
this.streamSubscribedCallback();
});
// 处理远端流被删除事件
this.client_.on('stream-removed', evt => {
...
// NOTE: 调用自己的业务逻辑
this.streamRemovedCallback();
});
}
}
这样我们就实现了视频的接入成功和挂断事件的监听回调,然后在video-chat.vue组件的connectSuccess和connectEnd方法中写相应逻辑即可。
使用RtcClient的API
RtcClient的API都是对client的再封装,仅提供了以下几种:
上一步我们在mounted中已经初始化了RtcClient并将它赋值给this.rtc。初始化完成后我们就可以通过this.rtc.XXX去使用实例的API了。我在初始化玩成后立即调用了join()加入房间,然后发送ws消息给小程序端用户,表示有人再向其发送视频邀请。若小程序端接听视频成功,则 stream-subscribed事件的回调会被触发,按上面所讲,我们可以在组件的connectSuccess事件中处理相应逻辑。
同理,在小程序端用户挂断视频时,stream-removed事件的回调会被触发,我们可以在组件的connectEnd事件中处理相应逻辑,调用RtcClient.leave()方法结束视频通话。
到这里web端的视频通话大概写完了,如果有疑问,欢迎下方评论!