trtc-electron音视频学习初体验

2020-10-31 16:01:55 浏览数 (2)

适用场景

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

0 人点赞