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

来源:https://www.cnblogs.com/zegodeveloper/archive/2022/06/15/16377772.html
-Advertisement-
Play Games

在開始集成 ZEGO Express SDK 前,請確保開發環境滿足以下要求 ...


1 準備環境

在開始集成 ZEGO Express SDK 前,請確保開發環境滿足以下要求:

  • Xcode 12.0 或以上版本。
  • iOS 9.0 或以上版本且支持音視頻的 iOS 設備。
  • iOS 設備已經連接到 Internet。

2 項目準備

2.1 創建項目

進入即構官網,【ZEGO控制台】創建項目,並申請有效的 AppID,這一步很關鍵,appid為應用的唯一標識,如身份證號,是應用的身份證明,用於明確你的項目及組織身份。zego提供的服務也是基於APP ID;

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 名稱。
target 'MyProject' do
    use_frameworks!
    pod 'ZegoExpressEngine/Video'
end
  1. 執行 pod repo update 命令更新本地索引,確保能安裝最新版本的 SDK,最新版本號請參考 下載 SDK 包 中的發佈歷史。
  2. 執行 pod install 命令安裝 SDK。

4 實現流程

用戶通過 ZEGO Express SDK 進行視頻通話的基本流程為:

用戶 A、B 加入房間,用戶 B 預覽並將音視頻流推送到 ZEGO 雲服務(推流),用戶 A 收到用戶 B 推送音視頻流的通知之後,在通知中播放用戶 B 的音視頻流(拉流)。

整個音視頻通話推拉流過程的 API 調用時序如下圖:

4.1 初始化

1. 創建界面

根據場景需要,為你的項目創建視頻通話的用戶界面。我們推薦你在項目中添加如下元素:

  • 本地視頻視窗
  • 遠端視頻視窗
  • 結束通話按鈕

2.引入頭文件,準備基礎工作

// 引入 ZegoExpressEngine.h 頭文件
#import <ZegoExpressEngine/ZegoExpressEngine.h>

@interface ViewController ()<ZegoEventHandler>
//拉取播放其他用戶音視頻流的 view
@property (strong, nonatomic) UIView *remoteUserView;
//開始視頻通話的按鈕
@property (strong, nonatomic) UIButton *startVideoTalkButton;
//停止視頻通話的按鈕
@property (strong, nonatomic) UIButton *stopVideoTalkButton;

@end
- (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”。

- (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” 與自己業務的賬號系統進行關聯。
- (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 由用戶自己的服務端生成,為了更快跑通流程,也可以通過即構控制台 https://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 說明 https://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” 相同的流,後推流的用戶推流失敗。

- (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 回調知曉是否成功拉取音視頻。

// 房間內其他用戶推流/停止推流時,我們會在這裡收到相應流增減的通知
- (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開發者帳號,快速開始。

音視頻場景解決方案分享,更多詳情可搜索官網(https://zegoguanwang.datasink.sensorsdata.cn/t/pB)
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文介紹 SQL 如何使用內聯結(INNER JOIN)、外聯結(OUTER JOIN)和交叉聯結(CROSS JOIN)。簡單來說,就是將其他表中的列添加過來,進行“添加列”的運算。 本文重點 聯結(JOIN)就是將其他表中的列添加過來,進行“添加列”的集合運算。UNION 是以行(縱向)為單位進 ...
  • 導讀: 本文主要介紹嗶哩嗶哩在數據湖與數據倉庫一體架構下,探索查詢加速以及索引增強的一些實踐。主要內容包括: 什麼是湖倉一體架構 嗶哩嗶哩目前的湖倉一體架構 湖倉一體架構下,數據的排序組織優化 湖倉一體架構下,索引增強與優化的實踐探索 -- 01 什麼是湖倉一體 當我們講湖倉一體時,涉及到數據湖和數 ...
  • 原文鏈接:實時開發平臺建設實踐,深入釋放實時數據價值 視頻回顧:點擊這裡 課件獲取:點擊這裡 一、實時數倉建設背景 隨著整體行業的數字化轉型不斷深入以及技術能力的不斷提高,傳統的 T+1 式(隔日)的離線大數據模式越來越無法滿足新興業務的發展需求,開展實時化的大數據業務,是企業深入挖掘數據價值的一條 ...
  • 本文將會和大家一起學習集合運算操作。集合在數學領域表示“(各種各樣的)事物的總和”,在資料庫領域表示記錄的集合。具體來說,表、視圖和查詢的執行結果都是記錄的集合。 本文重點 集合運算就是對滿足同一規則的記錄進行的加減等四則運算。 使用 UNION(並集)、INTERSECT(交集)、EXCEPT(差 ...
  • Redis緩存更新策略 本文整理自黑馬程式員相關資料 記憶體淘汰 超時剔除 主動更新 說明 不用自己維護,利用Redis的記憶體淘汰機制,當記憶體不足時自動淘汰部分數據。下次查詢時更新緩存 給緩存數據添加TTL時間,到期後自動刪除緩存,下次查詢時更新緩存 編寫業務邏輯,在修改數據的同時,更新緩存 一致性 ...
  • 一、課程介紹 數據服務API作為數據統一服務平臺建設的最上層,能夠將數據倉庫數據以服務化、介面化的方式提供給數據使用方,屏蔽底層數據存儲、計算的諸多細節,簡化和加強數據的使用。 隨著企業“互聯網化、數字化”進程的不斷深入,越來越多的業務被遷移到互聯網上,產生大量的業務交互和對外服務需求,對API介面 ...
  • 一、包的作用 • Oracle中包的概念與Java中包的概念非常類似,只是Java中的包是為了分類管理類,但是關鍵字都是package。 • 在一個大型項目中,可能有很多模塊,而每個模塊又有自己的過程、函數等。而這些過程、函數預設是放在一起的(如在PL/SQL中,過程預設都是放在一起的,即Proce ...
  • 一、android工程配置 buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.1.4' } } apply plugin: 'com.android. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...