1. 基本知識
1.1 webrtc
一、WebRTC的本質:實時通信的“網絡協議棧”類比
將WebRTC類比為Linux網絡協議棧極具洞察力,二者在架構設計和功能定位上高度相似:
-
分層協議棧架構
- Linux網絡協議棧:從底層物理層到應用層(如TCP/IP、UDP),負責數據的封裝、傳輸、路由及解析,是操作系統網絡能力的核心。
- WebRTC協議棧:
- 傳輸層:基于UDP實現自定義數據通道(DataChannel)和音視頻流傳輸,內置RTCPeerConnection處理連接建立、NAT穿越(STUN/TURN)和帶寬管理。
- 媒體處理層:集成音視頻編解碼模塊(VP8/VP9/H.264、Opus)、前向糾錯(FEC)、降噪算法等,實現低延遲媒體流的實時處理。
- 應用層接口:通過瀏覽器API(如
getUserMedia
、RTCPeerConnection
)暴露功能,類似Linux通過Socket接口供應用調用。
-
原生性與系統整合
- Linux協議棧是操作系統內核的原生組件,WebRTC則是瀏覽器內核的原生模塊(如Chrome的Blink引擎),直接調用操作系統的硬件接口(攝像頭、麥克風、網絡驅動),避免中間層性能損耗。
二、瀏覽器中的WebRTC:API接口的技術全景
WebRTC在瀏覽器中的實現,本質是將協議棧能力通過標準化API開放給開發者,其核心接口體系包括:
- 媒體采集與設備控制
getUserMedia
:直接調用設備傳感器,獲取音視頻流,支持參數配置(如分辨率、幀率、攝像頭方向)。navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" }, audio: true })
MediaRecorder
:基于WebRTC流實現客戶端錄制(如錄制會議內容)。
- 點對點連接建立
RTCPeerConnection
:核心接口,負責創建連接、交換SDP信令、管理ICE候選(網絡地址),并通過addTrack
/ontrack
處理媒體流傳輸。- 信令解耦設計:瀏覽器僅處理媒體通道,信令通道需開發者自建(如WebSocket),這種分離模式與Linux協議棧“內核處理傳輸,用戶態處理應用邏輯”的設計一致。
1.2 sfu模式
SFU模式(Selective Forwarding Unit)深度解析:架構、原理與應用場景
一、SFU模式的核心定義與定位
SFU(選擇性轉發單元)是流媒體服務器的一種轉發模式,其核心功能是接收多個客戶端的媒體流,根據訂閱關系選擇性地將流轉發給其他客戶端,而非對媒體流進行解碼、混流或重新編碼。
- 類比說明:
- 若將媒體流視為“快遞包裹”,SFU相當于快遞分揀中心:
- 包裹(原始流)到達分揀中心后,僅根據收件地址(訂閱關系)重新分揀投遞,不拆包(不解碼)、不合并包裹(不混流)。
- 優勢在于低延遲、低計算消耗,適合實時性要求高的場景(如互動直播、視頻會議)。
- 若將媒體流視為“快遞包裹”,SFU相當于快遞分揀中心:
二、SFU的技術架構與工作流程
1. 核心組件與網絡模型
(典型SFU架構示意圖:客戶端A/B/C發布流至SFU,SFU根據訂閱關系將流轉發給訂閱者)
-
關鍵角色:
- 發布者(Publisher):客戶端向SFU發送媒體流(如攝像頭采集的視頻流)。
- 訂閱者(Subscriber):客戶端向SFU請求訂閱特定流,接收轉發的流數據。
- SFU服務器:
- 維護流路由表(記錄每個流的發布者與訂閱者列表)。
- 通過傳輸層協議(如UDP、WebRTC DataChannel)接收和轉發流數據,不涉及媒體層處理。
-
數據流向:
- 發布者通過RTMP/WebRTC等協議將流推至SFU。
- SFU解析流元數據(如流ID),存儲到路由表。
- 訂閱者向SFU請求訂閱某個流ID。
- SFU根據路由表,將該流的數據包復制并轉發給所有訂閱者。
2. 與MCU模式的本質區別
維度 | SFU模式 | MCU模式(Multipoint Control Unit) |
---|---|---|
媒體處理 | 不解碼、不混流,僅轉發原始數據包 | 解碼所有流,混合成單一流(如將多路視頻合成畫中畫) |
延遲 | 極低(僅網絡傳輸延遲+轉發處理時間) | 高(需解碼、混流、重新編碼,引入處理延遲) |
帶寬消耗 | 發布者推1路流,訂閱者接收N路流(總帶寬≈發布帶寬×N) | 發布者推N路流,服務器混流后推1路流(總帶寬≈發布帶寬×N + 混流帶寬) |
計算資源 | 幾乎無媒體處理消耗,適合高并發 | 需大量CPU/GPU資源,并發量受限 |
典型場景 | 實時互動直播、多人視頻會議(如Zoom) | 低并發、需要畫面合成的場景(如傳統視頻會議) |
三、SFU模式的技術優勢與適用場景
1. 核心優勢
-
低延遲特性:
- 無解碼-編碼環節,延遲通常控制在100ms-500ms級別,滿足實時互動需求(如連麥、彈幕互動)。
- 對比:傳統CDN直播延遲約2-3秒,MCU模式延遲約500ms-1秒。
-
高擴展性與低資源消耗:
- 服務器僅負責轉發,單臺SFU可支持數萬路流并發轉發(取決于網絡帶寬)。
- 節省計算資源,適合構建大規模實時通信系統(如在線教育平臺、電商直播)。
-
靈活性與兼容性:
- 支持多協議接入(WebRTC、RTMP、SRT等),通過轉協議網關實現跨終端互通(如瀏覽器WebRTC流轉發給RTMP推流的手機端)。
- 支持動態路由:可根據訂閱者網絡質量動態選擇轉發策略(如丟棄高延遲訂閱者的流,或啟用FEC增強可靠性)。
2. 典型應用場景
-
實時互動直播:
- 場景:主播與觀眾連麥、多人PK直播。
- 實現:主播推流至SFU,觀眾訂閱主播流;連麥者推流至SFU,SFU將連麥者流轉發給主播和其他觀眾。
- 案例:Twitch的低延遲直播、B站“直播連麥”功能。
-
視頻會議系統:
- 場景:百人以上的遠程會議,需支持動態加入/退出。
- 實現:每個參會者發布自己的流至SFU,根據會議布局(如“發言人模式”),SFU將主講人流轉發給所有參會者。
- 案例:Zoom的“分組討論”功能基于SFU實現動態流轉發。
-
物聯網與實時監控:
- 場景:多個攝像頭實時回傳畫面至監控中心,支持多用戶實時查看。
- 實現:攝像頭通過RTSP推流至SFU,監控客戶端訂閱指定攝像頭流,SFU按需轉發。
2 srs流媒體服務器
2.1 SFU轉發單位
- 流接收與注冊:
- 協議適配:支持 WebRTC 協議,接收客戶端(發布者)通過 WebRTC 推來的音視頻流 ,也可處理 RTMP 等其他協議轉 WebRTC 后的流,通過如
/rtc/v1/publish/
接口邏輯,解析流的元數據(如流 ID、編碼格式、分辨率等) 。 - 流注冊:將接收的流信息(流 ID、發布者標識等)記錄到內部“流路由表”,建立“流 - 發布者”映射關系,為后續轉發做準備 。
- 協議適配:支持 WebRTC 協議,接收客戶端(發布者)通過 WebRTC 推來的音視頻流 ,也可處理 RTMP 等其他協議轉 WebRTC 后的流,通過如
- 訂閱與轉發決策:
- 訂閱請求處理:當其他客戶端(訂閱者)通過
/rtc/v1/play
或 WebRTC 協議發起訂閱請求時,SRS 依據請求中的流 ID,查詢“流路由表”,確定對應的發布者流 。 - 轉發策略:
- 選擇性轉發:作為 SFU,不解碼、不混流原始媒體流(或僅做輕量級處理,如適配編碼格式),直接復制流數據,根據訂閱關系轉發給訂閱者 。比如多人會議場景,把發言人的單路流,轉發給所有參會訂閱者,實現“一對多”高效分發 。
- 智能適配:結合客戶端網絡狀況(如帶寬、延遲)、終端能力(支持編碼格式),動態調整轉發的流參數。若訂閱者網絡差,可轉發低分辨率、低碼率流;若終端不支持 VP8 編碼,轉換為 H.264 再轉發 。
- 訂閱請求處理:當其他客戶端(訂閱者)通過
- 媒體傳輸與優化:
- 傳輸協議:基于 UDP 傳輸媒體數據包(WebRTC 常用方式),利用其低延遲特性;也適配 TCP,應對復雜網絡環境 。
- 網絡優化:
- NAT 穿透:配合 STUN/TURN 服務器,或通過配置
candidate
(候選地址),解決客戶端處于 NAT 環境下的互聯互通問題,讓流順利收發 。 - 擁塞控制:支持 NACK(丟包重傳)、TWCC(傳輸帶寬估計與擁塞控制反饋),檢測到丟包時重傳關鍵數據,根據網絡帶寬動態調整發送碼率,保障流傳輸穩定 。
- FEC(前向糾錯):添加冗余數據,訂閱者收到數據后,可通過冗余數據恢復丟失的數據包,降低重傳依賴,減少延遲 。
- NAT 穿透:配合 STUN/TURN 服務器,或通過配置
- 管理與協同:
- 控制臺管理:提供
srs 1985 控制臺
(對應 URL 可查看),可視化展示 SRS 服務狀態、流信息、客戶端連接情況,方便運維人員監控流轉發狀態、排查問題 。 - 信令協同:與信令服務器(如
signal1989
)配合,通過/sig/v1/rtc
等接口,處理房間創建、加入、流訂閱/取消等信令邏輯,協同完成“發布 - 訂閱”全流程 。比如信令通知 SRS 有新訂閱者加入,SRS 即刻啟動對應流的轉發 。
- 控制臺管理:提供
- 協議轉換與兼容(可選拓展):除純 WebRTC 流轉發,還支持協議轉換。如把 WebRTC 流轉為 RTMP/FLV ,供不支持 WebRTC 的終端(如老舊播放器通過
srs_player.html
播放)使用;也能將 RTMP 流轉為 WebRTC 流輸出,打通不同協議終端的實時通信 。
2.2 信令服務器
信令的本質:
信令服務器核心職責是 處理設備 / 客戶端之間的 “協商邏輯”,比如 WebRTC 里的 SDP 交換(協商編解碼、媒體能力)、房間管理(加入 / 退出、流訂閱關系)、ICE 候選交換(網絡地址協商)等,讓終端知道 “和誰連、怎么連、發什么流” 。
SRS 對信令的支持方式:
- SRS 可通過 集成簡易信令邏輯 或 對接獨立信令服務器,輔助流媒體業務:
內置輕量信令功能:
支持 WHIP(WebRTC HTTP 推流協議 )、WHEP(WebRTC HTTP 拉流協議 )等,可在協議層面處理部分 “推流 - 拉流” 的信令交互(如 SDP 協商、流標識綁定 )。
例如,客戶端通過 WHIP 協議向 SRS 推流時,SRS 會解析請求里的 SDP 信息,完成媒體能力協商,這一步涉及 “信令式” 的交互,但僅圍繞流媒體傳輸本身,并非完整的 “房間管理、多終端協同” 信令邏輯。 - 對接獨立信令服務器:
實際復雜場景(如多人會議)中,SRS 通常搭配 獨立信令服務器(如開源的 Janus 信令模塊、或業務自定義的信令服務 )。
信令服務器負責處理 “房間創建、用戶加入 / 退出、流訂閱關系同步” 等高層邏輯,再將 “誰需要推流、誰需要拉流” 的指令告知 SRS,由 SRS 執行實際的媒體轉發。
2.3 綜合示例
背景設定
- 信令服務器:負責房間管理、狀態同步,提供
join
/publish
/subscribe
等信令接口。 - SRS(SFU):負責媒體流轉發,提供
publish
(推流)和play
(拉流)的媒體接口。 - 用戶角色:
- CWR:先加入房間的用戶,發布自己的流。
- CZ:后加入房間的用戶,訂閱 CWR 的流,同時發布自己的流讓 CWR 訂閱。
流程拆解(Step by Step)
1. CWR 加入房間(join
信令)
-
CWR 操作:
調用信令服務器的join
接口,參數:roomId=1001
,userId=CWR
。// CWR 發送給信令服務器的 join 請求 {"action": "join","roomId": "1001","userId": "CWR" }
-
信令服務器邏輯:
- 檢查房間
1001
是否存在,若不存在則創建。 - 記錄 CWR 為房間
1001
的參與者,維護“房間 - 參與者列表”:{"1001": ["CWR"]}
。 - 返回房間當前狀態給 CWR:
// 信令服務器返回給 CWR 的響應 {"code": 0,"roomId": "1001","participants": ["CWR"], // 目前只有自己"streams": [] // 暫時沒有流發布 }
- 檢查房間
2. CWR 發布流(publish
信令 + SRS 推流)
-
CWR 操作:
- 調用信令服務器的
publish
接口,告知“要發布流”:{"action": "publish","roomId": "1001","userId": "CWR","streamId": "CWR_stream" // 自定義流標識 }
- 通過 WebRTC 協議,將本地攝像頭/麥克風采集的流,推送到 SRS 的
publish
地址(如webrtc://srs.server/1001/CWR_stream
)。
- 調用信令服務器的
-
信令服務器邏輯:
- 記錄“CWR 發布了流
CWR_stream
”,更新房間流列表:{"1001": {"streams": ["CWR_stream"]}}
。 - 向房間內所有參與者(目前只有 CWR 自己)推送流發布事件:
{"action": "stream_published","roomId": "1001","userId": "CWR","streamId": "CWR_stream","streamUrl": "webrtc://srs.server/1001/CWR_stream" // SRS 流地址 }
- 記錄“CWR 發布了流
-
SRS(SFU)邏輯:
- 接收 CWR 推來的 WebRTC 流,解析流元數據(編碼、分辨率等)。
- 建立“流標識(
CWR_stream
)- 發布者(CWR)”的映射,等待訂閱者。
3. CZ 加入房間(join
信令)
-
CZ 操作:
調用信令服務器的join
接口,參數:roomId=1001
,userId=CZ
。{"action": "join","roomId": "1001","userId": "CZ" }
-
信令服務器邏輯:
- 檢查房間
1001
已存在,將 CZ 加入參與者列表:{"1001": ["CWR", "CZ"]}
。 - 返回房間當前狀態給 CZ,包含已存在的參與者和流:
{"code": 0,"roomId": "1001","participants": ["CWR", "CZ"],"streams": [{"userId": "CWR","streamId": "CWR_stream","streamUrl": "webrtc://srs.server/1001/CWR_stream"}] }
- 向房間內其他參與者(CWR) 推送新成員加入事件:
{"action": "participant_joined","roomId": "1001","userId": "CZ" }
- 檢查房間
4. CZ 訂閱 CWR 的流(subscribe
信令 + SRS 拉流)
-
CZ 操作:
從信令服務器返回的streams
中,拿到 CWR 的流地址webrtc://srs.server/1001/CWR_stream
,調用信令服務器的subscribe
接口(或直接通過 WebRTC 發起play
請求 ):{"action": "subscribe","roomId": "1001","userId": "CZ","streamUrl": "webrtc://srs.server/1001/CWR_stream" }
-
信令服務器邏輯:
記錄“CZ 訂閱了 CWR 的流”,并通知 SRS 處理轉發。 -
SRS(SFU)邏輯:
- 收到 CZ 的
play
請求(對應webrtc://srs.server/1001/CWR_stream
)。 - 找到 CWR 發布的流,直接轉發給 CZ(不解碼、不混流,僅做網絡優化 )。
- 收到 CZ 的
5. CZ 發布自己的流(publish
信令 + SRS 推流)
-
CZ 操作:
- 調用信令服務器的
publish
接口,告知“要發布流”:{"action": "publish","roomId": "1001","userId": "CZ","streamId": "CZ_stream" }
- 通過 WebRTC 協議,將本地流推送到 SRS 的
publish
地址(如webrtc://srs.server/1001/CZ_stream
)。
- 調用信令服務器的
-
信令服務器邏輯:
- 記錄“CZ 發布了流
CZ_stream
”,更新房間流列表。 - 向房間內所有參與者(CWR、CZ) 推送流發布事件:
{"action": "stream_published","roomId": "1001","userId": "CZ","streamId": "CZ_stream","streamUrl": "webrtc://srs.server/1001/CZ_stream" }
- 記錄“CZ 發布了流
-
SRS(SFU)邏輯:
接收 CZ 推來的流,建立“流標識(CZ_stream
)- 發布者(CZ)”的映射,等待訂閱者(如 CWR 會觸發訂閱 )。
6. CWR 訂閱 CZ 的流(自動觸發或信令驅動)
-
CWR 操作:
收到信令服務器推送的“CZ 發布流”事件后,自動調用subscribe
接口(或直接play
),訂閱webrtc://srs.server/1001/CZ_stream
。 -
SRS(SFU)邏輯:
將 CZ 的流轉發給 CWR,此時 CWR 和 CZ 實現雙向音視頻互通(CWR 看/聽 CZ,CZ 看/聽 CWR )。
關鍵協同總結
角色 | 核心動作 | 數據/信令流向 | 作用 |
---|---|---|---|
CWR(發布者) | join → publish → 推流到 SRS | 信令服務器 ←→ CWR;SRS ← CWR(媒體流) | 初始化房間、發布本地流 |
CZ(訂閱者) | join → 訂閱 CWR 流 → publish → 推流 | 信令服務器 ←→ CZ;SRS ←→ CZ(媒體流) | 加入房間、訂閱他人流、發布自己流 |
信令服務器 | 管理房間、同步狀態、轉發事件 | 信令服務器 ←→ CWR/CZ | 指揮“誰連誰、什么時候連”,不碰媒體數據 |
SRS(SFU) | 接收流、轉發流(publish /play 接口) | SRS ← 發布者(媒體流);SRS → 訂閱者 | 只負責“搬流媒體數據”,依賴信令調度 |
3 實戰
3.1 srs 流媒體服務器分析
運行命令:./objs/srs -c ./conf/rtc.conf
# WebRTC streaming config for SRS.
# @see full.conf for detail config.listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;http_server {enabled on;listen 8080;dir ./objs/nginx/html;
}http_api {enabled on;listen 1985;
}
stats {network 0;
}
rtc_server {enabled on;listen 8000; # UDP port# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidatecandidate $CANDIDATE;
}vhost __defaultVhost__ {rtc {enabled on;# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtcrtmp_to_rtc off;# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmprtc_to_rtmp off;}http_remux {enabled on;mount [vhost]/[app]/[stream].flv;}
}
整體功能概述
該配置文件實現了一個基礎的WebRTC流媒體服務,主要包含以下核心功能:
- RTMP協議支持(端口1935)
- HTTP文件服務(端口8080)
- HTTP API管理接口(端口1985)
- WebRTC服務(UDP端口8000)
- HTTP-FLV直播流輸出
核心配置項解析
- 基礎服務配置
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
listen 1935
:啟用RTMP協議監聽,用于接收傳統RTMP推流max_connections 1000
:限制最大客戶端連接數為1000daemon off
:不以守護進程方式運行,便于調試srs_log_tank console
:日志輸出到控制臺
- HTTP服務配置
http_server {enabled on;listen 8080;dir ./objs/nginx/html;
}
- 啟用HTTP文件服務,端口8080
- 靜態文件目錄指向
./objs/nginx/html
,可用于存放播放器頁面等靜態資源
- HTTP API配置
http_api {enabled on;listen 1985;
}
- 啟用HTTP管理API,端口1985
- 通過該API可以查詢服務器狀態、流信息等,支持RESTful風格
RESTful 不是 “強制標準”,而是一套讓 API 更簡潔、規范的設計風格,核心通過 “資源 URI + HTTP 方法” 定義接口,讓系統交互清晰、易維護。像你之前提到的 SRS 的 HTTP API,若遵循 RESTful 設計,就能用GET /api/streams查列表、POST /api/streams創建流,比自定義復雜參數的接口好理解得多~
HTTPAPI:
HTTP API 雖然不直接參與媒體流的傳輸(由 SFU 模塊負責),但它為 WebRTC 服務提供了 控制平面 的能力:
動態配置 WebRTC 參數:通過 HTTP API 修改 rtc_server 的配置(如端口、候選地址),無需重啟服務。
監控 WebRTC 連接質量:實時查看 WebRTC 客戶端的連接數、丟包率、帶寬使用情況。
管理 WebRTC 房間 / 會話:結合業務邏輯,通過 HTTP API 創建 / 銷毀 WebRTC 會話(如多人會議房間)
- WebRTC核心配置
rtc_server {enabled on;listen 8000; # UDP portcandidate $CANDIDATE;
}
enabled on
:啟用WebRTC服務listen 8000
:使用UDP端口8000進行WebRTC數據傳輸(UDP更適合低延遲實時通信)candidate $CANDIDATE
:配置ICE候選地址,$CANDIDATE
通常會在啟動時被替換為服務器的公網IP或域名,用于NAT穿透
- 虛擬主機配置
vhost __defaultVhost__ {rtc {enabled on;rtmp_to_rtc off;rtc_to_rtmp off;}http_remux {enabled on;mount [vhost]/[app]/[stream].flv;}
}
-
WebRTC相關配置:
rtc.enabled on
:在默認虛擬主機上啟用WebRTC功能rtmp_to_rtc off
:關閉RTMP到WebRTC的轉換(不將RTMP流轉換為WebRTC流)rtc_to_rtmp off
:關閉WebRTC到RTMP的轉換(不將WebRTC流轉換為RTMP流)
-
HTTP-FLV配置:
http_remux.enabled on
:啟用HTTP-FLV流輸出mount [vhost]/[app]/[stream].flv
:定義HTTP-FLV流的訪問路徑格式,例如:http://server:8080/live/stream.flv
3.2 信令服務器分析
SRS 中第三方庫的信令服務器是一個用 Go 語言開發的組件,位于 SRS 的3rdparty/signaling目錄下,默認監聽 1989 端口。它在 SRS 的 WebRTC 功能中扮演著重要角色,主要負責以下任務:
- 房間管理:處理與房間相關的操作,包括創建房間、加入房間、離開房間等。例如,當用戶想要加入一個特定的視頻通話房間時,信令服務器會對該請求進行處理,確保用戶能夠正確地加入到指定房間。
- 用戶信息管理:負責管理參與 WebRTC 會話的用戶信息,如用戶的昵稱、狀態等。它可以跟蹤房間內的用戶列表,當有新用戶加入或現有用戶離開時,及時更新相關信息并通知其他用戶。
- 信令交互:作為客戶端之間信令消息的中轉站,處理 WebRTC 客戶端之間的信令交互,包括協商媒體能力、交換會話描述協議(SDP)信息、處理 ICE(Interactive Connectivity Establishment)候選等。比如,在多人視頻通話中,信令服務器會將一個用戶的媒體流信息轉發給其他用戶,使得各方能夠建立起正確的媒體連接。
cd ~/git/srs/trunk/3rdparty/signaling && make && ./objs/signaling
3.3 http-static
#運行命令
cd ~/git/srs/trunk/3rdparty/httpx-static && make &&
./objs/httpx-static -http 80 -https 443 -ssk server.key -ssc server.crt \-proxy http://127.0.0.1:1989/sig -proxy http://127.0.0.1:1985/rtc \-proxy http://127.0.0.1:8080/
httpx-static 是一個基于 C++ 開發的高性能 HTTP/HTTPS 反向代理服務器,主要用于將客戶端的 HTTP/HTTPS 請求轉發到后端的多個目標服務(如 API 接口、其他服務器等)
一、按請求類型拆分:HTTP vs WebSocket
httpx-static
同時支持 HTTP 請求 和 WebSocket 請求 的轉發,對應不同的業務場景:
1. HTTP 請求轉發(常規接口、靜態文件)
-
請求示例:
/rtc/v1/publish/
→ 轉發到srs 1985 http api
/console/ng_index.html
→ 轉發到srs 1985 控制臺
/players/srs_player.html
→ 轉發到srs 8080 播放器
-
作用:
- 靜態文件托管:像
srs_player.html
這類播放器頁面,通過httpx-static
直接代理到 SRS 的靜態文件服務器(8080 端口),客戶端訪問http://your-domain/players/srs_player.html
就能加載頁面。 - API 調用:
/rtc/v1/publish
是 SRS 的 HTTP API(1985 端口),用于觸發流發布邏輯(如推流到 SRS)。 - 控制臺訪問:
/console/ng_index.html
是 SRS 的 Web 管理界面,通過代理統一入口,方便運維人員訪問。
- 靜態文件托管:像
2. WebSocket 請求轉發(信令交互)
-
請求示例:
/sig/v1/rtc
→ 轉發到signal1989 信令服務器
(WebSocket 協議)
-
作用:
WebRTC 信令交互(如房間創建、SDP 交換、ICE 候選協商)依賴 WebSocket 長連接,httpx-static
作為代理,將客戶端的 WebSocket 請求(ws://your-domain/sig/v1/rtc
)轉發到信令服務器(1989 端口),確保實時信令能穩定傳輸。
二、路由邏輯:“流量分發規則”
httpx-static
通過 路徑匹配 決定請求轉發到哪個后端:
請求路徑 | 協議 | 轉發目標 | 作用 |
---|---|---|---|
/rtc/v1/publish/ | HTTP | srs 1985 http api | 調用 SRS 的流發布 API |
/console/ng_index.html | HTTP | srs 1985 控制臺 | 訪問 SRS 管理界面 |
/players/srs_player.html | HTTP | srs 8080 播放器 | 加載 SRS 播放器靜態頁面 |
/sig/v1/rtc | WebSocket | signal1989 信令服務器 | WebRTC 信令交互(房間、流協商) |
三、業務價值:為什么需要這個“中樞”?
1. 統一入口,簡化客戶端配置
- 客戶端只需記住
httpx-static
的地址(如http://your-domain
),無需關心后端多個服務的具體端口(1985、8080、1989 等)。 - 示例:
- 播放器頁面地址統一為
http://your-domain/players/srs_player.html
,無需拼接:8080
端口。 - 信令連接地址統一為
ws://your-domain/sig/v1/rtc
,無需關心信令服務器的 1989 端口。
- 播放器頁面地址統一為
2. 協議轉換與兼容
httpx-static
可以將 外部 HTTPS 請求 轉換為內部 HTTP 請求,反之亦然。- 示例:
- 客戶端用
https://your-domain
訪問(更安全),httpx-static
內部轉發到 SRS 的 HTTP 服務(1985、8080 等),無需后端服務單獨配置 HTTPS。
- 客戶端用
3. 隱藏后端細節,提升安全性
- 后端服務(如信令服務器 1989 端口)無需暴露到公網,只需在內部網絡與
httpx-static
通信。 - 減少公網暴露的端口數量,降低被攻擊的風險(如 1989 端口不直接對外,僅通過
httpx-static
代理)。
4. 支持復雜業務流程
- 比如 WebRTC 推流流程:
- 客戶端通過 HTTP 請求
/rtc/v1/publish
告訴 SRS “我要推流”。 - 通過 WebSocket 連接
/sig/v1/rtc
與信令服務器協商推流參數。 - 最終音視頻流通過 SRS 的 SFU 模塊傳輸,但所有“控制面”請求都由
httpx-static
統一路由。
- 客戶端通過 HTTP 請求
四、類比理解:把 httpx-static
當“小區門衛”
- 客戶端 = 小區居民,想訪問小區內的不同設施(健身房、物業、快遞柜)。
httpx-static
= 小區門衛,負責登記居民需求,然后幫居民把請求轉發到對應的設施:- 居民說“我要去健身房” → 門衛指引到健身房(轉發到
srs 8080 播放器
)。 - 居民說“我要找物業開證明” → 門衛指引到物業辦公室(轉發到
srs 1985 控制臺
)。 - 居民說“我要收發快遞” → 門衛指引到快遞柜(轉發到
signal1989 信令服務器
)。
- 居民說“我要去健身房” → 門衛指引到健身房(轉發到
這樣,居民(客戶端)無需記住每個設施的具體位置(端口),只需找門衛(httpx-static
)即可~
3.4 交互流程
以下結合 httpx-static
代理、SRS(SFU)、信令服務器 與這張前端交互流程圖,完整拆解 “用戶 → 前端 → 后端服務” 的交互邏輯,理解從“進入網頁”到“音視頻互通”的全流程:
一、核心角色回顧
-
前端側:
one2one.html
:前端頁面(用戶入口)。srs.sig.js
:信令交互工具庫(處理 WebSocket 連接、收發信令)。srs.sdk.js
:WebRTC 工具庫(處理音視頻采集、發布、訂閱)。
-
后端側:
httpx-static
:反向代理(統一入口,轉發 HTTP/WebSocket 請求)。- SRS(SFU):流媒體服務器(處理音視頻流的發布、訂閱、轉發)。
- 信令服務器:處理房間管理、SDP 協商、ICE 候選交換等信令邏輯。
二、流程拆解(從“用戶進入網頁”到“音視頻互通”)
1. 初始化階段:前端加載與配置
- 用戶操作:用戶 1 訪問
one2one.html
頁面(進入網頁)。 - 前端邏輯:
one2one.html
加載后,調用srs.sig.js
的SrsRtcSignalingParse
方法,解析配置:- 返回
wsHost
(WebSocket 信令地址,如ws://your-domain/sig/v1/rtc
,實際由httpx-static
代理)。 - 返回
room
(房間 ID,如1234
)、display
(用戶標識,如user1
)等參數。
- 返回
2. 信令連接階段:建立 WebSocket 通道
- 前端邏輯:
- 調用
srs.sig.js
的SrsRtcSignalingAsync
方法,基于wsHost
創建 WebSocket 連接:- 返回
sig
對象(封裝了 WebSocket 收發信令的能力)。
- 返回
- 通過
sig.connect()
發起 WebSocket 連接,請求到達httpx-static
。
- 調用
httpx-static
轉發:- 識別路徑
/sig/v1/rtc
,將 WebSocket 請求轉發到 信令服務器(如signal1989
)。
- 識別路徑
- 信令服務器邏輯:
- 接受連接,為用戶 1 分配信令通道,等待后續消息。
3. 加入房間階段:信令交互(join
)
- 前端邏輯:
- 通過
sig.send({ action: 'join', room: '1234', display: 'user1' })
發送join
信令。 - 信令內容:告知信令服務器“用戶 1 要加入房間 1234”。
- 通過
- 信令服務器邏輯:
- 檢查房間
1234
是否存在,若不存在則創建。 - 記錄用戶 1 為房間成員,返回房間信息(如現有成員、流列表)。
- 若有其他用戶(如用戶 2)已在房間,信令服務器會向用戶 2 推送“新成員加入”事件。
- 檢查房間
4. 發布流階段:采集并推送音視頻(publish
)
- 前端邏輯:
- 調用
srs.sdk.js
的new SrsRtcPublisherAsync()
方法,初始化發布器:- 請求瀏覽器權限(攝像頭、麥克風),采集音視頻流。
- 返回
Publisher
對象(封裝了發布流的能力)。
- 通過
Publisher.publish()
發起流發布:- 生成 WebRTC 的 SDP(媒體能力描述),并通過
sig.send({ action: 'publish', sdp: '...' })
發送給信令服務器。
- 生成 WebRTC 的 SDP(媒體能力描述),并通過
- 調用
- 信令服務器邏輯:
- 接收
publish
信令,解析 SDP 內容。 - 將 SDP 轉發給 SRS(SFU)(通過
httpx-static
代理的/rtc/v1/publish
接口)。
- 接收
- SRS(SFU)邏輯:
- 接收 SDP,創建流發布通道,返回 SRS 的 SDP 響應(包含 ICE 候選等網絡信息)。
- 信令服務器將 SRS 的響應回傳給前端
Publisher
。
5. 訂閱流階段:接收對方音視頻(用戶 2 同理)
- 用戶 2 流程:
用戶 2 重復 步驟 1-4,加入房間1234
并發布自己的流。 - 信令服務器通知:
當用戶 2 發布流后,信令服務器向用戶 1 推送“新流發布”事件(包含用戶 2 的流地址,如webrtc://your-domain/1234/user2
)。 - 前端訂閱邏輯:
- 用戶 1 的
srs.sdk.js
收到事件后,調用new SrsRtcSubscriberAsync()
初始化訂閱器。 - 通過訂閱器請求 SRS(SFU)拉取用戶 2 的流,建立 WebRTC 連接。
- 用戶 1 的
6. 音視頻互通階段:媒體流傳輸
- SRS(SFU)角色:
- 接收用戶 1 的流(通過 WebRTC 推流),并轉發給用戶 2。
- 接收用戶 2 的流(通過 WebRTC 推流),并轉發給用戶 1。
- 前端呈現:
- 用戶 1 和用戶 2 的瀏覽器通過
srs.sdk.js
渲染對方的音視頻流,實現“一對一通話”。
- 用戶 1 和用戶 2 的瀏覽器通過
三、關鍵交互鏈路總結
四、核心協同點
-
httpx-static
的“橋梁作用”:- 統一代理 HTTP(如
/rtc/v1/publish
)和 WebSocket(如/sig/v1/rtc
)請求,讓前端只需訪問一個域名,簡化配置。
- 統一代理 HTTP(如
-
信令服務器的“指揮作用”:
- 管理房間、用戶、流的狀態,協調 SRS 轉發媒體流,讓“誰該推流、誰該拉流”邏輯清晰。
-
SRS(SFU)的“管道作用”:
- 專注媒體流的轉發,不處理業務邏輯,確保音視頻傳輸低延遲、高性能。
-
前端 SDK 的“工具作用”:
srs.sig.js
封裝信令交互,srs.sdk.js
封裝 WebRTC 能力,讓前端開發者無需關注復雜的協議細節。
五、類比理解:把整個流程當“線上電話亭”
one2one.html
= 電話亭的“操作面板”(用戶輸入要撥打的號碼)。srs.sig.js
= 電話亭的“信號線路”(負責傳遞“撥號、接聽”等信令)。srs.sdk.js
= 電話亭的“話筒+聽筒”(負責采集、播放聲音/畫面)。httpx-static
= 電話局的“總機”(統一轉接所有通話請求)。- 信令服務器 = 電話局的“交換機”(決定“誰能接通誰、怎么接通”)。
- SRS(SFU) = 電話局的“傳輸線路”(負責把聲音/畫面從 A 傳到 B)。