Blame view

node_modules/videojs-contrib-hls/README.md 24.5 KB
2a09d1a4   liuqimichale   添加宜春 天水 宣化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  # Notice: this project will be deprecated and is succeeded by [videojs-http-streaming](https://github.com/videojs/http-streaming). VHS supports HLS and DASH and is built into video.js 7, see the [video.js 7 blog post](https://blog.videojs.com/video-js-7-is-here/)
  
  # video.js HLS Source Handler
  
  [![Build Status][travis-icon]][travis-link]
  [![Slack Status][slack-icon]][slack-link]
  [![Greenkeeper badge][greenkeeper-icon]][greenkeeper-link]
  
  Play back HLS with video.js, even where it's not natively supported.
  
  Maintenance Status: Deprecated
  
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
  **Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*
  
  - [Installation](#installation)
    - [NPM](#npm)
    - [CDN](#cdn)
    - [Releases](#releases)
    - [Manual Build](#manual-build)
  - [Contributing](#contributing)
  - [Talk to us](#talk-to-us)
  - [Getting Started](#getting-started)
    - [Video.js 6](#videojs-6)
  - [Documentation](#documentation)
    - [Options](#options)
      - [How to use](#how-to-use)
        - [Initialization](#initialization)
        - [Source](#source)
      - [List](#list)
        - [withCredentials](#withcredentials)
        - [useCueTags](#usecuetags)
        - [overrideNative](#overridenative)
        - [blacklistDuration](#blacklistduration)
        - [bandwidth](#bandwidth)
        - [enableLowInitialPlaylist](#enablelowinitialplaylist)
    - [Runtime Properties](#runtime-properties)
      - [hls.playlists.master](#hlsplaylistsmaster)
      - [hls.playlists.media](#hlsplaylistsmedia)
      - [hls.segmentXhrTime](#hlssegmentxhrtime)
      - [hls.bandwidth](#hlsbandwidth)
      - [hls.bytesReceived](#hlsbytesreceived)
      - [hls.selectPlaylist](#hlsselectplaylist)
      - [hls.representations](#hlsrepresentations)
      - [hls.xhr](#hlsxhr)
    - [Events](#events)
      - [loadedmetadata](#loadedmetadata)
    - [HLS Usage Events](#hls-usage-events)
      - [Presence Stats](#presence-stats)
      - [Use Stats](#use-stats)
    - [In-Band Metadata](#in-band-metadata)
    - [Segment Metadata](#segment-metadata)
  - [Hosting Considerations](#hosting-considerations)
  - [Known Issues](#known-issues)
    - [IE10 and Below](#ie10-and-below)
    - [Fragmented MP4 Support](#fragmented-mp4-support)
    - [Testing](#testing)
  - [Release History](#release-history)
  - [Building](#building)
  - [Development](#development)
    - [Tools](#tools)
    - [Commands](#commands)
  
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
  
  ## Installation
  ### NPM
  To install `videojs-contrib-hls` with npm run
  
  ```bash
  npm install --save videojs-contrib-hls
  ```
  
  ### CDN
  Select a version of HLS from [cdnjs](https://cdnjs.com/libraries/videojs-contrib-hls) or [jsDelivr](https://www.jsdelivr.com/package/npm/videojs-contrib-hls)
  
  ### Releases
  Download a release of [videojs-contrib-hls](https://github.com/videojs/videojs-contrib-hls/releases)
  
  ### Manual Build
  Download a copy of this git repository and then follow the steps in [Building](#building)
  
  ## Contributing
  See [CONTRIBUTING.md](/CONTRIBUTING.md)
  
  ## Talk to us
  Drop by our slack channel (#playback) on the [Video.js slack][slack-link].
  
  ## Getting Started
  Get a copy of [videojs-contrib-hls](#installation) and include it in your page along with video.js:
  
  ```html
  <video id=example-video width=600 height=300 class="video-js vjs-default-skin" controls>
    <source
       src="https://example.com/index.m3u8"
       type="application/x-mpegURL">
  </video>
  <script src="video.js"></script>
  <script src="videojs-contrib-hls.min.js"></script>
  <script>
  var player = videojs('example-video');
  player.play();
  </script>
  ```
  
  Check out our [live example](http://jsbin.com/vokipos/8/edit?html,output) if you're having trouble.
  
  ### Video.js 6
  With Video.js 6, by default there is no flash support. Instead, flash support is provided
  through the [videojs-flash](https://github.com/videojs/videojs-flash) plugin. If you are
  trying to use Video.js version 6 and want to include flash support, you must include
  [videojs-flash](https://github.com/videojs/videojs-flash) on your page before including
  videojs-contrib-hls
  
  ```html
  <script src="https://unpkg.com/videojs-flash/dist/videojs-flash.js"></script>
  <script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
  ```
  
  Flash, and the [videojs-flash](https://github.com/videojs/videojs-flash) plugin, are not
  required, but are recommended as a fallback option for browsers that don't have a native
  HLS player or support for [Media Source Extensions](http://caniuse.com/#feat=mediasource).
  
  ## Documentation
  [HTTP Live Streaming](https://developer.apple.com/streaming/) (HLS) has
  become a de-facto standard for streaming video on mobile devices
  thanks to its native support on iOS and Android. There are a number of
  reasons independent of platform to recommend the format, though:
  
  - Supports (client-driven) adaptive bitrate selection
  - Delivered over standard HTTP ports
  - Simple, text-based manifest format
  - No proprietary streaming servers required
  
  Unfortunately, all the major desktop browsers except for Safari are
  missing HLS support. That leaves web developers in the unfortunate
  position of having to maintain alternate renditions of the same video
  and potentially having to forego HTML-based video entirely to provide
  the best desktop viewing experience.
  
  This project addresses that situation by providing a polyfill for HLS
  on browsers that have support for [Media Source
  Extensions](http://caniuse.com/#feat=mediasource), or failing that,
  support Flash. You can deploy a single HLS stream, code against the
  regular HTML5 video APIs, and create a fast, high-quality video
  experience across all the big web device categories.
  
  Check out the [full documentation](docs/) for details on how HLS works
  and advanced configuration. A description of the [adaptive switching
  behavior](docs/bitrate-switching.md) is available, too.
  
  videojs-contrib-hls supports a bunch of HLS features. Here
  are some highlights:
  
  - video-on-demand and live playback modes
  - backup or redundant streams
  - mid-segment quality switching
  - AES-128 segment encryption
  - CEA-608 captions are automatically translated into standard HTML5
    [caption text tracks][0]
  - In-Manifest WebVTT subtitles are automatically translated into standard HTML5
    subtitle tracks
  - Timed ID3 Metadata is automatically translated into HTML5 metedata
    text tracks
  - Highly customizable adaptive bitrate selection
  - Automatic bandwidth tracking
  - Cross-domain credentials support with CORS
  - Tight integration with video.js and a philosophy of exposing as much
    as possible with standard HTML APIs
  - Stream with multiple audio tracks and switching to those audio tracks
    (see the docs folder) for info
  - Media content in
    [fragmented MP4s](https://developer.apple.com/videos/play/wwdc2016/504/)
    instead of the MPEG2-TS container format.
  
  [0]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track
  
  ### Options
  #### How to use
  
  ##### Initialization
  You may pass in an options object to the hls source handler at player
  initialization. You can pass in options just like you would for other
  parts of video.js:
  
  ```javascript
  // html5 for html hls
  videojs(video, {html5: {
    hls: {
      withCredentials: true
    }
  }});
  
  // or
  
  // flash for flash hls
  videojs(video, {flash: {
    hls: {
      withCredentials: true
    }
  }});
  
  // or
  
  var options = {hls: {
    withCredentials: true
  }};
  
  videojs(video, {flash: options, html5: options});
  
  ```
  
  ##### Source
  Some options, such as `withCredentials` can be passed in to hls during
  `player.src`
  
  ```javascript
  
  var player = videojs('some-video-id');
  
  player.src({
    src: 'https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8',
    type: 'application/x-mpegURL',
    withCredentials: true
  });
  ```
  
  #### List
  ##### withCredentials
  * Type: `boolean`
  * can be used as a source option
  * can be used as an initialization option
  
  When the `withCredentials` property is set to `true`, all XHR requests for
  manifests and segments would have `withCredentials` set to `true` as well. This
  enables storing and passing cookies from the server that the manifests and
  segments live on. This has some implications on CORS because when set, the
  `Access-Control-Allow-Origin` header cannot be set to `*`, also, the response
  headers require the addition of `Access-Control-Allow-Credentials` header which
  is set to `true`.
  See html5rocks's [article](http://www.html5rocks.com/en/tutorials/cors/)
  for more info.
  
  ##### handleManifestRedirects
  * Type: `boolean`
  * Default: `false`
  * can be used as a source option
  * can be used as an initialization option
  
  When the `handleManifestRedirects` property is set to `true`, manifest requests
  which are redirected will have their URL updated to the new URL for future
  requests.
  
  ##### useCueTags
  * Type: `boolean`
  * can be used as an initialization option
  
  When the `useCueTags` property is set to `true,` a text track is created with
  label 'ad-cues' and kind 'metadata'. The track is then added to
  `player.textTracks()`. Changes in active cue may be
  tracked by following the Video.js cue points API for text tracks. For example:
  
  ```javascript
  let textTracks = player.textTracks();
  let cuesTrack;
  
  for (let i = 0; i < textTracks.length; i++) {
    if (textTracks[i].label === 'ad-cues') {
      cuesTrack = textTracks[i];
    }
  }
  
  cuesTrack.addEventListener('cuechange', function() {
    let activeCues = cuesTrack.activeCues;
  
    for (let i = 0; i < activeCues.length; i++) {
      let activeCue = activeCues[i];
  
      console.log('Cue runs from ' + activeCue.startTime +
                  ' to ' + activeCue.endTime);
    }
  });
  ```
  
  ##### overrideNative
  * Type: `boolean`
  * can be used as an initialization option
  
  Try to use videojs-contrib-hls even on platforms that provide some
  level of HLS support natively. There are a number of platforms that
  *technically* play back HLS content but aren't very reliable or are
  missing features like CEA-608 captions support. When `overrideNative`
  is true, if the platform supports Media Source Extensions
  videojs-contrib-hls will take over HLS playback to provide a more
  consistent experience.
  
  __NOTE__: If you use this option, you must also set
  `videojs.options.html5.nativeAudioTracks` and
  `videojs.options.html5.nativeVideoTracks` to
  `false`. videojs-contrib-hls relies on audio and video tracks to play
  streams with alternate audio and requires additional capabilities only
  supported by non-native tracks in video.js.
  
  ##### blacklistDuration
  * Type: `number`
  * can be used as an initialization option
  
  When the `blacklistDuration` property is set to a time duration in seconds,
  if a playlist is blacklisted, it will be blacklisted for a period of that
  customized duration. This enables the blacklist duration to be configured
  by the user.
  
  ##### bandwidth
  * Type: `number`
  * can be used as an initialization option
  
  When the `bandwidth` property is set (bits per second), it will be used in
  the calculation for initial playlist selection, before more bandwidth
  information is seen by the player.
  
  ##### enableLowInitialPlaylist
  * Type: `boolean`
  * can be used as an initialization option
  
  When `enableLowInitialPlaylist` is set to true, it will be used to select
  the lowest bitrate playlist initially.  This helps to decrease playback start time.
  This setting is `false` by default.
  
  ### Runtime Properties
  Runtime properties are attached to the tech object when HLS is in
  use. You can get a reference to the HLS source handler like this:
  
  ```javascript
  var hls = player.tech({ IWillNotUseThisInPlugins: true }).hls;
  ```
  
  If you *were* thinking about modifying runtime properties in a
  video.js plugin, we'd recommend you avoid it. Your plugin won't work
  with videos that don't use videojs-contrib-hls and the best plugins
  work across all the media types that video.js supports. If you're
  deploying videojs-contrib-hls on your own website and want to make a
  couple tweaks though, go for it!
  
  #### hls.playlists.master
  Type: `object`
  
  An object representing the parsed master playlist. If a media playlist
  is loaded directly, a master playlist with only one entry will be
  created.
  
  #### hls.playlists.media
  Type: `function`
  
  A function that can be used to retrieve or modify the currently active
  media playlist. The active media playlist is referred to when
  additional video data needs to be downloaded. Calling this function
  with no arguments returns the parsed playlist object for the active
  media playlist. Calling this function with a playlist object from the
  master playlist or a URI string as specified in the master playlist
  will kick off an asynchronous load of the specified media
  playlist. Once it has been retreived, it will become the active media
  playlist.
  
  #### hls.segmentXhrTime
  Type: `number`
  
  The number of milliseconds it took to download the last media segment.
  This value is updated after each segment download completes.
  
  #### hls.bandwidth
  Type: `number`
  
  The number of bits downloaded per second in the last segment download.
  This value is used by the default implementation of `selectPlaylist`
  to select an appropriate bitrate to play.
  
  Before the first video segment has been downloaded, it's hard to
  estimate bandwidth accurately. The HLS tech uses a heuristic based on
  the playlist download times to do this estimation by default. If you
  have a more accurate source of bandwidth information, you can override
  this value as soon as the HLS tech has loaded to provide an initial
  bandwidth estimate.
  
  #### hls.bytesReceived
  Type: `number`
  
  The total number of content bytes downloaded by the HLS tech.
  
  #### hls.selectPlaylist
  Type: `function`
  
  A function that returns the media playlist object to use to download
  the next segment. It is invoked by the tech immediately before a new
  segment is downloaded. You can override this function to provide your
  adaptive streaming logic. You must, however, be sure to return a valid
  media playlist object that is present in `player.hls.master`.
  
  Overridding this function with your own is very powerful but is overkill
  for many purposes. Most of the time, you should use the much simpler
  function below to selectively enable or disable a playlist from the
  adaptive streaming logic.
  
  #### hls.representations
  Type: `function`
  
  It is recommended to include the [videojs-contrib-quality-levels](https://github.com/videojs/videojs-contrib-quality-levels) plugin to your page so that videojs-contrib-hls will automatically populate the QualityLevelList exposed on the player by the plugin. You can access this list by calling `player.qualityLevels()`. See the [videojs-contrib-quality-levels project page](https://github.com/videojs/videojs-contrib-quality-levels) for more information on how to use the api.
  
  Example, only enabling representations with a width greater than or equal to 720:
  
  ```javascript
  var qualityLevels = player.qualityLevels();
  
  for (var i = 0; i < qualityLevels.length; i++) {
    var quality = qualityLevels[i];
    if (quality.width >= 720) {
      quality.enabled = true;
    } else {
      quality.enabled = false;
    }
  }
  ```
  
  If including [videojs-contrib-quality-levels](https://github.com/videojs/videojs-contrib-quality-levels) is not an option, you can use the representations api. To get all of the available representations, call the `representations()` method on `player.hls`. This will return a list of plain objects, each with `width`, `height`, `bandwidth`, and `id` properties, and an `enabled()` method.
  
  ```javascript
  player.hls.representations();
  ```
  
  To see whether the representation is enabled or disabled, call its `enabled()` method with no arguments. To set whether it is enabled/disabled, call its `enabled()` method and pass in a boolean value. Calling `<representation>.enabled(true)` will allow the adaptive bitrate algorithm to select the representation while calling `<representation>.enabled(false)` will disallow any selection of that representation.
  
  Example, only enabling representations with a width greater than or equal to 720:
  
  ```javascript
  player.hls.representations().forEach(function(rep) {
    if (rep.width >= 720) {
      rep.enabled(true);
    } else {
      rep.enabled(false);
    }
  });
  ```
  
  #### hls.xhr
  Type: `function`
  
  The xhr function that is used by HLS internally is exposed on the per-
  player `hls` object. While it is possible, we do not recommend replacing
  the function with your own implementation. Instead, the `xhr` provides
  the ability to specify a `beforeRequest` function that will be called
  with an object containing the options that will be used to create the
  xhr request.
  
  Example:
  ```javascript
  player.hls.xhr.beforeRequest = function(options) {
    options.uri = options.uri.replace('example.com', 'foo.com');
  
    return options;
  };
  ```
  
  The global `videojs.Hls` also exposes an `xhr` property. Specifying a
  `beforeRequest` function on that will allow you to intercept the options
  for *all* requests in every player on a page. For consistency across
  browsers the video source should be set at runtime once the video player
  is ready.
  
  Example
  ```javascript
  videojs.Hls.xhr.beforeRequest = function(options) {
    /*
     * Modifications to requests that will affect every player.
     */
  
    return options;
  };
  
  var player = videojs('video-player-id');
  player.ready(function() {
    this.src({
      src: 'https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8',
      type: 'application/x-mpegURL',
    });
  });
  ```
  
  For information on the type of options that you can modify see the
  documentation at [https://github.com/Raynos/xhr](https://github.com/Raynos/xhr).
  
  ### Events
  Standard HTML video events are handled by video.js automatically and
  are triggered on the player object.
  
  #### loadedmetadata
  
  Fired after the first segment is downloaded for a playlist. This will not happen
  until playback if video.js's `metadata` setting is `none`
  
  ### HLS Usage Events
  
  Usage tracking events are fired when we detect a certain HLS feature, encoding setting,
  or API is used. These can be helpful for analytics, and to pinpoint the cause of HLS errors.
  For instance, if errors are being fired in tandem with a usage event indicating that the
  player was playing an AES encrypted stream, then we have a possible avenue to explore when
  debugging the error.
  
  Note that although these usage events are listed below, they may change at any time without
  a major version change.
  
  HLS usage events are triggered on the tech with the exception of the 3 hls-reload-error
  events, which are triggered on the player.
  
  #### Presence Stats
  
  Each of the following usage events are fired once per source if (and when) detected:
  
  | Name          | Description   |
  | ------------- | ------------- |
  | hls-webvtt    | master manifest has at least one segmented WebVTT playlist |
  | hls-aes       | a playlist is AES encrypted |
  | hls-fmp4      | a playlist used fMP4 segments |
  | hls-demuxed   | audio and video are demuxed by default |
  | hls-alternate-audio | alternate audio available in the master manifest |
  | hls-playlist-cue-tags | a playlist used cue tags (see useCueTags(#usecuetags) for details) |
  
  #### Use Stats
  
  Each of the following usage events are fired per use:
  
  | Name          | Description   |
  | ------------- | ------------- |
  | hls-gap-skip  | player skipped a gap in the buffer |
  | hls-player-access | player.hls was accessed |
  | hls-audio-change | a user selected an alternate audio stream |
  | hls-rendition-disabled | a rendition was disabled |
  | hls-rendition-enabled | a rendition was enabled |
  | hls-rendition-blacklisted | a rendition was blacklisted |
  | hls-timestamp-offset | a timestamp offset was set in HLS (can identify discontinuities) |
  | hls-unknown-waiting | the player stopped for an unknown reason and we seeked to current time try to address it |
  | hls-live-resync | playback fell off the back of a live playlist and we resynced to the live point |
  | hls-video-underflow | we seeked to current time to address video underflow |
  | hls-error-reload-initialized | the reloadSourceOnError plugin was initialized |
  | hls-error-reload | the reloadSourceOnError plugin reloaded a source |
  | hls-error-reload-canceled | an error occurred too soon after the last reload, so we didn't reload again (to prevent error loops) |
  
  
  ### In-Band Metadata
  The HLS tech supports [timed
  metadata](https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/HTTP_Live_Streaming_Metadata_Spec/Introduction/Introduction.html)
  embedded as [ID3 tags](http://id3.org/id3v2.3.0). When a stream is
  encountered with embedded metadata, an [in-band metadata text
  track](https://html.spec.whatwg.org/multipage/embedded-content.html#text-track-in-band-metadata-track-dispatch-type)
  will automatically be created and populated with cues as they are
  encountered in the stream. UTF-8 encoded
  [TXXX](http://id3.org/id3v2.3.0#User_defined_text_information_frame)
  and [WXXX](http://id3.org/id3v2.3.0#User_defined_URL_link_frame) ID3
  frames are mapped to cue points and their values set as the cue
  text. Cues are created for all other frame types and the data is
  attached to the generated cue:
  
  ```javascript
  cue.value.data
  ```
  
  There are lots of guides and references to using text tracks [around
  the web](http://www.html5rocks.com/en/tutorials/track/basics/).
  
  ### Segment Metadata
  You can get metadata about the segments currently in the buffer by using the `segment-metadata`
  text track. You can get the metadata of the currently rendered segment by looking at the
  track's `activeCues` array. The metadata will be attached to the `cue.value` property and
  will have this structure
  
  ```javascript
  cue.value = {
    byteLength, // The size of the segment in bytes
    bandwidth, // The peak bitrate reported by the segment's playlist
    resolution, // The resolution reported by the segment's playlist
    codecs, // The codecs reported by the segment's playlist
    uri, // The Segment uri
    timeline, // Timeline of the segment for detecting discontinuities
    playlist, // The Playlist uri
    start, // Segment start time
    end // Segment end time
  };
  ```
  
  Example:
  Detect when a change in quality is rendered on screen
  ```javascript
  let tracks = player.textTracks();
  let segmentMetadataTrack;
  
  for (let i = 0; i < tracks.length; i++) {
    if (tracks[i].label === 'segment-metadata') {
      segmentMetadataTrack = tracks[i];
    }
  }
  
  let previousPlaylist;
  
  if (segmentMetadataTrack) {
    segmentMetadataTrack.on('cuechange', function() {
      let activeCue = segmentMetadataTrack.activeCues[0];
  
      if (activeCue) {
        if (previousPlaylist !== activeCue.value.playlist) {
          console.log('Switched from rendition ' + previousPlaylist +
                      ' to rendition ' + activeCue.value.playlist);
        }
        previousPlaylist = activeCue.value.playlist;
      }
    });
  }
  ```
  
  ## Hosting Considerations
  Unlike a native HLS implementation, the HLS tech has to comply with
  the browser's security policies. That means that all the files that
  make up the stream must be served from the same domain as the page
  hosting the video player or from a server that has appropriate [CORS
  headers](https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS)
  configured. Easy [instructions are
  available](http://enable-cors.org/server.html) for popular webservers
  and most CDNs should have no trouble turning CORS on for your account.
  
  
  ## Known Issues
  Issues that are currenty know about with workarounds. If you want to
  help find a solution that would be appreciated!
  
  ### IE10 and Below
  As of version 5.0.0, IE10 and below are no longer supported.
  
  ### Fragmented MP4 Support
  Edge has native support for HLS but only in the MPEG2-TS container. If
  you attempt to play an HLS stream with fragmented MP4 segments, Edge
  will stall. Fragmented MP4s are only supported on browser that have
  [Media Source Extensions](http://caniuse.com/#feat=mediasource) available.
  
  ### Testing
  
  For testing, you run `npm run test`. This will run tests using any of the
  browsers that karma-detect-browsers detects on your machine.
  
  ## Release History
  Check out the [changelog](CHANGELOG.md) for a summary of each release.
  
  ## Building
  To build a copy of videojs-contrib-hls run the following commands
  
  ```bash
  git clone https://github.com/videojs/videojs-contrib-hls
  cd videojs-contrib-hls
  npm i
  npm run build
  ```
  
  videojs-contrib-hls will have created all of the files for using it in a dist folder
  
  ## Development
  
  ### Tools
  * Download stream locally with the [HLS Fetcher](https://github.com/imbcmdth/hls-fetcher)
  * Simulate errors with [Murphy](https://github.com/mrocajr/murphy)
  
  ### Commands
  All commands for development are listed in the `package.json` file and are run using
  ```bash
  npm run <command>
  ```
  
  [slack-icon]: http://slack.videojs.com/badge.svg
  [slack-link]: http://slack.videojs.com
  [travis-icon]: https://travis-ci.org/videojs/videojs-contrib-hls.svg?branch=master
  [travis-link]: https://travis-ci.org/videojs/videojs-contrib-hls
  [greenkeeper-icon]: https://badges.greenkeeper.io/videojs/videojs-contrib-hls.svg
  [greenkeeper-link]: https://greenkeeper.io/