保姆級教程!基於聲網 Web SDK實現音視頻通話及屏幕共享
前言
大家好,我是 @小曾同學,小夥伴們也可以叫我小曾~
如果你想實現一對一音視頻通話和屏幕共享功能,不妨來看看這篇文章,保姆級教程,不需要從零實現,直接集成聲網 SDK 即可輕鬆上手。
本文也分享了我在實踐過程中遇到的一些問題,幫助小夥伴們避坑。如果文章知識點有錯誤的地方,還請大家指正,讓我們一起學習,一起進步~
01 背景介紹
聲網提供了各端豐富的音視頻 SDK,本文將要使用的是 Web 端 SDK。
本篇文章主要給小夥伴們分享如何使用聲網 SDK 實現 Web 端音視頻通話及屏幕共享功能,其中也會涵蓋在實踐過程中遇到的一些問題,以此記錄防止小夥伴們踩坑,同時也希望通過從 0 到 1 實戰的分享,能夠幫助更多的小夥伴。
02 前期準備
在實戰之前,需要有以下準備條件:
- Npm & Node.js
- 前端開發基礎,如 html & CSS & JavaScript
- 註冊聲網賬號,申請聲網APPID、臨時Token ,詳見開始使用聲網平台。
如果你還沒有聲網賬號,可以通過這裏免費註冊,每個賬户每月都有10000分鐘免費額度。如果是個人學習/調試,時長完全夠用。
我個人的開發環境,具體信息如下:
- MacBook Pro
- Visual Studio Code:v1.75.1
- Npm:v8.19.3
- Node.js:v16.19.0
- 聲網 SDK:v4.2.1 ,sdk的下載可查看這裏。
- Google Chrome :v110.0.5481.177
03 實戰環節
通過[前期準備],我們已經完成了相關配置,已經擁有了 App ID、Channel、臨時 Token、聲網 SDK,在本次實戰中,主要詳細講解兩個 demo,分別是音視頻通話及屏幕共享連麥。
3.1 實現音視頻通話
在開始實戰之前,先聲明下 Demo 組成架構,
創建一個文件夾名為 Agora_VideoCall,文件夾中包含五個文件,分別是:
- index.html:用於設計 Web 應用的用户界面
- index.css:用於設計網頁樣式
- basicVideoCall.js:實現音視頻通話邏輯代碼,主要通過 AgoraRTCClient 實現
- AgoraRTC_N-4.2.1.js:聲網音視頻SDK
- assets:第三方庫,主要用於設計用户界面
在 index.html 文件中導入聲網SDK,具體內容可查看詳細代碼,接下來主要詳細講解音視頻通話及屏幕共享實現邏輯。
<script src="./AgoraRTC-N-4.2.1.js"></script>
3.1.1 實現音視頻通話邏輯
以下代碼均在 basicVideoCall.js 文本中寫入
1)首先調用 AgoraRTC.createClient 方法創建一個 client 對象,也就是創建客户端對象
var client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
2)定義變量 App ID,Token、Channel、User ID,並使用箭頭函數實現當頁面被調用時用於加入音視頻通話通道。
var options = {
appid: null,
channel: null,
uid: null,
token: null
};
$(() => {
var urlParams = new URL(location.href).searchParams;
options.appid = urlParams.get("appid");
options.channel = urlParams.get("channel");
options.token = urlParams.get("token");
options.uid = urlParams.get("uid");
if (options.appid && options.channel) {
$("#uid").val(options.uid);
$("#appid").val(options.appid);
$("#token").val(options.token);
$("#channel").val(options.channel);
$("#join-form").submit();
}
})
3)加入頻道
定義 join 函數主要是將本地音視頻 track 加入一個 RTC 頻道,此時需要在函數中傳入 App ID,Token、Channel、User ID。加入房間後,需要發佈音視頻track,所以還需要創建音視頻 track,並調用 publish 方法將這些本地音視頻track對象當作參數發佈到頻道中。
注意注意,在創建音視頻 track 時需要先調用 createMicrophoneAudioTrack :通過麥克風採集的音頻創建本地音頻軌道對象;再調用 createCameraVideoTrack :通過攝像頭採集的視頻創建本地視頻軌道對象。(如果先調用createCameraVideoTrack ,那麼頁面中將不會顯示本地視頻預覽畫面)
創建之後即可調用 play 方法展示本地預覽,並調用 publish 方法發佈到 RTC 頻道中。注意 play 和 publish 方法的使用沒有先後順序,誰在前在後沒有什麼影響。
async function join() {
[ options.uid, localTracks.audioTrack, localTracks.videoTrack ] = await Promise.all([
// 加入頻道
client.join(options.appid, options.channel, options.token || null, options.uid || null),
// 創建本地音視頻track
//AgoraRTC.createCameraVideoTrack(),
AgoraRTC.createMicrophoneAudioTrack(),
AgoraRTC.createCameraVideoTrack()
]);
localTracks.videoTrack.play("local-player");
$("#local-player-name").text(`localVideo(${options.uid})`);
await client.publish(Object.values(localTracks));
console.log("publish success");
}
4)在頻道中添加或移除遠端用户邏輯
實現將同頻道的遠端用户添加到本地接口,當遠端用户取消發佈時,則從本地將用户移除。
function handleUserPublished(user, mediaType) {
const id = user.uid;
remoteUsers[id] = user;
subscribe(user, mediaType);
}
function handleUserUnpublished(user, mediaType) {
if (mediaType === 'video') {
const id = user.uid;
delete remoteUsers[id];
$(`#player-wrapper-${id}`).remove();
}
}
5)訂閲遠端音視頻邏輯
當遠端用户發佈音視頻時,本地用户需要對其訂閲,從而實現音視頻通話,在 subscribe 函數中需要傳入兩個參數,分別是同頻道遠端用户 user id 和遠端 mediaType,並調用 play 方法,播放遠端用户音視頻,從而實現一對一連麥。
async function subscribe(user, mediaType) {
const uid = user.uid;
// 訂閲遠端用户
await client.subscribe(user, mediaType);
console.log("subscribe success");
if (mediaType === 'video') {
const player = $(`
<div id="player-wrapper-${uid}">
<p class="player-name">remoteUser(${uid})</p>
<div id="player-${uid}" class="player"></div>
</div>
`);
$("#remote-playerlist").append(player);
user.videoTrack.play(`player-${uid}`);
}
if (mediaType === 'audio') {
user.audioTrack.play();
}
}
6)監聽事件
當遠端用户發佈或者取消發佈音視頻 track 時,本地還需要對其監聽,在 join 函數中,監聽 client.on("user-published", handleUserPublished) 事件和 client.on("user-unpublished", handleUserUnpublished) 事件,具體如下
client.on("user-published", handleUserPublished);
client.on("user-unpublished", handleUserUnpublished);
7)離開頻道
當用户點擊 leave 按鈕時,則將 stop 本地和遠端音視頻 track。
async function leave() {
for (trackName in localTracks) {
var track = localTracks[trackName];
if(track) {
track.stop();
track.close();
localTracks[trackName] = undefined;
}
}
3.1.2 Demo展示
接下來可以運行我們的 Demo 啦,輸入 APPID、Token、Channel、Userid,點擊 join,即可看到自己本地的畫面,如果想和別人連麥,可以再複製一下網址,輸入相同的 APPID、Token、Channel,即可實現連麥,趕快試試吧。
3.2 屏幕共享連麥
屏幕共享就是將本地用户的屏幕內容,以視頻畫面的方式分享給其他遠端用户觀看。其工作原理實際上是通過 createScreenVideoTrack 創建一個屏幕共享的視頻軌道對象來實現。採集屏幕的過程中瀏覽器會詢問需要共享哪些屏幕,根據終端用户的選擇去獲取屏幕信息。
在上述音視頻 demo 的基礎上實現屏幕共享功能。
3.2.1 添加屏幕共享UI
在 index.html 頁面中添加屏幕共享(ScreenShare)button
3.2.2 屏幕共享實現邏輯
以下代碼均在 basicVideoCall.js 文本中寫入
1)實現 share 函數
和上述 join 函數功能類似,主要用於開啟屏幕共享,使用 createScreenVideoTrack 創建屏幕共享的視頻軌道對象,同時也可以對視頻編碼進行一些簡單的配置。函數中同樣也需要添加監聽事件。
async function share() {
client.on("user-published", handleUserPublished);
client.on("user-unpublished", handleUserUnpublished);
let screenTrack;
[options.uid, localTracks.audioTrack, screenTrack] = await Promise.all([
client.join(options.appid, options.channel, options.token || null, options.uid || null),
AgoraRTC.createMicrophoneAudioTrack(),
AgoraRTC.createScreenVideoTrack({
encoderConfig: {
framerate: 15,
height: 720,
width: 1280
}
}, "auto")
]);
2)添加屏幕共享音視頻軌道,並調用 play 方法播放本地屏幕共享的視頻。
if(screenTrack instanceof Array){
localTracks.screenVideoTrack = screenTrack[0]
localTracks.screenAudioTrack = screenTrack[1]
}
else{
localTracks.screenVideoTrack = screenTrack
}
localTracks.screenVideoTrack.play("local-player");
$("#local-player-name").text(`localVideo(${options.uid})`);
3)發佈屏幕共享
發佈本地音頻和屏幕共享畫面至 RTC 頻道中。
if(localTracks.screenAudioTrack == null){
await client.publish([localTracks.screenVideoTrack, localTracks.audioTrack]);
}
else{
await client.publish([localTracks.screenVideoTrack, localTracks.audioTrack, localTracks.screenAudioTrack]);
}
4)在 share 函數實現邏輯中需要綁定 "track-ended" 事件,當屏幕共享停止時,會有一個警報通知最終用户。
localTracks.screenVideoTrack.on("track-ended", () => {
alert(`Screen-share track ended, stop sharing screen ` + localTracks.screenVideoTrack.getTrackId());
localTracks.screenVideoTrack && localTracks.screenVideoTrack.close();
localTracks.screenAudioTrack && localTracks.screenAudioTrack.close();
localTracks.audioTrack && localTracks.audioTrack.close();
});
3.2.3 Demo 展示
當點擊 ScreenShare 時,會提示用户選擇哪一個 page 進行分享,同時也有一個默認音頻選項,點擊分享之後,即可發佈屏幕共享。
04 小結
如果你想實現音視頻和屏幕共享的 Web 應用,完全可以借鑑本篇文章 + 聲網SDK,如果不是很熟悉的話,可以先看聲網給出的「快速開始 - 實現音視頻通話」。
在實踐過程中需要注意的是:在創建音視頻 track 時需要先調用 createMicrophoneAudioTrack ,再調用 createCameraVideoTrack ,如果先調用 createCameraVideoTrack 那麼頁面中將不會顯示本地視頻預覽畫面。
Generally,本篇文章給出的 demo 比較簡單,如果想要添加其他的功能比如,虛擬背景、AI降噪等,可以在此基礎上繼續添加功能。
(正文完)
參考資料
• 註冊聲網賬號
- 保姆級教程!集成聲網 SDK 實現 iOS 平台音視頻通話和虛擬背景功能
- 在 Flutter 多人視頻中實現虛擬背景、美顏與空間音效
- 基於聲網 Flutter SDK 實現互動直播
- 保姆級教程!基於聲網 Web SDK實現音視頻通話及屏幕共享
- 基於聲網 Flutter SDK 實現多人視頻通話
- 把 ChatGPT 加入 Flutter 開發,會有怎樣的體驗?
- 如何基於開源 demo 在 Web 端實現一個多人數獨遊戲
- 《鵝鴨殺》爆火,一文帶你瞭解如何實現頂流社交遊戲
- 聲網許振明:RTC 場景 UHD 視頻應用和探索
- RTE 領域的發展,為視頻編解碼標準帶來哪些新變化?丨Dev for Dev 專欄
- 人臉關鍵點的應用場景及重難點解析丨Dev for Dev 專欄
- 糾刪碼在實時視頻流中的應用丨Dev for Dev 專欄
- 音頻技術的下一個“熱點”,會出現在哪個領域?丨一期一會 • 音頻工程師專場
- 一片紅的泛娛樂出海,藍色在哪裏?
- 聲網“失聲”的危機
- 百鍊成鋼 —— 聲網實時網絡的自動運維丨Dev for Dev 專欄
- 桌面軟件開發框架大賞
- 基於對象的實時空間音頻渲染丨Dev for Dev 專欄
- 即時通訊場景下安全合規的實踐和經驗
- 基於 Web SDK 實現視頻通話場景 | 聲網 SDK 教程