Written by Winlin, 李鵬
在很多網(wǎng)絡(luò)條件下,WebRTC不適合使用UDP傳輸,因此支持TCP傳輸是極其重要的能力;而且SRS支持的是直接TCP傳輸?shù)姆绞?,避免使用TURN中轉(zhuǎn)帶來(lái)的額外網(wǎng)絡(luò)層問(wèn)題;這對(duì)于LoadBalancer也是非常友好的,一般支持TCP會(huì)更友好。
Why Important?
大約兩年前SRS支持了WebRTC,雖然支持了不少功能但還不夠完善,這兩年收到了很多反饋,其中常見(jiàn)的而且非常重要的有:
- 用不了UDP,可能是公司網(wǎng)絡(luò)封掉了UDP協(xié)議,或者封掉了小于10000的UDP端口,總之各種不可用的場(chǎng)景,SRS有個(gè)小工具檢測(cè)UDP端口可用性,請(qǐng)參考#2843。
- 媒體協(xié)議和端口太多了,TCP有RTMP(1935)和HTTP(80/443),UDP有WebRTC(8000)和SRT(10080),還有HTTP API端口(1985),如何讓協(xié)議端口更收斂?多開(kāi)一個(gè)端口就多一份麻煩。HTTP API和Stream使用同樣端口的問(wèn)題,請(qǐng)參考#2881。
- UDP可用但丟包比較嚴(yán)重,有可能是系統(tǒng)設(shè)置問(wèn)題,也有可能是網(wǎng)絡(luò)設(shè)備或環(huán)境導(dǎo)致丟包,往往TCP是沒(méi)問(wèn)題的,請(qǐng)參考#2852
如果SRS能像HTTP-FLV那樣,在HTTP(80)端口傳輸媒體數(shù)據(jù),那該多么簡(jiǎn)單?多么可靠??!只要能上網(wǎng),HTTP(80)端口就一定是可用的。流傳輸圖如下:
Publisher --------RTC------> SRS --------RTC--------> Player
(over TCP/80) (over TCP/80)
Note: 實(shí)際上WebRTC是有個(gè)API請(qǐng)求的,所以這里還省略了HTTP API請(qǐng)求,可以在同樣端口上傳輸HTTP API,HTTP Stream和WebRTC數(shù)據(jù)。
專(zhuān)業(yè)人士一般會(huì)說(shuō):這個(gè)問(wèn)題可以用TURN解決,流傳輸圖如下:
Publisher -----> TURN ----> SRS -----> TURN -----> Player
(over TURN/3478). (over TURN/3478)
TURN的方案明顯是不好的,有幾個(gè)問(wèn)題:
- 多引入了一個(gè)網(wǎng)元,需要額外考慮部署和依賴(lài)問(wèn)題,而且有些TURN可能還沒(méi)提供Docker。
- 多引入了一個(gè)協(xié)議,看起來(lái)簡(jiǎn)單的協(xié)議(幾個(gè)交互),如何監(jiān)控和排查問(wèn)題,如何運(yùn)維都是非常麻煩的。
- 延遲和成本問(wèn)題,多一跳就多一次延遲,多一份網(wǎng)元就多一個(gè)集群,這都是真金白銀的CPU消耗。
因此,WebRTC支持TCP傳輸,最好的方案是直接TCP傳輸而不是TURN協(xié)議,參考以下兩個(gè)RFC:
- SDP and ICE: TCP Candidates with Interactive Connectivity Establishment (ICE)
- RTP over TCP: Framing RTP and RTCP Packets over Connection-Oriented Transport
下面介紹下SRS目前的進(jìn)展。
What's Now?
SRS 5.0正式解決了這個(gè)問(wèn)題:
- HTTP API、HTTP Stream、WebRTC over TCP,可以全部復(fù)用一個(gè)TCP端口,比如HTTPS(443)。
- 支持直接UDP或TCP傳輸,不依賴(lài)TURN協(xié)議,沒(méi)有額外的網(wǎng)元,沒(méi)有額外部署和資源消耗。
- 可部署在LoadBalancer后面(已實(shí)現(xiàn)),可配合Proxy(未實(shí)現(xiàn))或者Cluster(未實(shí)現(xiàn))實(shí)現(xiàn)負(fù)載均衡和擴(kuò)容。
Note: 注意需要升級(jí)到
v5.0.60+,若使用Docker也請(qǐng)先確認(rèn)SRS的版本。
我們先看最簡(jiǎn)單情況,用一個(gè)TCP(8080)端口,支持RTC推拉流:
docker run --rm -it -p 8080:8080/tcp \
-e CANDIDATE="192.168.3.82" \
-e SRS_HTTP_API_LISTEN=8080 \
-e SRS_RTC_SERVER_TCP_ENABLED=on \
-e SRS_RTC_SERVER_TCP_LISTEN=8080 \
-e SRS_RTC_SERVER_PROTOCOL=tcp \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v5.0.60
- 推流(WebRTC over TCP): webrtc://localhost:8080/live/livestream
- 播放(WebRTC over TCP): webrtc://localhost:8080/live/livestream
一般需要支持直播,所以下面,只用一個(gè)TCP(8080)端口,支持RTC和直播:
docker run --rm -it -p 8080:8080/tcp \
-e CANDIDATE="192.168.3.82" \
-e SRS_VHOST_RTC_RTC_TO_RTMP=on \
-e SRS_HTTP_API_LISTEN=8080 \
-e SRS_RTC_SERVER_TCP_ENABLED=on \
-e SRS_RTC_SERVER_TCP_LISTEN=8080 \
-e SRS_RTC_SERVER_PROTOCOL=tcp \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v5.0.60
- 推流(WebRTC over TCP): webrtc://localhost:8080/live/livestream
- 播放(WebRTC over TCP): webrtc://localhost:8080/live/livestream
- 播放(HTTP FLV): http://localhost:8080/live/livestream.flv
- 播放(HLS): http://localhost:8080/live/livestream.m3u8
如果是非localhost推流,得使用HTTPS,所以可以默認(rèn)使用TCP(8088),啟動(dòng)命令如下:
docker run --rm -it -p 8088:8088/tcp \
-e CANDIDATE="192.168.3.82" \
-e SRS_VHOST_RTC_RTC_TO_RTMP=on \
-e SRS_HTTP_API_LISTEN=8080 \
-e SRS_HTTP_API_HTTPS_ENABLED=on \
-e SRS_HTTP_API_HTTPS_LISTEN=8088 \
-e SRS_HTTP_SERVER_HTTTPS_ENABLED=on \
-e SRS_RTC_SERVER_TCP_ENABLED=on \
-e SRS_RTC_SERVER_TCP_LISTEN=8088 \
-e SRS_RTC_SERVER_PROTOCOL=tcp \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v5.0.60
- 推流(WebRTC over TCP): webrtc://localhost:8088/live/livestream
- 播放(WebRTC over TCP): webrtc://localhost:8088/live/livestream
- 播放(HTTP FLV): https://localhost:8088/live/livestream.flv
- 播放(HLS): https://localhost:8088/live/livestream.m3u8
Note: 可以換成IP訪問(wèn)。注意由于是自簽名證書(shū),所以需要點(diǎn)擊下空白處,然后敲入字符串
thisisunsafe
上面是通過(guò)環(huán)境變量配置的SRS,如果你習(xí)慣配置文件,也是可以的,和WebRTC over TCP相關(guān)的詳細(xì)配置如下:
rtc_server {
# For WebRTC over TCP directly, not TURN, see https://github.com/ossrs/srs/issues/2852
# Some network does not support UDP, or not very well, so we use TCP like HTTP/80 port for firewall traversing.
tcp {
# Whether enable WebRTC over TCP.
# Overwrite by env SRS_RTC_SERVER_TCP_ENABLED
# Default: off
enabled off;
# The TCP listen port for WebRTC. Highly recommend is some normally used ports, such as TCP/80, TCP/443,
# TCP/8000, TCP/8080 etc. However SRS default to TCP/8000 corresponding to UDP/8000.
# Overwrite by env SRS_RTC_SERVER_TCP_LISTEN
# Default: 8000
listen 8000;
}
# The protocol for candidate to use, it can be:
# udp Generate UDP candidates. Note that UDP server is always enabled for WebRTC.
# tcp Generate TCP candidates. Fail if rtc_server.tcp(WebRTC over TCP) is disabled.
# all Generate UDP+TCP candidates. Ignore if rtc_server.tcp(WebRTC over TCP) is disabled.
# Note that if both are connected, we will use the first connected(DTLS done) one.
# Overwrite by env SRS_RTC_SERVER_PROTOCOL
# Default: udp
protocol udp;
}
我們上面演示的是和HTTP復(fù)用端口,使用獨(dú)立的TCP端口也是完全沒(méi)問(wèn)題的,具體可以自己嘗試了。
Future Plan
飯一口口吃,路一步步走,代碼一行行碼;SRS歡迎大家貢獻(xiàn)和參與,我們的深度開(kāi)發(fā)者社區(qū)人越來(lái)越多了,已經(jīng)達(dá)到了近50個(gè)深度定制SRS的開(kāi)發(fā)者。
如果你在2013年錯(cuò)過(guò)了給SRS貢獻(xiàn)RTMP,在2014年錯(cuò)過(guò)了貢獻(xiàn)Edge集群,在2015年錯(cuò)過(guò)了貢獻(xiàn)FLV,在2016年錯(cuò)過(guò)了貢獻(xiàn)DVR,在2017年錯(cuò)過(guò)了MP4和DASH,在2018年錯(cuò)過(guò)了貢獻(xiàn)Origin集群,在2019年錯(cuò)過(guò)了貢獻(xiàn)Docker化和云原生,在2020年錯(cuò)過(guò)了SRT和WebRTC,在2021年錯(cuò)過(guò)了HLS集群,在2022年錯(cuò)過(guò)了新官網(wǎng)和SRT協(xié)程化。。。
今天,你又錯(cuò)過(guò)了貢獻(xiàn)WebRTC over TCP,我和李鵬(TOC)花了兩個(gè)下午搞定了;另外,也特別感謝夏立新(TOC)的預(yù)研,節(jié)省了我們不少時(shí)間。其實(shí)貢獻(xiàn)并不難,難的是克服自己的慣性啊。
縱然有一萬(wàn)個(gè)不貢獻(xiàn)的理由,對(duì)于程序員來(lái)說(shuō),有一個(gè)貢獻(xiàn)的理由就夠了:作為程序員,只白嫖開(kāi)源卻不曾貢獻(xiàn),和咸魚(yú)又有何分別?!
你打算在2022年尾巴上錯(cuò)過(guò)貢獻(xiàn)什么?還有4個(gè)月時(shí)間,我們就要凍結(jié)5.0的功能開(kāi)發(fā)了,趕緊加入我們吧,還有非常多有意思又有價(jià)值的功能,等著你來(lái)一起完成。