互聯(lián)網(wǎng)發(fā)展至今,實時視頻和語音通話越來越被大眾所依賴。
今天,我們將會繼續(xù)介紹如何基于ZEGO SDK實現(xiàn)音視頻通話功能,前兩篇文章分別介紹了Android,F(xiàn)lutter平臺的實現(xiàn)方式,感興趣的小伙伴可點擊了解: Android,F(xiàn)lutter。
接下來,我們將會一起開發(fā)一個RTC場景的windows應(yīng)用。
1 準(zhǔn)備環(huán)境
在開始集成 ZEGO Express SDK 前,請確保開發(fā)環(huán)境滿足以下要求:
Visual Studio 2015 或以上版本。
Windows 7 或以上版本。
麥克風(fēng)、攝像頭等支持音視頻功能的外部設(shè)備。
2 項目準(zhǔn)備
2.1 創(chuàng)建項目
進(jìn)入即構(gòu)官網(wǎng),在【ZEGO控制臺】創(chuàng)建項目,并申請有效的 AppID,這一步很關(guān)鍵,appid為應(yīng)用的唯一標(biāo)識,如身份證號,是應(yīng)用的身份證明,用于明確你的項目及組織身份。zego提供的服務(wù)也是基于APP ID;
App ID的獲取方式很簡單,只需3~5分鐘,在即構(gòu)官網(wǎng)-我的項目-創(chuàng)建即可。創(chuàng)建的項目信息可用于SDK的集成和配置;
2.2 Token 鑒權(quán)
登錄房間時必須 使用 Token 鑒權(quán) ,可參考 Token 鑒權(quán)教程
為了方便開發(fā)階段的調(diào)試,開發(fā)者可直接在 ZEGO 控制臺獲取臨時 Token(有效期為 24 小時) 來使用,詳情請參考 控制臺(新版) - 項目管理 中的 “項目信息”。
3 集成
3.1 項目設(shè)置
1.打開 Microsoft Visual Studio,選擇“文件 > 新建 > 項目”菜單。
2.在新建項目窗口,選擇項目類型為“MFC 應(yīng)用程序”,輸入項目名稱,選擇項目存儲路徑,并單擊“確定”。
3.進(jìn)入 MFC 應(yīng)用程序窗口,選擇“應(yīng)用程序類型”為“基于對話框”,并單擊“完成”。
3.2 導(dǎo)入 SDK
1.下載 SDK。
請從 下載 SDK 包 下載 SDK。
2.解壓 SDK,并拷貝到項目目錄下。
SDK 包含 “include” 和 “lib” 兩個目錄,每個目錄包含的文件說明如下。
include --------------- 包含SDK頭文件
lib --------------- 包含SDK的.lib和.dll文件
| x86 --------------- 32位版本
| x64 --------------- 64位版本
4 設(shè)置項目屬性
在解決方案資源管理器窗口中,右擊項目名稱,單擊“屬性”,進(jìn)入項目屬性頁。在項目屬性頁面內(nèi)進(jìn)行以下配置,配置完成后單擊“確定”。
1.將 “include” 目錄加入到文件搜索路徑。
選擇“配置屬性 > C/C++ > 常規(guī)”菜單,在“附加包含目錄”中添加 “include” 目錄。
2.將 “lib” 目錄加入到搜索路徑。
選擇“配置屬性 > 鏈接器 > 常規(guī)”菜單,在“附加目錄”中添加 “lib/x86” 或 “lib/x64” 目錄。
3.指定鏈接庫 “ZegoExpressEngine.lib”。
選擇“配置屬性 > 鏈接器 > 輸入”菜單,在“附加依賴項”中添加 “ZegoExpressEngine.lib”。
5 實現(xiàn)流程
如以下流程圖,用戶A與B通過 ZEGO Express SDK 進(jìn)行視頻通話,與用戶 A 拉取用戶 B 的流為例:
為保證實時音視頻的通話質(zhì)量,推拉流關(guān)鍵流程需按照API的正確調(diào)用時序進(jìn)行,完整時序如下圖:
5.1 創(chuàng)建引擎
1. 創(chuàng)建界面
根據(jù)場景需要,為您的項目創(chuàng)建視頻通話的用戶界面。我們推薦您在項目中添加如下元素:
- 本地視頻窗口
- 遠(yuǎn)端視頻窗口
- 結(jié)束通話按鈕
2. 引入頭文件
在項目中引入 ZegoExpressEngine 頭文件。
// 引入 ZegoExpressEngine.h 頭文件
#include "ZegoExpressSDK.h"
3. 創(chuàng)建引擎
調(diào)用 createEngine 接口,將申請到的 AppID 傳入?yún)?shù) “appID” 和,創(chuàng)建引擎單例對象。
注冊回調(diào),可將實現(xiàn)了 ZegoEventHandler 的對象(例如 “self”)傳入?yún)?shù) “eventHandler”。
ZegoEngineProfile profile;
// AppID 由 ZEGO 分配給各 App
profile.appID = appID;
profile.scenario = ZegoScenario::ZEGO_SCENARIO_GENERAL;
// 創(chuàng)建引擎實例
auto engine = ZegoExpressSDK::createEngine(profile, nullptr);
5.2 登錄房間
傳入用戶 ID 參數(shù) “userID” 創(chuàng)建 ZegoUser 用戶對象后,調(diào)用 loginRoom 接口,傳入房間 ID 參數(shù) “roomID” 和用戶參數(shù) “user”,登錄房間。
roomID 和 user 的參數(shù)由您本地生成,但是需要滿足以下條件:
- 同一個 AppID 內(nèi),需保證 “roomID” 全局唯一。
- 同一個 AppID 內(nèi),需保證 “userID”
全局唯一,建議開發(fā)者將其設(shè)置成一個有意義的值,可將 “userID” 與自己業(yè)務(wù)賬號系統(tǒng)進(jìn)行關(guān)聯(lián)。
// 創(chuàng)建用戶對象
ZegoUser user("user1", "user1");
// 只有傳入 “isUserStatusNotify” 參數(shù)取值為 “true” 的 ZegoRoomConfig,才能收到 onRoomUserUpdate 回調(diào)。
ZegoRoomConfig roomConfig;
//token 由用戶自己的服務(wù)端生成,為了更快跑通流程,也可以通過即構(gòu)控制臺獲取臨時的音視頻 token
roomConfig.token = "xxxx";
roomConfig.isUserStatusNotify = true;
// 登錄房間
engine->loginRoom(roomID, user, roomConfig);
調(diào)用登錄房間接口之后,您可通過監(jiān)聽 onRoomStateUpdate 回調(diào)實時監(jiān)控自己在本房間內(nèi)的連接狀態(tài)。
只有當(dāng)房間狀態(tài)是連接成功時,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收發(fā)音視頻。
void VideoTalk::onRoomStateUpdate(const std::string &roomID, ZegoRoomState state, int errorCode, const std::string &extendData) {
if (errorCode != 0) {
// 房間狀態(tài)出錯
}
if (state == ZegoRoomState::ZEGO_ROOM_STATE_CONNECTED) {
//只有當(dāng)房間狀態(tài)是連接成功時,推流(startPublishingStream)、拉流(startPlayingStream)才能正常收發(fā)音視頻
//將自己的音視頻流推送到 ZEGO 音視頻云
} else if (state == ZegoRoomState::ZEGO_ROOM_STATE_CONNECTING) {
// 房間連接中
} else if (state == ZegoRoomState::ZEGO_ROOM_STATE_DISCONNECTED) {
// 房間連接斷開
}
}
5.3 預(yù)覽自己的畫面,并推送到 ZEGO 音視頻云
1. 預(yù)覽自己的畫面
設(shè)置預(yù)覽視圖并啟動本地預(yù)覽。
如果希望看到本端的畫面,可調(diào)用 startPreview 接口設(shè)置預(yù)覽視圖,并啟動本地預(yù)覽。
// 設(shè)置本地預(yù)覽視圖并啟動預(yù)覽,視圖模式采用 SDK 默認(rèn)的模式,等比縮放填充整個 View
ZegoCanvas canvas((void*)view);
engine->startPreview(&canvas);
2. 將自己的音視頻流推送到 ZEGO 音視頻云
在用戶調(diào)用 loginRoom 接口后,可以直接調(diào)用 startPublishingStream 接口,傳入 streamID,將自己的音視頻流推送到 ZEGO 音視頻云。您可通過監(jiān)聽 onPublisherStateUpdate 回調(diào)知曉推流是否成功。
streamID 由您本地生成,但是需要保證: 同一個 AppID 下,“streamID” 全局唯一。如果同一個 AppID 下,不同用戶各推了一條 “streamID” 相同的流,會導(dǎo)致后推流的用戶推流失敗。
此處示例在調(diào)用 loginRoom 接口后立即進(jìn)行推流。在實現(xiàn)具體業(yè)務(wù)時,您可選擇其他時機(jī)進(jìn)行推流,只要保證先調(diào)用 loginRoom 即可。
// 用戶調(diào)用 loginRoom 之后再調(diào)用此接口進(jìn)行推流
// 在同一個 AppID 下,開發(fā)者需要保證“streamID” 全局唯一,如果不同用戶各推了一條 “streamID” 相同的流,后推流的用戶會推流失敗。
engine->startPublishingStream("stream1");
5.4 拉取其他用戶的音視頻
進(jìn)行視頻通話時,我們需要拉取到其他用戶的音視頻。
onRoomStreamUpdate:在同一房間內(nèi)的其他用戶將音視頻流推送到 ZEGO 音視頻云時,我們會在此回調(diào)中收到音視頻流新增的通知。
我們可以在該回調(diào)中,調(diào)用 startPlayingStream,傳入 “streamID” 拉取播放該用戶的音視頻。
// 房間內(nèi)其他用戶推流/停止推流時,我們會在這里收到相應(yīng)流增減的通知
void VideoTalk::onRoomStreamUpdate(const std::string &roomID, ZegoUpdateType updateType, const std::vector<ZegoStream> &streamList, const std::string &extendData) {
//當(dāng) updateType 為 ZEGO_UPDATE_TYPE_ADD 時,代表有音視頻流新增,此時我們可以調(diào)用 startPlayingStream 接口拉取播放該音視頻流
if (updateType == ZEGO_UPDATE_TYPE_ADD) {
// 開始拉流,設(shè)置遠(yuǎn)端拉流渲染視圖,視圖模式采用 SDK 默認(rèn)的模式,等比縮放填充整個 View
// 如下 playView 為 UI 窗口句柄
std::string streamID = streamList[0].streamID;
ZegoCanvas canvas((void*)playView);
engine->startPlayingStream(streamID , &canvas);
}
}
恭喜,你又get一種實現(xiàn)音視頻通話的新技能。