UNPKG

32.9 kBMarkdownView Raw
1<img width=300 src="./logo.svg" alt="VHS Logo consisting of a VHS tape, the Video.js logo and the words VHS" />
2
3# videojs-http-streaming (VHS)
4
5[![Build Status][travis-icon]][travis-link]
6[![Slack Status][slack-icon]][slack-link]
7[![Greenkeeper badge][greenkeeper-icon]][greenkeeper-link]
8
9Play HLS, DASH, and future HTTP streaming protocols with video.js, even where they're not
10natively supported.
11
12Included in video.js 7 by default! See the [video.js 7 blog post](https://blog.videojs.com/video-js-7-is-here/)
13
14Maintenance Status: Stable
15
16Video.js Compatibility: 6.0, 7.0
17
18<!-- START doctoc generated TOC please keep comment here to allow auto update -->
19<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
20**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
21
22- [Installation](#installation)
23 - [NPM](#npm)
24 - [CDN](#cdn)
25 - [Releases](#releases)
26 - [Manual Build](#manual-build)
27- [Contributing](#contributing)
28- [Troubleshooting](#troubleshooting)
29- [Talk to us](#talk-to-us)
30- [Getting Started](#getting-started)
31- [Compatibility](#compatibility)
32 - [Via MSE](#via-mse)
33 - [Native only](#native-only)
34 - [Flash Support](#flash-support)
35 - [DRM](#drm)
36- [Documentation](#documentation)
37 - [Options](#options)
38 - [How to use](#how-to-use)
39 - [Initialization](#initialization)
40 - [Source](#source)
41 - [List](#list)
42 - [withCredentials](#withcredentials)
43 - [handleManifestRedirects](#handlemanifestredirects)
44 - [useCueTags](#usecuetags)
45 - [overrideNative](#overridenative)
46 - [blacklistDuration](#blacklistduration)
47 - [bandwidth](#bandwidth)
48 - [useBandwidthFromLocalStorage](#usebandwidthfromlocalstorage)
49 - [enableLowInitialPlaylist](#enablelowinitialplaylist)
50 - [limitRenditionByPlayerDimensions](#limitrenditionbyplayerdimensions)
51 - [smoothQualityChange](#smoothqualitychange)
52 - [allowSeeksWithinUnsafeLiveWindow](#allowseekswithinunsafelivewindow)
53 - [customTagParsers](#customtagparsers)
54 - [customTagMappers](#customtagmappers)
55 - [cacheEncryptionKeys](#cacheencryptionkeys)
56 - [Runtime Properties](#runtime-properties)
57 - [hls.playlists.master](#hlsplaylistsmaster)
58 - [hls.playlists.media](#hlsplaylistsmedia)
59 - [hls.systemBandwidth](#hlssystembandwidth)
60 - [hls.bandwidth](#hlsbandwidth)
61 - [hls.throughput](#hlsthroughput)
62 - [hls.selectPlaylist](#hlsselectplaylist)
63 - [hls.representations](#hlsrepresentations)
64 - [hls.xhr](#hlsxhr)
65 - [hls.stats](#hlsstats)
66 - [Events](#events)
67 - [loadedmetadata](#loadedmetadata)
68 - [HLS Usage Events](#hls-usage-events)
69 - [Presence Stats](#presence-stats)
70 - [Use Stats](#use-stats)
71 - [In-Band Metadata](#in-band-metadata)
72 - [Segment Metadata](#segment-metadata)
73- [Hosting Considerations](#hosting-considerations)
74- [Known Issues](#known-issues)
75 - [Fragmented MP4 Support](#fragmented-mp4-support)
76- [Testing](#testing)
77- [Debugging](#debugging)
78- [Release History](#release-history)
79- [Building](#building)
80- [Development](#development)
81 - [Tools](#tools)
82 - [Commands](#commands)
83
84<!-- END doctoc generated TOC please keep comment here to allow auto update -->
85
86## Installation
87### NPM
88To install `videojs-http-streaming` with npm run
89
90```bash
91npm install --save @videojs/http-streaming
92```
93
94### CDN
95Select a version of VHS from the [CDN](https://unpkg.com/@videojs/http-streaming/dist/)
96
97### Releases
98Download a release of [videojs-http-streaming](https://github.com/videojs/http-streaming/releases)
99
100### Manual Build
101Download a copy of this git repository and then follow the steps in [Building](#building)
102
103## Contributing
104See [CONTRIBUTING.md](/CONTRIBUTING.md)
105
106## Troubleshooting
107See [our troubleshooting guide](/docs/troubleshooting.md)
108
109## Talk to us
110Drop by our slack channel (#playback) on the [Video.js slack][slack-link].
111
112## Getting Started
113This library is included in video.js 7 by default, if you are using an older version of video.js then
114get a copy of [videojs-http-streaming](#installation) and include it in your page along with video.js:
115
116```html
117<video-js id=vid1 width=600 height=300 class="vjs-default-skin" controls>
118 <source
119 src="https://example.com/index.m3u8"
120 type="application/x-mpegURL">
121</video-js>
122<script src="video.js"></script>
123<script src="videojs-http-streaming.min.js"></script>
124<script>
125var player = videojs('vid1');
126player.play();
127</script>
128```
129
130Check out our [live example](https://jsbin.com/gejugat/edit?html,output) if you're having trouble.
131
132Is it recommended to use the `<video-js>` element or load a source with `player.src(sourceObject)` in order to prevent the video element from playing the source natively where HLS is supported.
133
134## Compatibility
135
136### Via MSE
137- Chrome
138- Firefox
139- Internet Explorer 11 Windows 10 or 8.1
140
141Using the [overrideNative](#overridenative) option
142- Chrome Android
143- Edge
144
145### Native only
146- Mac Safari
147- iOS Safari
148
149### Flash Support
150This plugin does not support Flash playback. Instead, it is recommended that users use the [videojs-flashls-source-handler](https://github.com/brightcove/videojs-flashls-source-handler) plugin as a fallback option for browsers that don't have a native
151[HLS](https://caniuse.com/#feat=http-live-streaming)/[DASH](https://caniuse.com/#feat=mpeg-dash) player or support for [Media Source Extensions](http://caniuse.com/#feat=mediasource).
152
153### DRM
154
155DRM is supported through [videojs-contrib-eme](https://github.com/videojs/videojs-contrib-eme). In order to use DRM, include the videojs-contrib-eme plug, [initialize it](https://github.com/videojs/videojs-contrib-eme#initialization), and add options to either the [plugin](https://github.com/videojs/videojs-contrib-eme#plugin-options) or the [source](https://github.com/videojs/videojs-contrib-eme#source-options).
156
157Detailed option information can be found in the [videojs-contrib-eme README](https://github.com/videojs/videojs-contrib-eme/blob/master/README.md).
158
159## Documentation
160[HTTP Live Streaming](https://developer.apple.com/streaming/) (HLS) has
161become a de-facto standard for streaming video on mobile devices
162thanks to its native support on iOS and Android. There are a number of
163reasons independent of platform to recommend the format, though:
164
165- Supports (client-driven) adaptive bitrate selection
166- Delivered over standard HTTP ports
167- Simple, text-based manifest format
168- No proprietary streaming servers required
169
170Unfortunately, all the major desktop browsers except for Safari are
171missing HLS support. That leaves web developers in the unfortunate
172position of having to maintain alternate renditions of the same video
173and potentially having to forego HTML-based video entirely to provide
174the best desktop viewing experience.
175
176This project addresses that situation by providing a polyfill for HLS
177on browsers that have support for [Media Source
178Extensions](http://caniuse.com/#feat=mediasource).
179You can deploy a single HLS stream, code against the
180regular HTML5 video APIs, and create a fast, high-quality video
181experience across all the big web device categories.
182
183Check out the [full documentation](docs/README.md) for details on how HLS works
184and advanced configuration. A description of the [adaptive switching
185behavior](docs/bitrate-switching.md) is available, too.
186
187videojs-http-streaming supports a bunch of HLS features. Here
188are some highlights:
189
190- video-on-demand and live playback modes
191- backup or redundant streams
192- mid-segment quality switching
193- AES-128 segment encryption
194- CEA-608 captions are automatically translated into standard HTML5
195 [caption text tracks][0]
196- In-Manifest WebVTT subtitles are automatically translated into standard HTML5
197 subtitle tracks
198- Timed ID3 Metadata is automatically translated into HTML5 metedata
199 text tracks
200- Highly customizable adaptive bitrate selection
201- Automatic bandwidth tracking
202- Cross-domain credentials support with CORS
203- Tight integration with video.js and a philosophy of exposing as much
204 as possible with standard HTML APIs
205- Stream with multiple audio tracks and switching to those audio tracks
206 (see the docs folder) for info
207- Media content in
208 [fragmented MP4s](https://developer.apple.com/videos/play/wwdc2016/504/)
209 instead of the MPEG2-TS container format.
210
211[0]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track
212
213### Options
214#### How to use
215
216##### Initialization
217You may pass in an options object to the hls source handler at player
218initialization. You can pass in options just like you would for other
219parts of video.js:
220
221```javascript
222// html5 for html hls
223videojs(video, {
224 html5: {
225 hls: {
226 withCredentials: true
227 }
228 }
229});
230```
231
232##### Source
233Some options, such as `withCredentials` can be passed in to hls during
234`player.src`
235
236```javascript
237
238var player = videojs('some-video-id');
239
240player.src({
241 src: 'https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8',
242 type: 'application/x-mpegURL',
243 withCredentials: true
244});
245```
246
247#### List
248##### withCredentials
249* Type: `boolean`
250* can be used as a source option
251* can be used as an initialization option
252
253When the `withCredentials` property is set to `true`, all XHR requests for
254manifests and segments would have `withCredentials` set to `true` as well. This
255enables storing and passing cookies from the server that the manifests and
256segments live on. This has some implications on CORS because when set, the
257`Access-Control-Allow-Origin` header cannot be set to `*`, also, the response
258headers require the addition of `Access-Control-Allow-Credentials` header which
259is set to `true`.
260See html5rocks's [article](http://www.html5rocks.com/en/tutorials/cors/)
261for more info.
262
263##### handleManifestRedirects
264* Type: `boolean`
265* Default: `false`
266* can be used as a source option
267* can be used as an initialization option
268
269When the `handleManifestRedirects` property is set to `true`, manifest requests
270which are redirected will have their URL updated to the new URL for future
271requests.
272
273##### useCueTags
274* Type: `boolean`
275* can be used as an initialization option
276
277When the `useCueTags` property is set to `true,` a text track is created with
278label 'ad-cues' and kind 'metadata'. The track is then added to
279`player.textTracks()`. Changes in active cue may be
280tracked by following the Video.js cue points API for text tracks. For example:
281
282```javascript
283let textTracks = player.textTracks();
284let cuesTrack;
285
286for (let i = 0; i < textTracks.length; i++) {
287  if (textTracks[i].label === 'ad-cues') {
288    cuesTrack = textTracks[i];
289  }
290}
291
292cuesTrack.addEventListener('cuechange', function() {
293 let activeCues = cuesTrack.activeCues;
294
295  for (let i = 0; i < activeCues.length; i++) {
296 let activeCue = activeCues[i];
297
298    console.log('Cue runs from ' + activeCue.startTime +
299 ' to ' + activeCue.endTime);
300  }
301});
302```
303
304##### overrideNative
305* Type: `boolean`
306* can be used as an initialization option
307
308Try to use videojs-http-streaming even on platforms that provide some
309level of HLS support natively. There are a number of platforms that
310*technically* play back HLS content but aren't very reliable or are
311missing features like CEA-608 captions support. When `overrideNative`
312is true, if the platform supports Media Source Extensions
313videojs-http-streaming will take over HLS playback to provide a more
314consistent experience.
315
316```javascript
317// via the constructor
318var player = videojs('playerId', {
319 html5: {
320 hls: {
321 overrideNative: true
322 }
323 }
324});
325
326// via the source
327var player = videojs('playerId');
328
329player.src({
330 src: 'https://example.com/index.m3u8',
331 type: 'application/x-mpegURL',
332 overrideNative: true
333});
334```
335
336##### blacklistDuration
337* Type: `number`
338* can be used as an initialization option
339
340When the `blacklistDuration` property is set to a time duration in seconds,
341if a playlist is blacklisted, it will be blacklisted for a period of that
342customized duration. This enables the blacklist duration to be configured
343by the user.
344
345##### bandwidth
346* Type: `number`
347* can be used as an initialization option
348
349When the `bandwidth` property is set (bits per second), it will be used in
350the calculation for initial playlist selection, before more bandwidth
351information is seen by the player.
352
353##### useBandwidthFromLocalStorage
354* Type: `boolean`
355* can be used as an initialization option
356 If true, `bandwidth` and `throughput` values are stored in and retrieved from local
357storage on startup (for initial rendition selection). This setting is `false` by default.
358
359##### enableLowInitialPlaylist
360* Type: `boolean`
361* can be used as an initialization option
362
363When `enableLowInitialPlaylist` is set to true, it will be used to select
364the lowest bitrate playlist initially. This helps to decrease playback start time.
365This setting is `false` by default.
366
367##### limitRenditionByPlayerDimensions
368* Type: `boolean`
369* can be used as an initialization option
370
371##### useDevicePixelRatio
372* Type: `boolean`
373* can be used as an initialization option.
374
375If true, this will take the device pixel ratio into account when doing rendition switching. This means that if you have a player with the width of `540px` in a high density display with a device pixel ratio of 2, a rendition of `1080p` will be allowed.
376This setting is `false` by default.
377
378When `limitRenditionByPlayerDimensions` is set to true, rendition
379selection logic will take into account the player size and rendition
380resolutions when making a decision.
381This setting is `true` by default.
382
383##### smoothQualityChange
384* Type: `boolean`
385* can be used as a source option
386* can be used as an initialization option
387
388When the `smoothQualityChange` property is set to `true`, a manual quality
389change triggered via the [representations API](#hlsrepresentations) will use
390smooth quality switching rather than the default fast (buffer-ejecting)
391quality switching. Using smooth quality switching will mean no loading spinner
392will appear during quality switches, but will cause quality switches to only
393be visible after a few seconds.
394
395Note that this _only_ affects quality changes triggered via the representations
396API; automatic quality switches based on available bandwidth will always be
397smooth switches.
398
399##### allowSeeksWithinUnsafeLiveWindow
400* Type: `boolean`
401* can be used as a source option
402
403When `allowSeeksWithinUnsafeLiveWindow` is set to `true`, if the active playlist is live
404and a seek is made to a time between the safe live point (end of manifest minus three
405times the target duration,
406see [the hls spec](https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-6.3.3)
407for details) and the end of the playlist, the seek is allowed, rather than corrected to
408the safe live point.
409
410This option can help in instances where the live stream's target duration is greater than
411the segment durations, playback ends up in the unsafe live window, and there are gaps in
412the content. In this case the player will attempt to seek past the gaps but end up seeking
413inside of the unsafe range, leading to a correction and seek back into a previously played
414content.
415
416The property defaults to `false`.
417
418##### customTagParsers
419* Type: `Array`
420* can be used as a source option
421
422With `customTagParsers` you can pass an array of custom m3u8 tag parser objects. See https://github.com/videojs/m3u8-parser#custom-parsers
423
424##### customTagMappers
425* Type: `Array`
426* can be used as a source option
427
428Similar to `customTagParsers`, with `customTagMappers` you can pass an array of custom m3u8 tag mapper objects. See https://github.com/videojs/m3u8-parser#custom-parsers
429
430##### cacheEncryptionKeys
431* Type: `boolean`
432* can be used as a source option
433* can be used as an initialization option
434
435This option forces the player to cache AES-128 encryption keys internally instead of requesting the key alongside every segment request.
436This option defaults to `false`.
437
438### Runtime Properties
439Runtime properties are attached to the tech object when HLS is in
440use. You can get a reference to the HLS source handler like this:
441
442```javascript
443var hls = player.tech().hls;
444```
445
446If you *were* thinking about modifying runtime properties in a
447video.js plugin, we'd recommend you avoid it. Your plugin won't work
448with videos that don't use videojs-http-streaming and the best plugins
449work across all the media types that video.js supports. If you're
450deploying videojs-http-streaming on your own website and want to make a
451couple tweaks though, go for it!
452
453#### hls.playlists.master
454Type: `object`
455
456An object representing the parsed master playlist. If a media playlist
457is loaded directly, a master playlist with only one entry will be
458created.
459
460#### hls.playlists.media
461Type: `function`
462
463A function that can be used to retrieve or modify the currently active
464media playlist. The active media playlist is referred to when
465additional video data needs to be downloaded. Calling this function
466with no arguments returns the parsed playlist object for the active
467media playlist. Calling this function with a playlist object from the
468master playlist or a URI string as specified in the master playlist
469will kick off an asynchronous load of the specified media
470playlist. Once it has been retreived, it will become the active media
471playlist.
472
473#### hls.systemBandwidth
474Type: `number`
475
476`systemBandwidth` is a combination of two serial processes' bitrates. The first
477is the network bitrate provided by `bandwidth` and the second is the bitrate of
478the entire process after that (decryption, transmuxing, and appending) provided
479by `throughput`. This value is used by the default implementation of `selectPlaylist`
480to select an appropriate bitrate to play.
481
482Since the two process are serial, the overall system bandwidth is given by:
483`systemBandwidth = 1 / (1 / bandwidth + 1 / throughput)`
484
485#### hls.bandwidth
486Type: `number`
487
488The number of bits downloaded per second in the last segment download.
489
490Before the first video segment has been downloaded, it's hard to
491estimate bandwidth accurately. The HLS tech uses a starting value of 4194304 or 0.5 MB/s. If you
492have a more accurate source of bandwidth information, you can override
493this value as soon as the HLS tech has loaded to provide an initial
494bandwidth estimate.
495
496#### hls.throughput
497Type: `number`
498
499The number of bits decrypted, transmuxed, and appended per second as a cumulative average across active processing time.
500
501#### hls.selectPlaylist
502Type: `function`
503
504A function that returns the media playlist object to use to download
505the next segment. It is invoked by the tech immediately before a new
506segment is downloaded. You can override this function to provide your
507adaptive streaming logic. You must, however, be sure to return a valid
508media playlist object that is present in `player.hls.master`.
509
510Overridding this function with your own is very powerful but is overkill
511for many purposes. Most of the time, you should use the much simpler
512function below to selectively enable or disable a playlist from the
513adaptive streaming logic.
514
515#### hls.representations
516Type: `function`
517
518It is recommended to include the [videojs-contrib-quality-levels](https://github.com/videojs/videojs-contrib-quality-levels) plugin to your page so that videojs-http-streaming 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.
519
520Example, only enabling representations with a width greater than or equal to 720:
521
522```javascript
523var qualityLevels = player.qualityLevels();
524
525for (var i = 0; i < qualityLevels.length; i++) {
526 var quality = qualityLevels[i];
527 if (quality.width >= 720) {
528 quality.enabled = true;
529 } else {
530 quality.enabled = false;
531 }
532}
533```
534
535If 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.
536
537```javascript
538player.hls.representations();
539```
540
541To 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.
542
543Example, only enabling representations with a width greater than or equal to 720:
544
545```javascript
546player.hls.representations().forEach(function(rep) {
547 if (rep.width >= 720) {
548 rep.enabled(true);
549 } else {
550 rep.enabled(false);
551 }
552});
553```
554
555#### hls.xhr
556Type: `function`
557
558The xhr function that is used by HLS internally is exposed on the per-
559player `hls` object. While it is possible, we do not recommend replacing
560the function with your own implementation. Instead, the `xhr` provides
561the ability to specify a `beforeRequest` function that will be called
562with an object containing the options that will be used to create the
563xhr request.
564
565Example:
566```javascript
567player.hls.xhr.beforeRequest = function(options) {
568 options.uri = options.uri.replace('example.com', 'foo.com');
569
570 return options;
571};
572```
573
574The global `videojs.Hls` also exposes an `xhr` property. Specifying a
575`beforeRequest` function on that will allow you to intercept the options
576for *all* requests in every player on a page. For consistency across
577browsers the video source should be set at runtime once the video player
578is ready.
579
580Example
581```javascript
582videojs.Hls.xhr.beforeRequest = function(options) {
583 /*
584 * Modifications to requests that will affect every player.
585 */
586
587 return options;
588};
589
590var player = videojs('video-player-id');
591player.ready(function() {
592 this.src({
593 src: 'https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8',
594 type: 'application/x-mpegURL',
595 });
596});
597```
598
599For information on the type of options that you can modify see the
600documentation at [https://github.com/Raynos/xhr](https://github.com/Raynos/xhr).
601
602#### hls.stats
603Type: `object`
604
605This object contains a summary of HLS and player related stats.
606
607| Property Name | Type | Description |
608| --------------------- | ------ | ----------- |
609| bandwidth | number | Rate of the last segment download in bits/second |
610| mediaRequests | number | Total number of media segment requests |
611| mediaRequestsAborted | number | Total number of aborted media segment requests |
612| mediaRequestsTimedout | number | Total number of timedout media segment requests |
613| mediaRequestsErrored | number | Total number of errored media segment requests |
614| mediaTransferDuration | number | Total time spent downloading media segments in milliseconds |
615| mediaBytesTransferred | number | Total number of content bytes downloaded |
616| mediaSecondsLoaded | number | Total number of content seconds downloaded |
617| buffered | array | List of time ranges of content that are in the SourceBuffer |
618| currentTime | number | The current position of the player |
619| currentSource | object | The source object. Has the structure `{src: 'url', type: 'mimetype'}` |
620| currentTech | string | The name of the tech in use |
621| duration | number | Duration of the video in seconds |
622| master | object | The [master playlist object](#hlsplaylistsmaster) |
623| playerDimensions | object | Contains the width and height of the player |
624| seekable | array | List of time ranges that the player can seek to |
625| timestamp | number | Timestamp of when `hls.stats` was accessed |
626| videoPlaybackQuality | object | Media playback quality metrics as specified by the [W3C's Media Playback Quality API](https://wicg.github.io/media-playback-quality/) |
627
628
629### Events
630Standard HTML video events are handled by video.js automatically and
631are triggered on the player object.
632
633#### loadedmetadata
634
635Fired after the first segment is downloaded for a playlist. This will not happen
636until playback if video.js's `metadata` setting is `none`
637
638### HLS Usage Events
639
640Usage tracking events are fired when we detect a certain HLS feature, encoding setting,
641or API is used. These can be helpful for analytics, and to pinpoint the cause of HLS errors.
642For instance, if errors are being fired in tandem with a usage event indicating that the
643player was playing an AES encrypted stream, then we have a possible avenue to explore when
644debugging the error.
645
646Note that although these usage events are listed below, they may change at any time without
647a major version change.
648
649HLS usage events are triggered on the tech with the exception of the 3 hls-reload-error
650events, which are triggered on the player.
651
652#### Presence Stats
653
654Each of the following usage events are fired once per source if (and when) detected:
655
656| Name | Description |
657| ------------- | ------------- |
658| hls-webvtt | master manifest has at least one segmented WebVTT playlist |
659| hls-aes | a playlist is AES encrypted |
660| hls-fmp4 | a playlist used fMP4 segments |
661| hls-demuxed | audio and video are demuxed by default |
662| hls-alternate-audio | alternate audio available in the master manifest |
663| hls-playlist-cue-tags | a playlist used cue tags (see useCueTags(#usecuetags) for details) |
664| hls-bandwidth-from-local-storage | starting bandwidth was retrieved from local storage (see useBandwidthFromLocalStorage(#useBandwidthFromLocalStorage) for details) |
665| hls-throughput-from-local-storage | starting throughput was retrieved from local storage (see useBandwidthFromLocalStorage(#useBandwidthFromLocalStorage) for details) |
666
667#### Use Stats
668
669Each of the following usage events are fired per use:
670
671| Name | Description |
672| ------------- | ------------- |
673| hls-gap-skip | player skipped a gap in the buffer |
674| hls-player-access | player.hls was accessed |
675| hls-audio-change | a user selected an alternate audio stream |
676| hls-rendition-disabled | a rendition was disabled |
677| hls-rendition-enabled | a rendition was enabled |
678| hls-rendition-blacklisted | a rendition was blacklisted |
679| hls-timestamp-offset | a timestamp offset was set in HLS (can identify discontinuities) |
680| hls-unknown-waiting | the player stopped for an unknown reason and we seeked to current time try to address it |
681| hls-live-resync | playback fell off the back of a live playlist and we resynced to the live point |
682| hls-video-underflow | we seeked to current time to address video underflow |
683| hls-error-reload-initialized | the reloadSourceOnError plugin was initialized |
684| hls-error-reload | the reloadSourceOnError plugin reloaded a source |
685| hls-error-reload-canceled | an error occurred too soon after the last reload, so we didn't reload again (to prevent error loops) |
686
687
688### In-Band Metadata
689The HLS tech supports [timed
690metadata](https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/HTTP_Live_Streaming_Metadata_Spec/Introduction/Introduction.html)
691embedded as [ID3 tags](http://id3.org/id3v2.3.0). When a stream is
692encountered with embedded metadata, an [in-band metadata text
693track](https://html.spec.whatwg.org/multipage/embedded-content.html#text-track-in-band-metadata-track-dispatch-type)
694will automatically be created and populated with cues as they are
695encountered in the stream. UTF-8 encoded
696[TXXX](http://id3.org/id3v2.3.0#User_defined_text_information_frame)
697and [WXXX](http://id3.org/id3v2.3.0#User_defined_URL_link_frame) ID3
698frames are mapped to cue points and their values set as the cue
699text. Cues are created for all other frame types and the data is
700attached to the generated cue:
701
702```javascript
703cue.value.data
704```
705
706There are lots of guides and references to using text tracks [around
707the web](http://www.html5rocks.com/en/tutorials/track/basics/).
708
709### Segment Metadata
710You can get metadata about the segments currently in the buffer by using the `segment-metadata`
711text track. You can get the metadata of the currently rendered segment by looking at the
712track's `activeCues` array. The metadata will be attached to the `cue.value` property and
713will have this structure
714
715```javascript
716cue.value = {
717 byteLength, // The size of the segment in bytes
718 bandwidth, // The peak bitrate reported by the segment's playlist
719 resolution, // The resolution reported by the segment's playlist
720 codecs, // The codecs reported by the segment's playlist
721 uri, // The Segment uri
722 timeline, // Timeline of the segment for detecting discontinuities
723 playlist, // The Playlist uri
724 start, // Segment start time
725 end // Segment end time
726};
727```
728
729Example:
730Detect when a change in quality is rendered on screen
731```javascript
732let tracks = player.textTracks();
733let segmentMetadataTrack;
734
735for (let i = 0; i < tracks.length; i++) {
736 if (tracks[i].label === 'segment-metadata') {
737 segmentMetadataTrack = tracks[i];
738 }
739}
740
741let previousPlaylist;
742
743if (segmentMetadataTrack) {
744 segmentMetadataTrack.on('cuechange', function() {
745 let activeCue = segmentMetadataTrack.activeCues[0];
746
747 if (activeCue) {
748 if (previousPlaylist !== activeCue.value.playlist) {
749 console.log('Switched from rendition ' + previousPlaylist +
750 ' to rendition ' + activeCue.value.playlist);
751 }
752 previousPlaylist = activeCue.value.playlist;
753 }
754 });
755}
756```
757
758## Hosting Considerations
759Unlike a native HLS implementation, the HLS tech has to comply with
760the browser's security policies. That means that all the files that
761make up the stream must be served from the same domain as the page
762hosting the video player or from a server that has appropriate [CORS
763headers](https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS)
764configured. Easy [instructions are
765available](http://enable-cors.org/server.html) for popular webservers
766and most CDNs should have no trouble turning CORS on for your account.
767
768
769## Known Issues
770Issues that are currenty known. If you want to
771help find a solution that would be appreciated!
772
773### Fragmented MP4 Support
774Edge has native support for HLS but only in the MPEG2-TS container. If
775you attempt to play an HLS stream with fragmented MP4 segments, Edge
776will stall. Fragmented MP4s are only supported on browser that have
777[Media Source Extensions](http://caniuse.com/#feat=mediasource) available.
778
779## Testing
780
781For testing, you run `npm run test`. You will need Chrome and Firefox for running the tests.
782
783_videojs-http-streaming uses [BrowserStack](https://browserstack.com) for compatibility testing._
784
785## Debugging
786
787videojs-http-streaming makes use of `videojs.log` for debug logging. You can enable these logs
788by setting the log level to `debug` using `videojs.log.level('debug')`. You can access a complete
789history of the logs using `videojs.log.history()`. This history is maintained even when the
790log level is not set to `debug`.
791
792`hls.stats` can also be helpful when debugging. Accessing this object will give you
793a snapshot summary of various HLS and player stats. See [hls.stats](#hlsstats) for details
794about what this object contains.
795
796__NOTE__: The `debug` level is only available in video.js v6.6.0+. With earlier versions of
797video.js, no debug messages will be logged to console.
798
799## Release History
800Check out the [changelog](CHANGELOG.md) for a summary of each release.
801
802## Building
803To build a copy of videojs-http-streaming run the following commands
804
805```bash
806git clone https://github.com/videojs/http-streaming
807cd http-streaming
808npm i
809npm run build
810```
811
812videojs-http-streaming will have created all of the files for using it in a dist folder
813
814## Development
815
816### Tools
817* Download stream locally with the [HLS Fetcher](https://github.com/videojs/hls-fetcher)
818* Simulate errors with [Murphy](https://github.com/videojs/murphy)
819* Inspect content with [Thumbcoil](http://thumb.co.il)
820
821### Commands
822All commands for development are listed in the `package.json` file and are run using
823```bash
824npm run <command>
825```
826
827[slack-icon]: http://slack.videojs.com/badge.svg
828[slack-link]: http://slack.videojs.com
829[travis-icon]: https://travis-ci.org/videojs/http-streaming.svg?branch=master
830[travis-link]: https://travis-ci.org/videojs/http-streaming
831[issue-stats-link]: http://issuestats.com/github/videojs/http-streaming
832[issue-stats-pr-icon]: http://issuestats.com/github/videojs/http-streaming/badge/pr
833[issue-stats-issues-icon]: http://issuestats.com/github/videojs/http-streaming/badge/issue
834[greenkeeper-icon]: https://badges.greenkeeper.io/videojs/http-streaming.svg
835[greenkeeper-link]: https://greenkeeper.io/