查看原文
其他

云信小课堂|如何实现音视频通话

云信小课堂 网易云信 2021-09-19


大家好,欢迎大家来到「云信小课堂 」。


本栏目致力于解答有关IM和音视频的一切问题,产品特点、使用场景、技术名词、接入指南、功能实现......欢迎大家留言提问,我们每节课会选取大家感兴趣的问题进行解答。


第 01 课

如何快速实现音视频通话?


微信的火热让网络语音/视频通话逐步替代了传统手机通话,那么如何快速实现一款轻量的音视频通话应用呢?


其实并不复杂,几十行代码就能实现。


开学第一课,我们一起聊一聊如何快速实现音视频通话。


功 能 解 析


我们先来定义一下一款轻量的音视频通话应用需要哪些功能,首先基础类功能可能包含:

  • 加入/离开通话

  • 语音/视频通话

  • 音频/视频开启与关闭

具体可参见下图,当然在基础类功能之上我们也可以引入美颜、变声等更多高级的玩法,本期暂不做展开,后面会陆续为大家介绍哦!



功 能 实 现


本章以IOS为例介绍如何使用 NERTC SDK 实现音视频通话,更多终端可点击阅读原文,进入网易云信官方 Github。


以下内容为大家介绍如果基于 网易云信 音视频通话2.0 SDK 快速实现音视频通话功能,基本步骤如下:

  1. 集成SDK(网易云信音视频2.0 SDK)

  2. 设置本地视图

  3. 加入频道

  4. 设置远端视图

  5. 音频流

  6. 离开频道

  7. 销毁音视频实例


集成SDK


CocoaPods集成

集成前,请先前往SDK下载页面查看当前最新版本,并查询本地仓库中对应的版本是否为最新版本。若不是最新版本,建议先更新本地仓库,以确保可以集成最新的SDK版本。

pod search NERtcSDK //本地仓库中查询 NERtcSDK 信息 pod repo update //更新本地仓库 pod install //执行安装

至此, NERTC SDK 已经导入完成。


手动导入SDK集成

  • 请先前往SDK下载页获取当前最新版本。

  • 将解压得到的 NERtcSDK.framework 和 NMCBasicModuleFramework.framework 文件拷贝到工程项目文件夹下。

  • 以 Xcode Version 11.5 为例,进入TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content 菜单,点击 +,再点击 Add Other…,将上述解压得到的SDK文件添加进去。同时,将Embed 属性设置为 Embed & Sign,以使得SDK动态库和应用签名保持一致。

至此, NERTC SDK 已经导入完成。


实现音视频通话

本节以IOS为例介绍如何使用 NERTC SDK 实现音视频通话,主要流程如下图所示: 

(更多终端请点击阅读原文,进入网易云信官方 Github)

*此处Server指的是云信 SDK Sever


初始化

  • 引入头文件

#import <NERtcSDK/NERtcSDK.h>
  • 执行初始化

@interface Myapp ()<NERtcEngineDelegateEx>...NERtcEngine *coreEngine = [NERtcEngine sharedEngine];NERtcEngineContext *context = [[NERtcEngineContext alloc] init];context.engineDelegate = self;context.appKey = AppKey;[coreEngine setupEngineWithContext:context];...

初始化的参数类 NERtcEngineContext 属性说明:

@interface NERtcEngineContext : NSObject/** 已开通音视频功能的云信应用的AppKey。 */@property (nonatomic, copy) NSString *appKey;/** log的相关设置,由开发者提供。可选参数。 */@property (nonatomic, strong) NERtcLogSetting *logSetting;/** 通话相关信息的回调接口,由开发者提供。 */@property (nonatomic, weak) id<NERtcEngineDelegateEx> engineDelegate;@end


设置本地视图

启动视频流

  • API描述

@protocol INERtcEngine <NSObject>/** 开启自己的视频。可以在加入频道前和频道后调用。

@param enabled 是否开启 @return 操作返回值,成功则返回 0*/- (int)enableLocalVideo:(BOOL)enabled;@end
  • 示例代码

[NERtcEngine.sharedEngine enableLocalVideo:YES];


设置本地视频画布

启动视频流后,可以设置本地视频画布,用来显示本地采集的视频画面。

  • API描述

@protocol INERtcEngine <NSObject>/** 设置本地视频画布

@param canvas 视频窗口,如果需要删除则传 nil @return 操作返回值,成功则返回 0 */- (int)setupLocalVideoCanvas:(NERtcVideoCanvas *)canvas;@end
  • 示例代码

NERtcVideoCanvas *canvas = [[NERtcVideoCanvas alloc] init];canvas.container = self.localUserView;[NERtcEngine.sharedEngine setupLocalVideoCanvas:canvas];

设置成功后,即可显示本地视频画面。


 加入频道

加入频道前,请确保已完成初始化相关事项。若您的业务中涉及呼叫邀请等机制,可以使用信令。

  • API描述

@protocol INERtcEngine <NSObject>/**加入频道

@param token 频道token @param channelName 频道名 @param uId 当前用户的Id @param completion 操作完成的 block 回调 @return 操作返回值,被执行了则返回 0 */- (int)joinChannelWithToken:(NSString *)token channelName:(nullable NSString *)channelName myUid:(uint64_t)uId completion:(NERtcJoinChannelCompletion)completion;@end
  • 参数说明

(1) token:频道token。支持传入以下内容:

  • 空字符串。该种方式需要先开通非安全模式。安全性不高,建议在产品正式上线前转为安全模式。

  • 安全认证签名密钥。安全模式下必需。若未传入正确的token将无法进入频道。建议使用安全模式。

(2) channelName:频道名称,传入相同频道名称的用户会进入同一个通话频道。

(3) uId:用户的唯一标识Id,频道内每个用户的 UID 必须是唯一的。

  • 示例代码

//加入房间- (void)joinChannelWithRoomId:(NSString *)roomId userId:(uint64_t)userId { __weak typeof(self) weakSelf = self; [NERtcEngine.sharedEngine joinChannelWithToken:@"" channelName:roomId myUid:userId completion:^(NSError * _Nullable error, uint64_tchannelId, uint64_t elapesd) { if (error) { //加入失败了,弹框之后退出当前页面 } else { //加入成功 } }];}


设置远端视图

视频通话过程中,除了要显示本地的视频画面,通常也要显示参与通话的其他用户的远端视频画面。


监听远端用户进出频道

  • API描述

@protocol NERtcEngineDelegate <NSObject>/** 其他用户加入频道的回调

@param userID 用户的id @param userName 用户名称 */- (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID userName:(NSString *)userName;/** 其他用户离开频道的回调

@param userID 用户的id @param reason 离开的原因 */- (void)onNERtcEngineUserDidLeaveWithUserID:(uint64_t)userID reason:(NERtcSessionLeaveReason)reason;@end


设置远端视频画布

监听到远端用户加入频道后,可以设置远端视频画布,用来显示远端用户的视频画面。


  • API描述

@protocol INERtcEngine <NSObject>/** 设置远端的视频播放窗口 只能在加入频道后调用

@param userID 用户的id @param canvas 视频窗口,如果需要删除则传nil @return 操作返回值,成功则返回 0 */- (int)setupRemoteVideoCanvas:(NERtcVideoCanvas *)canvas forUserID:(uint64_t)userID;@end
  • 示例代码

- (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID userName:(NSString *)userName {

//如果已经setup了一个远端的canvas,则不需要再建立了 ... if (_remoteCanvas != nil) { return; }

//建立远端canvas,用来渲染远端画面 NERtcVideoCanvas *canvas = [self setupRemoteCanvasWithUid:userID]; [NERtcEngine.sharedEngine setupRemoteVideoCanvas:canvas forUserID:userID]; ...}

···

- (void)onNERtcEngineUserDidLeaveWithUserID:(uint64_t)userID reason:(NERtcSessionLeaveReason)reason {

//如果远端的人离开了,重置远端模型和UI ... [NERtcEngine.sharedEngine setupRemoteVideoCanvas:nil forUserID:userID]; ...}


监听远端视频流发布

当频道中的其他用户有视频流发出/关闭时,分别会走入以下回调:

  • API描述

@protocol NERtcEngineDelegate <NSObject>/** 其他用户打开视频的回调

@param userID 用户id @param profile 用户发送视频的最大分辨率类型 */- (void)onNERtcEngineUserVideoDidStartWithUserID:(uint64_t)userID videoProfile:(NERtcVideoProfileType)profile;/** 其他用户关闭视频的回调

@param userID 用户id */- (void)onNERtcEngineUserVideoDidStop:(uint64_t)userID;@end


订阅远端视频流

在设置完远端视频画布后,且监听到远端用户有视频发布时,可以订阅远端用户的视频流。

  • API描述


@protocol INERtcEngineEx <INERtcEngine>/** 订阅或取消订阅别人的视频,订阅了才会接收别人的视频数据。

@param subscribe 是否订阅 @param userID 用户的id @param streamType 订阅的远端视频流类型 @return 操作返回值,成功则返回 0 */- (int)subscribeRemoteVideo:(BOOL)subscribe forUserID:(uint64_t)userID streamType:(NERtcRemoteVideoStreamType)streamType;@end
  • 示例代码

// 监听到远端用户有视频流发布- (void)onNERtcEngineUserVideoDidStartWithUserID:(uint64_t)userID videoProfile:(NERtcVideoProfileType)profile { //如果已经订阅过远端视频流,则不需要再订阅了 ... if (_remoteCanvas.subscribedVideo) { return; }

//订阅远端视频流。 _remoteCanvas.subscribedVideo = YES; [NERtcEngine.sharedEngine subscribeRemoteVideo:YES forUserID:userID streamType:kNERtcRemoteVideoStreamTypeHigh]; ...}// 监听到远端用户停止视频流发布- (void)onNERtcEngineUserVideoDidStop:(uint64_t)userID { if (userID == _remoteCanvas.uid) { // 收到此回调后,SDK 内部会取消对应的视频流订阅,无需开发者主动取消订阅。 ... _remoteStatLab.hidden = YES; ... }}

订阅成功后,即可显示远端的视频画面。


音频流

在 NERtcSDK 中,本地音频的采集发布和远端音频订阅播放是默认启动的,正常情况下无需开发者主动干预。


离开频道

当通话结束,需要离开频道,可以调用以下接口:

  • API描述

@protocol INERtcEngine <NSObject>/** 离开频道

@return 操作返回值,成功则返回 0 */- (int)leaveChannel;@end
  • 示例代码

//UI 挂断按钮事件- (IBAction)onHungupAction:(UIButton *)sender { [NERtcEngine.sharedEngine leaveChannel]; [self dismiss];}

执行完 leaveChannel 方法后,SDK 会触发 离开频道回调通知开发者:

  • API描述

@protocol NERtcEngineDelegate <NSObject>/** 离开频道回调

@param result 离开的结果 */- (void)onNERtcEngineDidLeaveChannelWithResult:(NERtcError)result;@end
  • 示例代码

- (void)onNERtcEngineDidLeaveChannelWithResult:(NERtcError)result{ // 进行业务数据清理}


销毁音视频实例

释放当前的 NERtcEngine 实例,建议在 App 确定不再需要使用 NERtcEngine 实例时,通过该接口释放 NERtcEngine 实例的对象资源。

  • API描述

@interface NERtcEngine : NSObject <INERtcEngineEx>/** 释放当前的 NERtcEngine 实例 建议在 App 确定不再需要使用 NERtcEngine 实例时,通过该接口释放 NERtcEngine 实例的对象资源; 1. 该接口的工作方式为同步调用方式,必须在子线程中才能调用,否则会调用失败;如: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [NERtcEngine destroyEngine]; }); 2. 该接口不得在 SDK 的回调中调用,在接口返回前也不允许调用 SDK 的其他任何接口;3. 接口调用返回之后,如果需要再次使用 SDK,可以重新调用 sharedEngine 来获取一个新的 NERtcEngine 实例。

*/

+ (int)destroyEngine;@end
  • 示例代码

- (void)dealloc { [NERtcEngine destroyEngine]; //销毁实例}


示例项目

为了便于大家学习理解,我们将上文内容作为开源项目发布在了Github上,各位有兴趣可以点击阅读原文,前往查看示例项目。


: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存