0
\$\begingroup\$

The following code gets video renditions from Brightcove using the media API. It then generates an ordered source list for the JW Player and selects the default rendition based on a pre-set bitrate.

function buildSourcesFromBrighcoveID(brightcoveID, onComplete) {
    var sources = [];
    var brightcoveAPI = 'http://api.brightcove.com/services/library';
    var parameters = {
      command: 'find_video_by_id',
      video_id: brightcoveID,
      video_fields: 'renditions',
      media_delivery: 'http',
      token: 'jskS1rEtQHy9exQKoc14IcMq8v5x2gCP6yaB7d0hraRtO__6HUuxMg..'                
    };

    // Get renditions
    $.ajax({
      dataType: "jsonp",
      url: brightcoveAPI,
      data: parameters
    }).done(function(data){

      var targetRate = 800000; // Bps
      var lowestDiff;
      var closestRate;

      // Sort them by encoding rate, higher rate first
      data.renditions.sort(function(a, b) {
        return parseFloat(b.encodingRate) - parseFloat(a.encodingRate);
      });

      // Get the closest encoding rate to target
      var currentRate = data.renditions[0].encodingRate;
      var lowestDiff = Math.abs(currentRate - targetRate);

      $.each (data.renditions, function(id, rendition){
        var diff = Math.abs(rendition.encodingRate - targetRate);
        if (lowestDiff > diff) {
          lowestDiff = diff;
          closestRate = rendition.encodingRate;
        }
      });

      // Build sources for the player
      $.each (data.renditions, function(id, rendition){
        var newItem = {
          file: rendition.url,
          label: Math.round(rendition.encodingRate / 1000) + ' Kbps'
        }

        // Set default rendition
        if (rendition.encodingRate == closestRate) {
          newItem["default"] = true;
        }

        sources.push(newItem);

      });

      if (onComplete) onComplete(sources);
    });

    return sources;
  }

  function loadVideoPlayer(sources) {

    var playerInstance = jwplayer("player");
    playerInstance.setup({
      sources: sources,
      width: 727,
      height: 455,
      autostart: true
    }); 

  }

buildSourcesFromBrighcoveID('1520880903001', loadVideoPlayer);

Codepen

Questions

  1. How can I be sure buildSourcesFromBrighcoveID completed before doing anything else? I currently run the function that builds the player from within the first function to be sure the Ajax completed, but I would like them to be independent.
  2. Could I build the sources array in a more efficient way? I am currently iterating the renditions 3 times (to sort, to search for the best rendition and to build the sources array).
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

These two declarations are useless:

  var lowestDiff;
  var closestRate;

As you re-declare them later:

  var currentRate = data.renditions[0].encodingRate;
  var lowestDiff = Math.abs(currentRate - targetRate);

And, on that note, you shouldn't use the var keyword when you reference an already defined variable. However, in this case, the first block can be removed, making the second block the variable declaration.

The following block can be simplified:

  $.each (data.renditions, function(id, rendition){
    var newItem = {
      file: rendition.url,
      label: Math.round(rendition.encodingRate / 1000) + ' Kbps'
    }

    // Set default rendition
    if (rendition.encodingRate == closestRate) {
      newItem["default"] = true;
    }

    sources.push(newItem);

  });

into the following:

  $.each(data.renditions, function(id, rendition){
    sources.push({
      file: rendition.url,
      label: Math.round(rendition.encodingRate / 1000) + ' Kbps',
      default: (rendition.encodingRate == closestRate)
    });
  });

How can I be sure buildSourcesFromBrighcoveID is completed before doing anything else? I currently run the function that builds the player from within the first function to be sure the Ajax completed, but I would like them to be independent.

You should make the function a promise and use a done callback to ensure the function has been completed successfully before continuing. Read this Stack Overflow question for more information.

Could I build the sources array in a more efficient way? I am currently iterating the renditions 3 times (to sort, to search for the best rendition and to build the sources array).

Each loop does a different thing, so I'm not 100% sure whether they can be slimmed.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the reply. I hadn't though on pushing the values directly to the array, it is much more compact and readable. lowestDiff and closestRate are declared at the top of their scope to follow good practices, from MDN "...it is recommended to always declare variables at the top of their scope . . . so it's clear which variables are function scoped (local) and which are resolved on the scope chain.". Anyway you are right, no point in using var the second time ;-). \$\endgroup\$
    – Lando
    Nov 3, 2015 at 14:56
  • \$\begingroup\$ I will look into promises, it seems they are available from JQuery 1.8 onwards, do you know if there is an equivalent for prior versions or pure JS (Unfortunately I need to support IE8). \$\endgroup\$
    – Lando
    Nov 3, 2015 at 14:58
  • \$\begingroup\$ @Lando, you actually already use promises in your existing code. \$\endgroup\$
    – Quill
    Nov 3, 2015 at 21:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.