Skip to content

Latest commit

 

History

History
538 lines (417 loc) · 20.9 KB

API.md

File metadata and controls

538 lines (417 loc) · 20.9 KB

##Hello hls.js !

###first step : setup and support first include dist/hls.{min}.js in your web page and check whether your browser is supporting [MediaSource Extensions][]. [MediaSource Extensions]: http://w3c.github.io/media-source/ just invoke the following static method : Hls.isSupported()

 <script src="dist/hls.{min}.js"></script>
<script> 
  if(Hls.isSupported()) {
 	console.log("hello hls.js!");
 }
</script>

###second step: instanciate hls object and bind it to<video>element let's

  • create a<video>element
  • create a new HLS object
  • bind video element to this HLS object
 <script src="dist/hls.{min}.js"></script>
 
<video id="video"></video>
<script>
  if(Hls.isSupported()) {
    var video = document.getElementById('video');
    var hls = new Hls();
    // bind them together
    hls.attachVideo(video);
    // MSE_ATTACHED event is fired by hls object once MediaSource is ready
    hls.on(Hls.Events.MSE_ATTACHED,function() {
		  console.log("video and hls.js are now bound together !");
    });
 }
</script>

###third step: load a manifest you need to provide manifest URL as below:

 <script src="dist/hls.{min}.js"></script>
 
<video id="video"></video>
<script>
  if(Hls.isSupported()) {
    var video = document.getElementById('video');
    var hls = new Hls();
    // bind them together
    hls.attachVideo(video);
    hls.on(Hls.Events.MSE_ATTACHED,function() {
		console.log("video and hls.js are now bound together !");
		hls.loadSource("http://my.streamURL.com/playlist.m3u8");
		hls.on(Hls.Events.MANIFEST_PARSED, function(event,data) {
         console.log("manifest loaded, found " + data.levels.length + " quality level");
		}
     });
 }
</script>

###fourth step : control through <video> element

video is controlled through HTML <video> element.

HTMLVideoElement control and events could be used seamlessly.

  video.play();

###fifth step : error handling

all errors are signalled through a unique single event.

each error is categorized by :

  • its type:
    • Hls.ErrorTypes.NETWORK_ERRORfor network related errors
    • Hls.ErrorTypes.MEDIA_ERRORfor media/video related errors
    • Hls.ErrorTypes.OTHER_ERRORfor all other errors
  • its details:
    • Hls.ErrorDetails.MANIFEST_LOAD_ERRORraised when manifest loading fails because of a network error
    • Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUTraised when manifest loading fails because of a timeout
    • Hls.ErrorDetails.MANIFEST_PARSING_ERRORraised when manifest parsing failed to find proper content
    • Hls.ErrorDetails.LEVEL_LOAD_ERRORraised when level loading fails because of a network error
    • Hls.ErrorDetails.LEVEL_LOAD_TIMEOUTraised when level loading fails because of a timeout
    • Hls.ErrorDetails.LEVEL_SWITCH_ERRORraised when level switching fails
    • Hls.ErrorDetails.FRAG_LOAD_ERRORraised when fragment loading fails because of a network error
    • Hls.ErrorDetails.FRAG_LOOP_LOADING_ERRORraised upon detection of same fragment being requested in loop
    • Hls.ErrorDetails.FRAG_LOAD_TIMEOUTraised when fragment loading fails because of a timeout
    • Hls.ErrorDetails.FRAG_PARSING_ERRORraised when fragment parsing fails
    • Hls.ErrorDetails.FRAG_APPENDING_ERRORraised when mp4 boxes appending in SourceBuffer fails
  • its fatality:
    • falseif error is not fatal, hls.js will try to recover it
    • trueif error is fatal, an action is required to (try to) recover it.

full details is described below

see sample code below to listen to errors:

  hls.on(Hls.Events.ERROR,function(event,data) {

  var errorType = data.type;
  var errorDetails = data.details;
  var errorFatal = data.fatal;

    switch(data.details) {
      case hls.ErrorDetails.FRAG_LOAD_ERROR:
        // ....
        break;
      default:
        break;  
    }
  }

Fatal Error Recovery

hls.js provides means to 'try to' recover fatal network and media errors, through these 2 methods:

hls.startLoad()

should be invoked to recover network error.

hls.recoverMediaError()

should be invoked to recover media error

error recovery sample code
  hls.on(Hls.Events.ERROR,function(event,data) {
    if(data.fatal) {
      switch(data.type) {
      case Hls.ErrorTypes.NETWORK_ERROR:
      // try to recover network error
        console.log("fatal network error encountered, try to recover");
        hls.recoverNetworkError();
        break;
      case Hls.ErrorTypes.MEDIA_ERROR:
        console.log("fatal media error encountered, try to recover");
        hls.recoverMediaError();
        break;
      default:
      // cannot recover
        hls.destroy();
        break;  
    }
  }

###final step : destroying, switching between streams

hls.destroy() should be called to free used resources and destroy hls context.

Fine Tuning

configuration parameters could be provided to hls.js upon instantiation of Hls Object.

   var config = {
      debug : false,
      autoStartLoad : true,
      maxBufferLength : 30,
      maxBufferSize : 60*1000*1000,
      enableWorker : true,
      fragLoadingTimeOut : 20000,
      fragLoadingMaxRetry : 6,
      fragLoadingRetryDelay : 500,
      manifestLoadingTimeOut : 10000,
      manifestLoadingMaxRetry : 6,
      manifestLoadingRetryDelay : 500,
      fpsDroppedMonitoringPeriod : 5000,
      fpsDroppedMonitoringThreshold : 0.2,
      appendErrorMaxRetry : 200,
      loader : customLoader
    };


var hls = new Hls(config);

debug

(default false)

setting config.debug=true will turn on debug logs on JS console. a logger object could also be provided for custom logging : config.debug=customLogger

autoStartLoad

(default true)

  • if set to true, start level playlist and first fragments will be loaded automatically, after triggering of Hls.Events.MANIFEST_PARSED event
  • if set to false, an explicit API call (hls.startLoad()) will be needed to start quality level/fragment loading.

maxBufferLength

(default 30s)

maximum buffer Length in seconds. if buffer length is/become less than this value, a new fragment will be loaded.

maxBufferSize

(default 60 MB)

maximum buffer size in bytes. if buffer size upfront is bigger than this value, no fragment will be loaded.

enableWorker

(default true)

enable webworker (if available on browser) for TS demuxing/MP4 remuxing, to improve performance and avoid lag/frame drops.

fragLoadingTimeOut/manifestLoadingTimeOut

(default 60000ms for fragment/10000ms for manifest)

URL Loader timeout. A timeout callback will be triggered if loading duration exceeds this timeout. no further action will be done : the load operation will not be cancelled/aborted. It is up to the application to catch this event and treat it as needed.

fragLoadingMaxRetry/manifestLoadingMaxRetry

(default 3)

max nb of load retry

fragLoadingRetryDelay/manifestLoadingRetryDelay

(default 500ms)

initial delay between XmlHttpRequest error and first load retry (in ms) any I/O error will trigger retries every 500ms,1s,2s,4s,8s, ... capped to 64s (exponential backoff)

max nb of append retry

appendErrorMaxRetry

(default 200)

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).

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.load = function(url,responseType,onSuccess,onError,timeout,maxRetry,retryDelay) {}
  
  /* abort any loading in progress */
  this.abort = function() {}
  /* destroy loading context */
  this.destroy = function() {}
  }

Video Binding/Unbinding API

hls.attachVideo(videoElement)

calling this method will :

  • bind videoElement and hls instance,
  • create MediaSource and set it as video source
  • once MediaSource object is successfully created, MSE_ATTACHED event will be fired.

hls.detachVideo()

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 set to -1 for automatic level selection

hls.loadLevel

get : return last loaded fragment quality level.

set : set quality level for next loaded fragment set to -1 for automatic level selection

hls.firstLevel

get : first level index (index of first level appearing in Manifest. it is usually defined as start level hint for player)

hls.startLevel

get/set : start level index (level of first fragment that will be played back)

  • if not overrided by user : first level appearing in manifest will be used as start level.
  • if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment)

default value is firstLevel

hls.autoLevelEnabled

tell whether auto level selection is enabled or not

hls.autoLevelCapping

get/set : capping/max level value that could be used by automatic level selection algorithm

default value is -1 (no level capping)

Network Loading Control API

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.

Analytics

playback session analytics could be retrieved through two means.

hls.stats

get : return aggregated playback session stats

{ 
  tech : 'hls.js',
  levelNb : total nb of quality level referenced in Manifest
  levelStart : first quality level experienced by End User 
  autoLevelMin : min quality level experienced by End User (in auto mode)
  autoLevelMax : max quality level experienced by End User (in auto mode)
  autoLevelAvg : avg quality level experienced by End User (in auto mode)
  autoLevelLast : last quality level experienced by End User (in auto mode)
  autoLevelSwitch : nb of quality level switch in auto mode
  autoLevelCappingMin : min auto quality level capping value
  autoLevelCappingMax : max auto quality level capping value
  autoLevelCappingLast : last auto quality level capping value
  manualLevelMin : min quality level experienced by End User (in manual mode)
  manualLevelMax : max quality level experienced by End User (in manual mode)
  manualLevelLast : last quality level experienced by End User (in manual mode)  
  manualLevelSwitch : nb of quality level switch in manual mode
  fragMinKbps : min fragment load bandwidth
  fragMaxKbps : max fragment load bandwidth
  fragAvgKbps : avg fragment load bandwidth
  fragLastKbps : last fragment load bandwidth
  fragMinLatency : min fragment load latency
  fragMaxLatency : max fragment load latency
  fragAvgLatency : avg fragment load latency
  fragLastLatency : last fragment load latency
  fragBuffered : total nb of buffered fragments  
  fragBufferedBytes : total nb of buffered bytes
  fragChangedAuto : nb of frag played (loaded in auto mode)
  fragChangedManual : nb of frag played (loaded in manual mode)
  fpsDropEvent : nb of FPS drop event
  fpsTotalDroppedFrames : total nb of dropped frames since video element creation
}

Runtime Events

hls.js fires a bunch of events, that could be registered as below:

hls.on(Hls.Events.LEVEL_LOADED,function(event,data) {
  var level_duration = data.details.totalduration;
});

full list of Events available below :

  • Hls.Events.MSE_ATTACHED - fired when MediaSource has been succesfully attached to video element.
    • data: { mediaSource }
  • Hls.Events.MSE_DETACHED - fired when MediaSource has been detached from video element.
    • data: { }
  • Hls.Events.MANIFEST_LOADING - fired to signal that a manifest loading starts
    • data: { url : manifestURL}
  • Hls.Events.MANIFEST_LOADED - fired after manifest has been loaded
    • data: { levels : [available quality levels] , url : manifestURL, stats : { trequest, tfirst, tload, mtime}}
  • Hls.Events.MANIFEST_PARSED - fired after manifest has been parsed
    • data: { levels : [available quality levels] , firstLevel : index of first quality level appearing in Manifest}
  • Hls.Events.LEVEL_LOADING - fired when a level playlist loading starts
    • data: { url : level URL, level : id of level being loaded}
  • Hls.Events.LEVEL_LOADED - fired when a level playlist loading finishes
    • data: { details : levelDetails object, levelId : id of loaded level, stats : { trequest, tfirst, tload, mtime} }
  • Hls.Events.LEVEL_SWITCH - fired when a level switch is requested
    • data: { levelId : id of new level }
  • Hls.Events.FRAG_LOADING - fired when a fragment loading starts
    • data: { frag : fragment object}
  • Hls.Events.FRAG_LOAD_PROGRESS - fired when a fragment load is in progress
    • data: { frag : fragment object, stats : progress event }
  • 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_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
    • data: { frag : fragment object, stats : { trequest, tfirst, tload, tparsed, tbuffered, length} }
  • 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}

##Errors

full list of Errors is described below:

  • Hls.ErrorDetails.MANIFEST_LOAD_ERROR - raised when manifest loading fails because of a network error
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.MANIFEST_LOAD_ERROR, fatal : true,url : manifest URL, response : xhr response, loader : URL loader}
  • Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT - raised when manifest loading fails because of a timeout
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT, fatal : true,url : manifest URL, loader : URL loader}
  • Hls.ErrorDetails.MANIFEST_PARSING_ERROR - raised when manifest parsing failed to find proper content
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.MANIFEST_PARSING_ERROR, fatal : true,url : manifest URL, reason : parsing error reason}
  • Hls.ErrorDetails.LEVEL_LOAD_ERRORraised when level loading fails because of a network error
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.LEVEL_LOAD_ERROR, fatal : true,url : level URL, response : xhr response, loader : URL loader}
  • Hls.ErrorDetails.LEVEL_LOAD_TIMEOUTraised when level loading fails because of a timeout
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.LEVEL_LOAD_TIMEOUT, fatal : true,url : level URL, loader : URL loader}
  • Hls.ErrorDetails.LEVEL_SWITCH_ERRORraised when level switching fails
    • data: { type : OTHER_ERROR, details : Hls.ErrorDetails.LEVEL_SWITCH_ERROR, fatal : false,level : failed level index, reason : failure reason}
  • Hls.ErrorDetails.FRAG_LOAD_ERRORraised when fragment loading fails because of a network error
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.FRAG_LOAD_ERROR, fatal : true/false,frag : fragment object, response : xhr response}
  • Hls.ErrorDetails.FRAG_LOOP_LOADING_ERRORraised upon detection of same fragment being requested in loop
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.FRAG_LOOP_LOADING_ERROR, fatal : true/false,frag : fragment object}
  • Hls.ErrorDetails.FRAG_LOAD_TIMEOUTraised when fragment loading fails because of a timeout
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.FRAG_LOAD_TIMEOUT, fatal : true/false,frag : fragment object}
  • Hls.ErrorDetails.FRAG_PARSING_ERRORraised when fragment parsing fails
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.FRAG_PARSING_ERROR, fatal : true/false, reason : failure reason}
  • Hls.ErrorDetails.FRAG_APPENDING_ERRORraised when mp4 boxes appending in SourceBuffer fails
    • data: { type : NETWORK_ERROR, details : Hls.ErrorDetails.FRAG_APPENDING_ERROR, fatal : true, frag : fragment object}

Objects

Level

a level object represents a given quality level. it contains quality level related info, retrieved from manifest, such as

  • level bitrate
  • used codecs
  • video width/height
  • level name
  • level URL

see sample Level object below:

{
  url: ['http://levelURL.com','http://levelURLfailover.com']
  bitrate: 246440,
  name: "240",
  codecs: "mp4a.40.5,avc1.42000d",
  width: 320,
  height: 136,
}

url is an array, that might contains several items if failover/redundant streams are found in the manifest.

Level details

level detailed infos contains level details retrieved after level playlist parsing, they are specified below :

  • start sequence number
  • end sequence number
  • level total duration
  • level fragment target duration
  • array of fragments info
  • is this level a live playlist or not ?

see sample object below, available after corresponding LEVEL_LOADED event has been fired:

{
  startSN: 0,
  endSN: 50,
  totalduration: 510,
  targetduration: 10,   
  fragments: Array[51],
  live: false
}

Fragment

the Fragment object contains fragment related info, such as

  • fragment URL
  • fragment duration
  • fragment sequence number
  • fragment start offset
  • level Id

see sample object below:

{
  duration: 10,
  level : 3,
  sn: 35,
  start : 30,
  url: 'http://fragURL.com'
}