最近看到用 Nginx + vod_modlue 架設 HLS 伺服器的作法,其標榜的特色為:
特色: On-the-fly repackaging of MP4 files to DASH, HDS, HLS, MSS
也就是原來是 mp4 的影音檔,不需要自己用 ffmpeg 切成 ts 檔以及產生 m3u8 檔,使用這個 module,一切自動化產生。
雖然自己的工作在維護開放課程網站,必需用到媒體伺服器,但對於 HLS 伺服器與直接讀取 mp4 檔案的差別,仍不甚明瞭。這次就藉著架設 HLS 伺服器來探究其差異。
直接讀取 mp4 檔案,查看 access_log 的內容,主要是用 range 的功能。
---------
101.12.44.84 - - [03/Oct/2019:03:26:52] "GET /vod/099S103/099S103_AA04V01.mp4 HTTP/1.1" 206 413699931 "http://ocw.ntu.edu.tw/ntu-ocw/preview?fn=099S103_AA04V01.mp4" "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4 like Mac OS X)"
------------
mpv http://10.161.81.158:3030/hls/099S103/099S103_AA04V01.mp4/index.m3u8
-----------
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27] "HEAD /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27] "GET /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27] "GET /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 206 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27] "GET /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 206 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:28] "GET /hls/099S103/099S103_AA04V01.mp4/segment-1-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:28] "GET /hls/099S103/099S103_AA04V01.mp4/segment-2-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:28] "GET /hls/099S103/099S103_AA04V01.mp4/segment-3-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
### 時間往後跳
web_1 | 2019/10/03 03:47:29 [info] 25#25: *30 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 2019/10/03 03:47:29 [info] 27#27: *29 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29] "GET /hls/099S103/099S103_AA04V01.mp4/segment-688-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 2019/10/03 03:47:29 [info] 27#27: *31 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 2019/10/03 03:47:29 [info] 24#24: *32 client prematurely closed connection (104: Connection reset by peer) while processing frames, client: 10.161.86.117, server: localhost, request: "GET /hls/099S103/099S103_AA04V01.mp4/segment-689-v1-a1.ts HTTP/1.1", host: "10.161.81.158:3030"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29] "GET /hls/099S103/099S103_AA04V01.mp4/segment-689-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29] "GET /hls/099S103/099S103_AA04V01.mp4/segment-688-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29] "GET /hls/099S103/099S103_AA04V01.mp4/segment-689-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29] "GET /hls/099S103/099S103_AA04V01.mp4/segment-690-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
### 結束播放
web_1 | 2019/10/03 03:47:31 [info] 27#27: *33 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 2019/10/03 03:47:31 [info] 28#28: *34 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
------------
由以上的比較,可以看出兩者的差異。直接讀取mp4檔案,只有一個連線,透過 range 要求,讀取所需位置的資料。然後這連線會持續開啟,有些應用程式,不會根據播放速度讀取資料,而是一次把整個檔讀完,因而佔用網路頻寬。假若是採用 HLS,則會在一開始時,讀進約一分鐘緩衝的資料,然後在消耗完一個片段後,才會讀下一個片段,例如每10秒讀一次,因此網路資料會比較少。
1web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27 +0000] "HEAD /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 206 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:27 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/index.m3u8 HTTP/1.1" 206 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:28 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-1-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:28 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-2-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:28 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-3-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 2019/10/03 03:47:29 [info] 25#25: *30 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 2019/10/03 03:47:29 [info] 27#27: *29 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-688-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 2019/10/03 03:47:29 [info] 27#27: *31 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 2019/10/03 03:47:29 [info] 24#24: *32 client prematurely closed connection (104: Connection reset by peer) while processing frames, client: 10.161.86.117, server: localhost, request: "GET /hls/099S103/099S103_AA04V01.mp4/segment-689-v1-a1.ts HTTP/1.1", host: "10.161.81.158:3030"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-689-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-688-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-689-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 10.161.86.117 - [03/Oct/2019:03:47:29 +0000] "GET /hls/099S103/099S103_AA04V01.mp4/segment-690-v1-a1.ts HTTP/1.1" 200 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.26 Safari/537.36"
web_1 | 2019/10/03 03:47:31 [info] 27#27: *33 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
web_1 | 2019/10/03 03:47:31 [info] 28#28: *34 client 10.161.86.117 closed keepalive connection (104: Connection reset by peer)
一個360P 影片的 10秒 ts 切片可能在 1MB以內。然後每 10 秒讀取一個檔案。