http://elkpi.com/topics/ffmpeg-f-hls.html
HLS也就是HTTP Live Streaming,是蘋果出的一個基於HTTP的流媒體通信協議。字面意思有個live,也就是直播相關的。其實HLS可以分為點播以及直播兩種。后面具體說兩者在處理上有什么區別。目前HLS在RFC上還只是草案,並且一直不斷更新,發現ffmpeg對於HLS的實現,不同版本的實現對應rfc版本也不一樣,最新版本的,對應的HLS RFC草案規范也比較新(追新並不一定好,有些設備對於新版本的規范支持還不是很完整,可能會有播放失敗的問題,所以如果需要正常使用,選擇一個穩定的版本即可)。rfc的草案現在到了16版本。由於項目比較敢,這規范其實我看的不多。
HLS對於音視頻是有編碼要求的,HLS要求視頻必須是H264協議,H264是目前最流行也是最成熟的視頻編解碼方案了。而在音頻上,則要求為MP3, HE-AAC或AC-3這三種格式。在轉換成HLS流后,會生成多個的TS文件。如果是點播的話,則是對視頻文件進行TS的切片處理,一般情況下,每個TS文件的播放時間為10秒。但這並不是固定的,切片的多少,這是會影響直播的延遲情況。這個后面會稍微做一些說明。
HLS會生成一個m3u8的播放文件。這個播放文件可以通過VLC等一些播放器直接播放。現在大部分手機也支持HLS了,所以手機也是可以進行對HLS的直播或點播進行觀看。但是目前的桌面端瀏覽器尚未完全支持HTML5的HLS播放,大部分直播還是依賴flash player進行封裝直播(據說國內的很多視頻站有自己的播放技術)。這邊主要討論的並非是桌面端,主要還是移動端的支持。
現在簡單說一下m3u8文件。以下是由ffmpeg生成的一個直播的m3u8文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:4
#EXTINF:12.345667,
playlist4.ts
#EXTINF:9.217544,
playlist5.ts
#EXTINF:7.757744,
playlist6.ts
#EXTINF:11.928589,
playlist7.ts
#EXTINF:11.761744,
playlist8.ts
#EXTINF:1.710044,
playlist9.ts
#EXT-X-ENDLIST
|
EXT-X-TARGETDURATION用來表示每個TS分片間隔為13秒。該參數是必須的,並且在同一個列表中是不能被改變的(直播是有列表大小的,當列表被刷新后,這個參數也可能不一樣)。一般為10秒。
EXT-X-MEDIA-SEQUENCE用來表示當前列表中第一個播放的媒體序列號。
EXTINF則表示當前TS分片所播放的時常。
EXT-X-ENDLIST表示列表結束,是必須要有的參數。
m3u8文件還有一些其余的參數,並可以控制對應帶寬播放哪些文件(也就是HLS可以更好自適應當前的網絡帶寬)等,這些具體還是去看RFC草案吧。由於我也是新學習的,探究並不是很深。
先說說二者HLS實現上的一些區別吧。
- 點播就是將一個媒體文件切分成多個TS文件,並且m3u8文件包含全部的TS文件列表。
- 直播則列表長度上會有所控制,也就是一般會比較短,並且為了減少延遲,可能會將每個分片的時長控制低於10秒,而點播應該都會直接使用10秒這個默認值吧。(並不是十分清楚現在移動端的實現是否如我這邊所說)
- 點播的m3u8是死的,也就是一旦分片完成后,一般不會再去修改m3u8文件(內容)。而直播的m3u8文件(內容)則會根據直播的時間進行更新。(其實這點很重要,直播與點播的最大區別,也應該是大部分客戶端判斷的標准吧,目前還沒細致去研究任何一款客戶端)
既然已經說到這里了,這里順便說一下,HLS點播其實是很不錯的一個技術,支持不同帶寬的播放列表(前提切片后需要對應的子m3u8播放文件以及對應分辨率的TS文件),缺點就是10秒的切片,會導致有很多的小文件存在。而直播,怎么說,依托現有CDN技術以及HTTP的支持,可以很好的支持高清直播。但是也有一定的硬傷,那就是延遲。我自己在實驗的時候,兩台手機進行直播m3u8文件,都有不同發延遲(當然,也不是說其余的直播技術沒有延遲,只能說HLS這個短板比較大吧)。當然,可以通過減少每個TS文件的時長來降低部分延遲。
接下來就說一下ffmpeg如何來生成點播與直播吧。
首先是點播,點播就是用ffmpeg將視頻文件給切片成多個。
這個用的ffmpeg的segment模塊來進行對source.mp4文件進行切片,不帶上-re參數,這樣可以以最快的速度進行切片操作(當然該操作會消耗很大的CPU)。等一段時間后,就可以看到N個的outXXX.ts(其中XXX為數字,根據你視頻的大小,會有不同的數量),ffmpeg會根據out%03d,自動計算生成的文件名稱格式。由於生成的playlist.m3u8文件很長,這里就不貼出來了。這里簡單說一下ssegment的一些參數,segment_format來指定輸出格式為mpegts segment_list用來配置輸出的列表文件名,segment_time則是切片的時長。還有一些其余的參數,可以看ffmpeg的官方使用文檔,或直接看libavformat/segment.c源文件,就會比較清楚了。
接下來說一下直播,直播的話,ffmpeg可以通過上面的點播的ssegment模塊,也可以直接通過hls模塊來實現。先說說如果通過ssegment模塊來實現:
與點播的區別就是在加了-segment_list_flags +live以示直播,並且加上了-re參數(不加這個參數,一下子就切片過去,客戶端還來不及播放,列表已經被更新了,該參數表示ffmpeg將會按照source.mp4的播放速率進行轉碼)。帶上segment_list_size參數對列表數量進行控制在6個。但是目前的話,ssegment模塊有個缺點,雖然可以通過以上方式達到直播,但是生成的TS文件並不會循環,會一直被保留(當然如果要順帶將內容錄制下來,這反倒是一個優點,只能說其實現的還是切片的功能,並非純粹的直播)。這時候,HLS模塊就可以更好的勝任直播功能了(能獨立成模塊,相對術業有專攻吧!)。HLS模塊實現於libavformat/hlsenc.c libavformat/hls.c 以及 libavformat/hlsproto.c
hls_list_size即為HLS播放的列表,hls_wrap則表示為最大的TS循環數,也就是每10個一個循環,比如現在是生成playlist0.ts~playlist9.ts,10個文件,之后又會從playlist0.ts重新生成。目前新版本的ffmpeg的HLS模塊加了很多參數,具體可以看libavformat/hlsenc.c中的static const AVOption options[]的內容,其中HLS還支持加密的操作,加密操作目前沒做探究,下次有空再研究下吧。我目前開發用的1.2版本並沒有過多的參數。其余的參數也沒做太多的深究。有時間再補充吧。
從此次對HLS相關的實驗以及知識點的學習,HLS確實是一個很不錯的解決方案,主要是對移動設備的兼容非常之好,TS格式解碼方便。並且可以大量使用現成的HTTP的CDN加速功能。目前互聯網就HTTP協議的使用度最高,也最成熟了。關於ffmpeg生成HLS就先說到這里了。
轉載請注明: 轉載自elkPi
本文鏈接地址: 使用FFmpeg生成HLS