基於 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
  • 一:背景 準備開個系列來聊一下 PerfView 這款工具,熟悉我的朋友都知道我喜歡用 WinDbg,這東西雖然很牛,但也不是萬能的,也有一些場景他解決不了或者很難解決,這時候藉助一些其他的工具來輔助,是一個很不錯的主意。 很多朋友喜歡在項目中以記錄日誌的方式來監控項目的流轉情況,其實 CoreCL ...
  • 本來閑來無事,準備看看Dapper擴展的源碼學習學習其中的編程思想,同時整理一下自己代碼的單元測試,為以後的進一步改進打下基礎。 突然就發現問題了,源碼也不看了,開始改代碼,改了好久。 測試Dapper.LiteSql數據批量插入的時候,耗時20秒,感覺不正常,於是我測試了非Dapper版的Lite ...
  • 需求如下,在DEV框架項目中,需要在表格中增加一列顯示圖片,並且能編輯該列圖片,然後進行保存等操作,最終效果如下 這裡使用的是PictureEdit控制項來實現,打開DEV GridControl設計器,在ColumnEdit選擇PictureEdit: 綁定圖片代碼如下: DataTable dtO ...
  • 前兩天微軟偷偷更新了Visual Studio 2022 正式版版本 17.3 發佈,發佈摘要: MAUI 工作負荷 GA 生成 MAUI/Blazor CSS 熱重載支持 現在,你將能夠使用我們的新增功能在 Visual Studio 中使用每個更新試用一系列新功能。 選擇每個功能以瞭解有關特定功 ...
  • 航天和軍工領域的數字化轉型和建設正在積極推進,在與航天二院、航天三院、航天六院、航天九院、無線電廠、兵工廠等單位交流的過程中,用戶更聚焦試驗和生產過程中的痛點,迫切需要解決軟體平臺統一監測和控制設備及軟體與設備協同的問題。 ...
  • .NET 項目預設情況下 日誌是使用的 ILogger 介面,預設提供一下四種日誌記錄程式: 控制台 調試 EventSource EventLog 這四種記錄程式都是預設包含在 .NET 運行時庫中。關於這四種記錄程式的詳細介紹可以直接查看微軟的官方文檔 https://docs.microsof ...
  • 一:背景 上一篇我們聊到瞭如何去找 熱點函數,這一篇我們來看下當你的程式出現了 非托管記憶體泄漏 時如何去尋找可疑的代碼源頭,其實思路很簡單,就是在 HeapAlloc 或者 VirtualAlloc 時做 Hook 攔截,記錄它的調用棧以及分配的記憶體量, PerfView 會將這個 分配量 做成一個 ...
  • 背景 在 CI/CD 流程當中,測試是 CI 中很重要的部分。跟開發人員關係最大的就是單元測試,單元測試編寫完成之後,我們可以使用 IDE 或者 dot cover 等工具獲得單元測試對於業務代碼的覆蓋率。不過我們需要一個獨立的 CLI 工具,這樣我們才能夠在 Jenkins 的 CI 流程集成。 ...
  • 一、應用場景 大家在使用Mybatis進行開發的時候,經常會遇到一種情況:按照月份month將數據放在不同的表裡面,查詢數據的時候需要跟不同的月份month去查詢不同的表。 但是我們都知道,Mybatis是ORM持久層框架,即:實體關係映射,實體Object與資料庫表之間是存在一一對應的映射關係。比 ...
  • 我國目前並未出台專門針對網路爬蟲技術的法律規範,但在司法實踐中,相關判決已屢見不鮮,K 哥特設了“K哥爬蟲普法”專欄,本欄目通過對真實案例的分析,旨在提高廣大爬蟲工程師的法律意識,知曉如何合法合規利用爬蟲技術,警鐘長鳴,做一個守法、護法、有原則的技術人員。 案情介紹 深圳市快鴿互聯網科技有限公司 2 ...