基於 ZEGO SDK 實現 iOS 一對一音視訊聊天應用
1 準備環境
在開始整合 ZEGO Express SDK 前,請確保開發環境滿足以下要求:
- Xcode 12.0 或以上版本。
- iOS 9.0 或以上版本且支援音視訊的 iOS 裝置。
- iOS 裝置已經連線到 Internet。
2 專案準備
2.1 建立專案
進入即構官網,在【ZEGO控制檯】建立專案,並申請有效的 AppID,這一步很關鍵,appid為應用的唯一標識,如身份證號,是應用的身份證明,用於明確你的專案及組織身份。zego提供的服務也是基於APP ID;
App ID的獲取方式很簡單,只需3~5分鐘,在即構官網-我的專案-建立即可。建立的專案資訊可用於SDK的整合和配置;
2.2 Token 鑑權
- 登入房間時必須 使用 Token 鑑權 ,可參考 Token 鑑權教程
- 為了方便開發階段的除錯,開發者可直接在 ZEGO 控制檯獲取臨時 Token(有效期為 24 小時) 來使用,詳情請參考 控制檯(新版) - 專案管理 中的 “專案資訊”。
3 整合
3.1 專案設定
開始整合前,可參考如下步驟設定你的專案;
如已有專案,本步驟可忽略。
如需新建專案,可按照以下步驟建立你的新專案:
-
啟動 Xcode,在 “Welcome to Xcode” 視窗中單擊 “Create a new Xcode project” 或選擇 “File > New > Project” 選單。在出現的表單中,選擇 iOS 平臺,並在 “Application” 下選擇 “App”。
-
填寫表單並選取各個選項來配置專案,完成後,單擊 “Next”。 必須提供 “Product Name” 和 “Organization Identifier”,用於建立 App 的唯一標識 “Bundle Identifier”。
-
選擇專案儲存路徑,單擊 “Create” 建立專案。
3.2 匯入 SDK
使用 CocoaPods 自動整合
- 安裝 CocoaPods
- 開啟終端,進入專案根目錄,執行
pod init
命令建立 Podfile 檔案。 - 開啟 Podfile 檔案,在 “target” 下新增
po``d``'``Z``ego``E``xpress``Engine/V``ideo'
,需要將 “MyProject” 替換為開發者的 Target 名稱。plain target 'MyProject' do use_frameworks! pod 'ZegoExpressEngine/Video' end
- 執行
pod repo update
命令更新本地索引,確保能安裝最新版本的 SDK,最新版本號請參考 下載 SDK 包 中的釋出歷史。 - 執行
pod install
命令安裝 SDK。
4 實現流程
使用者通過 ZEGO Express SDK 進行視訊通話的基本流程為:
使用者 A、B 加入房間,使用者 B 預覽並將音視訊流推送到 ZEGO 雲服務(推流),使用者 A 收到使用者 B 推送音視訊流的通知之後,在通知中播放使用者 B 的音視訊流(拉流)。
整個音視訊通話推拉流過程的 API 呼叫時序如下圖:
4.1 初始化
1. 建立介面
根據場景需要,為你的專案建立視訊通話的使用者介面。我們推薦你在專案中新增如下元素:
- 本地視訊視窗
- 遠端視訊視窗
- 結束通話按鈕
2.引入標頭檔案,準備基礎工作
```plain // 引入 ZegoExpressEngine.h 標頭檔案
import
@interface ViewController ()
@end ```
```plain - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; }
-
(void)setupUI { self.remoteUserView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 180, 250)]; self.remoteUserView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:self.remoteUserView];
self.startVideoTalkButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:self.startVideoTalkButton]; self.startVideoTalkButton.frame = CGRectMake(100, self.view.bounds.size.height - 280, 150, 50); [self.startVideoTalkButton.titleLabel setFont:[UIFont systemFontOfSize:32]]; [self.startVideoTalkButton setTitle:@"開始通話" forState:UIControlStateNormal]; [self.startVideoTalkButton addTarget:self action:@selector(startVideoTalk:) forControlEvents:UIControlEventTouchUpInside];
self.stopVideoTalkButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:self.stopVideoTalkButton]; self.stopVideoTalkButton.frame = CGRectMake(100, self.view.bounds.size.height - 200, 150, 50); [self.stopVideoTalkButton.titleLabel setFont:[UIFont systemFontOfSize:32]]; [self.stopVideoTalkButton setTitle:@"停止通話" forState:UIControlStateNormal]; [self.stopVideoTalkButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [self.stopVideoTalkButton addTarget:self action:@selector(stopVideoTalk:) forControlEvents:UIControlEventTouchUpInside]; }
-
(void)startVideoTalk:(UIButton *)button { [self createEngine]; [self loginRoom]; [self startPublish]; } ```
3. 建立引擎
呼叫 createEngineWithProfile 介面,將申請到的 AppID 傳入引數 “appID”,建立引擎單例物件。
註冊回撥,可將實現了 ZegoEventHandler 的物件(例如 “self”)傳入引數 “eventHandler”。
plain
- (void)createEngine {
ZegoEngineProfile *profile = [[ZegoEngineProfile alloc] init];
// 請通過官網註冊獲取,格式為:1234567890
profile.appID = <#appID#>;
//通用場景接入
profile.scenario = ZegoScenarioGeneral;
// 建立引擎,並註冊 self 為 eventHandler 回撥。不需要註冊回撥的話,eventHandler 引數可以傳 nil,後續可呼叫 "-setEventHandler:" 方法設定回撥
[ZegoExpressEngine createEngineWithProfile:profile eventHandler:self];
}
6.2 登入房間
呼叫 loginRoom 介面登入房間。roomID 和 user 的引數由您本地生成,但是需要滿足以下條件:
- 同一個 AppID 內,需保證 “roomID” 全域性唯一。
- 同一個 AppID 內,需保證 “userID” 全域性唯一,建議開發者將 “userID” 與自己業務的賬號系統進行關聯。 ```plain
- (void)loginRoom { // roomID 由您本地生成,需保證 “roomID” 全域性唯一。不同使用者要登陸同一個房間才能進行通話 NSString roomID = @"room1"; // 建立使用者物件,ZegoUser 的構造方法 userWithUserID 會將 “userName” 設為與傳的引數 “userID” 一樣。“userID” 與 “userName” 不能為 “nil”,否則會導致登入房間失敗。 // userID 由您本地生成,需保證 “userID” 全域性唯一。 ZegoUser user = [ZegoUser userWithUserID:@"user1"]; // 只有傳入 “isUserStatusNotify” 引數取值為 “true” 的 ZegoRoomConfig,才能收到 onRoomUserUpdate 回撥。 ZegoRoomConfig *roomConfig = [[ZegoRoomConfig alloc] init]; //token 由使用者自己的服務端生成,為了更快跑通流程,也可以通過即構控制檯 http://console.zego.im/dashboard 獲取臨時的音視訊 token roomConfig.token = @"<#token#>"; roomConfig.isUserStatusNotify = YES; // 登入房間 [[ZegoExpressEngine sharedEngine] loginRoom:roomID user:user config:roomConfig callback:^(int errorCode, NSDictionary * _Nullable extendedData) { // (可選回撥) 登入房間結果,如果僅關注登入結果,關注此回撥即可 if (errorCode == 0) { NSLog(@"房間登入成功"); } else { // 登入失敗,請參考 errorCode 說明 http://doc-zh.zego.im/article/4377 NSLog(@"房間登入失敗"); } }]; } ```
登入狀態(房間連線狀態)回撥
呼叫登入房間介面之後,您可通過監聽 onRoomStateUpdate 回撥實時監控自己在本房間內的連線狀態。
3.3 預覽自己的畫面,並推送到 ZEGO 音視訊雲
1. 預覽自己的畫面
如果希望看到本端的畫面,可呼叫 startPreview 介面設定預覽檢視,並啟動本地預覽。
2. 將自己的音視訊流推送到 ZEGO 音視訊雲
在使用者呼叫 loginRoom 介面後,可以直接呼叫 startPublishingStream 介面,傳入 “streamID”,將自己的音視訊流推送到 ZEGO 音視訊雲。您可通過監聽 onPublisherStateUpdate 回撥知曉推流是否成功。
“streamID” 由您本地生成,但是需要保證:
同一個 AppID 下,“streamID” 全域性唯一。如果同一個 AppID 下,不同使用者各推了一條 “streamID” 相同的流,後推流的使用者推流失敗。
plain
- (void)startPublish {
// 設定本地預覽檢視並啟動預覽,檢視模式採用 SDK 預設的模式,等比縮放填充整個 View
[[ZegoExpressEngine sharedEngine] startPreview:[ZegoCanvas canvasWithView:self.view]];
// 使用者呼叫 loginRoom 之後再呼叫此介面進行推流
// 在同一個 AppID 下,開發者需要保證 “streamID” 全域性唯一,如果不同使用者各推了一條 “streamID” 相同的流,後推流的使用者會推流失敗。
[[ZegoExpressEngine sharedEngine] startPublishingStream:@"stream1"];
}
3.4 拉取其他使用者的音視訊
進行視訊通話時,我們需要拉取到其他使用者的音視訊。
在同一房間內的其他使用者將音視訊流推送到 ZEGO 音視訊雲時,我們會在 onRoomStreamUpdate 回撥中收到音視訊流新增的通知,並可以通過 ZegoStream 獲取到某條流的 “streamID”。
我們可以在該回調中,呼叫 startPlayingStream ,傳入 “streamID” 拉取拉取播放該使用者的音視訊。您可通過監聽 onPlayerStateUpdate 回撥知曉是否成功拉取音視訊。
plain
// 房間內其他使用者推流/停止推流時,我們會在這裡收到相應流增減的通知
- (void)onRoomStreamUpdate:(ZegoUpdateType)updateType streamList:(NSArray<ZegoStream *> *)streamList extendedData:(NSDictionary *)extendedData roomID:(NSString *)roomID {
//當 updateType 為 ZegoUpdateTypeAdd 時,代表有音視訊流新增,此時我們可以呼叫 startPlayingStream 介面拉取播放該音視訊流
if (updateType == ZegoUpdateTypeAdd) {
// 開始拉流,設定遠端拉流渲染檢視,檢視模式採用 SDK 預設的模式,等比縮放填充整個View
// 如下 remoteUserView 為 UI 介面上 View.這裡為了使示例程式碼更加簡潔,我們只拉取新增的音視訊流列表中第的第一條流,在實際的業務中,建議開發者迴圈遍歷 streamList ,拉取每一條音視訊流
NSString *streamID = streamList[0].streamID;
[[ZegoExpressEngine sharedEngine] startPlayingStream:streamID canvas:[ZegoCanvas canvasWithView:self.remoteUserView]];
}
}
7 執行效果
音視訊的基礎功能已完成,接下來我們執行下效果,1步快速檢驗成果。
step1 , 與好友一起安裝編譯好的App,在手機上可以看到對方並進行通話互動。
完成以上,說明你成功啦!
Enjoy與好友的歡樂時光!
獲取更多文件、Demo、技術幫助
註冊即構ZEGO開發者帳號,快速開始。