UNPKG

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