# TRTCUniApp **Repository Path**: jay-hardcoder/trtcuni-app ## Basic Information - **Project Name**: TRTCUniApp - **Description**: 腾讯TRTC SDK UniApp 插件使用实例 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2022-04-11 - **Last Updated**: 2022-04-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TRTC Uni-App 插件文档 该插件是腾讯 TRTC SDK 的UniApp插件,主要功能: - 直播直播(除了标识为组件方法的功能在组件,其他都是在模块上) - 进房、退房 - 开、关麦克风 - 开、关摄像头 - 将指定用户视频流渲染、取消渲染,视频控件上(组件方法) - 切换主播、观众角色 - 屏幕共享 - 开启屏幕录制 - 关闭屏幕录制 - IM消息 - 发送文本类型的IM消息 - 发送自定义内容IM消息 - 接收IM消息 ## 一些约定 - 调用插件,统一格式,模块对象.api方法,传入2个参数 - 配置对象,传入和文档中指定的参数键值对 - 回调函数,代表本次调用成功或失败,result对象为回调函数的入参,存放插件api返回的数据 - result对象的数据结构,该对象约定格式如下 ``` { error: false, code: 0, data: { //不同的api,有不同的结构,参考具体示例即可 }, msg: '信息'//如果error为true,则该属性为错误信息 } ``` - 登录API示例 ``` module.login({ username: 'admin', password: '123456' }, result => { //失败 if(result.error) { let {code, data, msg} console.log(`调用失败,code = ${code}, msg = ${msg}`); } else { //成功 let {token, userId, userName} = result.data console.log(`登录成功:token = ${token}, userId = ${userId},userName = ${userName}`); } ); ``` ## 插件使用 ### 引入插件 将插件**Py-TRTC**目录,拷贝到根目录下的**nativeplugins**目录,如果不存在,则手动创建该目录! 注意:不涉及UI的功能使用模块对象方法,涉及UI的功能调用组件对象。 ### 模块对象 - 获取模块对象 ``` const tRTC = uni.requireNativePlugin("Py-TRTC"); ``` ### 组件对象 - 申明组件对象(视频控件),使用ref属性指定名称,例如video ``` ``` - API调用,使用this.$refs.video,获取组件对象,再调用具体的api ``` this.$refs.video.api(); ``` ## 视频直播API > ***注意:插件使用前,需要申请麦克风、摄像头等权限,否则API可能会调用失败或异常!!!*** 建议每个API调用前,都先调用requestNeedPermission(),再串联调用具体的API,为了避免回调地狱,推荐使用Promise封装后进行串联。 ### 申请权限 ``` tRTC.requestNeedPermission({}, result => { if (result.error) { //用户拒绝 } else { //用户允许 } }); ``` ### 注册事件,后续直播间的事件,都回调在这里 - 事件类型 - onRegisterSuccess,注册事件成功,回调参数result中data参数内,eventCallbackId为本次注册回调id,取消注册时需要回传!如果不取消注册,可能会引起内存泄漏。 - onEnterRoom,进入房间成功 - onEnterRoomFail,进入房间失败 - onExitRoom,退出房间成功 - onRemoteUserEnterRoom,有用户进房 - onRemoteUserLeaveRoom,有用户退房 - onUserVideoAvailable,用户开、关摄像头,回调参数result中data参数内,userId为用户Id,available为是否开启摄像头,一般在这里将用户的视频流渲染到控件中,或者取消渲染吗 - onScreenCaptureStartFail,屏幕分享录制失败 - onReceiveRoomTextMsg,接收到房间文本消息 - onReceiveRoomCustomMsg,接收到房间自定义消息 ``` tRTC.registerEvent({}, result => { console.log(JSON.stringify(result)); let type = result.data.type; if ('onRegisterSuccess' === type) { //注册事件成功 let id = result.data.eventCallbackId; //记录id到data this.eventCallbackId = id; } else if ('onEnterRoom' === type) { //进入房间成功 if (result.error) { this.toast(`进房失败!`); } else { this.toast(`进房成功,耗时${result.data.time}毫秒`); } } else if ('onEnterRoomFail' === type) { this.toast(`进房失败,错误码:${result.data.errorCode}`); } else if ('onExitRoom' === type) { //退出房间成功 if (!result.error) { this.toast("退房成功"); } } else if ('onRemoteUserEnterRoom' === type) { //有用户进房 if (!result.error) { this.toast(`${result.data.userId} 用户进房`); } } else if ('onRemoteUserLeaveRoom' === type) { //有用户退房 if (!result.error) { this.toast(`${result.data.userId} 用户退房`); } } else if ('onUserVideoAvailable' === type) { let { userId, available } = result.data; if (!this.isAnchor) { if (available) { //我是观众时,判断进房的用户是否是主播,来显示主播的视频 if (userId === anchorUserId) { this.$refs.video.startRemoteView({ remoteUid: userId }, result => { console.log(JSON.parse(result)); }); this.toast("主播进房"); } } else { this.toast("主播暂时离开了"); } } } else if ('onScreenCaptureStartFail' === type) { this.toast("屏幕分享录制失败"); } else if ('onRoomDestroy' === type) { this.toast("IM房间销毁!"); } else if ('onReceiveRoomTextMsg' === type) { //接收到房间文本消息 let { userId, userName, avatarUrl } = result.data.userInfo; //插入到消息列表... } else if ('onReceiveRoomCustomMsg' === type) { //接收到房间自定义消息 let { roomId, cmd } = result.data; let { userId, userName, avatarUrl } = result.data.userInfo; //插入到消息列表... } }); ``` ### 取消注册事件 - 需要将注册事件成功时,插件传递的eventCallbackId回传,如果不取消注册,可能会引起内存泄漏。 ``` tRTC.unRegisterEvent({ eventCallbackId: this.eventCallbackId }, result => { console.log(JSON.parse(result)); }); ``` ### 切换角色 ``` //切换为主播角色 tRTC.switchToAnchor(); //切换为观众角色 tRTC.switchToAudience(); ``` ### 进入房间前的准备 #### setLocalViewFillMode(设置本地音视频流,不设参数,则默认Fit) - Fill:值0,模式表示填充,画面可能会被等比放大和裁剪,但不会有黑边 - Fit:值1,模式表示适应,画面可能会等比缩小以完全显示其内容,可能会有黑边 ``` tRTC.setLocalViewFillMode({ fillMode: 1 }, result => { console.log(JSON.parse(result)); }); ``` #### setVideoEncoderParam(设置本地视频编码参数,不设参数,则默认参数) - videoResolution,分辨率取值 - 960x540:110(默认值) - 1280x720:112 - 1920x1080: 114 - videoResolutionMode,分辨率模式取值 - 横屏:0 - 竖屏:1(默认值) ``` tRTC.setVideoEncoderParam({ //分辨率 videoResolution: 110, //帧率 videoFps: 15, //最高码率 videoBitrate: 1200, //分辨率模式 videoResolutionMode: 1 }, result => { console.log(JSON.parse(result)); }); ``` ### 麦克风开、关 ``` //开启麦克风 tRTC.startLocalAudio(); //关闭麦克风 tRTC.stopLocalAudio(); ``` ### 摄像头开、关 - isFrontCamera,true为前置摄像头,false为后置摄像头 ``` //开启摄像头 this.$refs.video.startLocalPreview({ //前置摄像头 isFrontCamera: true }, result => { console.log(JSON.stringify(result)); }); //关闭摄像头 this.$refs.video.stopLocalPreview(); ``` ### 进入房间 进入房间,有IM聊和直播间这2个房需要进,流程如下: 1. 登录IM 2. 创建IM房间(如果你是主播,会进行创建(如已创建,则不创建,并返回成功),不是主播,则不会创建,并返回成功) 3. 进入直播房间 - login,登录IM - sdkAppId,应用Id - userId,用户Id - userSig,用户签名 - createRoom,创建房间 - roomId,房间Id - roomType,IM房的类型,会议房:Meeting - roomName,房间名称 ``` //先登录IM,再登录直播 tRTC.login({ sdkAppId: this.sdkAppId, userId: this.userId, userSig: this.userSig }, result => { if (result.error) { this.toast(`登录IM失败,请稍后重试,code = ${result.code},msg = ${result.msg}`); } else { this.toast("登录IM成功"); //获取自己的用户信息 this.getUserInfo(); //创建房间 tRTC.createRoom({ roomId: this.roomId, roomType: this.imRoomType, roomName: this.roomName }, result => { if (result.error) { this.toast(`创建房间失败,code = ${result.code},msg = ${result.msg}`); } else { //进入直播房间 this.enterLiveRoom( this.sdkAppId, this.userId, this.userSig, this.roomId ); } }); } }); ``` 进入直播房 - sdkAppId,接入sdk时,需要创建应用,应用的id - userId,用户Id - userSig,用户签名 - roomId,房间Id - roomType,房间类型 - 视频互动直播模式,1(默认) - 语音互动直播模式:0 ``` //进入直播房 enterLiveRoom() { //设置角色 if (this.isAnchor) { tRTC.switchToAnchor(); } else { tRTC.switchToAudience(); } //设置本地音视频流 tRTC.setLocalViewFillMode({ fillMode: 1 }, result => { console.log(JSON.parse(result)); }); //设置本地视频码率 tRTC.setVideoEncoderParam({ //分辨率 videoResolution: 110, //帧率 videoFps: 15, //最高码率 videoBitrate: 1200, //分辨率模式 videoResolutionMode: 1 }, result => { console.log(JSON.parse(result)); }); //主播,直接开启麦克风和视频 console.log("this.isAnchor = " + this.isAnchor); if (this.isAnchor) { //开启麦克风,开启视频 this.controlAudio(true); if (this.isScreenCapture) { console.log("屏幕录制,不开启视频"); this.controlVideo(false); } else { //不是屏幕录制时,才开启视频,否则录制会冲突,不会起作用 console.log("视频直播,开启视频"); this.controlVideo(true); } } else { //观众,等待主播进房后,开启视频 } //进入房间 tRTC.enterRoom({ sdkAppId: this.sdkAppId, userId: this.userId, userSig: this.userSig, roomId: this.roomId, roomType: this.roomType }, result => { const resultStr = JSON.stringify(result); console.log(resultStr); }); } ``` ### 退出房间 退房也是同样,要退IM房和直播房 - 退出IM房 ``` tRTC.logout({}, result => { this.toast(JSON.parse(result)); }); ``` - 退出直播房,需要将房间Id回传 ``` tRTC.exitRoom({ roomId: this.roomId }, result => { console.log(JSON.stringify(result)); }); ``` - 退房一般要将摄像头、麦克风以及共享屏幕退出,根据实际需求调用即可! ``` //退出屏幕录制 tRTC.stopScreenCapture({}, result => { console.log(JSON.stringify(result)); }); //关闭麦克风 tRTC.stopLocalAudio({}, result => { console.log(JSON.stringify(result)); }); //关闭摄像头 this.$refs.video.stopLocalPreview({}, result => { console.log(JSON.stringify(result)); }); ``` ### 渲染其他用户的视频(可多个主播,一个Video组件对应一个主播的视频) - 当有多个主播视频需要渲染时,调用该方法进行渲染,remoteUid为要渲染的用户的Id - 一般在进房后,如果已经事先知道主播的userId,可以直接调用该方法传入主播Id,进行渲染 - 如果不知道主播的Id,则在事件回调注册中,处理onUserVideoAvailable事件,该事件中,获取主播的userId进行渲染 ``` this.$refs.video.startRemoteView({ remoteUid: userId }, result => { const resultStr = JSON.stringify(result); console.log(resultStr); }); ``` ### 设置屏幕常亮 一般直播都需要屏幕常亮,一般在页面的`onLoad`声明周期回调中,进行调用。并且在`onUnload`回调时,取消常亮。 - setScreenHoldOn - isHoldOn,是否常亮,true则常亮,false则取消常亮 ``` //设置常亮 tRTC.setScreenHoldOn({ isHoldOn: true }, result => { this.toast(JSON.parse(result)); }); ``` ## IM聊天 插件除了直播,还有IM的功能,主要有2个发送消息的API,文本消息和自定义消息。 ### 发送文本消息 - 参数 - roomId,房间Id - msg,需要发送的消息 - 注意,发送成功后,需要自己将消息插入到消息列表!(消息监听不会监听到自己发送的消息) ``` tRTC.sendRoomTextMsg({ roomId: this.roomId, msg: this.msgInput }, result => { this.toast(result.msg); if (!result.error) { //将我发的消息插入到列表 this.insertNewMsg(this.msgInput, cmd); //清空输入框 this.msgInput = ''; } }); ``` ### 发送自定义消息 - 参数 - roomId,房间Id - msg,需要发送的消息,可以为一个json字符串,内容可动态拓展,这里示例添加2个拓展字段,field1和field2 - cmd,本次发送的消息的命令,该值为一个字符串,需要自己定义 - 注意,发送成功后,需要自己将消息插入到消息列表!(消息监听不会监听到自己发送的消息) ``` let cmd = "10086"; let userId = this.userId; let userName = this.userName; let content = this.msgInput; //自定义json结构,这里将消息内容做成json,增加2个字段 let json = JSON.stringify({ field1: userId, field2: userName, content }); tRTC.sendRoomCustomMsg({ roomId: this.roomId, msg: json, cmd: cmd }, result => { this.toast(result.msg); if (!result.error) { //将我发的消息插入到列表 this.insertNewMsg(this.msgInput, cmd); //清空输入框 this.msgInput = ''; } }); ``` ### 消息监听 - IM消息的监听和直播事件的监听都在`registerEvent`方法中 - onReceiveRoomTextMsg,接受到文本消息 - onReceiveRoomCustomMsg,接收到自定义消息 ``` tRTC.registerEvent({}, result => { console.log(JSON.stringify(result)); let type = result.data.type; //...省略其他事件的判断处理,这里只示例消息接收处理 if ('onReceiveRoomTextMsg' === type) { //接收到房间文本消息 let { userId, userName, avatarUrl } = result.data.userInfo; //插入到消息列表... this.roomMsgList.push(result.data); } else if ('onReceiveRoomCustomMsg' === type) { //接收到房间自定义消息 let { roomId, cmd } = result.data; let { userId, userName, avatarUrl } = result.data.userInfo; //解析自定义消息后,再插入到消息列表中 if (cmd == '10086') { //解析msg字段,该字段被封装成一个字符串,我们转换为对象后,再插入到列表 //content字段,该字段就是发送的内容 let msg = JSON.parse(result.data.msg); console.log(`推展字段 field1 = ${msg.field1}`); console.log(`推展字段 field2 = ${msg.field2}`); console.log(JSON.stringify(msg.content)); //将解析出来的内容,替换到为json中的消息内容 result.data.msg = msg.content; this.roomMsgList.push(result.data); } } }); ``` ## 用户信息 IM中,提供了基础的用户信息设置和获取,信息只支持用户名`userName`,用户的头像Url`avatarUrl`,根据需求可使用可不使用。 ### 获取用户信息 - getUserInfo,该方法可以获取多个用户的用户信息。 - 说明 - 参数:userIdList,用户id列表,多个id使用英文逗号间隔。例如:123,456,789 - 返回结果,result对象中,data对象中的userInfoList为用户信息列表 - 用户信息的数据结构 ``` { "userId": 123456, "userName": admin, "avatarUrl": "http://www.pic.com" } ``` - 获取自己的用户信息 ``` tRTC.getUserInfo({ userIdList: this.userId }, result => { if (result.error) { console.log(`获取自己的用户信息 => 失败,原因:${result.msg}`); } else { console.log(`获取自己的用户信息 => 成功,${result}`); let myUserInfo = result.data.userInfoList[0] console.log(`用户Id:${myUserInfo.userId},用户名:${myUserInfo.userName},用户头像:${myUserInfo.avatarUrl}`); } }); ``` ### 修改用户信息 - setSelfProfile,该方法可以设置用户名、用户头像 ``` tRTC.setSelfProfile({ userName: newUserName avatarUrl: newAvatarUrl }, result => { if (!result.error) { //更新成功 this.userName = newUserName; this.avatarUrl = newAvatarUrl; } }); ``` ## 屏幕共享API ### 开启屏幕共享 ** 注意,开启屏幕共享前,确保关闭了摄像头,否则SDK会判定该次调用无效,也不会报错! ** - videoResolution,分辨率,取值 - 1280x720:112 - 1920x1080:114 - videoResolutionMode,分辨率模式,取值 - 横屏:0 - 竖屏:1 - videoFps,帧率,默认值为10 - videoBitrate,最高码率,默认值为1200 - enableAdjustRes,分辨率自适应,默认为false ```` tRTC.startScreenCapture({ videoResolution: 112, videoResolutionMode: 1, videoFps: 10, videoBitrate: 1200, enableAdjustRes: false }, result => { console.log(JSON.stringify(result)); if(result.code > 0) { this.isOpenCapture = true; this.toast("开启屏幕录制,成功"); } else { console.log("开启屏幕录制,失败"); } }); ```` ### 关闭屏幕共享 ``` tRTC.stopScreenCapture({}, result => { console.log(JSON.stringify(result)); if(result.code > 0) { this.isOpenCapture = false; this.toast("关闭屏幕录制,成功"); } else { console.log("关闭屏幕录制,失败"); } }); ```