admin管理员组

文章数量:1566978

文章目录

    • 简介
    • Media Source Extensions
    • m3u8测试地址
    • m3u8协议
    • 事件监控
      • 运行时事件
      • Video事件
      • MSE事件
        • SourceBuffer
      • 错误检测和处理
    • 解析
      • 目录
      • 流程
      • Fragment
    • 自定义loader
    • 自定义pLoader
    • 自定义fLoader
    • xhrSetup
    • 常用API
      • HLS
      • Video
    • 参考

简介

HLS 全称是 HTTP Live Streaming, 是一个由 Apple 公司实现的基于 HTTP 的媒体流传输协议。通过将整条流切割成一个小的可以通过 HTTP 下载的媒体文件,然后提供一个配套的媒体列表文件,提供给客户端,让客户端顺序地拉取这些媒体文件播放, 来实现看上去是在播放一条流的效果。

其基于 Media Source Extensions 开发,用于实现 HTTP Live Streaming 开源JavaScript类库。它可以实现将MPEG-2 和 AAC/MP3码流变成自制的 MP4的分片。并且可以直接绑定在Video 上,实现播放。

由于传输层协议只需要标准的 HTTP 协议,HLS 可以方便的透过防火墙或者代理服务器,而且可以很方便的利用 CDN 进行分发加速,并且客户端实现起来也很方便。

HLS 目前广泛地应用于点播和直播领域。

Github:https://github/video-dev/hls.js

Demo:

  • https://hls-jslify.app/demo/
  • https://hls-js-devlify.app/demo/

相关文档:

  • https://hls-js-devlify.app/api-docs/hls.js
  • https://hls-jslify.app/api-docs/
  • https://github/video-dev/hls.js/blob/master/docs/API.md
  • https://colinrds.gitbooks.io/myapi/content/hlsjsapi.html
  • https://www.jackpu/hls-js-yuan-ma-jie-du-1/
  • https://developer.apple/documentation/http_live_streaming

Media Source Extensions

文档:

  • https://developer.mozilla/zh-CN/docs/Web/API/Media_Source_Extensions_API

  • https://developer.mozilla/zh-CN/docs/Web/API/MediaSource

是什么?MSE(Media Source Extensions),即媒体源扩展,可以理解为一种API,其提供了实现无插件且基于 Web 的流媒体的功能。通过 MSE,媒体流可以使用 HTML5 的 和 标签进行播放。

Media Source Extensions 允许JavaScript动态地为和创建媒体流,而不再只能是引用一个视频文件的url。这样就极大地丰富了前端对音视频的处理能力,也赋予了其更多灵活性。

为什么?以前web浏览器播放音视频,需要使用诸如 Adobe Flash 或是微软的 Silverlight 等类似的插件,在浏览器中使用插件是不便捷并且不安全的。最新的HTML5标准中出现了 标签解决了这个问题。 标签可以看做是浏览器自带的、具有解封和解码功能的视频播放器。但是,随着视频点播、直播等视频业务的兴起,视频数据会通过流媒体传输协议(目前常用的 MPEG-DASH 和 Apple 的 HLS)从服务端分发给客户端,在这种情况下,媒体内容就被包含在传输协议中了,此时 HTML5 的 标签就无法识别并播放媒体内容了。引入 MSE 之后,支持 HTML5 的Web浏览器就变成了能够解析流协议的播放器了。

示例

<html><head>
    <meta charset="utf-8">
  </head>
  <body>
    <video controls=""></video>
    <script>
      var video = document.querySelector('video');

      var assetURL = 'frag_bunny.mp4';
      // Need to be specific for Blink regarding codecs
      // ./mp4info frag_bunny.mp4 | grep Codec
      var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';

      if ('MediaSource' in window && 
      MediaSource.isTypeSupported(mimeCodec)) {
     
        var mediaSource = new MediaSource;
        //console.log(mediaSource.readyState); // closed
        video.src = URL.createObjectURL(mediaSource);
        mediaSource.addEventListener('sourceopen', sourceOpen);
      } else {
     
        console.error('Unsupported MIME type or codec: ', mimeCodec);
      }

      function sourceOpen (e) {
     
        //console.log(this.readyState); // open
        var mediaSource = e.target;
        var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        fetchAB(assetURL, function (buf) {
     
          sourceBuffer.addEventListener('updateend', function (_) {
     
            mediaSource.endOfStream();
            video.play();
            //console.log(mediaSource.readyState); // ended
          });
          console.log("buf",buf);
          sourceBuffer.appendBuffer(buf);
        });
      };

      function fetchAB (url, cb) {
     
        console.log(url);
        var xhr = new XMLHttpRequest;
        xhr.open('get', url);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function () {
     
          cb(xhr.response);
        };
        xhr.send();
      };
    </script>
</body></html>

m3u8测试地址

  • https://cph-p2p-msl.akamaized/hls/live/2000341/test/master.m3u8【live多码流】
  • http://playertest.longtailvideo/adaptive/bipbop/gear4/prog_index.m3u8【vod计时器】
  • https://d2zihajmogu5jn.cloudfront/sintel/master.m3u8【vod多码流】
  • http://devimages.apple/iphone/samples/bipbop/gear1/prog_index.m3u8
  • http://220.161.87.62:8800/hls/0/index.m3u8
  • http://220.161.87.62:8800/hls/1/index.m3u8
  • https://players.akamai/players/hlsjs
  • bitmovin

m3u8协议

Master Playlist

只有多码流才会有Master Playlist

当 m3u8 作为主播放列表(Master Playlist)时,其内部提供的是同一份媒体资源的多份流列表资源(Variant Stream)。

#EXTM3U 标识当前是一个M3U8文件,该标签必须出现在文件的第一行。
#EXT-X-STREAM-INF:BANDWIDTH=150000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example/low/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=240000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example/lo_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=440000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example/hi_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=640000,RESOLUTION=640x360,CODECS="avc1.42e00a,mp4a.40.2"
http://example/high/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=64000,CODECS="mp4a.40.5"
http://example/audio/index.m3u8
  • #EXT-X-STREAM-INF:用于标识一个Variant Stream,这是由一系列的Redition组成的。该标签的属性列表中包含了Variant Stream的描述信息。例如:
  • BANDWIDTH表示Variant Stream中的峰值比特率,单位bits/s。
  • AVERAGE-BANDWIDTH表示Variant Stream中的平均比特率,单位bits/s。
  • CODECS包含Variant Stream中音视频编码格式相关的信息,比如上面的"mp4a.40.5"。
  • RESOLUTION包含Variant Stream中对应视频流的分辨率。
  • FRAME-RATE表示Variant Stream中的视频帧率。

Media PlayList

一般分为直播Live和点播VOD。

Live示例

#EXTM3U
#EXT-X-VERSION:3 协议版本号
#EXT-X-ALLOW-CACHE:NO 指定文件是否可以缓存
#EXT-X-MEDIA-SEQUENCE:268 第一个媒体片段的序列号 在 PlayList中只有唯一的序号,相邻之间序号+1。
#EXT-X-TARGETDURATION:3 表示最大的秒数
#EXT-X-KEY:METHOD=AES-128,URI="https://xxx/1111",IV=0x39333764333063306139653264353066 表示 Media Segment 已加密, 该值用于解密.
#EXTINF:2.015, 指定每个媒体段(ts)的持续时间
https://d23kaes948ag5n.cloudfront/1K
#EXTINF:2.031,
https://d23kaes948ag5n.cloudfront/2K

加密参数#EXT-X-KEY,包括加密算法METHOD=AES-128、密钥URI和可选参数IV(初始化向量)

客户端收到M3U8文件后,使用key URI发起请求。该请求检索密钥。然后,客户端使用加密算法和密钥解密传输流 (TS) 文件。

VOD示例

#EXTM3U 每个M3U文件第一行必须是这个tag,提供标示作用
#EXT-X-VERSION:3 用以标示协议版本。这里是3, 那么这里用的就是HLS协议第三个版本,此标签只能有0或1个,不写代表使用版本1
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:13  所有切片的最大时长,有些Apple设备这个参数不正确会无法播放。
#EXT-X-MEDIA-SEQUENCE:430 切片的开始序号。每一个切片都有唯一的序号,相邻之间序号+1。这个编号会继续增长,保证流的连续性。
#EXT-X-PLAYLIST-TYPE:VOD 类型,vod 表示点播。
#EXTINF:11.800  ts 切片的实际时长。duration : 媒体持续时间
news-430.ts ts 切片的文件名
#EXTINF:10.120
news-431.ts
#EXT-X-DISCONTINUITY 表示后续分片属性发生变化,如文件格式/编码/序号。
#EXTINF:11.952
news-430.ts
#EXTINF:12.640
news-431.ts
#EXTINF:11.160
news-432.ts
#EXT-X-DISCONTINUITY
#EXTINF:11.751
news-430.ts
#EXTINF:2.040
news-431.ts
// 重点
#EXT-X-ENDLIST  文件结束符号。表示不再向播放列表文件添加媒体文件。

事件监控

运行时事件

只记录核心事件,都是以Hls.Events.开头,例如:Hls.Events.MEDIA_ATTACHING。

事件 字符串 描述
MEDIA_ATTACHING hlsMediaAttaching 在MediaSource附加到媒体元素之前被触发
MEDIA_ATTACHED hlsMediaAttached 在MediaSource成功附加到媒体元素时触发
MANIFEST_LOADING hlsManifestLoading 在Manifest加载时触发
MANIFEST_LOADED hlsManifestLoaded 在Manifest被加载后触发
MANIFEST_PARSED hlsManifestParsed 在Manifest被解析后触发
LEVEL_SWITCHING hlsLevelSwitching 在Level切换被请求时触发
LEVEL_LOADING hlsLevelLoading 在Level加载时触发
LEVEL_LOADED hlsLevelLoaded 在Level被加载后触发
LEVEL_UPDATED hlsLevelUpdated 在Level的详细信息更新时触发
LEVEL_SWITCHED hlsLevelSwitched 在Level切换完成时触发
KEY_LOADING hlsKeyLoading 在解密Key加载开始前触发
FRAG_LOADING hlsFragLoading 在片段开始加载前时触发
KEY_LOADED hlsKeyLoaded 在解密Key加载完成后触发
FRAG_LOADED hlsFragLoaded 在片段加载完成后触发
BUFFER_CREATED hlsBufferCreated 当sourcebuffers被创建完成时触发**(只一次)**
FRAG_PARSING_INIT_SEGMENT hlsFragParsingInitSegment 当初始Segment从Fragment抽取完触发**(每个Level只一次)**
BUFFER_APPENDING hlsBufferAppending 在往sourcebuffer添加媒体数据前触发
FRAG_DECRYPTED hlsFragDecrypted 在fragment完成解密后触发
FRAG_PARSED hlsFragParsed 当片段解析完成时触发
BUFFER_APPENDED hlsBufferAppended 在往sourcebuffer添加媒体数据后触发
FRAG_CHANGED hlsFragChanged 当与当前视频位置的片段匹配发生变化时触发**(播放态 切换片段时)**
FRAG_BUFFERED hlsFragBuffered 当解码后的数据都加载到sourcebuffer后触发。
BUFFER_FLUSHING hlsBufferFlushing 当sourcebuffer被清空部分前触发
BUFFER_FLUSHED hlsBufferFlushed 当sourcebuffer被清空部分完成时触发
Hls.Events.DESTROYING hlsDestroying 当hls.js实例开始销毁时触发。不同于MEDIA_DETACHED人们可能希望将视频分离并重新连接到hls.js的实例来处理中端视频
Hls.Events.ERROR hlsError 错误事件的标识符
bufferStalledError 当播放卡住时引发,因为缓冲区数据不足 调到最新位置播放。
bufferNudgeOnStall
Hls.ErrorDetails.BUFFER_STALLED_ERROR  bufferStalledError
 - bufferStalledError 当播放卡住时引发,因为缓冲区数据不足 调到最新位置播放。
 -- data: { type : MEDIA_ERROR, 
            details : Hls.ErrorDetails.BUFFER_STALLED_ERROR, 
            fatal : true or false, 
            buffer : 缓冲区长度(可选)
          }

Video事件

       // 1、loadstart:视频查找。当浏览器开始寻找指定的音频/视频时触发,也就是当加载过程开始时
        video.addEventListener('loadstart', function (e) {
   
            console.log('提示视频的元数据已加载')
            console.log(e)
            console.log(video.duration)            // NaN
        })

        // 2、durationchange:时长变化。当指定的音频/视频的时长数据发生变化时触发,加载后,时长由 NaN 变为音频/视频的实际时长
        video.addEventListener

本文标签: 入门HLS