基于Trtc的内贸站视频聊天服务【二】
上一节课和大家聊了一下web端视频聊天的技术演变和发展,需要满足web端视频聊天的基本条件。以及介绍了一下腾讯云提供的Trtc服务,大概说了下腾讯云的sdk。本节课就以实际开发内贸站视频聊天的项目(Swan),和大家理一下这个项目的构造,以及重要的代码逻辑。
svn地址: http://192.168.16.81:58760/svn/ABIZ/SWAN/trunk/SWAN
项目框架
项目前端框架: React(16.12.0),TypeScript,Webpack,node服务等。
通过 WebpackDevServer(小型的node.js Express服务器)配置启动服务,node启动服务,经webpack打包,最后会生成6个js文件和4个css文件。
这个项目的最终目的就是**输出js和css。
通过在宿主页面引用不同的js和css,就可以将聊天的页面嵌入到其他的项目中,这样做对其他项目的影响较小,估计这也是设计这种类型项目的原因。
项目组成
这个项目主要分为3个页面,一个是视频聊天页,一个是等待聊天页,还有一个是各种错误显示页。
在宿主页通过script标签,给这3个页面传递数据,如下:
在主页面通过document.querySelector获取宿主页传递过来的数据进行初始化,如下:
项目框架是基于React,通过Typescript对页面形式进行约束,所以文件的形式是.tsx,实际上和jsx没有太大的区别。
逻辑介绍
因为核心代码逻辑都在聊天室这块,就以此为切入点。先看代码:
withStateManager(withTRTC(withRoomModules(DesktopRoom)))
这种是高阶组件的写法,主体是DesktopRoom模块,通过withStateManager,withTRTC,withRoomModules对主模块进行各种分类功能分类处理,使逻辑看的清晰。
但是通过这种写法,尽管逻辑清晰,但对初看代码的同学可能不是那么友好,在主组件看到调用的方法,可能是上层声明的,也可能是上上层,如果你重外层往里面看,可能又不知道,这写的是啥,一头雾水。这也是这种高阶组件的弊端。
下面我分别介绍各个模块的功能:
WithStateManager(辅助高阶模块一)
这个模块在最外层,主要处理的是用户和聊天房间的关系。
因为是和楼上麦通部门合作,通过和麦通建立联系,他们对状态进行管理;
let token_url = `https://membercenter.cn.made-in-china.com/tm/dom_get_token/?callback=?`;MaiTong.configWeb({token_url,token: this.props.miccnToken,roomId: roomNo.toString(),domain: "miccn",lang: "zh"
});MaiTong.showlog(true);await MaiTong.startWeb();
通过监听事件对麦通传过来的各个状态进行处理;
addTradeMessengerEventListener(){const MaiTong = window.MaiTong;const _this = this;const i18n = I18n.getInstance();const { roomNo, isSupplier,expoId } = this.props;const expoUrl = "//cn.made-in-china.com/expo/"+expoId+".html";//TradeServerEventEnumMaiTong.listen(function () {if(msg as ReceivedUserMessage && (msg as ReceivedUserMessage).msgType === "TEXT") {const { content, timestamp } = msg as ReceivedUserMessage;_this.handleMessageReceive(content, timestamp);}})...
}
WithTRTC(辅助高阶模块二)
这个模块主要处理视频流的创建于发布,通过腾讯云的SDK建立联系,通过监听事件,完成对视频流的调节与交互。
const { sdkAppId, userId, userSig } = this.props;this.trtcClient = TRTC.createClient({mode: ClientModeEnum.VIDEO_CALL,sdkAppId,userId,userSig
});
sdkAppId, userId, userSig这3个字段是在注册腾讯云的时候官方提供的。
腾讯云SDK的监听:
this.trtcClient?.on(ClientEventNameEnum.STREAM_ADDED, ({ stream }) => {console.log('远端流增加: ' + stream.getId());this.trtcClient?.subscribe(stream);this.onStreamsNumberChange();
});this.trtcClient?.on(ClientEventNameEnum.STREAM_REMOVED, ({ stream }) => {this.removeStream(stream);this.onStreamsNumberChange();
});this.trtcClient?.on(ClientEventNameEnum.STREAM_SUBSCRIBED, ({ stream }) => {console.log('远端流订阅成功:' + stream.getId());this.appendStream(stream);
});this.trtcClient?.on(ClientEventNameEnum.MUTE_AUDIO, ({ userId }) => {this.appendAudioMutedId(userId);
});。。。
第三方提供了丰富的环境监测系统,举个例子:
//监测当前网络环境
this.qualityCheckTask = window.setInterval(async () => {if (this.trtcClient) {const { rtt } = await this.trtcClient.getTransportStats();if (rtt > 300 || rtt === 0) {toast(I18n.getInstance().toast.poorNetwork, {containerId: ToastContainerEnum.TOP_CENTER,toastId: ToastContainerEnum.TOP_CENTER,updateId: ToastContainerEnum.TOP_CENTER});}}}, 1000 * 60)
rtt 就是通常所说的ping,我们认为超过300,就对视频聊天有一定影响了。
WithRoomModules(辅助高阶模块三)
这个模块是对房间加一些权限管理,比如聊天室的到期时间,会话倒计时,对聊天窗口的紧急关闭功能。另外还有一些比如和业务有关系的一些操作,都是在这个模块进行处理。
return (<VideoItem attendee={attendee} stream={stream} hostUserId={hostUserId} userId={userId}hasMultiCameras={hasMultiCameras}hostComId={company.encodeComId}audioEnabled={audioEnabled}visible={visible}volume={volume}isSelf={isSelf} isSupplier={isSupplier} isARMode={isAREnabled}isCameraSwitching={isCameraSwitching}mirror={isSelf && facingMode === FacingModeEnum.FRONT}onInvitePrivateMeeting={this.handleInvite.bind(this)}onSwitchCamera={onSwitchCamera}key={streamUserId}/>
);
DesktopRoom(主模块)
此模块是主要的渲染模块,在经过上面的辅助模块处理后,将梳理整顿好数据流输到当前模块,对数据进行实际的渲染。
以上就是这个项目的核心代码逻辑,通过高阶组件将业务逻辑进行分批次处理,最后引入到主模块进行集中渲染。
注意事项
1.关于腾讯云的web端视频聊天只支持谷歌浏览器,对其他的浏览器暂不支持。
await TRTC.checkSystemRequirements()
Trtc的SDK提供对浏览器的判断接口。
2.关于Socket服务,内贸站开发的会客厅是和麦通部门合作,通过他们的Socket服务对状态进行管理。对于后端创建Socket服务的情况不是很了解。
3.关于Api,腾讯开发的腾讯云服务时间不长,正处于快速迭代的时期,api的接口是和SDK的版本想绑定的,所以随意升级SDK会导致api不能适配,没有向下兼容的设计。看api的时候一定要关注SDK的版本。