实现音视频互动

  • Unity

更新时间不可用

了解如何快速接入实时互动 RTC,完成环境准备、参数配置、示例运行和核心流程验证。

本文介绍如何集成声网实时互动 SDK,通过少量代码从 0 开始实现一个简单的实时互动 App,适用于互动直播和视频通话场景。 首先,你需要了解以下有关音视频实时互动的基础概念:

  • 声网实时互动 SDK:由声网开发的、帮助开发者在 App 中实现实时音视频互动的 SDK。
  • 频道:用于传输数据的通道,在同一个频道内的用户可以进行实时互动。
  • 主播:可以在频道内发布音视频,同时也可以订阅其他主播发布的音视频。
  • 观众:可以在频道内订阅音视频,不具备发布音视频权限。

更多概念详见关键概念。

下图展示在 App 中实现音视频互动的基本工作流程:

  1. 所有用户调用 joinChannel 方法加入频道,并根据需要设置用户角色:

    • 互动直播:如果用户需要在频道中发流,则设为主播;如果用户只需要收流,则设为观众。
    • 视频通话:将所有用户的角色都设为主播。
  2. 加入频道后,不同角色的用户具备不同的行为:

    • 所有用户默认都可以接收频道中的音视频流。
    • 主播可以在频道内发布音视频流。
    • 观众如果需要发流,可在频道内调用 setClientRole 方法修改用户角色,使其具备发流权限。

前提条件

在实现功能以前,请按照以下要求准备开发环境:

  • 已下载 Unity Hub。

  • Unity 2018.4.0 或以上版本。

  • 可以访问互联网的计算机。如果你的网络环境部署了防火墙,参考应对防火墙限制以正常使用声网服务。

  • 不同开发平台的操作系统与编译器需满足下列版本要求:

开发平台操作系统版本编译器版本
AndroidAndroid 4.1 或以上Android Studio 3.0 或以上
iOSiOS 9.0 或以上Xcode 9.0 或以上
macOSmacOS 10.10 或以上Xcode 9.0 或以上
WindowsWindows 7 或以上Microsoft Visual Studio 2017 或以上
表格内容超出当前宽度,可横向滚动查看更多列。
  • 一个有效的声网账号以及声网项目。请参考 开通 RTC 服务,从声网控制台获得 App ID 和临时 Token。

    注意

    临时 Token 的有效期是 24 小时。Token 过期会导致加入频道失败。

创建项目

参考以下步骤或 Unity 官方文档创建一个 Unity 项目。若已有 Unity 项目,可略过此步骤至下一步集成 SDK。

  1. 开始前确保你已安装 Unity。若未安装,点击此处下载。
  2. 打开 Unity Editor,点击 New 新建一个项目。
  3. 依次填入以下内容后,点击 Create project 创建一个 Unity 项目。
    • Project name:项目名称。
    • Location:项目存储路径。
    • Template:项目类型。选择 3D。

集成 SDK

参考下列步骤来集成声网实时互动 SDK:

  1. 前往下载页面,下载最新版的 Unity SDK。
  2. 下载完成后在你的 Unity 编辑器中打开下载好的 SDK 包并取消勾选不需要的插件(默认会勾选 SDK 包含的所有插件),然后点击 Import 来导入 SDK。

创建用户界面

根据应用场景为你的项目创建一个用户界面(UI)。

例如,你可以在 UI 上添加以下控件:

  • 本地视图窗口
  • 远端视图窗口
  • 加入/离开频道按钮

创建好的用户界面如下图所示:

你可以参考以下步骤创建 UI。若你的项目中已有用户界面可略过此步骤。

实现步骤

本小节介绍如何实现一个实时音视频互动 App。你可以先复制完整的示例代码到你的项目中,快速体验实时音视频互动的基础功能,再按照实现步骤了解核心 API 调用。

下图展示了使用声网 RTC SDK 实现音视频互动的基本流程:

信息

在 _appId、_token 和 _channelName 字段中传入你在控制台获取到的 App ID、临时 Token,以及生成临时 Token 时填入的频道名。

导入类

新建脚本并导入 Unity 相关的类和声网 RTC Unity SDK 相关的类和接口。

  1. 在 Project 中,打开 Assets > Agora-Unity-RTC-SDK > Code >Rtc,右击然后选择 Create > C# Script,此时你的 Assets 中会有一个 NewBehaviourScript.cs 文件,将这个文件重新命名为 JoinChannelVideo.cs。后续步骤中的示例代码均指该文件中的代码。

  2. 将新建的脚本和 Canvas 绑定。选择 JoinChannelVideo.cs 文件,将其拖至左侧的 Canvas。在 Inspector 面板中你可以看到该文件已经和 Canvas 绑定。

  3. 导入 Unity 相关的类。

    C#
    using UnityEngine;
    using UnityEngine.UI;
  4. 导入 Agora.Rtc 命名空间,其中包含了实现实时音视频功能所需的各种类和接口。

    C#
    using Agora.Rtc;

处理权限请求

本小节介绍如何获取设备的摄像头、麦克风等权限。在 Unity 2018.3 或以上版本中,Unity 不会主动向用户获取麦克风和相机权限,因此你需要请求获取权限。

注意

Windows 系统会在应用程序首次尝试使用摄像头或麦克风等功能时,自动向用户弹出权限请求提示,因此你无需额外处理权限请求。

如果你开发的目标平台是 Android,Unity 提供了权限请求的 API CheckPermission。你可以调用该方法来获取相关权限。参考下列步骤来获取安卓权限:

  1. 导入 Unity 的 Android 命名空间。

    C#
    #if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
    using UnityEngine.Android;
    #endif
  2. 创建需要获取的权限列表,包括摄像头和麦克风。

    C#
    #if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
    private ArrayList permissionList = new ArrayList() { Permission.Camera, Permission.Microphone };
    #endif
  3. 检查是否已获取权限。

    C#
    private void CheckPermissions() {
        #if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID)
        foreach (string permission in permissionList) {
            if (!Permission.HasUserAuthorizedPermission(permission)) {
                Permission.RequestUserPermission(permission);
            }
        }
        #endif
    }

如果你开发的目标平台是 iOS 或 macOS,声网 RTC Unity SDK 在 Editor 文件夹下提供一个构建后处理脚本 BL_BuildPostProcess.cs。在你将项目从 Unity Editor 中构建并导出为 iOS 项目后,该脚本会自动向 Info.plist 文件添加摄像头和麦克风权限,无需你手动处理。

定义 App ID 和 Token

传入从声网控制台获取的 App ID、临时 Token,以及生成临时 Token 时填入的频道名,用于后续初始化引擎和加入频道。

C#
// 填入你的 App ID
private string _appID= "";
// 填入你的频道名
private string _channelName = "";
// 填入 Token
private string _token = "";

初始化引擎

在调用其他声网 API 前,需要创建并初始化 IRtcEngine 实例。调用 CreateAgoraRtcEngine 来创建 IRtcEngine 实例,调用 Initialize 进行初始化。

注意

你需要在用户同意 App 的隐私政策之后再调用下列代码来初始化 SDK。

C#
private void SetupVideoSDKEngine()
{
    // 创建 IRtcEngine 实例
    RtcEngine = Agora.Rtc.RtcEngine.CreateAgoraRtcEngine();
    RtcEngineContext context = new RtcEngineContext();
        context.appId = _appID;
        context.channelProfile = CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING;
        context.audioScenario = AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_DEFAULT;
    // 初始化 IRtcEngine
    RtcEngine.Initialize(context);
}

设置 UI 元素

将 UI 组件与代码进行绑定,包括加入频道、离开频道按钮的点击事件,以及本地视频显示和远端视频显示。

C#
private void SetupUI()
{
    GameObject go = GameObject.Find("LocalView");
    LocalView = go.AddComponent<VideoSurface>();
    go.transform.Rotate(0.0f, 0.0f, -180.0f);
    go = GameObject.Find("RemoteView");
    RemoteView = go.AddComponent<VideoSurface>();
    go.transform.Rotate(0.0f, 0.0f, -180.0f);
    go = GameObject.Find("Leave");
    go.GetComponent<Button>().onClick.AddListener(Leave);
    go = GameObject.Find("Join");
    go.GetComponent<Button>().onClick.AddListener(Join);
}

启用视频模块

按照以下步骤启用视频模块并开启本地视频预览:

  1. 调用 EnableVideo 启用视频模块。
  2. 调用 StartPreview 开启本地视频预览。
  3. 调用 SetForUser 设置本地视频显示。
  4. 调用 SetEnable(true) 渲染本地视频。
C#
private void PreviewSelf()
{
    // 启用视频模块
    RtcEngine.EnableVideo();
    // 开启本地视频预览
    RtcEngine.StartPreview();
    // 设置本地视频显示
    LocalView.SetForUser(0, "");
    // 渲染视频
    LocalView.SetEnable(true);
}

加入频道并发布音视频流

调用 JoinChannel [2/2] 加入频道。在 ChannelMediaOptions 中进行如下配置:

  • 设置频道场景为 CHANNEL_PROFILE_LIVE_BROADCASTING (直播场景) 并设置用户角色设置为 BROADCASTER (主播)。
  • 将 publishMicrophoneTrack 和 publishCameraTrack 设置为 true,发布麦克风采集的音频和摄像头采集的视频。
  • 将 autoSubscribeAudio 和 autoSubscribeVideo 设置为 true,自动订阅所有音视频流。
C#
public void Join()
{
    // 设置频道媒体选项
    ChannelMediaOptions options = new ChannelMediaOptions();
    // 发布麦克风采集的音频流
    options.publishMicrophoneTrack.SetValue(true);
    // 发布摄像头采集的视频流
    options.publishCameraTrack.SetValue(true);
    // 自动订阅所有音频流
    options.autoSubscribeAudio.SetValue(true);
    // 自动订阅所有视频流
    options.autoSubscribeVideo.SetValue(true);
    // 将频道场景设为直播
    options.channelProfile.SetValue(CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING);
    // 将用户角色设为主播
    options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
    // 加入频道
    RtcEngine.JoinChannel(_token, _channelName, 0, options);
}

实现常用回调

根据使用场景,定义必要的回调。下列示例代码展示本地用户加入频道、远端用户加入、离开频道的回调。

C#
// 实现你自己的回调类,可以继承 IRtcEngineEventHandler 接口类实现
internal class UserEventHandler : IRtcEngineEventHandler
{
    private readonly JoinChannelVideo _videoSample;
    internal UserEventHandler(JoinChannelVideo videoSample)
    {
        _videoSample = videoSample;
    }

    // 本地用户成功加入频道时,会触发该回调
    public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
    {
    }

    // SDK 接收到第一帧远端视频并成功解码时,会触发 OnUserJoined 回调
    public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed)
    {
        // 设置远端视频显示
        _videoSample.RemoteView.SetForUser(uid, connection.channelId, VIDEO_SOURCE_TYPE.VIDEO_SOURCE_REMOTE);
        // 开始视频渲染
        _videoSample.RemoteView.SetEnable(true);
        Debug.Log("Remote user joined");
    }

    // 远端用户离开当前频道时会触发该回调
    public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
    {
        _videoSample.RemoteView.SetEnable(false);
    }
}

设置远端视图

当远端用户加入频道时,触发 OnUserJoined 回调。调用 SetForUser 设置远端视频显示,调用 SetEnable(true) 渲染视频。

C#
// SDK 接收到第一帧远端视频并成功解码时,会触发 OnUserJoined 回调
public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed) {
    // 设置远端视频显示
    _videoSample.RemoteView.SetForUser(uid, connection.channelId, VIDEO_SOURCE_TYPE.VIDEO_SOURCE_REMOTE);
    // 开始视频渲染
    _videoSample.RemoteView.SetEnable(true);
    Debug.Log("Remote user joined");
}

设置远端用户离开频道或掉线后停止远端视频显示。远端用户离开频道后,触发 OnUserOffline 回调。调用 SetEnable(false) 停止显示视频。

C#
// 远端用户离开当前频道时会触发该回调
public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
{
    _videoSample.RemoteView.SetEnable(false);
    Debug.Log("Remote user offline");
}

开始音视频互动

在开始音频互动前,先检查是否已获取设备权限,然后在 Start 中调用一系列方法来初始化引擎、注册事件回调、加入频道,开始音频互动。

  1. 检查是否已获取设备权限。调用 CheckPermissions 方法检查是否已获取实现音视频互动所需的权限。

    C#
    void Update() {
        CheckPermissions();
    }
  2. 开始音视频互动。在 Start 方法中初始化引擎并开始实时音视频互动。

    C#
    void Start()
    {
        SetupVideoSDKEngine();
        InitEventHandler();
        SetupUI();
        PreviewSelf();
    }

结束音视频互动

按照以下步骤结束音视频互动:

  1. 调用 StopPreview 停止本地视频预览。
  2. 调用 LeaveChannel 来离开当前频道,释放所有会话相关的资源。
  3. 调用 SetEnable 停止远端视频渲染。
C#
public void Leave()
{
    Debug.Log("Leaving _channelName");
    // 离开频道
    RtcEngine.LeaveChannel();
    // 关闭视频模块
    RtcEngine.StopPreview();
    // 停止远端视频渲染
    RemoteView.SetEnable(false);
}

如果你想在退出时释放 IRtcEngine 内存,调用 Dispose 方法销毁 IRtcEngine。

注意

  • 调用 Dispose 后,你将无法再使用 SDK 的所有方法和回调。如需再次使用实时音视频互动功能,你必须重新创建一个新的引擎。详见初始化引擎。
  • 该方法为同步调用。需要等待引擎资源释放后才能执行其他操作,因此建议在子线程中调用该方法,避免主线程阻塞。
C#
void OnApplicationQuit()
{
    if (RtcEngine != null)
    {
        Leave();
        // 销毁 IRtcEngine
        RtcEngine.Dispose();
        RtcEngine = null;
    }
}

测试你的项目

按照以下步骤来测试你的音视频互动项目:

  1. 在声网控制台获取一个临时 Token。请参考开通 RTC 服务获取。
  2. 在 JoinChannelVideo.cs 中,将你的项目的 App ID、频道名以及临时 Token 分别填入到 _appID、_channelName、_token 之后。
  3. 在 Unity Editor 中,点击 Play 按钮来运行你的项目,然后点击 Join 按钮加入频道。
  4. 邀请一位朋友通过另一台设备来使用相同的 App ID、Token、频道名加入频道。你的朋友加入频道后,你们可以听见、看见对方。

后续步骤

在完成音视频互动后,你可以阅读以下文档进一步了解:

  • 本文的示例使用了临时 Token 加入频道。在测试或生产环境中,为确保通信安全,声网推荐使用 Token 服务器来生成 Token,详见使用 Token 鉴权。
  • 如果你想要实现极速直播场景,可以在互动直播的基础上,通过修改观众端的延时级别为低延时 (AUDIENCE_LATENCY_LEVEL_LOW_LATENCY)实现。详见实现极速直播。

参考信息

示例项目

声网提供了开源的音视频互动示例项目供你参考,你可以前往下载或查看其中的源代码。

常见问题

相关文档