
视频互动直播是当前比较热门的玩法,我们经常见到有 PK 连麦、直播答题、一起 KTV 、电商直播、互动大班课、视频相亲等。本文将演示如何通过声网视频 SDK 在 iOS 端实现一个视频直播应用。话不多说,我们开始动手实操。
在声网开发者控制台 Console https://console.agora.io 注册声网开发者账号后,需要获取项目 AppID 。另外,开发者每个月可获得 10000 分钟的免费使用额度,可实现各类实时音视频场景。
可能有些人,还不了解我们要实现的功能最后是怎样的。所以声网在 GitHub 上提供一个开源的基础视频直播 Demo 项目,在开始开发之前你可以通过该示例项目体验视频播的体验效果。

我们在这里要实现的是视频直播,声网的视频直播可以实现互动效果,所以也经常叫互动直播。你可以理解为是多个用户通过加入同一个频道,实现的音视频的互通,而这个频道的数据,会通过声网的 SD-RTN 实时网络来进行低延时传输的。
需要特别说明的是,声网互动直播不同于视频直播。视频通话不区分主播和观众,所有用户都可以发言并看见彼此;而互动直播的用户分为主播和观众,只有主播可以自由发言,且被其他用户看见。

声网 SDK 的兼容性良好,对硬件设备和软件系统的要求不高,开发环境和测试环境满足以下条件即可: Xcode 9.0 或以上版本 支持语音和视频功能的真机 App 要求支持 iOS 8.0 或以上版本的 iOS 设备
macOS 11.6 版本 Xcode Version 13.1
iPhone7 (iOS 15.3)
如果你此前还未接触过声网 SDK ,那么你还需要做以下准备工作 注册一个声网账号,进入后台创建 AppID 、获取 Token , 下载声网官方最新的视频直播 SDK ;
a) 如需创建新项目, Xcode 里,打开 Xcode 并点击 Create a new Xcode project 。(创建 iOS 项目链接:https://developer.apple.com/documentation/xcode/creating-an-xcode-project-for-an-app)
b) 选择平台类型为 iOS 、项目类型为 Single View App ,并点击 Next 。
c) 输入项目名称( Product Name )、开发团队信息( Team )、组织名称( Organization Name )和语言( Language )等项目信息,并点击 Next 。
注意:如果你没有添加过开发团队信息,会看到 Add account… 按钮。点击该按钮并按照屏幕提示登入 Apple ID ,完成后即可选择你的 Apple 账户作为开发团队。
d) 选择项目存储路径,并点击 Create 。
两种方法集成声网 SDK ,选择如下任意一种方式获取声网 iOS SDK 。
a) 开始前确保你已安装 Cocoapods 。参考 Getting Started with CocoaPods 安装说明。( Getting Started with CocoaPods 安装说明链接:CocoaPods Guides - Getting Started
b) 在终端里进入项目根目录,并运行 pod init 命令。项目文件夹下会生成一个 Podfile 文本文件。
c) 打开 Podfile 文件,修改文件为如下内容。注意将 Your App 替换为你的 Target 名称。
platform :ios, '9.0' target 'Your App' do pod 'AgoraRtcEngine_iOS' end a) 前往 SDK 下载页面,获取最新版的声网 iOS SDK ,然后解压。
b) 根据你的需求,将 libs 文件夹中的动态库复制到项目的 ./project_name 文件夹下( project_name 为你的项目名称)。
c) 打开 Xcode ,进入 TARGETS > Project Name > Build Phases > Link Binary with Libraries 菜单,点击 + 添加如下库(如:)。在添加 AgoraRtcEngineKit.framework 文件时,还需在点击 + 后点击 Add Other…,找到本地文件并打开。
共需要添加 11 个库文件:
i. AgoraRtcEngineKit.framework ii. Accelerate.framework iii. AudioToolbox.framework iv. AVFoundation.framework v. CoreMedia.framework vi. CoreML.framework vii. CoreTelephony.framework viii. libc++.tbd ix. libresolv.tbd x. SystemConfiguration.framework xi. VideoToolbox.framework 注意 1:如需支持 iOS 9.0 或更低版本的设备,请在 Xcode 中将对 CoreML.framework 的依赖设为 Optional 。
d) 打开 Xcode ,进入 TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content 菜单。
e) 点击 + > Add Other… > Add Files 添加对应动态库,并确保添加的动态库 Embed 属性设置为 Embed & Sign 。添加完成后,项目会自动链接所需系统库。
注意 2: 根据 Apple 官方要求,app 的 Extension 中不允许包含动态库。如果项目中的 Extension 需要集成 SDK ,则添加动态库时需将文件状态改为 Do Not Embed 。 声网 SDK 默认使用 libc++ (LLVM),如需使用 libstdc++ (GNU),请联系 [email protected] 。SDK 提供的库是 FAT Image ,包含 32/64 位模拟器、32/64 位真机版本。
1 ) Xcode 进入 TARGETS > Project Name > General > Signing 菜单,选择 Automatically manage signing ,并在弹出菜单中点击 Enable Automatic 。 
2 )添加媒体设备权限 根据场景需要,在 info.plist 文件中,点击 + 图标开始添加如下内容,获取相应的设备权限:

在项目中导入 AgoraRtcEngineKit 类:
Objective-C 版本
// Objective-C // 导入 AgoraRtcKit 类 // 自 3.0.0 版本起,AgoraRtcEngineKit 类名更换为 AgoraRtcKit // 如果获取的是 3.0.0 以下版本的 SDK ,请改用 #import <AgoraRtcEngineKit/AgoraRtcEngineKit.h> #import <AgoraRtcKit/AgoraRtcEngineKit.h> // 声明 AgoraRtcEngineDelegate ,用于监听回调 @interface ViewController : UIViewController <AgoraRtcEngineDelegate> // 定义 agoraKit 变量 @property (strong, nonatomic) AgoraRtcEngineKit *agoraKit; Swift 版本
// Swift // 导入 AgoraRtcKit 类 // 自 3.0.0 版本起,AgoraRtcEngineKit 类名更换为 AgoraRtcKit // 如果获取的是 3.0.0 以下版本的 SDK ,请改用 import AgoraRtcEngineKit import AgoraRtcKit class ViewController: UIViewController { ... // 定义 agoraKit 变量 var agoraKit: AgoraRtcEngineKit? } 在 KeyCenter.swift 文件中,将你的 AppID 填写到对应位置,可替换“Your App ID”; Objective-C 版本
// Objective-C // AppID.m // 声网 iOS Tutorial NSString *const appID = <#Your App ID#>; Swift 版本
// Swift // AppID.swift // 声网 iOS Tutorial Static let AppID: String = Your App ID 本节介绍如何使用声网视频 SDK 在你的 App 里实现视频直播的几个小贴士。
根据场景需要,为你的项目创建视频直播的用户界面。我们推荐你在项目中添加元素:本地视频窗口、远端视频窗口。
你可以参考以下代码创建一个基础的用户界面。
Objective-C 版本
// Objective-C // 导入 UIKit #import <UIKit/UIKit.h> @interface ViewController () // 定义 localView 变量 @property (nonatomic, strong) UIView *localView; // 定义 remoteView 变量 @property (nonatomic, strong) UIView *remoteView; @end @implementation ViewController ... - (void)viewDidLoad { [super viewDidLoad]; // 调用初始化视频窗口函数 [self initViews]; // 后续步骤调用声网 API 使用的函数 [self initializeAgoraEngine]; [self setChannelProfile]; [self setClientRole]; [self setupLocalVideo]; [self joinChannel]; } // 设置视频窗口布局 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.remoteView.frame = self.view.bounds; self.localView.frame = CGRectMake(self.view.bounds.size.width - 90, 0, 90, 160); } - (void)initViews { // 初始化远端视频窗口。只有当远端用户为主播时,才会显示视频画面 self.remoteView = [[UIView alloc] init]; [self.view addSubview:self.remoteView]; // 初始化本地视频窗口。只有当本地用户为主播时,才会显视频画面 self.localView = [[UIView alloc] init]; [self.view addSubview:self.localView]; } Swift 版本
// Swift // 导入 UIKit import UIKit class ViewController: UIViewController { ... // 定义 localView 变量 var localView: UIView! // 定义 remoteView 变量 var remoteView: UIView! override func viewDidLoad() { super.viewDidLoad() // 调用初始化视频窗口函数 initView() // 后续步骤调用声网 API 使用的函数 initializeAgoraEngine() setChannelProfile() setClientRole() setupLocalVideo() joinChannel() } // 设置视频窗口布局 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() remoteView.frame = self.view.bounds localView.frame = CGRect(x: self.view.bounds.width - 90, y: 0, width: 90, height: 160) } func initView() { // 初始化远端视频窗口。只有当远端用户为主播时,才会显示视频画面 remoteView = UIView() self.view.addSubview(remoteView) // 初始化本地视频窗口。只有当本地用户为主播时,才会显示视频画面 localView = UIView() self.view.addSubview(localView) } } 现在,我们已经将声网 iOS SDK 集成到项目中了。接下来我们要在 ViewController 中调用声网 iOS SDK 提供的核心 API 实现基础的视频直播功能。
参考上图,按照以下步骤实现该逻辑
在调用其他声网 API 前,需要创建并初始化 AgoraRtcEngineKit 对象。调用 sharedEngineWithAppId 方法,传入获取到的 App ID ,即可初始化 AgoraRtcEngineKit 。
Objective-C 版本
// Objective-C // 输入 App ID 并初始化 AgoraRtcEngineKit 类。 - (void) viewDidLoad{ self.rtcEngine = [AgoraRtcEngineKit sharedEngineWithAppId:[KeyCenter AppId] delegate:self]; } Swift 版本
// Swift // 输入 App ID 并初始化 AgoraRtcEngineKit 类。 private lazy var agoraKit: AgoraRtcEngineKit = { let engine = AgoraRtcEngineKit.sharedEngine(withAppId: KeyCenter.AppId, delegate: nil) return engine }() 你还可以根据场景需要,在初始化时注册想要监听的回调事件,如本地用户加入频道,及解码远端用户视频首帧等。
调用 setChannelProfile 方法,将频道场景设为直播。一个 AgoraRtcEngineKit 只能使用一种频道场景。如果想切换为其他频道场景,需要先调用 destroy 方法销毁当前的 AgoraRtcEngineKit 对象,然后使用 sharedEngineWithAppId 方法创建一个新的对象,再调用 setChannelProfile 设置新的频道场景。
Objective-C 版本
// Objective-C // 设置频道场景为直播模式 [self.rtcEngine setChannelProfile:AgoraChannelProfileLiveBroadcasting]; Swift 版本
// Swift // 设置频道场景为直播模式 agoraKit.setChannelProfile(.liveBroadcasting) 直播频道有两种用户角色:主播和观众,其中默认的角色为观众。设置频道场景为直播后,你可以在 app 中参考如下步骤设置用户角色:
让用户选择自己的角色是主播还是观众; 调用 setClientRole 方法,然后使用用户选择的角色进行传参。 注意,直播频道内的用户,只能看到主播的画面、听到主播的声音。加入频道后,如果你想切换用户角色,也可以调用 setClientRole 方法。
Objective-C 版本
// Objective-C // 设置用户角色 - (IBAction)doBroadcastPressed:(UIButton *)sender { if (self.isBroadcaster) { // 设置用户角色为主播 self.clientRole = AgoraClientRoleAudience; if (self.fullSession.uid == 0) { self.fullSession = nil; } } else { // 设置用户角色为观众 self.clientRole = AgoraClientRoleBroadcaster; } [self.rtcEngine setClientRole:self.clientRole]; [self updateInterfaceWithAnimation:YES]; } Swift 版本
// Swift // 选择用户角色 @IBAction func doBroadcasterTap(_ sender: UITapGestureRecognizer) { // 选择用户角色为主播 selectedRoleToLive(role: .broadcaster) } @IBAction func doAudienceTap(_ sender: UITapGestureRecognizer) // 选择用户角色为观众 selectedRoleToLive(role: .audience) // 设置用户角色 agoraKit.setClientRole(settings.role) // 设置为主播角色时 if settings.role == .broadcaster { addLocalSession() agoraKit.startPreview() } //设置为观众角色时 let isHidden = settings.role == .audience 成功初始化 AgoraRtcEngineKit 对象后,需要在加入频道前设置本地视图,以便在通话中看到本地图像。参考以下步骤设置本地视图: 调用 enableVideo 方法启用视频模块。 调用 setupLocalVideo 方法设置本地视图。
Objective-C 版本
// Objective-C // 启用视频模块。 [self.rtcEngine enableVideo]; // 设置本地视图。 - (void)addLocalSession { VideoSession *localSession = [VideoSession localSession]; [self.videoSessions addObject:localSession]; // 设置本地视图。 [self.rtcEngine setupLocalVideo:localSession.canvas]; [self updateInterfaceWithAnimation:YES]; } // VideoSession 部分 // VideoSession.m #import "VideoSession.h" @implementation VideoSession - (instancetype)initWithUid:(NSUInteger)uid { if (self = [super init]) { self.uid = uid; self.hostingView = [[UIView alloc] init]; self.hostingView.translatesAutoresizingMaskIntoCOnstraints= NO; self.canvas = [[AgoraRtcVideoCanvas alloc] init]; self.canvas.uid = uid; self.canvas.view = self.hostingView; self.canvas.renderMode = AgoraVideoRenderModeHidden; } return self; } + (instancetype)localSession { return [[VideoSession alloc] initWithUid:0]; } @end Swift 版本
// Swift // 启用视频模块。 agoraKit.enableVideo() // 设置本地视图。 agoraKit.setupLocalVideo(videoCanvas) // VideoSession 部分 // VideoSession.swift hostingView = VideoView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) hostingView.translatesAutoresizingMaskIntoCOnstraints= false canvas = AgoraRtcVideoCanvas() canvas.uid = uid canvas.view = hostingView.videoView canvas.renderMode = .hidden 频道是人们在同一个视频直播中的公共空间。完成初始化和设置本地视图后(视频直播场景),你就可以调用 joinChannelByToken 方法加入频道。你需要在该方法中传入如下参数:
更多的参数设置注意事项请参考 joinChannelByToken 接口中的参数描述。 Objective-C 版本
// Objective-C // 加入频道。 self.rtcEngine joinChannelByToken:[KeyCenter Token] channelId:self.roomName info:nil uid:0 joinSuccess:nil Swift 版本
// Swift // 加入频道。 agoraKit.joinChannel(byToken: KeyCenter.Token, channelId: channelId, info: nil, uid: 0, joinSuccess: nil) 视频互动直播中,通常你也需要看到其他主播。远端主播成功加入频道后,SDK 会触发 didJoinedOfUid 回调,该回调中会包含这个远端主播的 uid 信息。在该回调中调用 setupRemoteVideo 方法,传入获取到的 uid ,设置远端主播的视图。
Objective-C 版本
// Objective-C // 监听 didJoinedOfUid 回调 // 远端主播加入频道时,会触发该回调 - (void)rtcEngine:(AgoraRtcEngineKit *)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed { AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init]; videoCanvas.uid = uid; videoCanvas.renderMode = AgoraVideoRenderModeHidden; videoCanvas.view = self.remoteView; // 设置远端视图 [self.agoraKit setupRemoteVideo:videoCanvas]; } Swift 版本
// Swift //需要在额外添加以下代码 extension LiveRoomViewController: AgoraRtcEngineDelegate { // 监听 didJoinedOfUid 回调 // 远端主播加入频道时,会触发该回调 func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { guard videoSessions.count <= maxVideoSession else { return } let userSession = videoSession(of: uid) // 设置远端视图 agoraKit.setupRemoteVideo(userSession.canvas) } } 根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel 离开当前通话频道。
Objective-C 版本
// Objective-C // 离开频道的步骤 - (void)leaveChannel { [self setIdleTimerActive:YES]; [self.rtcEngine setupLocalVideo:nil]; // nil mean unbind // 离开频道。 [self.rtcEngine leaveChannel:nil]; // leave the channel, callback = nil if (self.isBroadcaster) { [self.rtcEngine stopPreview]; } for (VideoSession *session in self.videoSessions) { [session.hostingView removeFromSuperview]; } [self.videoSessions removeAllObjects]; if ([self.delegate respondsToSelector:@selector(liveVCNeedClose:)]) { [self.delegate liveVCNeedClose:self]; } } Swift 版本
// Swift // 离开频道的步骤 func leaveChannel() { // Step 1, release local AgoraRtcVideoCanvas instance agoraKit.setupLocalVideo(nil) // Step 2, leave channel and end group chat agoraKit.leaveChannel(nil) // Step 3, if current role is broadcaster, stop preview after leave channel if settings.role == .broadcaster { agoraKit.stopPreview() } setIdleTimerActive(true) navigationController?.popViewController(animated: true) } 最后,离开频道,我们需要调用 destroy 销毁 AgoraRtcEngineKit 对象,释放声网 SDK 使用的所有资源。 Objective-C 版本
// Objective-C // 将以下代码填入你定义的函数中 [AgoraRtcEngineKit destroy]; Swift 版本
// Swift // 将以下代码填入你定义的函数中 AgoraRtcEngineKit.destroy()
至此,完成声网视频 SDK 的集成,运行看看效果。拿两部手机安装编译好的 App ,加入同一个频道名,分别选择主播角色和观众角色,如果 2 个手机都能看见同一个自己,说明你成功了。
如果你在集成开发过程中遇到问题,可以访问 RTE 开发者社区 吐槽与声网工程师交流。