if audio codec is not signaled in variant manifest, or if only a stream manifest is provided, hls.js tries to guess audio codec by parsing audio sampling rate in ADTS header. if sampling rate is less or equal than 22050 Hz, then hls.js assumes it is HE-AAC, otherwise it assumes it is AAC-LC. This could result in bad guess, leading to audio decode error, ending up in media error.
it is possible to hint default audiocodec to hls.js by configuring this value as below:
in case playback is still stalling although a seek over buffer hole just occured, hls.js will seek to next buffer start + (nb of consecutive stalls * seekHoleNudgeDuration to try to restore playback
this tolerance factor is used during fragment lookup.
instead of checking whether buffered.end is located within [start, end] range, frag lookup will be done by checking within [start-maxFragLookUpTolerance, end-maxFragLookUpTolerance] range
this tolerance factor is used to cope with situations like
buffered.end = 9.991
frag[Ø] : [0,10]
frag[1] : [10,20]
=> buffered.end is within frag[0] range, but as we are close to frag[1], frag[1] should be choosen instead
if maxFragLookUpTolerance=0.2,
this lookup will be adjusted to
frag[Ø] : [-0.2,9.8]
frag[1] : [9.8,19.8]
=> this time, buffered.end is within frag[1] range, and frag[1] will be the next fragment to be loaded, as expected.
maximum buffer Length in seconds. hls.js will never exceed this value. even if maxBufferSize is not reached yet.
hls.js tries to buffer up to a maximum number of bytes (60 MB by default) rather than to buffer up to a maximum nb of seconds.
this is to mimic the browser behaviour (the buffer eviction algorithm is starting after the browser detects that video buffer size reaches a limit in bytes)
config.maxBufferLength is the minimum guaranteed buffer length that hls.js will try to achieve, even if that value exceeds the amount of bytes 60 MB of memory.
maxMaxBufferLength acts as a capping value, as if bitrate is really low, you could need more than one hour of buffer to fill 60 MB....
edge of live delay, expressed in multiple of ```EXT-X-TARGETDURATION```.
if set to 3, playback will start from fragment N-3, N being the last fragment of the live playlist.
decreasing this value is likely to cause playback stalls.
#### ```liveMaxLatencyDurationCount```
(default Infinity)
maximum delay allowed from edge of live, expressed in multiple of ```EXT-X-TARGETDURATION```.
if set to 10, the player will seek back to ```liveSyncDurationCount``` whenever the next fragment to be loaded is older than N-10, N being the last fragment of the live playlist.
If set, this value must be stricly superior to ```liveSyncDurationCount```
a value too close from ```liveSyncDurationCount``` is likely to cause playback stalls.
Alternative parameter to ```liveSyncDurationCount```, expressed in seconds vs number of segments.
If defined in the configuration object, ```liveSyncDuration``` will take precedence over the default```liveSyncDurationCount```.
You can't define this parameter and either ```liveSyncDurationCount``` or ```liveMaxLatencyDurationCount``` in your configuration object at the same time.
A value too low (inferior to ~3 segment durations) is likely to cause playback stalls.
#### ```liveMaxLatencyDuration```
(default undefined)
Alternative parameter to ```liveMaxLatencyDurationCount```, expressed in seconds vs number of segments.
If defined in the configuration object, ```liveMaxLatencyDuration``` will take precedence over the default```liveMaxLatencyDurationCount```.
If set, this value must be stricly superior to ```liveSyncDuration``` which must be defined as well.
You can't define this parameter and either ```liveSyncDurationCount``` or ```liveMaxLatencyDurationCount``` in your configuration object at the same time.
A value too close from ```liveSyncDuration``` is likely to cause playback stalls.
max number of sourceBuffer.appendBuffer() retry upon error.
such error could happen in loop with UHD streams, when internal buffer is full. (Quota Exceeding Error will be triggered). in that case we need to wait for the browser to evict some data before being able to append buffer correctly.
#### ```loader```
(default : standard XmlHttpRequest based URL loader)
override standard URL loader by a custom one.
could be useful for P2P or stubbing (testing).
Use this, if you want to overwrite both the fragment and the playlist loader.
Note: If fLoader or pLoader are used, they overwrite loader!
```js
var customLoader = function() {
/* calling load() will start retrieving content at given URL (HTTP GET)
params :
url : URL to load
responseType : xhr response Type (arraybuffer or default response Type for playlist)
onSuccess : callback triggered upon successful loading of URL.
it should return xhr event and load stats object {trequest,tfirst,tload}
onError : callback triggered if any I/O error is met while loading fragment
onTimeOut : callback triggered if loading is still not finished after a certain duration
timeout : timeout after which onTimeOut callback will be triggered(if loading is still not finished after that delay)
maxRetry : max nb of load retry
retryDelay : delay between an I/O error and following connection retry (ms). this to avoid spamming the server.
This enables the manipulation of the fragment loader.
Note: This will overwrite the default loader, as well as your own loader function (see above).
```js
var customFragmentLoader = function() {
//See loader for details
}
```
#### ```pLoader```
(default : undefined)
This enables the manipulation of the playlist loader.
Note: This will overwrite the default loader, as well as your own loader function (see above).
```js
var customPlaylistLoader = function() {
//See loader for details
}
```
#### ```xhrSetup```
(default : none)
XmlHttpRequest customization callback for default XHR based loader.
parameter should be a function with one single argument (of type XMLHttpRequest).
If ```xhrSetup``` is specified, default loader will invoke it before calling ```xhr.send()```.
This allows user to easily modify/setup XHR. see example below.
```js
var config = {
xhrSetup: function(xhr, url) {
xhr.withCredentials = true; // do send cookies
}
}
```
#### ```abrController```
(default : internal ABR controller)
customized Adaptive Bitrate Streaming Controller
parameter should be a class providing 2 getter/setters and a destroy() method:
- get/set nextAutoLevel : get/set : return next auto-quality level/force next auto-quality level that should be returned (currently used for emergency switch down)
- get/set autoLevelCapping : get/set : capping/max level value that could be used by ABR Controller
- once MediaSource object is successfully created, MEDIA_ATTACHED event will be fired.
#### ```hls.detachMedia()```
calling this method will :
- unbind VideoElement from hls instance,
- signal the end of the stream on MediaSource
- reset video source (```video.src = ''```)
## Quality switch Control API
by default, hls.js handles quality switch automatically, using heuristics based on fragment loading bitrate and quality level bandwidth exposed in the variant manifest.
it is also possible to manually control quality swith using below API:
#### ```hls.levels```
return array of available quality levels
#### ```hls.currentLevel```
get : return current playback quality level
set : trigger an immediate quality level switch to new quality level. this will pause the video if it was playing, flush the whole buffer, and fetch fragment matching with current position and requested quality level. then resume the video if needed once fetched fragment will have been buffered.
set to -1 for automatic level selection
#### ```hls.nextLevel```
get : return next playback quality level (playback quality level for next buffered fragment). return -1 if next fragment not buffered yet.
set : trigger a quality level switch for next fragment. this could eventually flush already buffered next fragment
by default, hls.js will automatically start loading quality level playlists, and fragments after Events.MANIFEST_PARSED event has been triggered (and video element has been attached).
however if ```config.autoStartLoad``` is set to ```false```, the following method needs to be called to manually start playlist and fragments loading:
#### ```hls.startLoad()```
start/restart playlist/fragment loading. this is only effective if MANIFEST_PARSED event has been triggered and video element has been attached to hls object.
-`Hls.Events.FRAG_LOADED` - fired when a fragment loading is completed
- data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length}}
-`Hls.Events.FRAG_PARSING_INIT_SEGMENT` - fired when Init Segment has been extracted from fragment
- data: { moov : moov MP4 box, codecs : codecs found while parsing fragment}
-`Hls.Events.FRAG_PARSING_METADATA` - fired when parsing id3 is completed
- data: { samples : [ id3 pes - pts and dts timestamp are relative, values are in seconds]}
-`Hls.Events.FRAG_PARSING_DATA` - fired when moof/mdat have been extracted from fragment
- data: { moof : moof MP4 box, mdat : mdat MP4 box, startPTS : PTS of first sample, endPTS : PTS of last sample, startDTS : DTS of first sample, endDTS : DTS of last sample, type : stream type (audio or video), nb : number of samples}
-`Hls.Events.FRAG_PARSED` - fired when fragment parsing is completed
- data: undefined
-`Hls.Events.FRAG_BUFFERED` - fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer
-`Hls.Events.FRAG_CHANGED` - fired when fragment matching with current video position is changing
- data: { frag : fragment object }
-`Hls.Events.FPS_DROP` - triggered when FPS drop in last monitoring period is higher than given threshold
- data: {curentDropped : nb of dropped frames in last monitoring period, currentDecoded: nb of decoded frames in last monitoring period, totalDropped : total dropped frames on this video element}
-`Hls.Events.ERROR` - Identifier for an error event
- data: { type : error Type, details : error details, fatal : is error fatal or not, other error specific data}
-`Hls.Events.DESTROYING` - fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a video to the instance of hls.js to handle mid-rolls for example.
- ```Hls.ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR```raised when manifest only contains quality level with codecs incompatible with MediaSource Engine.
- ```Hls.ErrorDetails.BUFFER_ADD_CODEC_ERROR```raised when MediaSource fails to add new sourceBuffer
- data: { type : ```MEDIA_ERROR```, details : ```Hls.ErrorDetails.BUFFER_ADD_CODEC_ERROR```, fatal : ```false```, err : error raised by MediaSource, mimeType: mimeType on which the failure happened}
- ```Hls.ErrorDetails.BUFFER_FULL_ERROR```raised when no data can be appended anymore in media buffer because it is full. this error is recovered automatically by performing a smooth level switching that empty buffers (without disrupting the playback) and reducing the max buffer length.