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

Posted anyRTC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
        });

总结

当前逻辑基本实现呼叫邀请+通话
需要更详细,更具体,更全面的代码请前往 demo 源码 地址

  • 注意事项
    • RTM 初始化、RTC 初始化都只需要执行一次,多次执行请杀掉程序
    • RTM 可以在 vue页面, RTC 视频容器必须在 nvue 页面

以上是关于uni-app技术分享|开源demo视频呼叫arcall uni-app端技术实现的主要内容,如果未能解决你的问题,请参考以下文章

uni-app技术分享| 怎么用uni-app实现呼叫邀请

uni-app技术分享| uni-app常见问题

IOS技术分享| ARCall视频通话重构

Android技术分享| 音视频呼叫邀请开发流程

uni-app技术分享| uni-app转小程序_实时音视频

Android技术分享| 视频通话开发流程