基於 ZEGO SDK 實現 iOS 一對一音視訊聊天應用

語言: CN / TW / HK

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 專案設定

開始整合前,可參考如下步驟設定你的專案;

如已有專案,本步驟可忽略。

如需新建專案,可按照以下步驟建立你的新專案:

  1. 啟動 Xcode,在 “Welcome to Xcode” 視窗中單擊 “Create a new Xcode project” 或選擇 “File > New > Project” 選單。在出現的表單中,選擇 iOS 平臺,並在 “Application” 下選擇 “App”。

  2. 填寫表單並選取各個選項來配置專案,完成後,單擊 “Next”。 必須提供 “Product Name” 和 “Organization Identifier”,用於建立 App 的唯一標識 “Bundle Identifier”。

  3. 選擇專案儲存路徑,單擊 “Create” 建立專案。

3.2 匯入 SDK

使用 CocoaPods 自動整合

  1. 安裝 CocoaPods
  2. 開啟終端,進入專案根目錄,執行 pod init 命令建立 Podfile 檔案。
  3. 開啟 Podfile 檔案,在 “target” 下新增 po``d``'``Z``ego``E``xpress``Engine/V``ideo',需要將 “MyProject” 替換為開發者的 Target 名稱。 plain target 'MyProject' do use_frameworks! pod 'ZegoExpressEngine/Video' end
  4. 執行 pod repo update 命令更新本地索引,確保能安裝最新版本的 SDK,最新版本號請參考 下載 SDK 包 中的釋出歷史。
  5. 執行 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 () //拉取播放其他使用者音視訊流的 view @property (strong, nonatomic) UIView remoteUserView; //開始視訊通話的按鈕 @property (strong, nonatomic) UIButton startVideoTalkButton; //停止視訊通話的按鈕 @property (strong, nonatomic) UIButton *stopVideoTalkButton;

@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、技術幫助

獲取本文的Demo、開發文件、技術支援。

獲取SDK的商務活動、熱門產品。

註冊即構ZEGO開發者帳號,快速開始。