Yes, the Limecraft IFrame Player API lets you embed our player on your website and control it using JavaScript.


Using the API's JavaScript functions, you can load playlists for playback, play, pause etc. those videos. You can also add event listeners that will execute in response to certain player events, such as a player state change or a video reaching the end.


1. Requirements


The user's browser must support the HTML5 postMessage feature. Most modern browsers support it. The player should be at least 500px wide.


Any web page that uses the Limecraft iFrame API must also implement the following JavaScript function: onLimecraftPlayerAPIReady. The API will call this function when the page has finished downloading the JavaScript for the player API, which enables you to then use the API on your page. Thus, this function might create the player objects that you want to display when the page loads. 


2. Getting started


2.1 HTML structure


Create a HTML page with a div element (1) where the player should be created. also load the script https://platform.limecraft.com/player/player-api.js and define a function onLimecraftPlayerAPIReady


        <!DOCTYPE html>
        <html>
        <body>
          <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
          <div id="lc-player" style="width: 800px; height: 600px;"></div>

          <script>
              // 2. This code loads the Limecraft IFrame Player API code asynchronously.
              var tag = document.createElement('script');

              tag.src = "https://platform.limecraft.com/player/player-api.js";
              var firstScriptTag = document.getElementsByTagName('script')[0];
              firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

              // 3. This function creates an <iframe> (and Limecraft Player)
              //    after the API code downloads.
              function onLimecraftPlayerAPIReady() {
                //we will set up the player here
              }
          </script>
        </body>
        </html>



2.2 Initialise the player in onLimecraftPlayerAPIReady


The function onLimecraftPlayerAPIReady s called by the Player API once it is ready to create a player. From then on you can create a new Limecraft.Player.


The onPlayerReady callback is fired once the player is initialised and ready to be controlled. All calls on playerInstance should happen after this function was called.


  var player;
  function onLimecraftPlayerAPIReady() {
    //create a new Limecraft.Player
    playerInstance = new Limecraft.Player({
      //points to the <div> element we set up earlier in the HTML
      selector: '#lc-player',

      //called once the player is ready to be controlled
      onPlayerReady: function () {
          //Load a playlist with one video
          playerInstance.setPlaylist([
              {
                  sources: [
                      {
                          "src": "http://bit.ly/karl_heynen--tromso_the_arctic_gateway",
                          "type": "video/mp4"
                      }
                  ],
                  title: "karl_heynen--tromso_the_arctic_gateway"
              }
          ]);
      }
    });
  }



3. Loading media


3.1 Generic loading of media


Use setPlaylist to load a video. The example below loads a single mp4 video.


  playerInstance.setPlaylist([
      //this is a playlist entry
      {
          sources: [
              {
                  "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",               //any public url which is playable in a html video element
                  "type": "video/mp4"                           //the mime type
              }
          ],
          title: "Snow_Bench_Looping_Background-HD.mp4"         //(optional) shown briefly after media is loaded
      }
  ]);Try It


These events can be useful for your application when loading media: 


eventarg0arg1Description
lc:player:error{String} reason{Object} errorObject with a String message propertyan error occured while trying to load media
lc:player:playlist:loaded{Array.} playlistthe playlist is loaded
state:changed{String} newState{String} oldStatethe state changed


You can optionally pass the framerate, and a timecode offset, so the frame-by-frame controls work. Some more options are detailed in the example playlist entry below:


    playerInstance.setPlaylist([
        //more advanced playlist entry
        {
            sources: [
                {
                    "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",                 //see above
                    "type": "video/mp4",                            //see above
                    "supported-players": "remote,local"             //support playout in regular player (local) and Chromecast casting (remote)
                }
            ],
            frameRate: "25/1",          //pass framerate as a fraction. Valid framerates include "25/1", "30000/1001", "30000/1001drop"
            offsetFrames: 25,           //offsetFrames controls the starting timecode of the video. This will set the start timecode to 00:00:01:00.
            title: "Snow_Bench_Looping_Background-HD.mp4"
        }
    ]);Try It



As the name suggests, you can queue multiple items as a playlist.



playerInstance.setPlaylist([ { sources: [ { "src": "http://bit.ly/FDR_and_7th", "type": "video/mp4" } ], title: "FDR_and_7th_Street_Skateboarding-HD" }, { sources: [ { "src": "http://bit.ly/karl_heynen--tromso_the_arctic_gateway", "type": "video/mp4" } ], title: "karl_heynen--tromso_the_arctic_gateway" }, { sources: [ { "src": "http://bit.ly/Snow_Bench_Looping_Background-HD", "type": "video/mp4" } ], title: "Snow_Bench_Looping_Background-HD.mp4" } ]);
Try It



3.2 Load Flow clips by query or Flow ID 


A typical use case when integrating with Limecraft Flow would be to perform a query against a production to get certain media, then create a playlist to play those media.


We created a call which does just this:


    //this is just for the demo
    if (!window.productionId) {
      window.productionId = prompt("productionId?", 242);
    }
    if (!window.token) {
      window.token = prompt("token?", "eyJ1c2VySSomethingSomethingiOmZhbHNlfQ");
    }
    if (!window.fqStr) {
      window.fqStr = prompt("comma separated filter queries?", "funnel:MediaObjectAnnotation,circled:true");
    }

    playerInstance.setPlaylistToQuery({
        productionId: window.productionId,
        token: window.token,
        fq: window.fqStr.split(","),
        rows: 20,
        offset: 0,
        sort: "mediaObjectCreated asc"
    });Try It



Production ID


If you browse to your clip in Limecraft Flow, the productionID is the number in the URL just after "#productions/". 


Token


When a user logs in with Limecraft Flow, he receives an access token. Such a token is requested here to be able to perform the search query. It should correspond to a user which is a participant of the production. 


The login procedure should be done on the server side, and the user should preferably only have "VIEW" rights in the production. Note that anyone having this token can access the production in Limecraft Flow! 


to get the access token of your own session, you can go to the developer console while in Limecraft Flow and run Limecraft.session.getToken(). Do not share that token with anyone else. 


3.2.1 Load by Flow ID


If you want to play a single clip, you can do it like this: 


    //this is just for the demo
    if (!window.productionId) {
      window.productionId = prompt("productionId?", 242);
    }
    if (!window.token) {
      window.token = prompt("token?", "eyJ1c2VySSomethingSomethingiOmZhbHNlfQ");
    }
    if (!window.mediaObjectId) {
      window.mediaObjectId = prompt("What is the Flow ID (aka mediaObjectId) of the clip?", "12345");
    }

    playerInstance.setPlaylistToQuery({
        productionId: window.productionId,
        token: window.token,
        fq: "+funnel:MediaObjectAnnotation +mediaObjectId:" + window.mediaObjectId,
        rows: 1,
        offset: 0
    });Try It



Flow ID


If you browse to your clip in Limecraft Flow and click on the "i" to show the clip info, the Flow ID of your clip is shown in the clip info sidebar on the right. 


ProductionID and token parameters are explained above.


3.2.2 Query playlist events


 These events help you keep track of the query playlist loading:


eventarg0arg1Description
queryplaylist:loadingthe query is loading
queryplaylist:loaded{Object} object with playlist propertythe query has executed and a playlist was generated
queryplaylist:error{Object} errorAn error occured, the query did not execute succesfully


4. Events


You can subscribe to events to be updated about certain state changes. Bind your events in the onPlayerReady callback and implement your logic in the onPlayerEvent callback.


All Media Events triggered on the HTML5 video element can be subscribed to, but pass in a second argument (isVideoEvent: true) when binding them: 

p.addListener("seeking", {isVideoEvent: true});


In addition, other events are exposed as well (documented in the appropriate sections of this document). For example, to be informed about the player position: 

p.addListener("timeupdateframes");



4.1 Events example: render the playlist


    playerInstance = new Limecraft.Player({
        ...
        onPlayerReady: function (p) {
            //bind the lc:player:playlist:loaded event, which is called
            // when a playlist is loaded
            p.addListener("lc:player:playlist:loaded");
            ...
        },
        onPlayerEvent: function (p, eventName, eventArgs) {
            var playlistArray, i, playlistEl, itm, itmEl;

            //render the playlist once it is loaded
            if (eventName === "lc:player:playlist:loaded") {
                renderPlaylist(eventArgs[0]);
            }
        }
    });

    function renderPlaylist(playlistArray) {
      var i, playlistEl, itm, itmEl;
      playlistEl = document.getElementById("playlist");
      playlistEl.innerHTML = "";
      for (i = 0; i < playlistArray.length; i += 1) {
          itm = playlistArray[i];
          itmEl = document.createElement("li");
          itmEl.onclick = Limecraft.simpleBind(function () {
              playerInstance.pluginCall("playlist.skipTo", this);
          }, i);
          itmEl.innerHTML = "<p>" + (i + 1) + ". " + itm.title + "</p>";
          playlistEl.appendChild(itmEl);
      }
    }



5. Structure of a playlist entry


5.1 Timecode visualisation


FrameRate


Although optional, we advise to pass the framerate so the timecode counters are correct. If no framerate is passed, the player assumes 25 frames per second. 


To avoid loss of precision, the frame rate is provided as a fracture.Append "drop" for dropframerates. 


Examples:

  • 25000/100
  • 30000/1001
  • 25/1
  • 30000/1001drop

 

  playerInstance.setPlaylist([
      {
          sources: [
              {
                  "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",
                  "type": "video/mp4"
              }
          ],
          title: "Snow_Bench_Looping_Background-HD.mp4",
          frameRate: "30/1"     //make this look like a 30fps video. Note the timecodes' frame part will go up to 29.
      }
  ]);Try It



OffsetFrames


Use offsetFrames to set a smart timecode of your video. Frame 0 of the video will get this timecode.


Examples:

  • 0 (default, timecode starts at 00:00:00:00à
  • 25 (25 frames. If frameRate is "25/1", this would set the start timecode at 00:00:01:00)


You can also use the offset parameter to pass the start timecode in seconds. 


  playerInstance.setPlaylist([
      {
          sources: [
              {
                  "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",
                  "type": "video/mp4"
              }
          ],
          title: "Snow_Bench_Looping_Background-HD.mp4",
          offsetFrames: "50",   //start at 00:00:02:00
          frameRate: "25/1"
      }
  ]);Try It


5.2 Play a range of the video


Range, frameRange


If you want to show only a certain timerange of the video, you can pass in a range (in seconds). The user will not be able to seek outside this range. 


Examples:

  • 13,20 (13s > 20s)
  • 20 (20 > end)
  • ,25 (begin > 25s)


Note: a tech-savy user will still be able to play the entire video, so this is not to be used as a security measure.


  playerInstance.setPlaylist([
      {
          sources: [
              {
                  "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",               //any public url which is playable in a html video element
                  "type": "video/mp4"                           //the mime type
              }
          ],
          title: "Snow_Bench_Looping_Background-HD.mp4",         //(optional) shown briefly after media is loaded
          range: "3,5"     //play from 00:00:03:00 until 00:00:05:00
      }
  ]);Try It


It is also possible to pass in the range in frames, using the frameRange parameter. 


Example:

  • 300,500


TimelineMode


Note that the timeline still shows the entire range of the video. If this is not desired, set the timelineMode to "range".


Possible values:

  • "all" default
  • "range" will clip the timeline to the range (frameRange) passed as options to the player.


  playerInstance.setPlaylist([
      {
          sources: [
              {
                  "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",               //any public url which is playable in a html video element
                  "type": "video/mp4"                           //the mime type
              }
          ],
          title: "Snow_Bench_Looping_Background-HD.mp4",         //(optional) shown briefly after media is loaded
          range: "3,5",     //play from 00:00:03:00 until 00:00:05:00
          timelineMode: "range"
      }
  ]);Try It



MarkRange, markFrameRange


Using markRange, you can highlight a range on the player's scrubber bar. Same syntax as range.


  playerInstance.setPlaylist([
      {
          sources: [
              {
                  "src": "http://bit.ly/Snow_Bench_Looping_Background-HD",               //any public url which is playable in a html video element
                  "type": "video/mp4"                           //the mime type
              }
          ],
          title: "Snow_Bench_Looping_Background-HD.mp4",         //(optional) shown briefly after media is loaded
          markRange: "3,5"  //optionally, also mark the range
      }
  ]);Try It



Use markFrameRange if you prefer to specify your range using frames. Same syntax as frameRange.


6. Take control


You can control the playout via JavaScript as shown in the code snippets below.


6.1 Play / pause


  playerInstance.play();Try It
  playerInstance.pause();Try It
  playerInstance.togglePlayPause();Try It


6.2 Playback speed


  playerInstance.faster();Try It
  playerInstance.slower();Try It


6.3 Seeking


  //seek to 00:00:02:00
  playerInstance.seek(2);Try It
  //seek to 00:00:01:00 if at 25fps
  playerInstance.seekFrames(25);Try It
  //seek one second back
  playerInstance.seekRelative(-1);Try It
  //seek 25 frames back
  playerInstance.seekRelativeFrames(-25);Try It
  playerInstance.pause();
  playerInstance.nextFrame();Try It
  playerInstance.pause();
  playerInstance.previousFrame();Try It


6.4 Playlist


  playerInstance.playlistPrevious();Try It
  playerInstance.playlistNext();Try It


6.5 On screen display and timecode overlay


The On Screen Display (osd) gives you a convenient way of showing information to the user.


  //show a message for 4 seconds
  playerInstance.osdShow("hello world!", 4000);Try It
  //showing a new message will hide the previous one
  playerInstance.osdShow("hello moon!");
  playerInstance.osdShow("hello earth!");Try It
  //hide the message, but only if it is still showing "hello world!"
  playerInstance.osdHide("hello world!");Try It
  //hide anything shown on the osd
  playerInstance.osdHide();Try It



If the timecode overlay bothers you, you can turn it on and off. 


  playerInstance.timecodeShow();Try It
  playerInstance.timecodeHide();Try It
  playerInstance.timecodeToggle();Try It



6.6 Header


A header can optionally be enabled for the player. The example below shows how to enable the header and set its contents. 

function onLimecraftPlayerAPIReady() {
    playerInstance = new Limecraft.Player({
        // pass embedOptions.showHeader = true
        embedOptions: {
            showHeader: true
        },

        // set the header via playerInstance.setHeaderTitle
        onMediaLoaded: function (event, data) {
            if (data.searchResult) {
                playerInstance.setHeaderTitle({
                    title: "[" +
                        (data.playlistIndex + 1) +
                        " / " +
                        (data.playlistLength) +
                        "]" +
                        " " +
                        (data.searchResult.mediaObjectName || "")
                });
            }
        },
        ...
    });