JWPlayer HLS Mystery

 

hsl.png

Since a couple of days before, I have been started looking into the JwPlayer latest version changes and understanding its behavior especially for HLS rendering support.

While investigation I came across a lot of facts’s about the JW player internal functional flow, hope this will help you too, in case you are interested in exploring the player mystery. 🙂

Here my intention to consider the name of JW player especially because I did research only on it till now, and love to share my experience with you all.

So the story begins by considering the facts about the latest changes going on from browser side. Hope every one of you already knows that nowadays most of the browsers are updated multiple times per month.

Let’s talk about one big update recently announced by famous browser chrome. you will find more in detailed article’s and blogs on this topic from the google search but just let me set you the context for further discussion. I am talking about the google chrome announcement.

Google Chrome will start blocking all Flash content next month

I read this article from one of the blog just couple of months before, you can refer below link for the same

Guys this is not the small announcement, it will impact almost all the industries associated with the online media/video streaming business, but such changes are always welcome by industries towards performance & user experience practices. so we can say that this will be complete transformation phase going on in all technological area and we all must have to adopt it.

I am not going to focus on another discussion now, you guys are smart enough to do further investigation on this relevant topic, let me strict on the topic related to JwPlayer mystery.

What do think, Why this topic titled “jwPlayer HLS Mystery” and How above context is relevant to this topic? 🙂

Confused……?

No issue, I will explain you all the story in sequence. first of all, I would like to help you understanding about the transformation phase between latest browsers changes and player releases, here you can expect some issues because due to a lot of frequent changes going on both side browsers & player release, so things are not stable but believe me those changes must be required for betterment.

Due to frequent browser changes, Player industries should have to make changes in their code base accordingly and I found Jwplayer doing it very fast, I personally appreciate their efforts.

Here the word mystery used to indicate non-documented or ignored things which required more attention while integrating JW player in your project.

I am providing you all the details related to latest Jwplayer version 7.8.6

Let’s start with JwPlayer Limitation: 

In reference to the documentation, If you look at the browser support table for streaming media on Media Format Reference, you will notice that JW player team state that DASH playback is only available in Firefox 45, or higher, or in IE 11 in Windows 8.1 or 10. There are no such browser version-specific limitations for HLS playback but most preferably all modern browsers which support HTML5 will good for HLS rendering.

The general rule of thumb is that if a browser is more than 6-12 months old, JW player cannot be expected to perform at its highest potential.

An m3u8 is an HLS stream. It can be displayed natively only in Safari, iOS, and Android. In all other desktop browsers, it requires Flash. You can’t “push” HTML5 – Chrome, Firefox, and IE can’t display an HLS stream in HTML5. And even in Flash, it requires a JW Player Premium license or higher.

Jwplayer renders HLS streams in HTML5, here is the list of all modern browsers

  • Mac – Chrome, Firefox, Safari
  • Windows – Chrome, Firefox, Edge
  • iOS – Safari
  • Android – Chrome

This means that the only browser JW player supports that would still require Flash for HLS playback are Internet Explorer. JW player Engineers are introducing functionality to render HLS streams in HTML5 in Internet Explorer 11 in an upcoming version, but that will only work in Windows 8.1 or 10. This limitation is due to the fact that IE 11 in Windows 7 does not contain the functionality needed to make this work in that environment, which is the same reason why it would not work in IE 9 or 10.

In order to properly serve those users who are using Internet Explorer but do not have Flash enabled or installed, I recommend providing a MP4 fallback source. Please see Configuring Multiple Sources support article for more information on how this would work. This would obviously only work for on-demand content, not live streams, as there is no streaming format that is playable in those versions of IE without the use of Flash.

let me list down some more important point about limitations below

  • HLS in Flash is only supported by JW Premium or higher licenses
  • DASH is only supported by JW Premium or higher licenses
  • HLS is playable in HTML5 in Chrome using JW Player 7.4.2, or higher, and by either enabling the option in the cloud-hosted player configuration, or by adding “hlshtml: true” to your embed code.
  • DASH is playable in Firefox 45, or higher, using JW Player 7.4.2, or higher
  • HLS is playable in HTML5 in Firefox using JW Player 7.7.0, or higher, and by either enabling the option in the cloud-hosted player configuration or by adding “hlshtml: true” to your embed code.
  • HLS will only work on Android 4.1+.
  • Can only be enabled on by setting the option “androidhls: true” within your JW Player embed.
  • Internet Explorer HLS supported in Flash is only

Two common mistakes prevent smooth playback of videos in Internet Explorer 9+. First, always start your HTML document with to prevent triggering IE’s quirks mode. Second, serve up your videos with the video/mp4 mimetype or IE will refuse to play them.

If you would like to alternatively provide a custom error message to your users when Flash is not available, you could potentially write custom JavaScript with JavaScript API. One example of how you may be able to do this can be found below

         <script type="text/javascript">
          var playerInstance = jwplayer("myElement");
          var hasFlash = false;
          playerInstance.setup({
            file: "http://content.jwplatform.com/manifests/BW8lmtBQ.m3u8",
            primary: "flash"
          });

          playerInstance.on("setupError", function(e){
            if (e.message == "Error loading player: No playable sources found") {
              try {
                hasFlash = Boolean(new ActiveXObject("ShockwaveFlash.ShockwaveFlash"));
              } catch(exception) {
                hasFlash = ("undefined" != typeof navigator.mimeTypes["application/x-shockwave-flash"]);
              }

              if (!hasFlash) {
                document.getElementById("myElement").innerHTML = "This video requires Flash Player. Either it is not installed, or otherwise disabled.";
              } else {
                return;
              }
            }
          });
playerInstance.on("setupError", function(e){
if (e.message =="Error loading playlist: No playable sources found") {
 try { 
     hasFlash = Boolean(new ActiveXObject("ShockwaveFlash.ShockwaveFlash")); 
     } catch(exception) { 
   hasFlash = ("undefined" != typeof navigator.mimeTypes["application/x-shockwave-flash"]); 
} 
if (!hasFlash) { 
    document.getElementById("myElement").innerHTML = "This video requires Flash Player. Either it is not installed, or otherwise disabled."; 
} else { 
    return; 
  }
 } 
}); 
         playerInstance.on("mediaError", function(e){
            // your error log code here
          }); 

JwPlayer Configuration:

Refer below setup config with default values which can be overwritten, please note that most of the attributes from below list are not documented in JW player site but I found it while debugging the code so mentioned, rest all the attributes which is not listed here can be found on JW player website documentation.

Here few points to remember.

  • playlist object must require at least one item to play without error
  • setup object should be in the correct format, recommend to parsed using JSON.parse, and use JSON.Stringify, just to avoid any string parsing errors, here I am also assuming that few of the objects are referred dynamically generated from the server and assigned to setup object attribute.

For example:

var playerInstance = jwplayer('player');
//Player setup
playerInstance.setup(JSON.parse(JSON.stringify(setupObject)));

Setup Config Object

{
androidhls: false,
castAvailable : false,
mobilecontrols: false,
mediaContainer: {},// this will give you player DOM object
controls: false,
dash: false,
flashBlocked: false,
flashloader: "jwplayer-7.8.4/jwplayer.loader.swf",
flashplayer: "jwplayer-7.8.4/jwplayer.flash.swf",
fullscreen: false,
ga: {},// optional , if you need googleAnalytics integration then use
hlshtml: false,
key: "----your key goes here----",
plugins: {
"http://ssl.p.jwpcdn.com/player/v/7.8.4/gapro.js": {},
"http://ssl.p.jwpcdn.com/player/v/7.8.4/googima.js": {},
"http://ssl.p.jwpcdn.com/player/v/7.8.4/jwpsrv.js": {},
"http://ssl.p.jwpcdn.com/player/v/7.8.4/related.js": {
   disableRelated: true,
   showDockButton: true
  }
},
preload: "none",
scrubbing:false,
repeat: false,
renderCaptionsNatively: false,
skin: "seven",
type: "hls",
base: "http://ssl.p.jwpcdn.com/player/v/7.8.4/",//by default it refer '/'
captions: {
   back: true,
   backgroundColor: "#000",
   backgroundOpacity: 100,
   color:"#FFF",
   edgeStyle: null,
   fontFamily: "Arial,sans-serif",
   fontOpacity: 100,
   fontSize: 14,
   windowColor: "#FFF",
   windowOpacity: 0
}, advertising : {
  autoplayadsmuted: false,
  client: "googima",
  schedule: {
     // --- you can refer jwplayer documentation for ads more detail
  }
},
localization: {
  audioTracks: "Audio tracks",
  buffer: "Loading",
  cast: "Chromecast",
  cc: "Closed captions",
  fullscreen: "Fullscreen",
  hd: "Quality",
  liveBroadcast: "Live broadcast",
  loadingAd: "Loading ad",
  more: "More",
  next: "Next",
  nextUp: "Next Up",
  pause: "Pause",
  play: "Play",
  playback: "Start playback",
  playlist: "Playlist",
  prev: "Previous",
  related: "Related",
  replay: "Replay",
  rewind: "Rewind 10s",
  volume: "Volume"
}
playlist: [{}] // refer documentation for more detail
}
}

Jwplayer Utils Library 

JwPlayer also provides you one small utility library which you can use in your project instead of using any external library for some utility tasks while JW player integration like below.

some examples are given like below, you can all details by below line

console.log( playerInstance.utils );

You will get a lot of details from utils which you can utilize, let me give you some example from this util only.

Check the browser details

playerInstance.utils.isMobile();
playerInstance.utils.isAndriod();
playerInstance.utils.isChrome();
playerInstance.utils.isSafari();
playerInstance.utils.isSafari602();
playerInstance.utils.isYouTube();
playerInstance.utils.isEdge();
playerInstance.utils.isFF();
playerInstance.utils.isFlashSupported();
playerInstance.utils.flashVersion();
playerInstance.utils.iframe();
playerInstance.utils.isIPad();
playerInstance.utils.isMSIE();
playerInstance.utils.isInt();
playerInstance.utils.trim();
playerInstance.utils.versionCheck();
playerInstance.utils.rssparser();
playerInstance.utils.parseXML();
playerInstance.utils.serialize();
playerInstance.utils.scriptloader();
playerInstance.utils.streamType();
..
.
.etc
and much more..

JwPlayer Events Flow:

Refer below code according to the event flow in JW player, I arranged it in sequence it triggered.

When this sequence of the events will be important?

If you are using “use strict“, in your javascript file then variable assigned in the event call back required to follow the sequence accordingly in case they are interdepended, Otherwise it will give you a wrong/unexpected result, and another advantage of arranging it in a sequence is increase in readability of your code.

//Fired when player setup ready
playerInstance.on('ready', function (event) {
  
  //Play list loaded
  playerInstance.on('playlist', function (event) {
    // Add Your Code here
  });

  playerInstance.on('playlistItem', function (event) {
    // Add Your Code here

  });

  playerInstance.on('buffer', function (event) {
    // Add Your Code here

  });

  playerInstance.on('playAttempt', function (event) {
    // Add Your Code here

  });

  playerInstance.on('levels', function () {
    // Add Your Code here

  });

  playerInstance.on('firstFrame', function (event) {
    // Add Your Code here

  });

  playerInstance.on('play', function () {
    // Add Your Code here

  });

  playerInstance.on('time', function (event) {
   // Add Your Code here

  });

  playerInstance.on('pause', function () {
    // Add Your Code here

  });

  playerInstance.on('complete', function (e) {
    // Add Your Code here

  });
});

Hope this will help you.

I will keep updating my learning story here,

to be continued….. 🙂

Keep in touch.

Advertisements