01 背景介紹
聲網(wǎng)提供了各端豐富的音視頻 SDK,本文將要使用的是 Web 端 SDK。
本篇文章主要給小伙伴們分享如何使用聲網(wǎng) SDK 實(shí)現(xiàn) Web 端音視頻通話及屏幕共享功能,其中也會(huì)涵蓋在實(shí)踐過程中遇到的一些問題,以此記錄防止小伙伴們踩坑,同時(shí)也希望通過從 0 到 1 實(shí)戰(zhàn)的分享,能夠幫助更多的小伙伴。
02 前期準(zhǔn)備
在實(shí)戰(zhàn)之前,需要有以下準(zhǔn)備條件:
? Npm & Node.js
? 前端開發(fā)基礎(chǔ),如 html & CSS & JavaScript
? 注冊(cè)聲網(wǎng)賬號(hào),申請(qǐng)聲網(wǎng)APPID、臨時(shí)Token ,詳見開始使用聲網(wǎng)平臺(tái)。
如果你還沒有聲網(wǎng)賬號(hào),可以通過這里免費(fèi)注冊(cè),每個(gè)賬戶每月都有10000分鐘免費(fèi)額度。如果是個(gè)人學(xué)習(xí)/調(diào)試,時(shí)長完全夠用。
我個(gè)人的開發(fā)環(huán)境,具體信息如下:
? MacBook Pro
? Visual Studio Code:v1.75.1
? Npm:v8.19.3
? Node.js:v16.19.0
? 聲網(wǎng) SDK:v4.2.1 ,sdk的下載可查看這里。
? Google Chrome :v110.0.5481.177
03 實(shí)戰(zhàn)環(huán)節(jié)
通過[前期準(zhǔn)備],我們已經(jīng)完成了相關(guān)配置,已經(jīng)擁有了 App ID、Channel、臨時(shí) Token、聲網(wǎng) SDK,在本次實(shí)戰(zhàn)中,主要詳細(xì)講解兩個(gè) demo,分別是音視頻通話及屏幕共享連麥。
3.1 實(shí)現(xiàn)音視頻通話
在開始實(shí)戰(zhàn)之前,先聲明下 Demo 組成架構(gòu),
創(chuàng)建一個(gè)文件夾名為 Agora_VideoCall,文件夾中包含五個(gè)文件,分別是:
? index.html:用于設(shè)計(jì) Web 應(yīng)用的用戶界面
? index.css:用于設(shè)計(jì)網(wǎng)頁樣式
? basicVideoCall.js:實(shí)現(xiàn)音視頻通話邏輯代碼,主要通過 AgoraRTCClient 實(shí)現(xiàn)
? AgoraRTC_N-4.2.1.js:聲網(wǎng)音視頻SDK
? assets:第三方庫,主要用于設(shè)計(jì)用戶界面
在 index.html 文件中導(dǎo)入聲網(wǎng)SDK,具體內(nèi)容可查看詳細(xì)代碼,接下來主要詳細(xì)講解音視頻通話及屏幕共享實(shí)現(xiàn)邏輯。
<script src="./AgoraRTC-N-4.2.1.js"></script>
3.1.1 實(shí)現(xiàn)音視頻通話邏輯
以下代碼均在 basicVideoCall.js 文本中寫入
1)首先調(diào)用 AgoraRTC.createClient 方法創(chuàng)建一個(gè) client 對(duì)象,也就是創(chuàng)建客戶端對(duì)象
var client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
2)定義變量 App ID,Token、Channel、User ID,并使用箭頭函數(shù)實(shí)現(xiàn)當(dāng)頁面被調(diào)用時(shí)用于加入音視頻通話通道。
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 函數(shù)主要是將本地音視頻 track 加入一個(gè) RTC 頻道,此時(shí)需要在函數(shù)中傳入 App ID,Token、Channel、User ID。加入房間后,需要發(fā)布音視頻track,所以還需要?jiǎng)?chuàng)建音視頻 track,并調(diào)用 publish 方法將這些本地音視頻track對(duì)象當(dāng)作參數(shù)發(fā)布到頻道中。
注意注意,在創(chuàng)建音視頻 track 時(shí)需要先調(diào)用 createMicrophoneAudioTrack :通過麥克風(fēng)采集的音頻創(chuàng)建本地音頻軌道對(duì)象;再調(diào)用 createCameraVideoTrack :通過攝像頭采集的視頻創(chuàng)建本地視頻軌道對(duì)象。(如果先調(diào)用createCameraVideoTrack ,那么頁面中將不會(huì)顯示本地視頻預(yù)覽畫面)
創(chuàng)建之后即可調(diào)用 play 方法展示本地預(yù)覽,并調(diào)用 publish 方法發(fā)布到 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), // 創(chuàng)建本地音視頻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)在頻道中添加或移除遠(yuǎn)端用戶邏輯
實(shí)現(xiàn)將同頻道的遠(yuǎn)端用戶添加到本地接口,當(dāng)遠(yuǎn)端用戶取消發(fā)布時(shí),則從本地將用戶移除。
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)訂閱遠(yuǎn)端音視頻邏輯
當(dāng)遠(yuǎn)端用戶發(fā)布音視頻時(shí),本地用戶需要對(duì)其訂閱,從而實(shí)現(xiàn)音視頻通話,在 subscribe 函數(shù)中需要傳入兩個(gè)參數(shù),分別是同頻道遠(yuǎn)端用戶 user id 和遠(yuǎn)端 mediaType,并調(diào)用 play 方法,播放遠(yuǎn)端用戶音視頻,從而實(shí)現(xiàn)一對(duì)一連麥。
async function subscribe(user, mediaType) { const uid = user.uid; // 訂閱遠(yuǎn)端用戶 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)監(jiān)聽事件
當(dāng)遠(yuǎn)端用戶發(fā)布或者取消發(fā)布音視頻 track 時(shí),本地還需要對(duì)其監(jiān)聽,在 join 函數(shù)中,監(jiān)聽 client.on(“user-published”, handleUserPublished) 事件和 client.on(“user-unpublished”, handleUserUnpublished) 事件,具體如下
client.on("user-published", handleUserPublished); client.on("user-unpublished", handleUserUnpublished);
7)離開頻道
當(dāng)用戶點(diǎn)擊 leave 按鈕時(shí),則將 stop 本地和遠(yuǎn)端音視頻 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展示
接下來可以運(yùn)行我們的 Demo 啦,輸入 APPID、Token、Channel、Userid,點(diǎn)擊 join,即可看到自己本地的畫面,如果想和別人連麥,可以再復(fù)制一下網(wǎng)址,輸入相同的 APPID、Token、Channel,即可實(shí)現(xiàn)連麥,趕快試試吧。
3.2 屏幕共享連麥
屏幕共享就是將本地用戶的屏幕內(nèi)容,以視頻畫面的方式分享給其他遠(yuǎn)端用戶觀看。其工作原理實(shí)際上是通過 createScreenVideoTrack 創(chuàng)建一個(gè)屏幕共享的視頻軌道對(duì)象來實(shí)現(xiàn)。采集屏幕的過程中瀏覽器會(huì)詢問需要共享哪些屏幕,根據(jù)終端用戶的選擇去獲取屏幕信息。
在上述音視頻 demo 的基礎(chǔ)上實(shí)現(xiàn)屏幕共享功能。
3.2.1 添加屏幕共享UI
在 index.html 頁面中添加屏幕共享(ScreenShare)button
3.2.2 屏幕共享實(shí)現(xiàn)邏輯
以下代碼均在 basicVideoCall.js 文本中寫入
1)實(shí)現(xiàn) share 函數(shù)
和上述 join 函數(shù)功能類似,主要用于開啟屏幕共享,使用 createScreenVideoTrack 創(chuàng)建屏幕共享的視頻軌道對(duì)象,同時(shí)也可以對(duì)視頻編碼進(jìn)行一些簡單的配置。函數(shù)中同樣也需要添加監(jiān)聽事件。
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)添加屏幕共享音視頻軌道,并調(diào)用 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)發(fā)布屏幕共享
發(fā)布本地音頻和屏幕共享畫面至 RTC 頻道中。
if(localTracks.screenAudioTrack == null){ await client.publish([localTracks.screenVideoTrack, localTracks.audioTrack]); } else{ await client.publish([localTracks.screenVideoTrack, localTracks.audioTrack, localTracks.screenAudioTrack]); }
4)在 share 函數(shù)實(shí)現(xiàn)邏輯中需要綁定 “track-ended” 事件,當(dāng)屏幕共享停止時(shí),會(huì)有一個(gè)警報(bào)通知最終用戶。
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 展示
當(dāng)點(diǎn)擊 ScreenShare 時(shí),會(huì)提示用戶選擇哪一個(gè) page 進(jìn)行分享,同時(shí)也有一個(gè)默認(rèn)音頻選項(xiàng),點(diǎn)擊分享之后,即可發(fā)布屏幕共享。
04 小結(jié)
如果你想實(shí)現(xiàn)音視頻和屏幕共享的 Web 應(yīng)用,完全可以借鑒本篇文章 + 聲網(wǎng)SDK,如果不是很熟悉的話,可以先看聲網(wǎng)給出的「快速開始 - 實(shí)現(xiàn)音視頻通話」。
在實(shí)踐過程中需要注意的是:在創(chuàng)建音視頻 track 時(shí)需要先調(diào)用 createMicrophoneAudioTrack ,再調(diào)用 createCameraVideoTrack ,如果先調(diào)用 createCameraVideoTrack 那么頁面中將不會(huì)顯示本地視頻預(yù)覽畫面。
Generally,本篇文章給出的 demo 比較簡單,如果想要添加其他的功能比如,虛擬背景、AI降噪等,可以在此基礎(chǔ)上繼續(xù)添加功能。
(正文完)
參考資料文章來源:http://www.zghlxwxcb.cn/news/detail-569330.html
? 注冊(cè)聲網(wǎng)賬號(hào)
? 相關(guān) SDK 下載
? 快速開始 - 實(shí)現(xiàn)音視頻通話文章來源地址http://www.zghlxwxcb.cn/news/detail-569330.html
到了這里,關(guān)于保姆級(jí)教程!基于聲網(wǎng) Web SDK實(shí)現(xiàn)音視頻通話及屏幕共享的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!