Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)

文章目录

  • Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)
    • 一、前言
    • 二、后台创建应用
    • 三、获取 SDK
    • 四、接入 Agora Voice 语音 SDK
      • 1. 导入工程
      • 2. 搭建测试场景
      • 3. 申请麦克风权限
      • 4. 初始化 IRtcEngine
      • 5. 常用 API
        • 5.1 加入频道
        • 5.2 静音
        • 5.3 离开频道 & 销毁 IRtcEngine
      • 6. 最终效果
    • 五、接入 Agora Video 视频 SDK
      • 1. 导入工程
      • 2. 搭建测试场景
      • 3. 申请麦克风+相机权限
      • 4. 初始化 IRtcEngine
      • 5. 常用 API
        • 5.1 设置自己画面
        • 5.2 设置其他用户画面
        • 5.3 开关视频
      • 6. 最终效果
    • 六、总结

一、前言

当前游戏为了增加社交互动和代入感,比如狼人杀、团队竞技游戏等,经常会产生需要实时语音和视频通话的需求。但是对于个人开发者和小团队,这种需要前后端配合,重网络的开发需求会带来很大的挑战。

为此我们需要寻找一个成熟、可靠的解决方案。每个月提供 10000 分钟免费使用时长的声网 Agora成为了我的最佳选择。并且声网的 SDK(Software Development Kit) 包体积很小,运行时CPU和内存占用率低,对于移动端的游戏开发很友好。2019年7月声网正式成为了 Unity 官方认证合作伙伴,语音和视频的 SDK 也已经发布在了 Unity 资源商店中,能够非常方便的接入。

注意:语音和视频的包有冲突,不兼容(一些库和平台配置不同,可以自己手动修改),请根据需求,第四步和第五步二选一。引擎支持开关视频和声音,所以可以接入视频 SDK 包,关闭视频,仅仅使用语音通话。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第1张图片

二、后台创建应用

为了方便后续接入操作,这里先注册和登录到 官方后台 创建应用,获取我们之后需要的 App ID。可以根据官网的新手引导来创建应用,也可以参考如下步骤。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第2张图片

输入项目名称,目前暂时使用 APP ID 的鉴权模式,后续根据需要也可以在项目编辑界面切换到 Token 鉴权模式,该模式更加安全,生成 Token 程序需要搭建在服务器上,可以参考官方文档。

创建成功后,我们点击 APP ID 下的显示按钮,APPID 就会复制到粘贴板。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第3张图片

三、获取 SDK

这里我使用的 Unity 版本为 2019.3.14,进入商店我们搜索 Agora,可以发现视频和语音两个 SDK 包。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第4张图片

如果打不开 Unity Store 的同学还可以从官网开发者中心下载。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第5张图片

四、接入 Agora Voice 语音 SDK

1. 导入工程

从 Asset Store 的我的资源(My Asset)中找到我们下载的 Agora Voice SDK For Unity ,点击 Import 导入到工程中。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第6张图片
导入的文件结构如下。

  • Demo:官方提供的测试语音 Demo
  • Edior:iOS 构建后处理脚本
  • Plugins:不同平台所依赖的库
  • Scripts:SDK 源码

2. 搭建测试场景

为了验证 Agora Voice 的效果,我们打开官方的 Demo,或者是自己搭建一个类似的简单场景。主要有三个按钮,分别用来测试加入频道、离开频道和静音。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第7张图片

3. 申请麦克风权限

在 Unity 2018.3 版本以后的新版本中,需要我们主动申请麦克风权限。

#if(UNITY_2018_3_OR_NEWER)
using UnityEngine.Android;
#endif
// ...
    private void PermissionRequest()
    {
#if (UNITY_2018_3_OR_NEWER)
			if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))	// 判断是否有麦克风权限
			{
				Permission.RequestUserPermission(Permission.Microphone);	// 申请麦克风权限
			}
#endif
    }
// ...

4. 初始化 IRtcEngine

我们在调用 Agora 的接口前,需要先初始化 IRtcEngine。此时我们第二步获取的 APP ID,就在这里派上用处了。在通过 APP ID 创建 IRtcEngine 后,可以根据需求增加回调事件,这里我接入了一些比较常用的回调。

using agora_gaming_rtc;
// ...
    private IRtcEngine mRtcEngine = null;
    public const string APP_ID = "你自己的应用 APP ID";
	private void InitEngine()
    {
    	// 通过 APP ID 创建
        mRtcEngine = IRtcEngine.GetEngine(APP_ID);
        
        // 加入频道成功后的回调
        // channelName:频道名称
        // uid:用户ID(发起请求时候如果没有指定,服务器会自动分配一个)
        // elapsed:从本地用户调用 JoinChannelByKey 到该回调触发的延迟(毫秒)。
        mRtcEngine.OnJoinChannelSuccess += (string channelName, uint uid, int elapsed) =>
        {
            // ...
        };
		
        
        // 离开频道的回调
        // stats:通话统计的数据
        //		duration:通话时长
        //		txBytes:发送字节数(bytes)
        //		rxBytes:接收字节数(bytes)
        //		txKBitRate:发送码率(kbps)
        //		rxKBitRate:接收码率(kbps)
        mRtcEngine.OnLeaveChannel += (RtcStats stats) =>
        {
            string leaveChannelMessage = string.Format("onLeaveChannel callback duration {0}, tx: {1}, rx: {2}, tx kbps: {3}, rx kbps: {4}", stats.duration, stats.txBytes, stats.rxBytes, stats.txKBitRate, stats.rxKBitRate);
			// ...
        };
		
        // 用户加入回调
        // uid:新加入频道的远端用户/主播 ID
        // elapsed:从本地用户调用 JoinChannelByKey 到该回调触发的延迟(毫秒)。
        mRtcEngine.OnUserJoined += (uint uid, int elapsed) =>
        {
			// ...
        };
		
        // 用户离开回调
        // uid:离线用户或主播的用户 ID
        // reason:离线原因(主动离开、超时、直播模式身份切换)
        mRtcEngine.OnUserOffline += (uint uid, USER_OFFLINE_REASON reason) =>
        {
            string userOfflineMessage = string.Format("onUserOffline callback uid {0} {1}", uid, reason);
            Debug.Log(userOfflineMessage);
        };
		
        // 提示频道内谁在说话
        // speakers:说话人信息
        // speakerNumber:说话人数[0,3]
        // totalVolume:总音量
        mRtcEngine.OnVolumeIndication += (AudioVolumeInfo[] speakers, int speakerNumber, int totalVolume) =>
        {
            // ...
        };
	
        // 用户静音提示回调
        // uid:用户 ID
        // muted:是否静音
        mRtcEngine.OnUserMutedAudio += (uint uid, bool muted) =>
        {
            // ...
        };
		
        // 发生警告回调
        mRtcEngine.OnWarning += (int warn, string msg) =>
        {
            // ...
        };
		
        // 发生错误回调
        mRtcEngine.OnError += (int error, string msg) =>
        {
            // ...
        };
		
        // 当前通话统计回调,每两秒触发一次。
        mRtcEngine.OnRtcStats += (RtcStats stats) =>
        {
            // ...
        };
		
        // 语音路由已发生变化回调。(只在移动平台生效)
        mRtcEngine.OnAudioRouteChanged += (AUDIO_ROUTE route) =>
        {
            // ...
        };
		
        // Token 过期回调
        mRtcEngine.OnRequestToken += () =>
        {
            // ...
        };
		
        // 网络中断回调(建立成功后才会触发)
        mRtcEngine.OnConnectionInterrupted += () =>
        {
            // ...
        };
		
        // 网络连接丢失回调
        mRtcEngine.OnConnectionLost += () =>
        {
            // ...
        };
		
	    // 设置 Log 级别
        mRtcEngine.SetLogFilter(LOG_FILTER.INFO);
		// 设置为自由说话模式,常用于一对一或者群聊
        mRtcEngine.SetChannelProfile(CHANNEL_PROFILE.CHANNEL_PROFILE_COMMUNICATION);
    }
...

5. 常用 API

5.1 加入频道
    public void JoinChannel()
    {
        // 从界面的输入框获取频道名称
        string channelName = mChannelNameInputField.text.Trim();

        Debug.Log(string.Format("tap joinChannel with channel name {0}", channelName));

        if (string.IsNullOrEmpty(channelName))
        {
            return;
        }
		// 加入频道
        // channelKey: 动态秘钥,我们最开始没有选择 Token 模式,这里就可以传入 null;否则需要传入服务器生成的 Token
        // channelName: 频道名称
        // info: 开发者附带信息(非必要),不会传递给频道内其他用户
        // uid: 用户ID,0 为自动分配
        mRtcEngine.JoinChannelByKey(channelKey: null, channelName: channelName, info:"extra",uid: 0);
    }
5.2 静音
    void MuteButtonTapped()
    {
        string labeltext = isMuted ? "静音" : "取消静音";
        Text label = muteButton.GetComponentInChildren();
        if (label != null)
        {
            label.text = labeltext;
        }
        isMuted = !isMuted;
        // 设置静音(停止推送本地音频)
        mRtcEngine.MuteLocalAudioStream(!isMuted);
    }
5.3 离开频道 & 销毁 IRtcEngine
    public void LeaveChannel()
    {
        // 离开频道
        mRtcEngine.LeaveChannel();
        string channelName = mChannelNameInputField.text.Trim();
        Debug.Log(string.Format("left channel name {0}", channelName));
    }

    void OnApplicationQuit()
    {
        if (mRtcEngine != null)
        {
            // 销毁 IRtcEngine
            IRtcEngine.Destroy();
            mRtcEngine = null;
        }
    }

6. 最终效果

我们可以先在编辑器上验证,能够正常运行后,将平台切换到 Android 后,直接出包就行,Agora SDK 中已经提供了 Android 中所需要的库。

最后运行在 Android 上的效果如下:

  1. 输入1234 成功加入频道,分配给我们用户 id:1186284123
  2. 有其他用户加入,用户id:2996662973
  3. 用户id:2996662973 开启静音
  4. 用户id:2996662973 离开频道
  5. 我们离开频道,显示通话统计数据

语音通话的 API 时序图如下:

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第8张图片

五、接入 Agora Video 视频 SDK

1. 导入工程

如果你按照第五步导入过音频了,这里类似直接从商店导入 Agora Video SDK。要注意的是两个包的内容不同,当然两个 SDK 包的本质还是相同的,只是不同平台中的配置相关有些不同,如果同时使用,会出现问题。有能力的同学也可以尝试修改兼容,这里还是比较推荐直接删除音频 Voice 的包,再导入新的 Video 的包,这样就不用我们费尽的设置不同平台配置了。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第9张图片

2. 搭建测试场景

同样的我们可以直接使用Demo 中提供的场景,SceneHome 是启动场景,在最后测试的时候,注意需要修改 Build Setting 中场景列表。或者可以搭建一个简易如下的场景。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第10张图片

3. 申请麦克风+相机权限

与音频不同,视频需要我们添加相机权限的申请。

    private void PermissionRequest () {
#if (UNITY_2018_3_OR_NEWER)
        if (!Permission.HasUserAuthorizedPermission (Permission.Microphone)) {
            Permission.RequestUserPermission (Permission.Microphone);
        }
        // 增加相机权限
        if (!Permission.HasUserAuthorizedPermission (Permission.Camera)) {
            Permission.RequestUserPermission (Permission.Camera);
        }
#endif
    }

4. 初始化 IRtcEngine

与音频唯一不同的是需要打开视频功能。

 private void InitEngine () {
        mRtcEngine = IRtcEngine.GetEngine (APP_ID);
        // 启用视频
        mRtcEngine.EnableVideo ();
        // 允许相机回调
        mRtcEngine.EnableVideoObserver ();

     // 后续与音频相同添加回调...
 }

5. 常用 API

5.1 设置自己画面

官方已经提供好了一个用于显示的 VideoSurface 类,我们只要把它添加到需要显示的对象上即可,默认显示的即为自己相机拍摄画面。

    private void CreateMyCamera()
    {
        GameObject myCamera = GameObject.Find("MyCamera");
        if (ReferenceEquals(myCamera, null))
        {
            Debug.LogError("没有找到 MyCamera 对象!");
            return;
        }
        else
        {
            // 添加显示画面类
            myCamera.AddComponent();
            // 画面需要垂直翻转
            myCamera.transform.Rotate(0f, 0.0f, 180.0f);
        }
    }
5.2 设置其他用户画面
    private void CreateUserCamera(uint uid)
    {
        VideoSurface videoSurface;
        GameObject userCamera = GameObject.Find("UserCamera");
        if (ReferenceEquals(userCamera, null))
        {
            Debug.LogError("没有找到 UserCamera 对象!");
            return;
        }
        else
        {
            videoSurface = userCamera.AddComponent();
            userCamera.transform.Rotate(0f, 0.0f, 180.0f);

        }
        // 设置显示用户
        videoSurface.SetForUser(uid);
        videoSurface.SetEnable(true);
        // 设置平面类型
        videoSurface.SetVideoSurfaceType(AgoraVideoSurfaceType.RawImage);
        // 设置画面帧率
        videoSurface.SetGameFps(30);
    }
5.3 开关视频

我们可以在应用暂停的时候,停止视频,画面将不会再更新。

    public void EnableVideo(bool pauseVideo)
    {
        if (mRtcEngine != null)
        {
            if (!pauseVideo)
            {
                // 启动视频
                mRtcEngine.EnableVideo();
            }
            else
            {
                // 关闭视频
                mRtcEngine.DisableVideo();
            }
        }
    }

6. 最终效果

最后在 Android 上运行的效果如下:

  1. 我们加入到 123 频道
  2. 给我们分配id 722438456,并显示出我们自己的画面
  3. 显示频道内另一个用户 1173951071 的画面
  4. 离开频道,视频画面停止

视频通话的 API 时序图如下:
Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第11张图片

六、总结

总的来说,声网的接入还是较为简单的。我们可以从商店导入对应的包,就能够直接使用,最麻烦的不同平台的配置,官方已经帮忙解决了。而且通话和视频质量不错,再加上有免费使用时长,对于开发者来说是相当友好的。具体细节**官方文档**说的也比较清楚。

几行就搞定了麻烦的语音和视频,光速下班,真香。

Unity 语音和视频通话快速解决方案——声网 SDK接入指南(Android)_第12张图片

你可能感兴趣的:(编程,游戏开发,unity,android,unity3d)