摘要:在本文中,我將先從協議開始,一步步帶領大家搭建一個簡易高性能的直播平臺。停止應用簡介俄羅斯人民開發的一款的流媒體插件,除了直播發布音視頻流之外具備流媒體服務器的常見功能在線直播。語法上下文描述使視頻流從一個關鍵幀開始。
前言來自 GitChat 作者:七夜
現在直播已經成為移動互聯網時代一個新的重要流量入口,從YY、斗魚到花椒直播,直播已經成為人們分享交流的新方式,應用場景眾多,主要分為:
金融類直播:金融直播可應用于實時解盤,在線專家講座,專家在線直播技術分析、指導投資者等使用場景。
大型賽事,演唱會類直播:可應用于大型演唱會,音樂會,游戲,體育賽事等類直播場景。
互動類直播:娛樂類互動,如YY等。
會議類直播:大型會議直播。
等4大類。在本文中,我將先從rtmp協議開始,一步步帶領大家搭建一個簡易高性能的直播平臺。
RTMP協議詳解RTMP協議Real Time Message Protocol(實時信息傳輸協議)的首字母縮寫,是由Adobe公司開發的一種用于解決多媒體數據傳輸流多路復用和分包的網絡協議。它工作在TCP協議之上,因此是一種提供可靠交付的協議,在傳輸時不會出現丟包情況,從而保證了用戶體驗(QoE)。雖然TCP協議為了提供可靠交付付出了一些額外的開銷做為代價,占用了一些帶寬和處理器資源,但是隨著網絡帶寬的提高和硬件的發展,這些開銷會顯得越來越微不足道。因此RTMP協議在為了有很好的發展前景。
協議分類官方定義:
The Real-Time Messaging Protocol (RTMP) was designed for
high-performance transmission of audio, video, and data between Adobe
Flash Platform technologies, including Adobe Flash Player and Adobe
AIR. RTMP is now available as an open specification to create products
and technology that enable delivery of video, audio, and data in the
open AMF, SWF, FLV, and F4V formats compatible with Adobe Flash
Player.
RTMP協議工作在TCP之上,是應用層協議, 默認的端口是1935。
RTMPE在RTMP的基礎上增加了加密功能。
RTMPT工作在HTTP之上,默認端口是80或443,可穿透防火墻。
RTMPS類似RTMPT,增加了TLS/SSL的安全功能。
RTMFP為RTMP協議的UDP版本。
雖然協議變種有很多,但實際在我們的直播應用中最常見的是原生的RTMP協議,因此本篇文章以該協議的1.0版本為基礎,對其它演進協議感興趣的同學可以關注本文的后續知識。
交互流程RTMP的交互流程可以分為握手過程、控制命令傳輸與數據傳輸。
握手過程
RTMP 連接以握手開始,RTMP 握手由三個固定長度的塊組成。客戶端 (發起連接請求的終端) 和服務器端各自發送相同的三塊。便于演示,本文將從客戶端發送的這些塊指定為 C0、C1 和 C2;將從服務器端發送的這些塊分別指定為 S0、S1 和 S2。
RTMP握手以客戶端發送 C0 和 C1 塊開始,客戶端要等收到S1之后才能發送C2,客戶端要等收到S2之后才能發送其他信息(控制信息和真實音視頻等數據),服務端要等到收到C0之后發送S1, 服務端必須等到收到C1之后才能發送S2, 服務端必須等到收到C2之后才能發送其他信息(控制信息和真實音視頻等數據)。以下為RTMP握手的時序圖介紹。
流程圖中所提到的各種狀態如下:
狀態 | 描述 |
---|---|
未初始化 | 客戶端在C0中發送協議版本,如服務端支持,則回發送S0和S1,如果不能,則連接結束 |
版本發送 | 客戶端等待S1包,服務端等待C1包,當接收到想要的包,客戶端發送C2,服務端發送S2,此時階段變成了ACK的發送 |
ACK發送 | 客戶端和服務端分別等待S2和C2 |
握手完成 | 客戶端和服務交換消息 |
理論上來講只要滿足以上條件,如何安排6個Message的順序都是可以的。但在實際實現中為了盡量減少通信的次數,客戶端發送C0+C1,服務端發送S0+S1+S2,再客戶端在發送C2結束握手。
控制命令傳輸
握手結束以后,RTMP協議進入控制命令傳輸過程,客戶端通過發送connnect命令與服務器實現雙向連接。連接成功后,通過發送createStream命令建立網絡流。
數據傳輸
網絡流建立成功后,推流(將直播內容推送至服務器的過程)過程會發送publish命令發布音視頻內容,拉流(服務器已有直播內容,用指定地址進行拉取的過程)過程會發送play命令播放內容。
協議格式URI格式
rtmpt://127.0.0.1/{app}/{stream_name}
{app}為音頻/視頻和其他內容定義的一個容器。
{stream_name}為具體的一個流名稱。
消息(Message)格式
消息是RTMP協議中基本的數據單元,不能種類的消息包含有不能的消息類型(Message Type)。RTMP協議一共規范了十多種消息類型。其中類型為8,9的消息分別用于傳輸音頻和視頻數據。消息頭包含以下信息:
Message Type: 消息類型,占用1個字節。
Length: 有效負載的字節數,占用3個字節。該字段是用大字節序表示的。
Timestamp: 時間戳,占用4個字節,用大字節序表示。
Message Stream Id: 消息流ID,標識消息所使用的流,用大字節序表示。
消息塊格式
在網絡上傳輸數據時,消息需要被拆分成較小的數據塊才適合在相應的網絡環境上傳輸。RTMP協議中規范了對消息拆分成消息塊,每個消息塊首部(ChunkHeader)有三部分組成:用于標識本塊的ChunkBasicHeader,用于標識本塊負載所屬消息的ChunkMessageHeader,以及當時間戳溢出時才出現的ExtendedTimestamp。
消息分塊
RTMP傳輸媒體數據的過程中,發送端首先把媒體數據封裝成消息,然后把消息分割成消息塊,最后將分割后的消息塊通過TCP協議發送出去。接收端在通過TCP協議收到數據后,首先把消息塊重新組合成消息,然后通過對消息進行解封裝處理就可以恢復出媒體數據。
開源技術選型目前直播服務器有開源和商業兩種版本,商業版本主要又FMS(Flash Media Server)與Wowza。本文章僅針對開源版本做介紹,相應的開源項目主要分為Red5與 Nginx-Rtmp兩類:
Red5簡介
GitHub:https://github.com/Red5/red5-... (1k+ stars)
Red5是一個采用Java開發開源的Flash流媒體服務器。它支持:把音頻(MP3)和視頻(FLV)轉換成播放流; 錄制客戶端播放流(只支持FLV);共享對象;現場直播流發布;遠程調用。Red5使用RTMP, RTMPT, RTMPS, 和RTMPE作為流媒體傳輸協議,在其自帶的一些示例中演示了在線錄制,flash流媒體播放,在線聊天,視頻會議等一些基本功能。
官方給出的主要特性:
Red5 is an Open Source Flash Server written in Java that supports:
Streaming Video (FLV, F4V, MP4, 3GP)
Streaming Audio (MP3, F4A, M4A, AAC)
Recording Client Streams (FLV and AVC+AAC in FLV container)
Shared Objects
Live Stream Publishing
Remoting
Protocols: RTMP, RTMPT, RTMPS, and RTMPE
Additional features supported via plugin:
WebSocket (ws and wss)
RTSP (From Axis-type cameras)
HLS
安裝與簡單應用實例(Mac下安裝)
前置條件(jdk已安裝)。
創建安裝目錄:
mkdir -p /Users/ypzdw/gitchat/rtmp/red5
設置主目錄環境變量:
export RED5_HOME=/Users/ypzdw/gitchat/rtmp/red5
下載red5應用,并解壓到RED5_HOME:
https://github.com/Red5/red5-...
目錄簡介:由于 Red5 是在 Tomcat 中運行的,因此 Red5 項目與普通 JAVAEE 項目結構類似
conf:red5配置目錄
lib:存放的是一些依賴jar包
weapps:用來存放應用程序,與tomcat下的webapps目錄作用類似。
運行:
cd /Users/ypzdw/gitchat/rtmp/red5
./red5.sh &
簡單實例
經過前面的介紹,這里將用red5介紹一個簡單的實例。打開http://127.0.0.1:5080 出現red5 管理控制臺。
選擇"Publisher" demo,該項目提供了主播端與聽課端。
主播端:“1”中 Name表示流名,publish可以發布一個直播。
直播收聽端:“1”中Name為收聽的流名;“2”中 Location為直播端地址;“3”中Log可以觀察到整個直播的交流日志。
停止應用:
cd /Users/ypzdw/gitchat/rtmp/red5
./red5-shutdown.sh
Nginx-RtmpGithub:https://github.com/arut/nginx... (5k+ stars)
簡介
俄羅斯人民開發的一款NGINX的流媒體插件,除了直播發布音視頻流之外具備流媒體服務器的常見功能:
RTMP在線直播。
基于HTTP的FLV/MP4 VOD點播。
HLS (HTTP Live Streaming) M3U8的支持。
基于http的操作(發布、播放、錄制)。
可以很好的協同現有的流媒體服務器以及播放器一起工作。
在線調用ffmpeg對流媒體進行轉碼。
H264/AAC音視頻編碼格式的支持。
linux/BSD/MAC系統的支持。
官方承諾的功能:
RTMP/HLS/MPEG-DASH live streaming
RTMP Video on demand FLV/MP4, playing from local filesystem or HTTP
Stream relay support for distributed streaming: push & pull models
Recording streams in multiple FLVs
H264/AAC support
Online transcoding with FFmpeg
HTTP callbacks (publish/play/record/update etc)
Running external programs on certain events (exec)
HTTP control module for recording audio/video and dropping clients
Advanced buffering techniques to keep memory allocations at a minimum level for faster streaming and low memory footprint
Proved to work with Wirecast, FMS, Wowza, JWPlayer, FlowPlayer, StrobeMediaPlayback, ffmpeg, avconv, rtmpdump, flvstreamer and many more
Statistics in XML/XSL in machine- & human- readable form
Linux/FreeBSD/MacOS/Windows
常用指令與語法
Core
rtmp
語法:rtmp { ... }
上下文:nginx根上下文
描述:保存所有 RTMP 配置的塊
server
語法:server { ... }
上下文:rtmp
描述:聲明一個 RTMP 實例。
rtmp {
server {
}
}
listen
語法:listen (addr[:port]|port|unix:path)
上下文:server
描述:給 NGINX 添加一個監聽端口以接收 RTMP 連接。
server {
listen 1935;
}
application
語法:application name { ... }
上下文:server
描述:創建一個 RTMP 應用,application 名不支撐正則表達式。
server {
listen 1935; application myapp { }
}
timeout
語法:timeout value
上下文:rtmp, server
描述:Socket 超時。這個值主要用于寫數據時。
timeout 60s;
ping
語法:ping value
上下文:rtmp, server
描述:RTMP ping 間隔。零值的話將 ping 關掉。RTMP ping 是一個用于檢查活動連接的協議功能。發送一個特殊的包到遠程連接,然后在 ping_timeout 指令指定的時間內期待一個回復。如果在這個時間里沒有收到 ping 回復,連接斷開。ping 默認值為一分鐘。ping_timeout 默認值為 30 秒。
ping 3m;
ping_timeout 30s;
Access
allow
語法:allow [play|publish] address|subnet|all
上下文:rtmp, server, application
允許來自指定地址或者所有地址發布/播放。allow 和 deny 指令的先后順序可選。
allow publish 127.0.0.1;
deny publish all;
allow play 192.168.0.0/24;
deny play all;
deny
語法:deny [play|publish] address|subnet|all
上下文:rtmp, server, application
描述:參考 allow 的描述。
Exec
exec_push
語法:exec_push command arg*
上下文:rtmp, server, application
描述:定義每個流發布時要執行的帶有參數的外部命令。發布結束時進程終止。第一個參數是二進制可執行文件的完整路徑。執行外部命令時可以使用參數替換:
$name - 流的名字。
$app - 應用名。
$addr - 客戶端地址。
$flashver - 客戶端 flash 版本。
$swfurl - 客戶端 swf url。
$tcurl - 客戶端 tc url。
$pageurl - 客戶端頁面 url。也可以在 exec 指令中定義 Shell 格式的轉向符用于寫輸出和接收輸入。
exec_pull
與exec_push類似,主要工作在play端。
Live
live
語法:live on|off
上下文:rtmp, server, application
描述:切換直播模式,即一對多廣播。
live on;
meta
語法:meta on|off
上下文:rtmp, server, application
描述:切換發送元數據到客戶端。默認為 on。
meta off;
interleave
語法:interleave on|off
上下文:rtmp, server, application
描述:切換交叉模式。在這個模式下,音頻和視頻數據會在同一個 RTMP chunk 流中傳輸。默認為 off。
interleave on;
wait_key
語法:wait_key on|off
上下文:rtmp, server, application
描述:使視頻流從一個關鍵幀開始。默認為 off。
wait_key on;
wait_video
語法:wait_video on|off
上下文:rtmp, server, application
描述:在第一個視頻幀發送之前禁用音頻。默認為 off。可以和 wait_key 進行組合以使客戶端可以收到具有所有其他數據的視頻關鍵幀。然而這通常增加連接延遲。您可以通過在編碼器中調整關鍵幀間隔來減少延遲。
wait_video on;
publish_notify
語法:publish_notify on|off
上下文:rtmp, server, application
描述:發送 NetStream.Publish.Start 和 NetStream.Publish.Stop 給用戶。默認為 off。
publish_notify on;
drop_idle_publisher
語法:drop_idle_publisher timeout
上下文:rtmp, server, application
描述:終止指定時間內閑置(沒有音頻/視頻數據)的發布連接。默認為 off。注意這個僅僅對于發布模式的連接起作用(發送 publish 命令之后)。
drop_idle_publisher 10s;
sync
語法:sync timeout
上下文:rtmp, server, application
描述:同步音頻和視頻流。如果用戶帶寬不足以接收發布率,服務器會丟棄一些幀。這將導致同步問題。當時間戳差超過 sync 指定的值,將會發送一個絕對幀來解決這個問題。默認為 300 ms。
sync 10ms;
play_restart
語法:play_restart on|off
上下文:rtmp, server, application
描述:使 nginx-rtmp 能夠在發布啟動或停止時發送 NetStream.Play.Start 和 NetStream.Play.Stop 到每個用戶。如果關閉的話,那么每個用戶就只能在回放的開始和結束時收到這些通知了。默認為 on。
play_restart off;
Record
record
語法:record [off|all|audio|video|keyframes|manual]*
上下文:rtmp, server, application, recorder
描述:切換錄制模式。流可以被記錄到 flv 文件。本指令指定應該被記錄的:
off - 什么也不錄制
all - 音頻和視頻(所有)
audio - 音頻
video - 視頻
keyframes - 只錄制關鍵視頻幀
manual - 用不自動啟動錄制,使用控制接口來啟動/停止
在單個記錄指令中可以有任何兼容的組合鍵。
record all;
record_path
語法:record_path path
上下文:rtmp, server, application, recorder
描述:指定錄制的 flv 文件存放目錄。
record_path /tmp/rec;
record_suffix
語法:record_suffix value
上下文:rtmp, server, application, recorder
描述:設置錄制文件后綴名。默認為 ".flv"。
record_suffix _recorded.flv;
錄制后綴可以匹配 strftime 格式。以下指令
record_suffix -%d-%b-%y-%T.flv
將會產生形如 mystream-24-Apr-13-18:23:38.flv 的文件。所有支持 strftime 格式的選項可以在 strftime man page 里進行查找
record_append
語法:record_append on|off
上下文:rtmp, server, application, recorder
描述:切換文件附加模式。當這一指令為開啟是,錄制時將把新數據附加到老文件,如果老文件丟失的話將重新創建一個。文件中的老數據和新數據沒有時間差。默認為 off。
record_append on;
Relay
pull
語法:pull url [key=value]*
上下文:application
描述:創建 pull 中繼。流將從遠程服務器上拉下來,成為本地可用的。僅當至少有一個播放器正在播放本地流時發生。
Url 語法:[rtmp://]host:port]。如果 application 找不著那么將會使用本地 application 名。如果找不著 playpath 那么就是用當前流的名字。
支持以下參數:
app:明確 application 名。
name:捆綁到 relay 的本地流名字。如果為空或者沒有定義,那么將會使用 application 中的所有本地流。
tcUrl:如果為空的話自動構建。
pageUrl:模擬頁面 url。
swfUrl:模擬 swf url。
flashVer:模擬 flash 版本,默認為 "LNX.11,1,102,55"。
playPath:遠程播放地址。
live:切換直播特殊行為,值:0,1。
start:開始時間。
stop:結束時間。
static:創建靜態 pull,這樣的 pull 在 nginx 啟動時創建。
如果某參數的值包含空格,那么你應該在整個 key=value 對周圍使用引號,比如:"pageUrl=FAKE PAGE URL"。
pullrtmp://cdn2.example.com/another/a?b=1&c=d pageUrl=http://www.example.com/video.html swfUrl=http://www.example.com/player.swf live=1;
push
語法:push url [key=value]*
上下文:application
描述:push 的語法和 pull 一樣。不同于 pull 指令的是 push 推送發布流到遠程服務器。
push_reconnect
語法:push_reconnect time
上下文:rtmp, server, application
描述:在斷開連接后,在 push 重新連接前等待的時間。默認為 3 秒。
push_reconnect 1s;
session_relay
語法:session_relay on|off
上下文:rtmp, server, application
描述:切換會話 relay 模式。在這種模式下連接關閉時 relay 銷毀。當設置為 off 時,流關閉,relay 銷毀,這樣子以后另一個 relay 可以被創建。默認為 off。
session_relay on;
Notify
on_connect
語法:on_connect url
上下文:rtmp, server
描述:設置 HTTP 連接回調。當客戶分發連接命令一個連接命令時,一個 HTTP 請求異步發送,命令處理將被暫停,直到它返回結果代碼。當 HTTP 2XX 碼(成功狀態碼)返回時,RTMP 會話繼續。返回碼 3XX (重定向狀態碼)會使 RTMP 重定向到另一個從 HTTP 返回頭里獲取到的 application。否則(其他狀態碼)連接丟棄。
注意這一指令在 application 域是不允許的,因為 application 在連接階段還是未知的。
HTTP 請求接收到一些參數。在 application/x-www-form-urlencoded MIME 類型下使用 POST 方法。以下參數將被傳給調用者:
call=connect。
addr - 客戶端 IP 地址。
app - application 名。
flashVer - 客戶端 flash 版本。
swfUrl - 客戶端 swf url。
tcUrl - tcUrl。
pageUrl - 客戶端頁面 url。
除了上述參數以外,所有顯式傳遞給連接命令的參數也由回調發送。你應該將連接參數和 play/publish 參數區分開。播放器常常有獨特的方式設置連接字符串不同于 play/publish 流名字。
on_play
語法:on_play url
上下文:rtmp, server, application
描述:設置 HTTP 播放回調。每次一個客戶分發播放命令時,一個 HTTP 請求異步發送,命令處理會掛起 - 直到它返回結果碼。之后再解析 HTTP 結果碼。
HTTP 2XX 返回碼的話繼續 RTMP 會話。
HTTP 3XX 返回碼的話 重定向 RTMP 到另一個流,這個流的名字在 HTTP 返回頭的 Location 獲取。
HTTP 請求接收到一些個參數。在 application/x-www-form-urlencoded MIME 類型下使用 POST 方法。以下參數會被傳送給調用者:
call=play。
addr - 客戶端 IP 地址。
app - application 名。
flashVer - 客戶端 flash 版本。
swfUrl - 客戶端 swf url。
tcUrl - tcUrl。
pageUrl - 客戶端頁面 url。
name - 流名。
on_publish
語法:on_publish url
上下文:rtmp, server, application
描述:同上面提到的 on_play 一樣,唯一的不同點在于這個指令在發布命令設置回調。不同于遠程 pull,push 在這里是可以的。
on_done
語法:on_done url
上下文:rtmp, server, application
描述:設置播放/發布禁止回調。上述所有適用于此。但這個回調并不檢查 HTTP 狀態碼。
on_play_done
語法:on_publish_done url
上下文:rtmp, server, application
描述:等同于 on_done 的表現,但只適用于播放結束事件。
on_publish_done
語法:on_publish_done url
上下文:rtmp, server, application
描述:等同于 on_done 的表現,但只適用于發布結束事件。
on_record_done
語法:on_record_done url
上下文:rtmp, server, application, recorder
描述:設置 record_done 回調。除了普通 HTTP 回調參數它接受錄制文件路徑。
on_record_done http://example.com/recorded;
on_update
語法:on_update url
上下文:rtmp, server, application
描述:設置 update 回調。這個回調會在 notify_update_timeout 期間調用。如果一個請求返回結果不是 2XX,連接禁止。這可以用來同步過期的會話。追加 time 參數即播放/發布調用后的秒數會被發送給處理程序。
on_update http://example.com/update;
notify_update_timeout
語法:notify_update_timeout timeout
上下文:rtmp, server, application
描述:在 on_update 回調之間的超時設置。默認為 30 秒。
notify_update_timeout 10s;
on_update http://example.com/update;
notify_update_strict
語法:notify_update_strict on|off
上下文:rtmp, server, application
描述:切換 on_update 回調嚴格模式。默認為 off。當設置為 on 時,所有連接錯誤,超時以及 HTTP 解析錯誤和空返回會被視為更新失敗并導致連接終止。當設置為 off 時只有 HTTP 返回碼不同于 2XX 時導致失敗。
notify_update_strict on;
on_update http://example.com/update;
notify_relay_redirect
語法:notify_relay_redirect on|off
上下文:rtmp, server, application
描述:使本地流可以重定向為 on_play 和 on_publish 遠程重定向。新的流名字是 RTMP URL 用于遠程重定向。默認為 off。
notify_relay_redirect on;
notify_method
語法:notify_method get|post
上下文:rtmp, server, application, recorder
描述:設置 HTTP 方法通知。默認是帶有 application/x-www-form-urlencoded 的 POST 內容類型。在一些情況下 GET 更好,例如如果你打算在 nginx 的 http{} 部分處理調用。在這種情況下你可以使用 arg_* 變量去訪問參數。
notify_method get;
Statistics
statistics 模塊不同于本文列舉的其他模塊,它是 NGINX HTTP 模塊。因此 statistics 指令應該位于 http{} 塊內部。
rtmp_stat
語法:rtmp_stat all
上下文:http, server, location
描述:為當前 HTTP location 設置 RTMP statistics 處理程序。RTMP statistics 是一個靜態的 XML 文檔。可以使用 rtmp_stat_stylesheet 指令在瀏覽器中作為 XHTML 頁面查看這個文檔。
http { server { location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { root /path/to/stat/xsl/file; } }
}
rtmp_stat_stylesheet
語法:rtmp_stat_stylesheet path
上下文:http, server, location
描述:添加 XML 樣式表引用到 statistics XML 使其可以在瀏覽器中可視。
測試我所在的公司的直播業務中,前期也是采用red5,但是隨著用戶數的不斷增長,red5完全不能支撐整個業務。問題集中爆發在幾個方面:
對于單主播,聽者超過400人時,CPU超過90%(主機為4核,32G)。
人數越多,音質,畫面卡頓很多,不穩定,用戶體驗很差。于是我們決定對red5進行替換,對各種選型進行了調研,并在red5相同環境下做了測試,發現nginx-rtmp的性能非常突出,最終選用nginx-rtmp替換Red5,到目前為止,已經無故障運行近一年。附nginx-rtmp測試數據:
Server | CPU | 內存 | 連接數 | 帶寬 | 延遲 |
---|---|---|---|---|---|
nginx-rtmp | 8.3% | 13MB | 500 | 100Mbps | 0.8秒 |
nginx-rtmp | 27.3% | 19MB | 1000 | 200Mbps | 0.8秒 |
nginx-rtmp | 50.2% | 37MB | 2500 | 500Mbps | 0.8秒 |
nginx-rtmp | 70.2% | 61MB | 4000 | 650Mbps | 0.8秒 |
從測試結果可以得知,nginx-rtmp模塊運行穩定,單CPU4000人時負載只有70%,已經接近網卡流量的極限,比Red5 在性能上高一個數量級。
快速實現一個直播平臺 實戰前準備硬件
阿里云ECS: CPU:2核心,內存:8G,硬盤:40G
操作系統
CentOS 7.2 x86_64 Linux
配置服務器
超過1024的連接數測試需要打開linux的限制。且必須以root登錄和執行
設置連接數:ulimit -HSn 10240
查看連接數:
域名
非必須,如沒有,可以直接使用ip也可以。但是正式環境中為了減少收聽端對ip地址的依賴性,一般會使用域名而非ip地址來連接直播服務器。本文使用域名為datahq.cn.
申請域名:國內可以選擇萬網或新網;國外的name.com和godaddy.com口碑不錯。
域名備案:國外的服務器和網站在上線前都需要經過工信部備案和公安部備案;如果在阿里云上購買ECS可以直接使用其的免費備案服務。
建立直播子域名:
客戶端
為方便測試,本文使用Red5 作為直播的客戶端
直播端
目前最好用的直播端軟件是OBS(Open Broadcaster Software)。下載地址是:
https://obsproject.com/download
快速設置:
視頻的清晰度與碼率和品質有關,碼率大,品質高,那么視頻的清晰度就高,同時,對帶寬的要求也越大。詳細的參數設定參考如下:
在來源中新增“視頻捕捉設備”,并設置分辨率,您可以從分辨率選擇最接近的一項。本例分辨率為1280x720,如下圖所示
通過“設置”->“視頻”中設置壓縮分辨率,您可以從壓縮分辨率選擇與自己期望最接近的一項。本例期望分辨率為960x540,如下圖所示
直播推流設置,打開“設置”->"流",URL輸入推流地址的URL,流名稱輸入推流的名稱,如下圖所示
實戰架構方案
目前,我們線上的直播架構為:
支撐線上峰值近10萬人,并無故障運行一年有余。
配置中心會定期刷新直播端與收聽端APP的路由信息。
直播端APP推流到Master集群。
由于nginx-rtmp本身不支持集群,因此我們在架構時沒有采用從Master集群Forward推流到Slave集群的方式,而是設計了當收聽端拉流到slave服務器集群時,如果不存在該流,就會從Master集群主動拉取流的架構,解決了直播集群的大規模并發問題。
該架構在大規模并發情況下,比Master推流到Slave流的架構節省了很大的帶寬。
除此之外我們對nginx-rtmp進行了源代碼的修改,支撐了一些如合成,轉碼,高級錄制等功能。
本文為了各位同學能夠更快的掌握如何搭建的過程,因此沒有采用以上的架構,相信通過下面的實踐,各位也能夠搭建相應的架構。
架構圖中黃色標識了我們要使用的直播server。
編譯與部署
創建源碼存儲目錄:mkdir -p /root/rtmp/src。
進入源碼目錄:
cd /root/rtmp/src
下載nginx源碼并解壓,注意nginx-rtmp對nginx版本的選擇限制較多,在選擇時為了少踩不需要的坑,建議根據官方提示選擇對應的nginx 版本,如圖本文選擇nginx-1.11.5:
wget http://nginx.org/download/ngi...
tar -zxvf nginx-1.11.5.tar.gz
下載nginx-rtmp模塊源碼:
wget https://github.com/arut/nginx...
tar -zxvf v1.1.10.tar.gz
編譯nginx,如果需要調試消息則打開--with-debug:
./configure --add-module=/root/rtmp/src/nginx-rtmp-module-1.1.10 --with-debug
make
make install
默認編譯到路徑:
/usr/local/nginx
驗證編譯是否成功:
創建錄制文件存儲目錄:
mkdir -p /usr/local/nginx/files
rtmp 模塊配置(nginx.conf):
本文所采用的配置如下
user root;//使用root用戶運行nginx worker_processes 1;//指明了nginx要開啟的進程數,一般等于cpu的總核數,如果沒有出現io性能問題,最好不要修改 error_log logs/error.log debug;//錯誤日志存放路徑;日志級別為debug,調試用。 events { worker_connections 1024;//每個工作進程的最大連接數量; } http { include mime.types;//設定mime類型,類型由mime.type文件定義 default_type application/octet-stream; client_max_body_size 3m;//設定通過nginx上傳文件的大小 log_format main "$remote_addr - $remote_user [$time_local] "$request" " "$status $body_bytes_sent "$http_referer" " ""$http_user_agent" "$http_x_forwarded_for"";//日志格式設置 access_log logs/access.log main;//訪問日志存儲路徑 sendfile on;//指定 nginx 是否調用sendfile 函數(zero copy 方式)來輸出文件 keepalive_timeout 65;//keepalive超時時間 server {//配置虛擬機 listen 8080;//監聽端口 server_name rtmp.datahq.cn 59.110.237.245;//名稱 location /stat{//配置統計頁面路徑 rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl{//統計模板路徑 root /usr/local/nginx/conf; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } rtmp{ server{ listen 0.0.0.0:1935;//監聽端口 ping 30s;//活動連接檢查周期 application live{//應用名 live on;//打開直播模式 meta copy; //是否發送直播端元數據信息 session_relay on;//打開會話轉發模式 drop_idle_publisher 10s;//10s沒有推流,自動斷開直播端 sync 10ms;//同步流時間閥值 record_append on;//打開直播流錄制追加模式 record_path /usr/local/nginx/files;//錄制文件地址 record all;//打開錄制功能 } } }
拷貝統計模板到ngin配置目錄:
cp /root/rtmp/src/nginx-rtmp-module-1.1.10/stat.xsl /usr/local/nginx/conf/
啟動直播服務器:
cd /usr/local/nginx/sbin && ./nginx
打開統計頁面控制臺:
http://rtmp.datahq.cn:8080/stat
統計表各屬性說明為:
clients:連接數
live streams:流名
codec:編碼
bits:分辨率
size:視頻畫面大小
fps:每秒傳輸幀數
freq:音頻率
chan:音頻聲道
State:流狀態
Time:流活動時間
其它4個為輸入與輸出流的每秒傳輸速率。
測試直播
打開OBS,推流至rtmp://rtmp.datahq.cn/live,流名為demo
打開red5,從rtmp://rtmp.datahq.cn/live拉取直播流,流名為demo
打開直播統計后臺:如果看到已經有一個推流,一個拉流,并有數據傳輸時,說明整個直播鏈路已經暢通。
查看直播錄制文件:
此時看下系統的負載:可以發現CPU,內存的負載都很低,可以忽略不計。
上線
到本節為止,一個簡單的直播平臺就搭建好了,接下來我們要做的就是上線,因為沒有上線,一切都是零。下面是我們在上線過程中遇到的一些坑,供各位同學參考:
系統打開文件數默認太低,造成部分用戶連接不上。
遇到活動高峰,網絡帶寬成為瓶頸,造成收聽用戶卡頓很多。在生產環境中需要時刻關注是否升級帶寬。
上線盡量選擇在沒有直播的時候進行。
總結今天給大家分享了直播平臺搭建的一些知識,涉及到了rtmp協議,直播選型的一些注意點,大規模直播架構,nginx-rtmp直播服務器實戰搭建等。如果各位有直播的需要,可以順著本文的一些知識點進行實戰。
第一次寫Chat,不知道效果如何,如果大家有興趣,我們在后續推出nginx模塊開發與nginx-rtmp的分享,感謝大家的參與。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11786.html
摘要:來自作者鍋蜀黍背景本文主要根據作者個月以來對于人的零基礎教學經驗總結而出,適合零基礎負基礎學習編程語言的同學閱讀。學生黨和工作黨的比例是。基礎幾乎都沒有。顯然這兩個人的學習方式勢必是不一樣的。而不是媽的如何又報錯了。 來自 GitChat 作者:鍋蜀黍 背景 本文主要根據作者2個月以來對于 300 人的零基礎python教學經驗總結而出,適合零基礎、負基礎學習 python 編程語言...
閱讀 1166·2021-11-22 15:22
閱讀 3837·2021-10-19 13:13
閱讀 3570·2021-10-08 10:05
閱讀 3292·2021-09-26 10:20
閱讀 2984·2019-08-29 14:21
閱讀 2192·2019-08-27 10:55
閱讀 1871·2019-08-26 10:31
閱讀 2578·2019-08-23 16:47