uni-app技术分享|开源demo视频呼叫arcall uni-app端技术实现

少年意气强不羁,虎胁插翼白日飞。这篇文章主要讲述uni-app技术分享|开源demo视频呼叫arcall uni-app端技术实现相关的知识,希望能为你提供帮助。
uniapp_arcall 介绍 基本
uniapp_arcall 是通过 uniapp 实现的语音通话、视频通话以及相关配套的呼叫邀请。
解决向指定用户发起呼叫通知,对方接受后进行通话的场景需求。
呼叫邀请基本流程

graph TD A[主叫] --> |发起呼叫|B{被叫收到呼叫} A --> |收到被叫接听|C[主叫执行 RTC] A --> |收到被叫拒绝|G[相关逻辑] B--> D[被叫接听] B--> E[被叫拒绝] D --> |通知主叫接听|A D --> F[被叫执行 RTC] E --> |通知主叫拒绝|A B --> H[60s 无操作邀请自动失败]

通话基本流程
graph LR A[初始化 RTC 实例] --> |采集音视频|B[加入房间] B --> |本地采集音视频| C[发布并渲染音视频] B --> |通过回调获取远端音视频| D[渲染远端音视频]

arcall 具体实现demo 源码 地址
呼叫邀请相关逻辑
引入呼叫邀请所需插件
// rtm 实时消息引入 const rtmModule = uni.requireNativePlugin(\'AR-RtmModule\');

呼叫邀请初始化uniapp_arcall的是项目启动就登陆 RTM,因此写在 onLaunch中,调试时会发生以下错误
Error: [JS Framework] Failed to receiveTasks, instance (1) is not available.

原因是多次将 RTM 实例初始化,会影响到 RTM 相关的使用请将程序杀死后在进行调试
// 初始化回调 await rtmModule.setCallBack(res => { switch (res.rtmEvent) { // SDK 与 RTM 系统的连接状态发生改变回调。 case \'onConnectionStateChanged\': break; // 收到点对点消息回调 case \'onPeerMessageReceived\':break; // 被订阅用户在线状态改变 case \'onPeersOnlineStatusChanged\':break; // 返回给主叫:被叫已接受呼叫邀请 case \'onLocalInvitationAccepted\':break; // 返回给主叫:呼叫邀请已被取消 case \'onLocalInvitationCanceled\':break; // 返回给主叫:呼叫邀请进程失败 case \'onLocalInvitationFailure\':break; // 返回给主叫:被叫已收到呼叫邀请 case \'onLocalInvitationReceivedByPeer\':break; // 返回给主叫:被叫已拒绝呼叫邀请 case \'onLocalInvitationRefused\':break; // 返回给被叫:接受呼叫邀请成功 case \'onRemoteInvitationAccepted\':break; // 返回给被叫:主叫已取消呼叫邀请 case \'onRemoteInvitationCanceled\':break; // 返回给被叫:来自主叫的呼叫邀请进程失败 case \'onRemoteInvitationFailure\':break; // 返回给被叫:收到一个呼叫邀请 case \'onRemoteInvitationReceived\':break; // 返回给被叫:拒绝呼叫邀请成功 case \'onRemoteInvitationRefused\':break; default: break; } }) // 初始化实例 await rtmModule.createInstance({ "appId": "你的 appid" }, res => { console.log(res); }) // 登录 RTM 系统 await rtmModule.login({ "token": "", "userId": "本地用户标识" }, (res) => { console.log("登录 RTM 系统", res); }) // // 使用 RTM 呼叫邀请(设置邀请呼叫实例的监听器) await rtmModule.setCallEventListener();

主叫
  • 查询呼叫用户是否在线
    rtmModule.queryPeersOnlineStatus({ "peerIds": ["呼叫用户"] }, (res) => { console.log(res); })

  • 呼叫用户在线时发起呼叫并订阅
    • 发起呼叫
      把本地创建的频道房间发送过去
    rtmModule.sendLocalInvitation({ "calleeId": calleeId, // 被呼叫者的 user ID "content": JSON.stringify(info) // 邀请内容 }, (res) => { resolve(res.code); })

    • 订阅(获取对方在线状态)
      当结束通话或结束邀请时记得取消订阅
    rtmModule.subscribePeersOnlineStatus({ "peerIds": ["对方 uid"] }, (res) => { //smething console.log("订阅指定单个或多个用户的在线状态", res); })

    • 主叫取消呼叫
    rtmModule.cancelLocalInvitation({ "calleeId": calleeId, // 被呼叫者的 user ID "content": JSON.stringify(info) // 邀请内容 }, (res) => { console.log("取消给对方的呼叫邀请", res); });

被叫通过回调 onRemoteInvitationReceived 收到主叫
  • 拒绝呼叫
rtmModule.refuseRemoteInvitation({ "calleeId": userId, "response": JSON.stringify(info) /邀请内容 }, (res) => { });

  • 接受呼叫
rtmModule.acceptRemoteInvitation({ "calleeId": calleeId, // 供被叫获取主叫的用户 ID "response": info ? JSON.stringify(info) : "" // 邀请响应 }, (res) => { }); // 订阅对方在线状态 ...

相关提示相关的提示、逻辑都可通过回调来进行操作
通话相关逻辑
视频组件必须实在 nvue 页面
< AR-CanvasView ref="location" style="flex: 1; " />

不管是主叫还是被叫,收到接听的回调后就可以进入 RTC 的相关逻辑
  • 引入插件
const rtcModule = uni.requireNativePlugin(\'AR-RtcModule\');

  • 初始化
// 初始化回调 await rtcModule.setCallBack(res => { switch (res.engineEvent) { case "onConnectionLost": console.log("onConnectionLost", res); break; // 网络连接状态已改变回调 case "onConnectionStateChanged": console.log("网络连接状态已改变回调", res); break; // 发生警告回调 case "onWarning":break; // 发生错误回调 case "onError":break; // 加入频道成功回调 case "onJoinChannelSuccess": // 本地渲染break; // 远端用户加入当前频道回调 case "onUserJoined":break; // 远端用户离开当前频道回调 case "onUserOffline": console.log("远端用户离开当前频道回调", res); break; // 网络连接状态已改变回调 case "onConnectionStateChanged":break; // 已显示远端视频首帧回调 case "onFirstRemoteVideoFrame": break; case "onFirstRemoteVideoDecoded":break; // 远端用户视频状态发生已变化回调(当频道内的用户超过 17 时,该回调可能不准确) case "onRemoteVideoStateChanged":break; //// 本地网络类型发生改变回调 // case "onNetworkTypeChanged": //break; //// 网络连接中断 // case "onConnectionLost": //break; //// 远端音频状态发生改变回调 // case "onRemoteAudiostateChanged": //break; //// 本地音频状态发生改变回调 // case "onLocalAudioStateChanged": //break; //// 本地视频状态发生改变回调 // case "onLocalVideoStateChanged": //break; //// 重新加入频道回调 // case "onRejoinChannelSuccess": //break; //// 离开频道回调 // case "onLeaveChannel": //break; // 已发送本地音频首帧回调 // case "onFirstLocalAudioFrame": //break; //// 已显示本地视频首帧回调 // case "onFirstLocalVideoFrame": //break; //// Token 服务即将过期回调 // case "onTokenPrivilegeWillExpire": //break; //// Token 过期回调 // case "onRequestToken": //break; //// 用户角色已切换回调(直播场景下) // case "onClientRoleChanged": //break; //// 本地或远端视频大小或旋转信息发生改变回调 // case "onVideoSizeChanged": //break; //// 通话中远端音频流的统计信息回调 // case "onRemoteAudioStats": //break; //// 当前通话统计回调。 该回调在通话中每两秒触发一次 // case "onRtcStats": //break; //// 通话中每个用户的网络上下行 last mile 质量报告回调 // case "onNetworkQuality": //break; //// 通话中本地视频流的统计信息回调 // case "onLocalVideoStats": //break; //// 通话中本地音频流的统计信息回调 // case "onLocalAudioStats": //break; //// 通话中远端视频流的统计信息回调 // case "onRemoteVideoStats": //break; }}); // 初始化实例 await rtcModule.create({ "appId": \'你的 appid\' }, res => { console.log(\'初始化实例 rtc\', res); }); // 开启智能降噪 await rtcModule.setParameters({ Cmd: \'SetAudioAiNoise\', Enable: 1 }, (res) => { console.log(\'私人定制\', res); });

  • 采集音视频
    如果是语音通话可以不执行下列代码
// 设置视频编码属性 await rtcModule.setVideoEncoderConfiguration({},res) => { console.log(\'RTC 设置视频编码属性 setVideoEncoderConfiguration 方法调用\', res.code ===0 ? \'成功\' :\'失败:\' + res); }); // 启用视频 await rtcModule.enableVideo((res) => { console.log(\'RTC 启用视频 enableVideo 方法调用\', res.code === 0 ? \'成功\' : \'失败:\' +res); });

  • 加入房间
rtcModule.joinChannel({ "token": \'\', "channelId": 本地创建的频道/通过呼叫邀请传递过来的频道, "uid": 本地的userid, }, (res) => { console.log(\'RTC joinChannel 方法调用\', res.code === 0 ? \'成功\' : \'失败:\' + res); });

  • 本地视频渲染
    < AR-CanvasView ref="location" style="flex: 1; " />

    获取容器
    // 请确保可以获取到容器 Store.location = this.$refs.location; console.log(Store.location); // 打印后 类似这种 { "ref": "68", "type": "AR-CanvasView", "attr": { "@styleScope": "data-v-39c12bd0" }, "style": { "flex": "1" } }

    // 渲染视频 await Store.location.setupLocalVideo({ "renderMode": 1, "channelId": 加入的频道房间 "uid": 本地的userid "mirrorMode": 0 }, (res) => { console.log(\'渲染视频\', res); }); // 本地预览 await Store.location.startPreview((res) => { console.log(\'本地预览\', res); })

  • 远端视频渲染
    通过回调 onFirstRemoteVideoDecoded 获取远端用户发布视频
    Store.remote 与 Store.location 类似
    await Store.remote.setupRemoteVideo({ "renderMode": 1, "channelId": 加入的频道 "uid": res.uid "mirrorMode": 0 }, (res) => { console.log(\'渲染远端视频\', res); }) // 本地预览 await Store.remote.startPreview((res) => { console.log(\'远端本地预览\', res); })

  • 挂断
    // 销毁实例 rtcModule.destroyRtc((res) => { console.log("销毁实例", res); });

总结【uni-app技术分享|开源demo视频呼叫arcall uni-app端技术实现】当前逻辑基本实现呼叫邀请+通话
需要更详细,更具体,更全面的代码请前往 demo 源码 地址
  • 注意事项
    • RTM 初始化、RTC 初始化都只需要执行一次,多次执行请杀掉程序
    • RTM 可以在 vue页面, RTC 视频容器必须在 nvue 页面

    推荐阅读