整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          html5的video標簽實現對m3u8格式視頻(HLS)的支持 親測可用

          切圖網一個項目切圖中遇到的,網頁中嵌入視頻 理所當然用html5自帶的video標簽即可實現,也有比較主流的插件videojs,但是這個比較特別播放的視頻是m3u8格式的 (這種好像imac safari下用的多),這種情況需要添加額外的支持,好在hls.min.js可以實現。附代碼 親測可用

          html5的video標簽實現對HLS(m3u8格式)的支持 親測可用

          1. <script src=“https://cdn.jsdelivr.net/hls.js/latest/hls.min.js”></script>
          2. <video id=“video”></video>
          3. <script>
          4. if(Hls.isSupported()) {
          5. var video = document.getElementById(‘video’);
          6. var hls = new Hls();
          7. hls.loadSource(‘http://www.streambox.fr/playlists/test_001/stream.m3u8’);
          8. hls.attachMedia(video);
          9. hls.on(Hls.Events.MANIFEST_PARSED,function() {
          10. video.play();
          11. });
          12. }
          13. </script>

          技術提升美好事物發生的概率。Technologically, for greater probability to be happy

          前言

          只要在 HTML5 中使用過視頻播放的同學對 video 標簽一定不會陌生,不過很多同學只使用了 video 的基礎功能,實際上 video 擁有強大潛能的,只要姿勢正確就能讓其擁有超能力。不妨從下面幾個場景來逐漸了解下video 未曾被發掘的神秘空間:

          • 清晰度無縫切換
          • 節省視頻流量

          清晰度無縫切換

          點播領域里 mp4 是最普遍、兼容性最好的視頻容器,不過 mp4 也有它的局限性,比如常見的清晰度切換,我們是無法像youtube那樣做到無縫切換的。我們可以看下普通的mp4播放的網絡請求和youtube視頻播放的網絡請求的區別。

          圖1.1 普通mp4的下載請求過程

          圖1.2 Youtube視頻下載請求過程

          這兩張圖不難看出,在默認情況下 mp4 使用一次 http 請求所有的視頻數據,Youtube 則分次請求。當然這個描述很不專業,但確實形象。造成這種差異的是 video 不支持流式的視頻數據,Youtube 采用的是流式的視頻容器 webm,而 mp4 是非流式的。那如何解釋清楚流式的視頻數據呢,從專業的角度三言兩語很難說清楚,但用大白話翻譯過來就是流式的視頻數據支持分段獨立播放,非流式的不可以。換句話說一個10M的視頻文件,流式的視頻可以把0~1M的數據請求回來單獨播放,但是非流式的不可以。

          上面我們描述了視頻格式的不同,接下來我們要說的是第一張圖中的視頻加載是瀏覽器來控制的,通過給 video 的 src 屬性配置視頻地址,觸發播放之后瀏覽器就會開始下載了,JS干涉不了。而 Youtube 的視頻加載是通過JS來控制的,各位可以再次看下第二張圖的網絡請求類型:xhr,足以證明這一點。

          上面兩點搞清楚之后我們就該說下清晰度切換的事情了。這個需求大家都不陌生,但是直接使用 mp4 格式做無縫清晰度切換,難度還挺大的。先解釋下“無縫清晰度切換”的概念:從播放一個分辨率的視頻到另一個分辨率且保證畫面、聲音不停頓的平滑切換過程。了解了這個概念,大家應該知道了用 video 無縫切換 mp4 有多難。一方面,video 是不支持流式的視頻格式的,一方面,video 的加載是不受JS控制的。通過切換 video 的 src 屬性,必然會導致畫面中斷、重新請求視頻數據等。有的同學想到說利用兩個 video 再結合 z-index 來搞,但是當你生成另一個video去加載視頻的時候,無法保證兩個畫面是嚴格一致的,即使將原來的畫面暫停到一個時刻,用另一個視頻通過 currentTime 屬性與之同步,切換仍然看到畫面閃爍,基本無法和 Youtube 無縫切換的體驗匹敵。而且還會造成更多流量的浪費,背后的原因大家可以研究下 mp4 容器和 webm 容器的異同,也可以看下視頻解碼相關的文章。

          還有一種方法就是將 mp4 格式統統轉碼到流式的視頻格式比如 hls、webm 等。不過這種看上去可行的方式實際上會帶來很大的成本開銷,如將大量視頻做轉碼會消耗高昂的機器資源、雙倍存儲的費用、CDN的雙倍費用等等。其實我們也是在這種背景下研究出來新的技術問題解決清晰度無縫切換的。

          首先,我們改變對 mp4 視頻的播放流程,不再直接使用 video 的 src 來播放,因為我們沒有任何可以操作的空間。video不僅支持 src 屬性還支持 Blob 對象,我們就是利用后者。播放的流程如下:

          圖1.3 mp4 視頻新播放流程

          1. 來請求 mp4 視頻數據,這樣可以結合視頻 Range 服務,做到精確加載。
          2. 編寫解析器將加載回來的部分 mp4 視頻數據進行解復用
          3. 將解復用的視頻數據轉成 fmp4 格式并傳遞給 MediaSource
          4. 使用 video 進行解碼完成播放

          然后在做清晰度切換的時候流程如下:

          圖1.4 mp4視頻清晰度切換原理示意圖

          1. 播放視頻A,過程同上
          2. 在某個時刻,用戶切換到播放視頻B,首先解析B的索引文件(moov),反向計算mp4的range區間
          3. 加載B的視頻區間數據
          4. 解復用
          5. 把數據轉換成fmp4格式并傳遞給MediaSource
          6. 刪除A的部分Buffer
          7. 在下一個關鍵幀自動完成畫質的切換

          圖1.5 mp4視頻清晰度切換流程示意圖

          這個過程看上去比較繁瑣,但是所有的操作都是在瀏覽器端完成,也就是說都是JS來實現的。這樣之前說的所有成本問題都不存在,還能做到youtube相同體驗的無縫切換。如果大家也想使用這個功能不需要自己再去實現一遍上述流程,可以使用如下代碼:

          如果對這段代碼有什么疑惑,或者想深入了解下它背后是如何實現的,可以參考 Github:https://github.com/bytedance/xgplayer 或 閱讀原文:https://techblog.toutiao.com/

          節省視頻流量

          使用 video 的同學基本上都是這樣用的,如下:

          1. 利用src屬性

          2.利用source標簽

          這樣就可以播放視頻了,不過前面我們講過這樣使用 video ,視頻的加載是受瀏覽器控制的,可以看下瀏覽器在視頻剛開始播放的時候下載了多少數據:

          圖2.1 video默認下載截圖

          我隨便找了個視頻,大家看下視頻總長度是 02:08,在播放到 00:05 的時候,瀏覽器已經下載到 01:30 了,如果用戶終止觀看,下載的視頻就這樣被浪費掉了。當然,如果不斷的 seek 也會造成較多的流量浪費。按照我們之前的統計在短視頻領域,用戶 seek 的頻率在 80%,所以這部分流量是可以節省掉的。具體原理如下:

          圖2.2 播放器加載視頻原理

          1. 設置每次加載的數據包大小
          2. 設置預加載時長
          3. 開啟加載隊列,完成第一次數據包下載,判斷緩沖時間和預加載時長是否滿足,不滿足請求下一個數據包

          具體實現代碼如下:

          這樣就實現了視頻在播放過程中永遠只預加載10秒的數據,進而保證節省流量。

          擴展鏈接,了解超能力西瓜視頻是怎樣煉成的。

          LS 概述

          HLS 全稱是 HTTP Live Streaming, 是一個由 Apple 公司實現的基于 HTTP 的媒體流傳輸協議. 他跟 DASH 協議的原理非常類似. 通過將整條流切割成一個小的可以通過 HTTP 下載的媒體文件, 然后提供一個配套的媒體列表文件, 提供給客戶端, 讓客戶端順序地拉取這些媒體文件播放, 來實現看上去是在播放一條流的效果.

          由于傳輸層協議只需要標準的 HTTP 協議, HLS 可以方便的透過防火墻或者代理服務器, 而且可以很方便的利用 CDN 進行分發加速, 并且客戶端實現起來也很方便.

          HLS 目前廣泛地應用于點播和直播領域.

          在 HTML5 頁面上使用 HLS 非常簡單:

          直接:

          <video src="example.m3u8" controls></video>

          或者:

          <video controls>   
            <source src="example.m3u8">
              </source></video>

          下面, 我將會概括性地介紹 HLS 協議的方方面面(并且包括 AES 加密部分的內容), 配合 HLS 的 RFC 食用效果更佳.

          HLS 協議詳解

          hls_arch 上面是 HLS 整體架構圖, 可以看出, 總共有三個部分: Server, CDN, Client.

          其實, HLS 協議的主要內容是關于 M3U8 這個文本協議的, 其實生成與解析都非常簡單. 為了更加直接地說明這一點, 我下面舉兩個簡單的例子:

          簡單的 Media Playlist:

          #EXTM3U
          
          #EXT-X-VERSION:3
          
          #EXT-X-TARGETDURATION:8
          
          #EXT-X-MEDIA-SEQUENCE:2680
          
           
          
          #EXTINF:7.975,
          
          https://priv.example.com/fileSequence2680.ts
          
          #EXTINF:7.941,
          
          https://priv.example.com/fileSequence2681.ts
          
          #EXTINF:7.975,
          
          https://priv.example.com/fileSequence2682.ts

          包含多種比特率的 Master Playlist:

          #EXTM3U
          
          #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000
          
          http://example.com/low.m3u8
          
          #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000
          
          http://example.com/mid.m3u8
          
          #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000
          
          http://example.com/hi.m3u8
          
          #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS="mp4a.40.5"
          
          http://example.com/audio-only.m3u8
          • HLS 通過 URI(RFC3986) 指向的一個 Playlist 來表示一個媒體流.
          • 一個 Playlist 可以是一個 Media Playlist 或者 Master Playlist, 使用 UTF-8 編碼的文本文件, 包含一些 URI 跟描述性的 tags.
          • 一個 Media Playlist 包含一個 Media Segments 列表,當順序播放時, 能播放整個完整的流.
          • 要想播放這個 Playlist, 客戶端需要首先下載他, 然后播放里面的每一個 Media Segment.
          • 更加復雜的情況是, Playlist 是一個 Master Playlist, 包含一個 Variant Stream 集合, 通常每個 -
          • Variant Stream 里面是同一個流的多個不同版本(如: 分辨率, 碼率不同).

          HLS Media Segments

          • 每一個 Media Segment 通過一個 URI 指定, 可能包含一個 byte range.
          • 每一個 Media Segment 的 duration 通過 EXTINF tag 指定.
          • 每一個 Media Segment 有一個唯一的整數 Media Segment Number.
          • 有些媒體格式需要一個 format-specific sequence 來初始化一個 parser, 在 Media Segment 被 parse 之前. 這個字段叫做 Media Initialization Section, 通過 EXT-X-MAP tag 來指定. 支持的 Media Segment 格式

          MPEG-2 Transport Streams

          即最常見的 TS 文件.

          • RFC: ISO_13818.
          • Media Initialization Section: PAT(Program Association Table) 跟 PMT(Program Map Table).
          • 每個 TS segment 必須值含一個 MPEG-2 Program.
          • 每一個 TS segment 包含一個 PAT 和 PMT, 最好在 segment 的開始處, 或者通過一個 EXT-X-MAP tag 來指定.

          免費分享,2022最新最全學習提升資料包,資料內容包括《Andoird音視頻開發必備手冊+音視頻最新學習視頻+大廠面試真題+2022最新學習路線圖》點擊領取FFmpegWebRTCRTMPRTSPHLSRTP播放器-音視頻流媒體高級開發

          音視頻學習交流扣裙788280672

          Fragmented MPEG-4

          即常提到的 fMP4.

          • RFC: ISOBMFF.
          • Media Initialization Section: ftyp box(包含一個高于 ios6 的 brand), ftypbox 必須緊跟在 moov box 之后. moov box 必須包含一個 trak box(對于每個 fMP4 segment 里面的 traf box, 包含匹配的 track_ID). 每個 trakbox 應該包含一個 sample table, 但是他的 sample count 必須為 0. mvhd box 跟 tkhd 的 duration 必須為 0. mvex box 必須跟在上一個 trak box 后面.
          • 不像普通的 MP4 文件包含一個 moov box(包含 sample tables) 和一個 mdatbox(包含對應的 samples), 一個 fMP4 包含一個 moof box (包含 sample table 的子集), 和一個 mdat box(包含對應的 samples).
          • 在每一個 fMP4 segment 里面, 每一個 traf box 必須包含一個 tfdt box, fMP4 segment 必須使用 movie-fragment relative addressing. fMP4 segments 絕對不能使用外部的 data references.
          • 每一個 fMP4 segment 必須有一個 EXT-X-MAP tag.

          Packed Audio

          • 一個 Packed Audio Segment 包含編碼的 audio samples 和 ID3 tags. 簡單的打包到一起, 包含最小的 framing, 并且沒有 per-sample timestamp.
          • 支持的 Packed Audio: AAC with ADTS framing [ISO138187], MP3 [ISO138183], AC-3 [AC3], Enhanced AC-3 [AC3].
          • 一個 Packed Audio Segment 沒有 Media Initialization Section.
          • 每一個 Packed Audio Segment 必須在他的第一個 sample 指定 timestamp 通過一個 ID3 PRIV tag.
          • ID3 PRIV owner identifier 必須是 com.apple.streaming.transportStreamTimestamp.
          • ID3 payload 必須是一個 33-bit MPEG-2 Program Elementary Stream timestamp 的大端 eight-octet number, 高 31 為設置為 0.

          WebVTT

          • 一個 WebVTT Segment 是一個 WebVTT 文件的一個 section, WebVTT Segment 包含 subtitles. Media Initialization Section: WebVTT header.
          • 每一個 WebVTT Segment 必須有以一個 WebVTT header 開始, 或者有一個 EXT-X-MAP tag 來指定.
          • 每一個 WebVTT header 應該有一個 X-TIMESTAMP-MAP 來保證音視頻同步.

          HLS Playlists

          Playlist 文件的格式是起源于 M3U, 并且繼承兩個 tag: EXTM3U 和 EXTINF 下面的 tags 通過 BNF-style 語法來指定.

          • 一個 Playlist 文件必須通過 URI(.m3u8 或 m3u) 或者 HTTP Content-Type 來識別(application/vnd.apple.mpegurl 或 audio/mpegurl).
          • 換行符可以用 \n 或者 \r\n.
          • 以 # 開頭的是 tag 或者注釋, 以 #EXT 開頭的是 tag, 其余的為注釋, 在解析時應該忽略.
          • Playlist 里面的 URI 可以用絕對地址或者相對地址, 如果使用相對地址, 那么是相對于 Playlist 文件的地址.

          Attribute Lists

          • 有的 tags 的值是 Attribute Lists.
          • 一個 Attribute List 是一個用逗號分隔的 attribute/value 對列表.
          • 格式為: AttributeName=AttributeValue.

          Basic Tags

          Basic Tags 可以用在 Media Playlist 和 Master Playlist 里面.

          • EXTM3U: 必須在文件的第一行, 標識是一個 Extended M3U Playlist 文件.
          • EXT-X-VERSION: 表示 Playlist 兼容的版本.

          Media Segment Tags

          每一個 Media Segment 通過一系列的 Media Segment tags 跟一個 URI 來指定. 有的 Media Segment tags 只應用與下一個 segment, 有的則是應用所有下面的 segments. 一個 Media Segment tag 只能出現在 Media Playlist 里面.

          • EXTINF: 用于指定 Media Segment 的 duration
          • EXT-X-BYTERANGE: 用于指定 URI 的 sub-range
          • EXT-X-DISCONTINUITY: 表示不連續.
          • EXT-X-KEY: 表示 Media Segment 已加密, 該值用于解密.
          • EXT-X-MAP: 用于指定 Media Initialization Section.
          • EXT-X-PROGRAM-DATE-TIME: 和 Media Segment 的第一個 sample 一起來確定時間戳.
          • EXT-X-DATERANGE: 將一個時間范圍和一組屬性鍵值對結合到一起.

          Media Playlist Tags

          Media Playlist tags 描述 Media Playlist 的全局參數. 同樣地, Media Playlist tags 只能出現在 Media Playlist 里面.

          • EXT-X-TARGETDURATION: 用于指定最大的 Media Segment duration.
          • EXT-X-MEDIA-SEQUENCE: 用于指定第一個 Media Segment 的 Media Sequence Number.
          • EXT-X-DISCONTINUITY-SEQUENCE: 用于不同 Variant Stream 之間同步.
          • EXT-X-ENDLIST: 表示結束.
          • EXT-X-PLAYLIST-TYPE: 可選, 指定整個 Playlist 的類型.
          • EXT-X-I-FRAMES-ONLY: 表示每個 Media Segment 描述一個單一的 I-frame.

          Master Playlist Tags

          Master Playlist tags 定義 Variant Streams, Renditions 和 其他顯示的全局參數. Master Playlist tags 只能出現在 Master Playlist 中.

          • EXT-X-MEDIA: 用于關聯同一個內容的多個 Media Playlist 的多種 renditions.
          • EXT-X-STREAM-INF: 用于指定一個 Variant Stream.
          • EXT-X-I-FRAME-STREAM-INF: 用于指定一個 Media Playlist 包含媒體的 I-frames.
          • EXT-X-SESSION-DATA: 存放一些 session 數據.
          • EXT-X-SESSION-KEY: 用于解密.

          Media or Master Playlist Tags

          這里的 tags 可以出現在 Media Playlist 或者 Master Playlist 中. 但是如果同時出現在同一個 Master Playlist 和 Media Playlist 中時, 必須為相同值.

          • EXT-X-INDEPENDENT-SEGMENTS: 表示每個 Media Segment 可以獨立解碼.
          • EXT-X-START: 標識一個優選的點來播放這個 Playlist.

          服務器端與客戶端邏輯

          以下流程僅供參考, 其實不同的播放器客戶端以及服務器端的拉取規則都有很多細節差異.

          服務器端邏輯

          • 1、將媒體源切片成 Media Segment, 應該優先從可以高效解碼的時間點來進行切片(如: I-frame).
          • 2、為每一個 Media Segment 生成 URI.
          • 3、Server 需要支持 “gzip” 方式壓縮文本內容.
          • 4、創建一個 Media Playlist 索引文件, EXT-X-VERSION 不要高于他需要的版本, 來提供更好的兼容性.
          • 5、Server 不能隨便修改 Media Playlist, 除了 Append 文本到文件末尾, 按順序移除 Media Segment URIs, 增長 EXT-X-MEDIA-SEQUENCE 和 EXT-X-DISCONTINUITY-SEQUENCE, 添加 EXT-X-ENDLIST 到文件尾.
          • 6、在最后添加 EXT-X-ENDLIST tag, 來減少 Client reload Playlist 的次數.
          • 7、注意點播與直播服務器不同的地方是, 直播的 m3u8 文件會不斷更新, 而點播的 m3u8 文件是不會變的, 只需要客戶端在開始時請求一次即可.

          客戶端邏輯

          • 1、客戶端通過 URI 獲取 Playlist. 如果是 Master Playlist, 客戶端可以選擇一個 Variant Stream 來播放.
          • 2、客戶端檢查 EXT-X-VERSION 版本是否滿足.
          • 3、客戶端應該忽略不可識別的 tags, 忽略不可識別的屬性鍵值對.
          • 4、加載 Media Playlist file.
          • 5、 播放 Media Playlist file.
          • 6、重加載 Media Playlist file.
          • 7、決定下一次要加載的 Media Segment.

          HLS 的優勢

          • 客戶端支持簡單, 只需要支持 HTTP 請求即可, HTTP 協議無狀態, 只需要按順序下載媒體片段即可.
          • 使用 HTTP 協議網絡兼容性好, HTTP 數據包也可以方便地通過防火墻或者代理服務器, CDN 支持良好.
          • Apple 的全系列產品支持, 由于 HLS 是蘋果提出的, 所以在 Apple 的全系列產品包括 iphone, ipad, safari 都不需要安裝任何插件就可以原生支持播放 HLS, 現在, Android 也加入了對 HLS 的支持.
          • 自帶多碼率自適應, Apple 在提出 HLS 時, 就已經考慮了碼流自適應的問題.

          HLS 的劣勢

          • 相比 RTMP 這類長連接協議, 延時較高, 難以用到互動直播場景.
          • 對于點播服務來說, 由于 TS 切片通常較小, 海量碎片在文件分發, 一致性緩存, 存儲等方面都有較大挑戰.

          改進的 HLS 技術

          由于客戶端每次請求 TS 或 M3U8 有可能都是一個新的連接請求, 所以, 我們無法有效的標識客戶端, 一旦出現問題, 基本無法有效的定位問題, 所以, 一般工業級的服務器都會對傳統的 HLS 做一些改進.

          這里主要介紹網宿的 Variant HLS 與又拍云的 HLS+.

          網宿的 Variant HLS

          首先, 我們可以下載一條網宿的 M3U8 文件:

          wget http://bililive.kksmg.com/hls/stvd6edb9a6_45b34047833af658bf4945a8/playlist.m3u8

          然后, 打開下載得到的 playlist 文件:

          #EXTM3U
          
          #EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=781000
          
          http://bililive.kksmg.com/hls/stvd6edb9a6_45b34047833af658bf4945a8/playlist.m3u8?
          
          wsSession=0105cb4e8fe63bccab511a4a-
          
          149017212774715&wsIPSercert=b80d38c068c9e3634a7ebb2f2bbf9b89&wsMonitor=-1

          可以看出這是一個 Master Playlist, 里面嵌套了一層 M3U8, 同時可以看出網宿采用 wsSession 來標識一條播放連接.

          又拍云的 HLS+

          Variant HLS

          首先, 我們可以下載一條又拍云的 M3U8 文件:

          wget http://uplive.b0.upaiyun.com/live/loading.m3u8

          然后, 打開下載得到的 playlist 文件:

          #EXTM3U
          
          #EXT-X-VERSION:3
          
          #EXT-X-ALLOW-CACHE:YES
          
          #EXT-X-MEDIA-SEQUENCE:0
          
          #EXT-X-TARGETDURATION:1
          
          #EXTINF:0.998, no desc
          
          http://183.158.35.12:8080/uplive.b0.upaiyun.com/live/loading-0.ts?
          
          shp_uuid=e4989f34fcab282e21ef1fd2980284cb&shp_ts=1490172420851&shp_cid=17906&shp_pid=3
          
          370578&shp_sip0=127.0.0.1&shp_sip1=183.158.35.12&domain=uplive.b0.upaiyun.com&shp_seqno=0

          可以看出又拍云的 HLS+ 也支持這種 Variant HLS 方式來標識一條 HLS 連接, 可以看出, 又拍云使用 uuid 來表示一條 HLS 連接.

          HTTP 302

          首先, 以 HTTP 302 方式來請求播放地址.

          ? curl -v http://uplive.b0.upaiyun.com/live/loading.m3u8\?shp_identify\=302 -o playlist
          
           % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
          
                                          Dload  Upload   Total   Spent    Left  Speed
          
           0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 183.158.35.59...
          
          * TCP_NODELAY set
          
          * Connected to uplive.b0.upaiyun.com (183.158.35.59) port 80 (#0)
          
          > GET /live/loading.m3u8?shp_identify=302 HTTP/1.1
          
          > Host: uplive.b0.upaiyun.com
          
          > User-Agent: curl/7.51.0
          
          > Accept: */*
          
          >
          
          < HTTP/1.1 302 Found
          
          < Server: marco/0.26
          
          < Date: Wed, 22 Mar 2017 08:54:11 GMT
          
          < Content-Type: text/plain; charset=utf-8
          
          < Content-Length: 259
          
          < Connection: keep-alive
          
          < Access-Control-Allow-Methods: GET
          
          < Access-Control-Allow-Origin: *
          
          < Location: http://183.158.35.19:8080/uplive.b0.upaiyun.com/live/loading.m3u8?
          
          shp_uuid=2862b1b817a74cf719b1cd8f554616cd&shp_ts=1490172851450&shp_cid=59553&shp_pid=1
          
          730488&shp_sip0=127.0.0.1&shp_sip1=183.158.35.19&domain=uplive.b0.upaiyun.com&shp_iden
          
          tify=302
          
          <
          
          { [259 bytes data]
          
          * Curl_http_done: called premature == 0
          
          100   259  100   259    0     0   4813      0 --:--:-- --:--:-- --:--:--  4886
          
          * Connection #0 to host uplive.b0.upaiyun.com left intact

          打開 playlist 內容:

          Redirect to http://183.158.35.19:8080/uplive.b0.upaiyun.com/live/loading.m3u8?
          
          shp_uuid=2862b1b817a74cf719b1cd8f554616cd&shp_ts=1490172851450&shp_cid=59553&shp_pid=1
          
          730488&shp_sip0=127.0.0.1&shp_sip1=183.158.35.19&domain=uplive.b0.upaiyun.com&shp_identify=302

          在跳轉之后的地址存放真正的 playlist, 同時, 也能夠將 uuid 加入到了連接上.

          總地來說, 不管通過哪種方式, 最終我們都能通過一個唯一的 id 來標識一條流, 這樣在排查問題時就可以根據這個 id 來定位播放過程中的問題.

          HLS 延時分析

          HLS 理論延時 = 1 個切片的時長 + 0-1個 td (td 是 EXT-X-TARGETDURATION, 可簡單理解為播放器取片的間隔時間) + 0-n 個啟動切片(蘋果官方建議是請求到 3 個片之后才開始播放) + 播放器最開始請求的片的網絡延時(網絡連接耗時) 為了追求低延時效果, 可以將切片切的更小, 取片間隔做的更小, 播放器未取到 3 個片就啟動播放. 但是, 這些優化方式都會增加 HLS 不穩定和出現錯誤的風險.

          播放未加密的HLS

          1、我們知道HLS格式的視頻,只有安卓4.0以上才支持,目前基本4.0一下的機子基本可以考慮,不兼容了,所以為了減少工作量,就沒有打算使用三方的播放器,就繼續使用MediaPlayer來進行播放

          2、HLS格式的視頻,他是通過一個m3u8文件,然后里面包含若干個TS文件片段,這里有個蘋果的官方的一個例子:

          http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8

          畢竟這個是蘋果研發的所以看官方的格式肯定沒錯。

          3、里面的內容

          #EXTM3U
          
          #EXT-X-TARGETDURATION:10
          
          #EXT-X-MEDIA-SEQUENCE:0
          
          #EXTINF:10, no desc
          
          fileSequence0.ts
          
          #EXTINF:10, no desc
          
          fileSequence1.ts
          
          #EXTINF:10, no desc
          
          fileSequence2.ts
          
          #EXTINF:10, no desc
          
          fileSequence3.ts
          
          #EXTINF:10, no desc
          
          fileSequence4.ts
          
          #EXTINF:10, no desc
          
          fileSequence5.ts
          
          #EXTINF:10, no desc
          
          fileSequence6.ts
          
          #EXTINF:10, no desc
          
          fileSequence7.ts

          我們可以看到里面他又一個一個ts視頻片段,這個一個一個視頻片段就是我們需要的播放,那么他是如何被播放器識別播放的呢。

          4、其實上面的這些關鍵的字段都是約定好的,所以在MediaPlayer這個類的native層,會去按照規定好的字段去解析這個m3u8文件,那么他在播放器是最終播放的地址是怎么樣的呢,是這樣的

          http://devimages.apple.com/iphone/samples/bipbop/gear1/fileSequence0.ts

          組拼起來的,你可以直接用這個地址播放看看。

          5、實現這種未加密的緩存還是比較好實現的,大概可以分為這幾步。

          • a.我們首先按照特定的格式去解析這m3u8文件。
          • b.按照解析出來的ts文件按照我們知道的規則組拼起來,其下載這些ts文件,存放在手機的sd卡
          • c.我們需要在本地搭建一個本地http服務器,我們之前本打算搭建一個https,但是由于生成的證書是自己生成導致播放器不去訪問本地的服務器。
          • d.本地服務器我們通過過濾特定的接口名字,來實現根據不同ts名字返回不同的視頻文件(這里最好生成和原始的ts文件的名字一樣)
          • e.我們如何知道播放器播完一段視頻呢,因為他是一段一段播放的,所以這里就需要我們在本地生成一份本地指向我們本地服務器的m3u8文件,直接播

          播放加密HLS

          看下加密的m3u8文件的格式

          #EXTM3U
          
          #EXT-X-VERSION:3
          
          #EXT-X-KEY:METHOD=AES-128,URI="http://xxxxxx:5555//test/1102/test/segments.key"
          
          #EXT-X-MEDIA-SEQUENCE:0
          
          #EXT-X-ALLOW-CACHE:YES
          
          #EXT-X-TARGETDURATION:19
          
          #EXTINF:13.966667,
          
          http://xxxxxx:5555/test/1102/test/segments0.ts
          
          #EXTINF:10.000000,
          
          http://xxxxxx:5555/test/1102/test/segments1.ts
          
          #EXTINF:10.000000,
          
          http://xxxxxx:5555/test/1102/test/segments2.ts
          
          #EXTINF:10.000000,
          
          http://xxxxxx.cn:5555/test/1102/test/segments3.ts
          
          #EXTINF:10.000000,
          
          http://xxxxxxn.cn:5555/test/1102/test/segments4.ts
          
          #EXTINF:7.033333,
          
          http://xxxxxx:5555/test/1102/test/segments5.ts
          
          #EXTINF:10.000000,

          我們看到了多了個字段EXT-X-KEY,這個也是m3u8給規定好的加密字段,如果包含這個字段播放器就會先去請求這個key,然后拿這個這個key去訪問加密的TS視頻就可以播放了。 其實看到這我們就因該有思路怎么去做,加密的緩存播放了。

          實現播放加密緩存的思路

          • a、我們首先按照特定的格式去解析這m3u8文件。
          • b、按照解析出來的ts文件按照我們知道的規則組拼起來,其下載這些ts文件,存放在手機的sd卡,這些下載下來的TS視頻文件是播放不了的,再把正確的key下載下來。
          • c、我們需要在本地搭建一個本地http服務器,我們之前本打算搭建一個https,但是由于生成的證書是自己生成導致播放器不去訪問本地的服務器。
          • d、本地服務器我們通過過濾特定的接口名字,來實現根據不同ts名字返回不同的視頻文件(這里最好生成和原始的ts文件的名字一樣)
          • e、我們如何知道播放器播完一段視頻呢,因為他是一段一段播放的,所以這里就需要我們在本地生成一份本地指向我們本地

          推薦一個免費學習音視頻的地址,里面都是視頻教程干貨滿滿:【免費】FFmpeg/WebRTC/RTMP/NDK/Android音視頻流媒體高級開發-學習視頻教程-騰訊課堂


          主站蜘蛛池模板: 好爽毛片一区二区三区四| 一区二区国产在线观看| 精品视频一区二区三区四区五区| 91久久精品午夜一区二区| 国产亚洲综合精品一区二区三区| 国产一区二区三区免费| 日韩视频一区二区| 亚洲愉拍一区二区三区| 久久精品黄AA片一区二区三区| 波多野结衣的AV一区二区三区| 国产成人久久一区二区三区| 国产精品一区二区久久精品| 日韩精品在线一区二区| 国产精品区AV一区二区| 日韩A无码AV一区二区三区| 国产未成女一区二区三区 | 色妞色视频一区二区三区四区| 精品日本一区二区三区在线观看| 国产视频一区在线播放| 韩国精品福利一区二区三区| 精品无码成人片一区二区98| 91video国产一区| 亚洲午夜精品一区二区公牛电影院| 中文字幕一区二区区免| 国产在线观看一区二区三区精品| 大伊香蕉精品一区视频在线| 国产一区二区精品尤物| 国产在线一区二区在线视频| 亚洲熟女少妇一区二区| 亚洲熟女一区二区三区| 人妻久久久一区二区三区| 精品无码人妻一区二区三区品| 在线视频一区二区| 国产精品久久久久久一区二区三区| 国产怡春院无码一区二区 | 国产无人区一区二区三区 | 日产亚洲一区二区三区| 精品人妻一区二区三区浪潮在线| 91精品一区二区综合在线| 好吊妞视频一区二区| 亚洲AⅤ无码一区二区三区在线|