[時間:2018-04] [狀態:Open]
[關鍵詞:流媒體,stream,HLS, ffmpeg,live,直播,點播, nginx, ssegment]
0 引言
本文作為HLS綜述的后續文章。
主要目的是使用ffmpeg搭建一個簡單的HLS點播及直播系統。使用nginx作為HTTP服務器。
HLS不管點播還是直播,都是基於HTTP的文件分發系統,所以本文的基本思路是:
- 使用nginx搭建HTTP服務器
- 使用ffmpeg實現ts文件的分片,並生成m3u8
- ffmpeg使用本地文件模擬HLS直播
- 支持多碼率HLS生成
1 基於nginx的網絡服務器搭建
伴隨着大數據、雲計算與雲服務的興起,nginx作為一款輕量級、高性能的web服務器,得到廣泛的應用,其特點是占用內存小、並發能力強。目前國內的BAT基本上都在使用nginx。(如果你對nginx一無所知,不妨找找資料簡單了解下)
言歸正傳,這里我們要是會用nginx搭建web服務器。先說明下我的系統環境:Ubuntu 15.04 (帶有各種開發環境)
1.1 安裝nginx
之前諸多網絡資料中介紹的nginx安裝都是從源碼編譯而來,但從目前的nginx開源環境來看,如果不修改相關代碼,可以直接下載[nginx官網]((http://nginx.org)所提供的編譯后的可執行文件。(如果你想從源碼編譯nginx,官網也有提供對應的文檔)
我這里安裝nginx比較簡單,直接通過apt-get安裝,命令如下:
sudo apt-get install nginx
就跟ubuntu上正常安裝一個軟件一樣。
安裝之后的nginx版本如下:
獲取:2 http://mirrors.ustc.edu.cn/ubuntu/ precise-updates/universe nginx-common all 1.1.19-1ubuntu0.8 [17.1 kB]
獲取:3 http://mirrors.ustc.edu.cn/ubuntu/ precise-updates/universe nginx-full amd64 1.1.19-1ubuntu0.8 [379 kB]
獲取:4 http://mirrors.ustc.edu.cn/ubuntu/ precise-updates/universe nginx all 1.1.19-1ubuntu0.8 [5,812 B]
1.2 nginx啟動及關閉
啟動nginx很簡單,直接使用以下命令即可:(nginx安裝之后運行,需要權限較高,簡單期間這里直接使用管理員啟動,實際使用不建議這么做)
sudo nginx
啟動之后你就可以通過ps aux | grep nginx
檢索到,我的主機上輸出結果如下:
$ ps aux | grep nginx
root 14443 0.0 0.0 100240 3012 ? Ss 14:49 0:00 nginx: master process nginx
www-data 14444 0.0 0.0 100544 3780 ? S 14:49 0:00 nginx: worker process
www-data 14445 0.0 0.0 100544 3780 ? S 14:49 0:00 nginx: worker process
www-data 14446 0.0 0.0 100544 3780 ? S 14:49 0:00 nginx: worker process
www-data 14447 0.0 0.0 100544 3780 ? S 14:49 0:00 nginx: worker process
nginx啟動成功之后,可以在瀏覽器中輸入本機IP,就可以看到"Welcome to nginx!"的頁面顯示。
nginx退出可以使用nginx -s stop
(強制退出,相當於直接殺進程)或nginx -s quit
(優雅關閉,推薦使用)。
在修改nginx配置文件之后,可以通過nginx -s reload
重新加載配置,無需重啟。
1.3 配置nginx以支持html文件發布
nginx配置文件位於/etc/nginx
目錄下,日志文件位於/var/log/nginx
下。下面是nginx配置文件的目錄構成:
$ ls
conf.d koi-utf mime.types naxsi.rules proxy_params sites-available uwsgi_params
fastcgi_params koi-win naxsi_core.rules nginx.conf scgi_params sites-enabled win-utf
其中最主要的nginx.conf
和sites-enabled/default
兩個文件。我們需要修改后者以保證網絡可以訪問指定目錄下資源。
比如我們創建一個hls目錄,放到/data/
目錄下,並在hls目錄中創建一個名為index.html的文件,你可以在其中添加任何想添加的資源。要通過網絡訪問hls目錄需要在sites-enabled/default
中添加如下修改:
location /hls/ {
#alias /data/hls/;
root /data;
}
如果你對nginx配置文件語法感興趣,建議參考官網中的用戶手冊。
修改完成之后重啟nginx或者重新加載下nginx配置文件,就可以通過瀏覽器訪問了,網址為: http://localhost/hls/index.html
到此我們基於nginx的網絡服務器搭建完成,可以對外提供網絡服務了。
1.4 參考資料
2. 使用ffmpeg實現文件的分片,並生成m3u8
2.1 准備工作
你需要下載或者編譯一個可以在你系統運行的ffmpeg,自己編譯的話請確保所有關於HLS的部分是使能的。
我是通過 https://johnvansickle.com/ffmpeg 網站下載的ubuntu下可運行的ffmpeg。
2.2 ffmpeg對文件分片①
這里使用直播中比較常用的hls_muxer對本地文件進行分片,其命令格式如下:
./ffmpeg -i s1080p.mp4 -c:v copy -c:a copy -f hls -hls_time 10 -hls_playlist_type vod high.m3u8
這里hls_time表示分片長度為10s,high.m3u8是最后輸出的m3u8文件,同時這里設置了HLS類型為VOD。
成功運行之后,就可以通過 http://localhost/hls/high.m3u8 訪問了。
關於ffmpeg的HLS demuxer更多參數介紹,請參考hls-doc。
2.3 ffmpeg對文件分片②
ffmpeg還提供了segment_demuxer,提供了更通用的分片機制及參數。
實現跟2.2同樣的本地文件分片,可以使用下面命令:
./ffmpeg -i s1080p.mp4 -c:v copy -c:a copy -f ssegment -segment_format mpegts -segment_list shigh.m3u8 -segment_time 10 shigh%d.ts
segment_format表示輸出格式,這里設置為mpegts;segment_list表示輸出切片之后的文件列表;segment_time表示切片長度,最后一個字符串給定輸出文件名的格式。
關於ffmpeg的segment demuxer更多參數介紹,請參考segment-doc
2.4 參考資料
3. ffmpeg使用本地文件模擬HLS直播
既然點播實現了,直播就相對簡單了,你可以直接換個直播源就實現了轉播,輸出還是直播。當然你也可以從攝像頭讀取數據編碼輸出,也可以使用本地文件模擬直播(類似循環播放)。本文件使用最簡單的本地文件模擬直播。(對於其他情況,ffmpeg直接支持各種設備和協議,換個-i參數即可。)
對於直播的情況,一般使用hls muxer。其命令格式如下:
./ffmpeg -re -i s1080p.mp4 -c:v libx264 -s 720x576 -c:a copy -f hls -hls_time 10 live.m3u8
hls muxer默認的是輸出類型是直播的,所有這里去掉了設置hls_playlist_type的選項;由於我的主機性能一般,這里就不直接轉碼1080p的,將輸出分辨率設置為720x576。
模擬直播最主要的參數是ffmpeg提供的re
,這個參數的意思是按照實際幀率讀取輸入文件,多數用於模擬直播設備的輸入的情況下。
更多信息建議參考ffmpeg-StreamingGuide
4. 支持多碼率HLS生成
對於點播而言,當然可以通過獨立的m3u8,然后自己編寫一個master playlist來實現類似HLS多碼率的效果。但是ffmpeg是否有提供類似一次性生成master playlist的機制呢?(畢竟能少一步是一步,提供效率是主要的。)
沒找到網上相關的資料,那就直接看ffmpeg官網的HLS文檔吧。各種命令嘗試了下,最終驗證可實現的命令行如下:
./ffmpeg -i s1080p.mp4 -c:v:0 copy -c:v:1 libx264 -s 640x320 -c:a:0 copy -b:a:1 32k \
-map 0:v -map 0:a -map 0:v -map 0:a -f hls -var_stream_map "v:0,a:0 v:1,a:1" 、
-hls_time 10 -hls_playlist_type vod -master_pl_name master.m3u8 out%v/out.m3u8`
這里多了幾個特殊hls參數。master_pl_name
用於指定輸出的master playlist文件名;var_stream_map
用於指定variant list中包含的節目信息,其中以空格分隔,比如上面的參數表示:variant#0中包含原始的1080p視頻和音頻,variant#1包含640x320的視頻和32k的音頻。
這個命令輸出的master.m3u8格式如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=1029895,RESOLUTION=1920x1080
out0/out.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=35200,RESOLUTION=640x320,CODECS="avc1.64001e,mp4a.40.2"
out1/out.m3u8
所生成的ts文件分別位於out0和out1目錄下。
要是需要多碼率直播,請參考2.2節和3小節的介紹
5. 小結
本文首先介紹了如何安裝配置nginx,這樣就可以實現http服務器,並在此基礎上使用ffmpeg實現HLS點播/直播的處理,最后給出了ffmpeg命令以實現一條語句生成HLS所需的master playlist。
總體來說,做完這些讓我對HLS系統環境搭建有了大體上的認識,僅作記錄,以供后續參考。