适用场景
TRTC 支持四种不同的进房模式,其中视频通话(VideoCall)和语音通话(VoiceCall)统称为通话模式,视频互动直播(Live)和语音互动直播(VoiceChatRoom)统称为 直播模式。在学习测试中主要使用到VideoCall和VoiceCall模式 通话模式下的 TRTC,支持单个房间最多300人同时在线,支持最多30人同时发言。适合1对1视频通话、300人视频会议、在线问诊、远程面试、视频客服、在线狼人杀等应用场景
原理解析
TRTC 云服务由两种不同类型的服务器节点组成,分别是“接口机”和“代理机”:
- 接口机 该类节点都采用最优质的线路和高性能的机器,善于处理端到端的低延时连麦通话,单位时长计费较高。
- 代理机 该类节点都采用普通的线路和性能一般的机器,善于处理高并发的拉流观看需求,单位时长计费较低。
- 通话示例
在通话模式下,TRTC 房间中的所有用户都会被分配到接口机上,相当于每个用户都是主播,都可以进行推流。
使用流程
集成使用
代码语言:javascript复制npm install trtc-electron-sdk --save
代码语言:javascript复制import TRTCCloud from 'trtc-electron-sdk';
let trtcCloud = new TRTCCloud();
此外在从trtc-electron-sdk/liteav/trtc_define中导入进房需要的TRTCParams实例。
vue项目开发
1获取承载DOM的节点
this.videoContainer = document.querySelector('#video-container');
2.计算签名
this.sdkInfo = genTestUserSig(this.userId);
3.实例化一个trtc-electron-sdk
trtcCloud = new TRTCCloud();
4.配置两个监听事件,进房和退房事件,这两个事件必须成对出现,并且在退房exitRoom时使用进房操作会引起不可预计的问题
trtcCloud.on('onEnterRoom', this.onEnterRoom.bind(this));
trtcCloud.on('onExitRoom', this.onExitRoom.bind(this));
5.设置视频编码和美颜以及进房参数
encParam = new TRTCVideoEncParam();
trtcCloud.setBeautyStyle(TRTCBeautyStyle.TRTCBeautyStyleNature, 5, 5, 5);
param = new TRTCParams();
6.执行进房操作
trtcCloud.enterRoom(param, TRTCAppScene.TRTCAppSceneVideoCall);
demo中还将整个trtc-electron-sdk的实例挂在到了全局的windows中
7.当检测到用户id、用户签名等必要条件时便会触发onEnterRoom事件,然后将进入房间的用户添加至承载用户容器的video-container中,下方代码已做相应的注释。这里房间号若不存在则会系统默认创建一个随机的房间号,
代码语言:javascript复制startCameraAndMic() {
//这里将第一次进来的视频作为大画面视频流,相当于是主播
//TRTCVideoStreamType三个值,0,1,2分别对应大画面小画面和辅流
let id = `local_video-${this.roomId}-${TRTCVideoStreamType.TRTCVideoStreamTypeBig}`;
console.log(`startCameraAndMic: ${id}`);
//这里先判断是否有该用户进房
let view = document.getElementById(id);
console.log(view,'line in 417')
// if (!view) {
view = document.createElement('div');
view.id = id;
view.className = 'local-video-container';
this.videoContainer.appendChild(view);
// }
trtcCloud.startLocalPreview(view);
trtcCloud.startLocalAudio();
trtcCloud.setLocalViewFillMode(TRTCVideoFillMode.TRTCVideoFillMode_Fill);
trtcCloud.setLocalViewRotation( TRTCVideoRotation.TRTCVideoRotation0 );
trtcCloud.setLocalViewMirror = true
// console.log(trtcCloud.setLocalViewMirror)
//TRTCVideoFillMode_Fill: 图像铺满屏幕,超出显示视窗的视频部分将被截掉,所以画面显示可能不完整
//TRTCVideoFillMode_Fit: 图像长边填满屏幕,短边区域会被填充黑色,但画面的内容肯定是完整的。
},
本地视频展示还能设置以下几点:
setRemoteViewRotation,显示视频的旋转方向,支持0、90、180和270度旋转;
setNetworkQosParam,设置网络流控相关。有preference和controlMode两种方式,前者用于弱网下是“保清晰”还是“保流畅”的判断,而后者则用于设置流 控模式,一般走默认的云端控制即可。
setLocalViewMirror,设置显示本地是否显示镜像,默认选择false。但是这个初始时设置好像有点问题。
8.检测远端用户
远端用户id设置形式
id = `${uid}-${this.roomId}-${TRTCVideoStreamType.TRTCVideoStreamTypeSub}`;
创建远端用户承载的view组件并添加到video-container容器中
代码语言:javascript复制startCameraAndMic() {
//这里将第一次进来的视频作为大画面视频流,相当于是主播
//TRTCVideoStreamType三个值,0,1,2分别对应大画面小画面和辅流
let id = `local_video-${this.roomId}-${TRTCVideoStreamType.TRTCVideoStreamTypeBig}`;
console.log(`startCameraAndMic: ${id}`);
//这里先判断是否有该用户进房
let view = document.getElementById(id);
console.log(view,'line in 417')
// if (!view) {
view = document.createElement('div');
view.id = id;
view.className = 'local-video-container';
this.videoContainer.appendChild(view);
// }
trtcCloud.startLocalPreview(view);
trtcCloud.startLocalAudio();
trtcCloud.setLocalViewFillMode(TRTCVideoFillMode.TRTCVideoFillMode_Fill);
trtcCloud.setLocalViewRotation( TRTCVideoRotation.TRTCVideoRotation0 );
trtcCloud.setLocalViewMirror = true
// console.log(trtcCloud.setLocalViewMirror)
//TRTCVideoFillMode_Fill: 图像铺满屏幕,超出显示视窗的视频部分将被截掉,所以画面显示可能不完整
//TRTCVideoFillMode_Fit: 图像长边填满屏幕,短边区域会被填充黑色,但画面的内容肯定是完整的。
},
将远端用户承载画面使用removeVideos对象进行保存,然后开始渲染远端用户视频并设置视频的渲染模式为fill还是fit
最后是设置远端用户加载的布局样式,其实这个可以通过CSS做
代码语言:javascript复制 videoTypeSetting() {
let marginTop = 80 ;
let margin = 5;
let H = this.subStreamHeight;
let m = 0;
let topIndex = 0;
let remoteVideos = this.remoteVideos;
let typeClassName = '';
let top = 0;
let i = 0;
for (let id in remoteVideos) {
topIndex = Math.floor( i / 2 );
typeClassName = i % 2 ===0 ? 'right' : 'left';
top = (topIndex * H (topIndex 1) * margin ) marginTop;
remoteVideos[id].className = `user-video-container ${typeClassName}`;
remoteVideos[id].style.top = `${top}px`;
logger.log(`videoTypeSetting: i:${i}, ti: ${topIndex}, top ${top}, H: ${H}, m: ${m}, id:${id},` );
console.log(`videoTypeSetting: i:${i}, ti: ${topIndex}, top ${top}, H: ${H}, m: ${m}, id:${id},` );
i ;
}
},
这里主要是将远端用户呈现的方式为左右依次呈现,同时这里也有一个问题,当用户过多时会造成布局混乱。
至此便完成了trtc-electron的音视频通话。
理解分享代码块
1.获取屏幕窗口属性,getScreenCaptureSources,设置当前电脑已经打开可以分享窗口的缩略大小,返回一个TRTCScreenCaptureSourceInfo属性
代码语言:javascript复制getScreensList() {
// 获取窗口快照,这是资源消耗很高的函数,做个防抖,防频繁点击。
clearTimeout(this.getScreensTaskID);
let my = this;
this.getScreensTaskID = setTimeout(()=>{
console.log('getScreensList');
my.screensList = trtcCloud.getScreenCaptureSources(200, 160, 10, 10);
console.log(my.screensList)
my.screensListVisiable = true;
}, 200);
},
2.如果至此不做任何处理,分享是electron返回的是一个白屏界面,我们需要将返回的TRTCScreenCaptureSourceInfo
中的第一帧图片画在对应的位置
代码语言:javascript复制for (let i = 0; i < list.length; i ) {
srcInfos = list[i];
console.log(srcInfos,'line in 67')
//获取缩略图内容
if (srcInfos.thumbBGRA.length===0) continue;
elId = `screen_${srcInfos.sourceId}`;
cnvs = document.getElementById(elId);
cnvs.width = srcInfos.thumbBGRA.width;
cnvs.height = srcInfos.thumbBGRA.height;
imgData = new ImageData(new Uint8ClampedArray(srcInfos.thumbBGRA.buffer), srcInfos.thumbBGRA.width, srcInfos.thumbBGRA.height );
cnvs.getContext("2d").putImageData(imgData, 0, 0);
}
3.触发点击操作,这里需要注意的一个点是,demo是将父组件的一个方法直接传递给子组件,子组件通过this.XXXd的方式直接使用
代码语言:javascript复制chooseWindowCapture(event) {
let source = {
sourceId: event.currentTarget.dataset.id,
sourceName: event.currentTarget.dataset.name,
type: parseInt(event.currentTarget.dataset.type),
};
console.log('chooseWindowCapture', source);
this.startScreenShare(source);
this.screensListVisiable = false;
this.isScreenSharing = true;
},
然后选择需要渲染的目标selectScreenCaptureTarget并开始渲染startScreenCapture
代码语言:javascript复制startScreenShare(source) {
let rect = new Rect();
rect.top = 0;
rect.left = 0;
rect.width = 0;
rect.height = 0;
trtcCloud.selectScreenCaptureTarget(source.type, source.sourceId, source.sourceName, rect, true, false);
trtcCloud.startScreenCapture()
},
至于停止分享就是一句话
代码语言:javascript复制trtcCloud.stopScreenCapture();
4.通过监听事件onUserSubStreamAvailable我们可以将远端流的分享画面展现到我们的布局当中,该方法会传递两个参数uid和available,前者为用户id后者是否开启辅路画面
代码语言:javascript复制 showRemoteScreenSharing(uid) {
let id = `${uid}-${this.roomId}-${TRTCVideoStreamType.TRTCVideoStreamTypeSub}`;
logger.log(`showRemoteScreenSharing: uid: ${id}`);
console.log(`showRemoteScreenSharing: uid: ${id}`);
let W = this.subStreamWidth;
let H = this.subStreamHeight;
let view = document.getElementById(id);
if (!view) {
view = document.createElement('div');
view.id = id;
view.style.width = `${W}px`;
view.style.height = `${H}px`;
this.videoContainer.appendChild(view);
}
this.remoteVideos[id] = view;
trtcCloud.startRemoteSubStreamView(uid, view);
trtcCloud.setRemoteSubStreamViewFillMode(uid, TRTCVideoFillMode.TRTCVideoFillMode_Fill);
// this.videoTypeSetting()
//trtcCloud.setRemoteSubStreamViewRotation() 设置旋转方向
//const opt = new TRTCVideoEncParam()
//opt.videoResolution = TRTCVideoResolution.TRTCVideoResolution_640_360
//opt.resMode = TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape
//opt.videoFps = 15
//opt.videoBitrate = 600
//opt.minVideoBitrate = 360
//设置辅流输出参数
//trtcCloud.setSubStreamEncoderParam(opt)
},
整块代码完成三步,首先创建一个DOM节点,然后开始渲染画面,最后设置渲染画面的方式为fill还是fit。
5.取消屏幕分享
代码语言:javascript复制 closeRemoteScreenSharing (uid) {
let id = `${uid}-${this.roomId}-${TRTCVideoStreamType.TRTCVideoStreamTypeSub}`;
let view = document.getElementById(id);
if (view) {
this.videoContainer.removeChild(view);
}
delete this.remoteVideos[id];
}
注:本文代码全部来自于腾讯云TRTCSimpleDemo,如果需要可以下载对比观看。更多SDK详情请参考官网https://trtc-1252463788.file.myzijiebao.com/electron_sdk/docs/TRTCCloud.html#setSubStreamEncoderParam