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