戰(zhàn)詳解)
mediasoup-client Transport 完全指南sendTransport 與 recvTransport 實(shí)戰(zhàn)詳解【免費(fèi)下載鏈接】mediasoup-clientmediasoup client side JavaScript library項(xiàng)目地址: https://gitcode.com/gh_mirrors/me/mediasoup-client如果你正在開(kāi)發(fā) WebRTC 實(shí)時(shí)音視頻應(yīng)用那么 mediasoup-client Transport 是無(wú)論如何都繞不開(kāi)的核心概念。作為 mediasoup 官方瀏覽器端 JavaScript 庫(kù)mediasoup-client 通過(guò)sendTransport與recvTransport兩條通道分別完成媒體上行推送與下行接收理解它們的分工與協(xié)作方式是搭建穩(wěn)定、可擴(kuò)展的 SFU 音視頻通話系統(tǒng)的第一步。本指南將從零開(kāi)始帶你徹底搞懂 Transport 的原理、創(chuàng)建流程與實(shí)戰(zhàn)要點(diǎn)。一、什么是 mediasoup-client TransportTransport 的本質(zhì)一條端到端的媒體通道在 mediasoup 架構(gòu)中服務(wù)端mediasoup server為每個(gè)參與者創(chuàng)建一個(gè)名為T(mén)ransport的邏輯實(shí)體它內(nèi)部封裝了一條 WebRTC 連接RTCPeerConnection所需的 ICE 與 DTLS 參數(shù)。而 mediasoup-client 的作用就是在瀏覽器端復(fù)刻出與服務(wù)端一一對(duì)應(yīng)的 Transport 實(shí)例。客戶端 Transport 的核心代碼位于 src/Transport.ts其類定義中有一個(gè)關(guān)鍵字段direction: send | recv它決定了這條通道的用途方向創(chuàng)建方法核心用途核心 APIsenddevice.createSendTransport()上行推送本地音視頻produce()、produceData()recvdevice.createRecvTransport()下行拉取遠(yuǎn)端音視頻consume()、consumeData()客戶端 Transport 的三大核心參數(shù)創(chuàng)建 Transport 時(shí)必須傳入來(lái)自服務(wù)端的四件套參數(shù)缺一不可對(duì)應(yīng) src/Device.ts 中的類型校驗(yàn)邏輯id服務(wù)端 Transport 的唯一標(biāo)識(shí)iceParametersICE 用戶名片段與密碼iceCandidatesICE 候選者列表dtlsParametersDTLS 指紋與角色這些參數(shù)由服務(wù)端通過(guò)信令WebSocket 等下發(fā)客戶端拿到后原樣傳入即可。二、sendTransport 實(shí)戰(zhàn)如何發(fā)布本地音視頻第一步創(chuàng)建 sendTransport 的正確姿勢(shì)sendTransport 負(fù)責(zé)把本地畫(huà)面和聲音推給遠(yuǎn)端典型創(chuàng)建流程如下const sendTransport device.createSendTransport({ id, iceParameters, iceCandidates, dtlsParameters, sctpParameters, // 如需 DataChannel 傳數(shù)據(jù)則必須提供 });創(chuàng)建之后必須立刻注冊(cè)connect事件監(jiān)聽(tīng)否則后續(xù)調(diào)用produce()會(huì)直接拋錯(cuò)Transport 內(nèi)部會(huì)在 src/Transport.ts 的produce()方法中檢查監(jiān)聽(tīng)器是否存在。第二步connect 事件——打通 DTLS 握手connect事件是整個(gè)流程中最容易踩坑的一環(huán)。當(dāng)瀏覽器需要建立媒體連接時(shí)會(huì)觸發(fā)該事件你需要把本地生成的dtlsParameters通過(guò)信令發(fā)給服務(wù)端sendTransport.on(connect, async ({ dtlsParameters }, callback, errback) { try { await signaling.request(transport-connect, { transportId: sendTransport.id, dtlsParameters, }); callback(); // 服務(wù)端處理成功通知 Transport 繼續(xù) } catch (error) { errback(error); // 失敗則回傳錯(cuò)誤 } });第三步produce 事件與 produce() 的完整配合produce()調(diào)用后Transport 會(huì)先在本地創(chuàng)建 RTP Sender然后觸發(fā)produce事件把協(xié)商好的rtpParameters交給你發(fā)往服務(wù)端sendTransport.on(produce, async ({ kind, rtpParameters, appData }, callback, errback) { try { const { id } await signaling.request(produce, { transportId: sendTransport.id, kind, rtpParameters, appData, }); callback({ id }); // 把服務(wù)端返回的 producer id 傳回 } catch (error) { errback(error); } }); // 推送攝像頭畫(huà)面 const stream await navigator.mediaDevices.getUserMedia({ video: true }); const producer await sendTransport.produce({ track: stream.getVideoTracks()[0] });關(guān)鍵點(diǎn)produce事件的callback({ id })必須傳回服務(wù)端生成的 producer idTransport 會(huì)用它在本地創(chuàng)建 Producer 實(shí)例見(jiàn) src/Transport.ts 的produce()實(shí)現(xiàn)。第四步DataChannel 數(shù)據(jù)通道produceData需要傳輸二進(jìn)制消息或低延遲數(shù)據(jù)時(shí)可以在 sendTransport 上創(chuàng)建 DataProducerconst dataProducer await sendTransport.produceData({ ordered: true, label: chat });此時(shí)同樣需要監(jiān)聽(tīng)producedata事件把sctpStreamParameters上報(bào)給服務(wù)端換取 id。三、recvTransport 實(shí)戰(zhàn)如何接收遠(yuǎn)端音視頻創(chuàng)建 recvTransport 的差異點(diǎn)recvTransport 與 sendTransport 的創(chuàng)建參數(shù)完全一致唯一區(qū)別是方向const recvTransport device.createRecvTransport({ id, iceParameters, iceCandidates, dtlsParameters, sctpParameters, }); recvTransport.on(connect, async ({ dtlsParameters }, callback, errback) { // 同樣通過(guò)信令完成 DTLS 協(xié)商 });consume() 一鍵拉流訂閱遠(yuǎn)端 Producer當(dāng)遠(yuǎn)端有新的 Producer 加入時(shí)服務(wù)端會(huì)通過(guò)信令通知你此時(shí)調(diào)用consume()即可在 recvTransport 上創(chuàng)建 Consumerconst consumer await recvTransport.consume({ id: consumerId, // 服務(wù)端下發(fā)的 consumer id producerId, // 對(duì)應(yīng)的 producer id kind: video, // audio 或 video rtpParameters, // 服務(wù)端下發(fā)的接收參數(shù) });注意consume()返回的 Consumer 默認(rèn)是paused狀態(tài)需要調(diào)用consumer.resume()才會(huì)真正開(kāi)始接收媒體流。拿到consumer.track后把它addTrack到video元素即可播放畫(huà)面。consumeData()接收數(shù)據(jù)通道對(duì)應(yīng) sendTransport 的produceData()recvTransport 側(cè)使用consumeData()訂閱 DataConsumer實(shí)現(xiàn)聊天消息、文件分片等下行數(shù)據(jù)接收。四、Transport 事件監(jiān)聽(tīng)清單與連接狀態(tài)管理無(wú)論是 sendTransport 還是 recvTransport都共享同一套事件體系定義于 src/Transport.ts 的TransportEvents事件觸發(fā)時(shí)機(jī)實(shí)戰(zhàn)建議connect需要建立 DTLS 連接時(shí)必監(jiān)聽(tīng)轉(zhuǎn)發(fā) dtlsParametersproduce/producedata創(chuàng)建 Producer 時(shí)sendTransport 必監(jiān)聽(tīng)connectionstatechange連接狀態(tài)變化用于 UI 顯示與斷線重連icegatheringstatechangeICE 收集狀態(tài)變化調(diào)試網(wǎng)絡(luò)問(wèn)題利器icecandidateerrorICE 候選者出錯(cuò)排查 NAT/防火墻問(wèn)題監(jiān)聽(tīng)connectionstatechange是提升用戶體驗(yàn)的關(guān)鍵狀態(tài)機(jī)依次為new → connecting → connected → failed/disconnected/closed當(dāng)出現(xiàn)disconnected時(shí)可調(diào)用transport.restartIce()觸發(fā) ICE 重啟實(shí)現(xiàn)網(wǎng)絡(luò)恢復(fù)。五、Transport 常用方法速查表restartIce()傳入服務(wù)端新的iceParameters完成 ICE 重啟斷線重連必備updateIceServers()動(dòng)態(tài)更新 ICE 服務(wù)器如 TURN 憑證過(guò)期時(shí)刷新getStats()獲取底層RTCPeerConnection的統(tǒng)計(jì)報(bào)告用于帶寬監(jiān)控close()關(guān)閉 Transport同時(shí)級(jí)聯(lián)關(guān)閉其下所有 Producer/Consumer此外每個(gè) Transport 都暴露了observer屬性可以通過(guò)監(jiān)聽(tīng)newproducer、newconsumer等事件實(shí)現(xiàn)旁觀者模式這在調(diào)試和統(tǒng)計(jì)場(chǎng)景中非常有用。六、新手最容易踩的 5 個(gè)坑忘記監(jiān)聽(tīng)connect事件produce()/consume()直接拋TypeError。produce回調(diào)未返回 idProducer 創(chuàng)建失敗務(wù)必callback({ id })。Consumer 忘記resume()畫(huà)面黑屏、無(wú)聲因?yàn)槟J(rèn)是暫停狀態(tài)。在device.load()之前創(chuàng)建 Transport會(huì)拋InvalidStateError(not loaded)。sendTransport 與 recvTransport 混用consume()只能用于 recvproduce()只能用于 send方向錯(cuò)誤會(huì)拋UnsupportedError。七、總結(jié)一張圖看懂雙 Transport 協(xié)作一次完整的雙向通話需要兩個(gè) Transport 并行工作sendTransport把自己的麥克風(fēng)/攝像頭通過(guò)produce()推給服務(wù)端recvTransport把對(duì)方的音視頻通過(guò)consume()拉回來(lái)播放兩者互不干擾、各自獨(dú)立管理連接狀態(tài)這正是 mediasoup 設(shè)計(jì)上收發(fā)分離的優(yōu)雅之處。掌握了 sendTransport 與 recvTransport 的創(chuàng)建、事件處理與生命周期管理你就已經(jīng)掌握了 mediasoup-client 最核心的 80% 能力。建議對(duì)照 src/Transport.ts 源碼和 src/Device.ts 中的createSendTransport()/createRecvTransport()實(shí)現(xiàn)親手跑通一遍信令流程很快就能寫(xiě)出屬于自己的 WebRTC 音視頻應(yīng)用。【免費(fèi)下載鏈接】mediasoup-clientmediasoup client side JavaScript library項(xiàng)目地址: https://gitcode.com/gh_mirrors/me/mediasoup-client創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考