本文最初發佈在計量部落格:WebRTC WHIP 和 WHEP 教學:建立即時串流應用程式
WHIP(WebRTC-HTTP 攝取協定) 和 WHEP(WebRTC-HTTP 出口協定) 是旨在藉助標準 HTTP 方法簡化 WebRTC 中訊號傳送的協定
-
WHIP 的定義:WHIP 簡化了客戶端裝置將媒體串流傳送到伺服器的方式。
- 它取代了簡單 HTTP GET 請求所需的複雜訊號機制,從而更容易將媒體攝取到伺服器
WHEP 的定義:WHEP 協定用於將媒體串流從伺服器傳送到客戶端。它使用 HTTP 協定來處理媒體消費的訊號,從而使客戶端設備無需複雜的設定即可接收媒體串流
簡化 WebRTC 訊號的作用
易於實施: WHEP 和 WHIP 使用 HTTP 協議,因此這些協議降低了與
相關的複雜性
無狀態通訊:這是因為 HTTP 是無狀態協議,伺服器不需要維護請求之間持續的會話資訊。
相容性提高:由於HTTP具有通用相容性,因此使用HTTP進行訊號是跨平台和裝置相容性的最佳選擇
快速開發:開發人員可以更有效地實現 WebRTC 應用程序,因為他們不需要考慮傳統信號方法的複雜細節
WHIP 是如何運作的
WHIP 如何處理媒體串流攝取
WHIP 協定徹底改變如何使用 HTTP 訊號方法將媒體串流從客戶端裝置傳送到伺服器
傳統上,要設定 WebRTC,您需要使用 Web 套接字或其他協定來設定複雜的訊號機制。借助 WHIP,透過使用 HTTP 協定發送訊號並啟動 WebRTC 會話,此過程變得簡單
HTTP POST 請求: 此處,用戶端裝置將正文中包含 SDP 或會話描述協定的 HTTP POST 要求傳送至 WHIP 端點
伺服器回應: 媒體伺服器然後處理 SDP Offer 並使用 200 狀態碼回應,包括請求正文中的 SDP 答案
ICE 候選交換: WHIP 協議支援 ICE 協議,允許客戶端在新的 ICE 候選可用時發送額外的 HTTP PATCH 請求
連接建立: 一旦 SDP 交換完成,就會建立點對點連接,使客戶端能夠將媒體串流傳輸到伺服器
相對於傳統攝取方法的優勢
簡單性: 透過使用 WHIP 方法,WHIP 減少了對持久連線和訊號伺服器的需求。
易於實作: 開發者可以使用具有通用相容性的 HTTP 來加快開發流程
可擴充性:無狀態 HTTP 請求允許伺服器同時處理多個連線請求,從而輕鬆管理大量連線。
防火牆和代理友好: HTTP 是防火牆友好的,幾乎所有類型的防火牆都允許 HTTP 流量
成本效益: 透過 HTTP 進行的簡化訊號降低了與新增訊號伺服器相關的成本
WHEP 是如何運作的
WHEP 協定簡化了將媒體從伺服器傳輸到客戶端裝置的過程。
因此,WHEP 協定可讓您使用 HTTP 來設定從伺服器和用戶端裝置接收媒體的訊號。
WHEP 在媒體串流中如何運作
HTTP GET 請求: 客戶端透過傳送 HTTP GET 請求至伺服器 WHEP 請求來要求媒體串流
SDP Exchange: 伺服器在 HTTP 回應中以 SDP Offer 回應,然後用戶端在後續 POST 請求中發回 SDP 回應
媒體接收: 建立連線後,將透過已建立的 WebRTC 連線接收媒體串流。注意:很多時候您需要TURN 伺服器來建立 WebRTC 連線
對 ICE 的支援: WHEP 允許透過額外的 HTTP 修補程式要求交換 ICE 候選者,從而實現更好的連接
客戶端串流的優勢
簡化的客戶實現: 使用 HTTP 請求,從而減少複雜信號機制的需求
改進的兼容性: 對 HTTP 協定的普遍支援確保了改進的跨裝置相容性
增強的可擴展性: 由於 HTTP 是無狀態協議,這提高了伺服器的可擴展性,並且使用少量資源即可擴展到大量用戶
更好的網路遍歷: 因為您可以使用 HTTP 進行訊號傳輸,並且不需要 Web 套接字或其他機制,所以這可以改善連接的 NAT 遍歷。建立連線後,您確實需要WebRTC 的 TURN 伺服器
減少延遲: 使用 HTTP 發送訊號可以實現更快的連接,從而增強用戶體驗。
WHIP 與 WHEP 之間的協同作用
結合兩種協定以實現高效率的端到端通訊:
透過結合 WHIP 和 WHEP,開發人員可以為 WebRTC 建立全面的訊號解決方案
這種組合簡化了媒體串流的攝取和交付,確保 WebRTC 的實施更加順利
統一訊號方法: 使用 HTTP 進行攝取與交付,建立一致的訊號方法
降低複雜性: 開發者只需處理 HTTP 協議,從而減少程式碼的學習曲線和維護
增強的效能:使用單一訊號協定簡化程式碼,可以在傳輸媒體時縮短連線時間並降低延遲
展示效能改進的用例
直播平台:
互動式應用程式
可擴充架構
建立直播應用程式
在 WebRTC 應用程式中實作 WHIP 和 WHEP 非常簡單。在本節中,我們將設定一個 WHIP 伺服器並使用節點和 docker 等現代技術將其整合到您的應用程式中
這裡我們將使用 Metered.ca TURN 伺服器服務進行 NAT 穿越
設定 WHIP 伺服器
先決條件與環境設定:
Node.js 和 NPM: 確保您安裝了最新的 Node 和 nvm
Metered.ca 帳戶: 在 Metered TURN 伺服器
上建立免費帳戶
公用 IP 位址: 這是可透過網際網路存取伺服器所必需的。如果您的應用程式使用任何雲端供應商,您將獲得一個免費的公用 IP 位址
WebRTC 媒體伺服器: 我們需要一個支援 WHIP 的媒體伺服器,例如 GStreamer 或 Janus
使用 Node.Js 和 GStreamer 加強步驟設定
安裝支援 WHIP 的 GStreamer
-
使用 GStreamer 設定 WHIP 伺服器
- 建立一個 GStreamer 管道來監聽 WHIP 連接,如下所示
gst-launch-1.0 whipserversrc name=whip \ ! queue ! videoconvert ! autovideosink
上述指令啟動一個 WHIP 伺服器,該伺服器接受傳入的媒體流並顯示它們
-
設定伺服器以使用Metered.ca TURN 伺服器
- 修改 GStreamer 管道以使用 TURN 伺服器。這很重要,因為 NAT 路由器和防火牆會阻止連接
gst-launch-1.0 whipserversrc name=whip ice-server="turn://YOUR_USERNAME:YOUR_CREDENTIAL@relay.metered.ca:80" \ ! queue ! videoconvert ! autovideosink
-
使用 Node.JS 設定反向代理(可選):
- 如果您想管理 HTTP 端點或新增任何其他附加邏輯,您可以設定一個簡單的 Express js 伺服器
const express = require('express'); const httpProxy = require('http-proxy'); const app = express(); const proxy = httpProxy.createProxyServer(); app.post('/whip', (req, res) => { proxy.web(req, res, { target: 'http://localhost:PORT_WHERE_GSTREAMER_IS_RUNNING' }); }); app.listen(3000, () => { console.log('Proxy server running on port 3000'); });
在您的應用程式中實作 WHIP
整合 WHIP 的程式碼片段:
在用戶端,您可以藉助 RTCPeerConnection 擷取媒體串流,並使用 HTTP 請求來處理建立連線所需的訊號
-
捕捉媒體串流:
- 您可以捕捉媒體串流,例如
const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
- 建立 RTCPeerConnection:
您可以在計量 TURN 伺服器的協助下建立 RTCPeerConnection
var myPeerConnection = new RTCPeerConnection({ iceServers: [ { urls: "stun:stun.relay.metered.ca:80", }, { urls: "turn:global.relay.metered.ca:80", username: "your-username", credential: "your-credential", }, { urls: "turn:global.relay.metered.ca:80?transport=tcp", username: "your-username", credential: "your-credential", }, { urls: "turn:global.relay.metered.ca:443", username: "your-username", credential: "your-credential", }, { urls: "turns:global.relay.metered.ca:443?transport=tcp", username: "your-username", credential: "your-credential", }, ], });
- 將媒體軌道加入連結:
mediaStream.getTracks().forEach((track) => { pc.addTrack(track, mediaStream); });
- 建立 SDP 報價並將其發送到 WHIP 伺服器:
const offer = await pc.createOffer(); await pc.setLocalDescription(offer); const response = await fetch('http://YOUR_SERVER_IP:3000/whip', { method: 'POST', headers: { 'Content-Type': 'application/sdp' }, body: pc.localDescription.sdp, }); const sdpAnswer = await response.text(); await pc.setRemoteDescription({ type: 'answer', sdp: sdpAnswer });
處理訊號的 HTTP 請求和回應
-
客戶端:
-
HTTP POST 請求:
- 網址:http://YOUR_SERVER_IP:3000/whip
- 標頭:{ 'Content-Type': 'application/sdp' }
- 正文:純文字形式的 SDP 報價
-
期待回覆:
- 狀態:201 已創建
- 標題:帶有資源 URL 的位置標題
- 正文:純文字形式的 SDP 答案
-
-
伺服器端:
-
接收 SDP 優惠:
- 從 req.body 讀取 SDP
- 建立WebRTC端點並設定遠端描述
-
產生 SDP 答案
- 來自伺服器 WebRTC 端點的 SDP 應答
- 將 SDP 答案傳回 res.body
- 使用 Metered.ca TURN 伺服器服務
-
使用 Metered.ca TURN 伺服器服務
TURN 伺服器的用途
當無法進行直接點對點連線時,促進媒體穿越 NAT 和防火牆
將 TURN 伺服器合併到 ICE 伺服器設定
這是 TURN 伺服器憑證和 ICE 伺服器
gst-launch-1.0 whipserversrc name=whip \ ! queue ! videoconvert ! autovideosink
部署 WHEP 用戶端
擁有 WHIP 用戶端可讓您的應用程式使用 HTTP 訊號從伺服器接收媒體串流。
在客戶端整合 WHEP
基本上了解 Javascript 中的 WebRTC API
支援 WHEP GStreamer Janus 或任何其他
的媒體伺服器
Metered.ca TURN 伺服器憑證
逐步將 WHEP 整合到您的應用程式中。
-
初始化 RTCPeerConnection
- 使用具有metered.ca轉伺服器的ICE伺服器建立一個RTCPeerConnection實例
gst-launch-1.0 whipserversrc name=whip ice-server="turn://YOUR_USERNAME:YOUR_CREDENTIAL@relay.metered.ca:80" \ ! queue ! videoconvert ! autovideosink
- 處理傳入的媒體軌道
設定事件偵聽器以從伺服器恢復遠端軌道
const express = require('express'); const httpProxy = require('http-proxy'); const app = express(); const proxy = httpProxy.createProxyServer(); app.post('/whip', (req, res) => { proxy.web(req, res, { target: 'http://localhost:PORT_WHERE_GSTREAMER_IS_RUNNING' }); }); app.listen(3000, () => { console.log('Proxy server running on port 3000'); });
- 傳送 HTTP GET 伺服器到 WHEP 伺服器:
向伺服器發送 GET 請求
const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
- 收到的 SDP 報價的遠端描述
var myPeerConnection = new RTCPeerConnection({ iceServers: [ { urls: "stun:stun.relay.metered.ca:80", }, { urls: "turn:global.relay.metered.ca:80", username: "your-username", credential: "your-credential", }, { urls: "turn:global.relay.metered.ca:80?transport=tcp", username: "your-username", credential: "your-credential", }, { urls: "turn:global.relay.metered.ca:443", username: "your-username", credential: "your-credential", }, { urls: "turns:global.relay.metered.ca:443?transport=tcp", username: "your-username", credential: "your-credential", }, ], });
- 建立並發送 SDP 答案
建立 SDP 應答並透過 HTTP POST 請求將其傳送至伺服器
mediaStream.getTracks().forEach((track) => { pc.addTrack(track, mediaStream); });
- 處理 ICE 候選人交換(可選):
如果您需要單獨發送 ICE 候選人,請處理icecandidate 事件
const offer = await pc.createOffer(); await pc.setLocalDescription(offer); const response = await fetch('http://YOUR_SERVER_IP:3000/whip', { method: 'POST', headers: { 'Content-Type': 'application/sdp' }, body: pc.localDescription.sdp, }); const sdpAnswer = await response.text(); await pc.setRemoteDescription({ type: 'answer', sdp: sdpAnswer });
在前端處理媒體串流
- 在 HTML 中建立影片元素
var myPeerConnection = new RTCPeerConnection({ iceServers: [ { urls: "stun:stun.relay.metered.ca:80", }, { urls: "turn:global.relay.metered.ca:80", username: "e13b9bsdfdsfsdfb0676cc5b6", credential: "dedewdewfer+gq5iT", }, { urls: "turn:global.relay.metered.ca:80?transport=tcp", username: "e13bdfdsfds6b0676cc5b6", credential: "dewfrefre+gq5iT", }, { urls: "turn:global.relay.metered.ca:443", username: "e13b9fsdfdsfsd86b0676cc5b6", credential: "csdfwefeer+gq5iT", }, { urls: "turns:global.relay.metered.ca:443?transport=tcp", username: "e13b9dsfsdfe6b0676cc5b6", credential: "sdfewtrererer+gq5iT", }, ], });
- 將遠端串流附加到視訊元素
當觸發追蹤事件時,將收到的串流附加到視訊元素
-
處理媒體串流事件
- 連線狀態改變
var myPeerConnection = new RTCPeerConnection({ iceServers: [ { urls: "stun:stun.relay.metered.ca:80", }, { urls: "turn:global.relay.metered.ca:80", username: "e13b9bsdfdsfsdfb0676cc5b6", credential: "dedewdewfer+gq5iT", }, { urls: "turn:global.relay.metered.ca:80?transport=tcp", username: "e13bdfdsfds6b0676cc5b6", credential: "dewfrefre+gq5iT", }, { urls: "turn:global.relay.metered.ca:443", username: "e13b9fsdfdsfsd86b0676cc5b6", credential: "csdfwefeer+gq5iT", }, { urls: "turns:global.relay.metered.ca:443?transport=tcp", username: "e13b9dsfsdfe6b0676cc5b6", credential: "sdfewtrererer+gq5iT", }, ], });
b.需要協商
pc.addEventListener('track', (event) => { const [remoteStream] = event.streams; // Attach the remote stream to a video element const remoteVideo = document.getElementById('remoteVideo'); remoteVideo.srcObject = remoteStream; });
- 完整範例程式碼
const whepServerEndpoint = 'http://YOUR_SERVER_IP:3000/whep'; // Replace with your server's WHEP endpoint const response = await fetch(whepEndpoint, { method: 'GET', headers: { Accept: 'application/sdp', }, }); const sdpOffer = await response.text();
計量 TURN 伺服器
API: 使用強大的 API 進行 TURN 伺服器管理。您可以執行以下操作:透過 API 新增/刪除憑證、透過 API 檢索每個使用者/憑證和使用者指標、透過 API 啟用/停用憑證、透過 API 按日期檢索使用資料。
全球地理位置定位:自動將流量定向到最近的伺服器,以實現盡可能低的延遲和最高的品質效能。全球任何地方的延遲均低於 50 毫秒
全球所有地區的伺服器:多倫多、邁阿密、舊金山、阿姆斯特丹、倫敦、法蘭克福、班加羅爾、新加坡、雪梨、首爾、達拉斯、紐約
低延遲: 低於 50 毫秒的延遲,在世界任何地方。
經濟高效:即用即付定價,並提供頻寬和批量折扣。
輕鬆管理: 取得使用日誌、帳戶達到門檻限制時的電子郵件、帳單記錄以及電子郵件和電話支援。
符合標準: 符合 UDP、TCP、TLS 和 DTLS 的 RFC 5389、5769、5780、5766、6062、6156、5245、5768、6336、925336、92536、92536、92536。
多租用戶: 建立多個憑證並依客戶或不同應用程式分開使用。取得使用日誌、計費記錄和閾值警報。
企業可靠性: SLA 正常運作時間達 99.999%。
企業規模: 不限制併發流量或總流量。計量 TURN 伺服器提供企業可擴充性
每月 5 GB 免費: 透過免費方案每月獲得 5 GB 免費 TURN 伺服器使用量
在連接埠 80 和 443 上運作
支援 TURNS SSL 以允許透過深度封包偵測防火牆進行連線。
同時支援 TCP 和 UDP
免費無限制 STUN
您可以考慮我們的其他一些文章:
WebRTC 資料通道:指引
簡單對等教學:為影片、DataChannel 新增 TURN 伺服器
使用計量設定 WebRTC TURN 伺服器的指南
WebRTC 與 HLS:哪個最適合您?
以上是WebRTC WHIP 和 WHEP 教學:建立即時串流應用程式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

WebStorm Mac版
好用的JavaScript開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Dreamweaver CS6
視覺化網頁開發工具