human: 如何处理七牛云的实时音视频实现视频通话

gpt: [实时音视频](https://developer.qiniu.com/rtc) > 快速入门 > Uniapp >实现视频通话

#  实现视频通话

最近更新时间: 2023-12-18 15:11:10

# 初始化房间并加入房间

到这里您应该已经完成了开发准备，您已经可以拿到 RoomToken 。SDK 通过传入 RoomToken 来完成加入房间。RoomToken
是一个包含了一次连麦所需要的主要信息的 token，这些信息包括 七牛的账户标识、连麦的应用 ID(appId)、连麦的房间号
(roomName)、连麦的用户名(userId)、有效期等等。

> 如果您还不知道如何生成 RoomToken，请先阅读
> [七牛实时音视频云接入指南](https://developer.qiniu.com/rtc/8802/pd-overview) 。
    
    
    import { QNRTC } from "@/js_sdk/QNRTC-UniPlugin-JS/QNRTC-UniPlugin-JS/RTCIndex.native.js"
    // 必须在使用其它接口前调用
    QNRTC.init()
    // 初始化客户端
    const client = QNRTC.createClient()
    // 加入房间
    await client.join(roomToken, userData);
    

# 添加原生 component 组件

添加音视频通话需要的原生组件

    
    
    <QNRTC-UniPlugin-SurfaceView class="track-video" v-for="(item,index) in localTracks" :key="item.identifyID" v-if="item.kind === 'video'" :local="0" :identifyID="item.identifyID" fillMode="QNVideoFillModePreserveAspectRatioAndFill" :trackID="item.trackID"></QNRTC-UniPlugin-SurfaceView>
    <QNRTC-UniPlugin-SurfaceView class="track-video" v-for="(item,index) in remoteTracks" :key="item.identifyID" v-if="item.kind === 'video'" :local="1" :identifyID="item.identifyID" :userID="item.userID" fillMode="QNVideoFillModePreserveAspectRatioAndFill" :trackID="item.trackID"></QNRTC-UniPlugin-SurfaceView>
    

  * local: 0 本地 track 视图，1 远端 track 视图
  * identifyID: uniapp 中每个 track 的唯一标识符
  * trackID: 服务器对于每个 track 的唯一标识符（track 未发布时该值为""）
  * userID 发布该 track 的 用户 ID（local = 1 时需要该属性）
  * fillMode 对应视图层的渲染模式（暂时只支持iOS）

# 采集音视频轨

这里我们将要采集 2 个音视频轨，分别是 **摄像头视频轨** 和 **麦克风音频轨** 。

    
    
    const cameraVideoTrack = QNRTC.createCameraVideoTrack()
    const microphoneAudioTrack = QNRTC.createMicrophoneAudioTrack()
    

# 发布本地音视频轨

成功加入房间后，可在
[**onConnectionStateChanged**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onConnectionStateChanged)
事件中 **state** 为 **QNConnectionState.CONNECTED** 后发布本地 Track 。

    
    
    this.client.on("onConnectionStateChanged", ({
        state
    }) => {
        if (state === QNConnectionState.CONNECTED) {
            this.client.publish(this.localTracks, ({
                onPublished,
                data,
                info
            }) => {
                if (onPublished) {
                    // ...
                } else {
                    // ...
                }
            })
        }
    })
    

发布成功后，本地通过回调获得发布成功的结果。而远端用户则会通过
[**onUserPublished**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onUserPublished)
收到发布成功的回调。

# 订阅远端音视频 Track

SDK 默认会进行自动订阅，订阅成功后根据媒体类型收到
[**onAudioSubscribed**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onAudioSubscribed)
或者
[**onVideoSubscribed**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onVideoSubscribed)
的回调，然后通过原生组件传入对应参数，实现远端窗口显示。

    
    
    this.client.on("onAudioSubscribed", (params) => {
        for (let i of params.trackList) {
            this.remoteTracks.push(i)
        }
    })
    this.client.on("onVideoSubscribed", (params) => {
        for (let i of params.trackList) {
            this.remoteTracks.push(i)
        }
    })
    

# 订阅流

从上文发布的过程中我们可以知道，推流成功后一般会生成一个 **Track** ，一个用户可以发布多个音视频 **Track**
，在实际需求中我们不一定会把他所有发布的 **Track** 都订阅（可能只订阅音频之类的），所以订阅的目标是以 **Track** 为单位的。

我们可以通过 SDK 的
[**onUserPublished**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onUserPublished)
事件获取当前房间发布的 **Track** 。

    
    
    this.client.on("onUserPublished", (params) => {
        console.log(params.trackList)
    })
    

> 需要在join房间之前监听对应事件，**join**
> 加入房间成功后，[**onUserPublished**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onUserPublished)
> 会返回当前所有房间内已发布 **Track** 列表以及用户 **userID** 。

进入房间后，当一个远端用户发布了自己的 **Track** ，此时在我们这边也会触发
[**onUserPublished**](https://developer.qiniu.com/rtc/11404/UniappQNRTCClinetEvent#onUserPublished)
事件，事件会带上远端用户的 **userID** 以及所发布的 **Track** 列表。

# 离开房间

在进入音视频通话房间之后，用户可以根据业务场景的需求在适当的时间调用离开房间的接口退出连麦。例如客户端踢人：

    
    
    client.on("onMessageReceived", (params) => {
        if(params.content === "kickOut") {
            client.leave()
        }
    })
    

#### 销毁

在整个页面销毁时，用户需要调用以下代码对资源进行释放，一般此操作建议在页面生命周期 **onUnload** 和 **onBackPress**
中进行，示例代码如下：

    
    
    onUnload() {
        this.client.leave()
        QNRTC.deinit()
    }
    onBackPress() {
        this.client.leave()
        QNRTC.deinit()
    }
    

# 结语

到了这里我们已经了解 SDK 的基本使用方式。  
更多请参考我们的 github 开源 [Demo __](https://github.com/pili-engineering/QNRTC-Uniapp)

以上内容是否对您有帮助？