support Contact Support | system status System Status
Page Contents

    Creating a Simulated Live Event

    Before you invest in the cost and workflow of creating and running live events, you may want to try a test to gauge the interest of your viewers. This sample shows you how to simulate a live streaming event to do that.

    Introduction

    What distinguishes live streaming from VOD is the passage of time. The content stream is tied to time and all viewers are in sync to that timeline.

    This sample simulates this effect of a live streaming event using VOD content in a Video Cloud playlist, and some JavaScript to keep all viewers at the same point in the playlist regardless of when they start playback.

    You will see two players below, followed by an explanation of how this was created.

    The players

    See the Pen Simulated Live Event by Brightcove Learning Services (@rcrooks1969) on CodePen.

    App logic

    The logic for creating the simulated live stream is fairly straightforward:

    Simulated Live Logic
    Simulated Live Logic

    Player details

    The player is enabled for playlists (to get the Playlist API) but without a playlist display. The JSON for the player configuration is as follows:

    {
        "compatibility": true,
        "video_cloud": {
          "policy_key": "{your player policy key will be here}"
        },
        "player": {
          "template": {
            "name": "single-video-template",
            "version": "6.40.3"
          }
        },
        "studio_configuration": {
          "player": {
            "responsive": true,
            "height": 540,
            "width": 960,
            "units": "px"
          }
        },
        "muted": true,
        "plugins": [
          {
            "name": "simulated_live",
            "scripts": [
              "https://{path to your version of the hosted plugin}/simulated-live.js"
            ]
          }
        ]
      }

    API methods used

    • catolog.getPlaylist() to fetch the playlist
    • catalog.loadPlaylist() to load the playlist into the player
    • playlist.autoadvance(0) sets playlist to autoadvance with no pause between videos
    • playlist.repeat(true) sets playlist to repeat after finishing
    • player.playlist() gets the video data from the playlist
    • playlist.currentItem sets a specific video in the playlist as the current one
    • player.currentTime() seeks to a specified time in the video

    Javascript code for the plugin

    videojs.registerPlugin('simulated_live', function() {
        var my_player = this,
        playlist_id = '1664503635149515112', // replace with your playlist id
        video_data,
        video_ranges = [],
        playlist_duration = 0,
        playlist_position,
        current_video_index,
        current_video_position,
        origin_time = new Date('2020-01-01T00:00:00'),
        now_time,
        time_passed,
        logger = document.getElementById('logger');
      
      /**
       * @Desc:  gets the duration of the whole playlist and array of video start times
       * @param {array} video_data array of video data for the playlist videos
       */
      function get_playlist_duration() {
        var i,
          i_max = video_data.length;
        
        for (i = 0; i < i_max; i++) {
          video_ranges[i] = playlist_duration;
          playlist_duration = playlist_duration + video_data[i].duration;
        }
      }
      
      /** 
       * @Desc:  gets time position in current playlist
       */
      function get_playlist_position() {
        now_time = new Date();
        time_passed = now_time - origin_time;
        playlist_position = time_passed % playlist_duration;
        return playlist_position;
      }
      
      /**
       * @Desc:  gets the index of the video that corresponds to the current position in the playlist
       */
      function get_current_video_index() {
        var i,
          i_max = video_ranges.length;
          for (i = 0; i < i_max; i++) {
            if (playlist_position > video_ranges[i] && playlist_position < video_ranges[i + 1]) {
              current_video_index = i;
              return;
            }
          }
      }
      
      /**
       * @Desc:  gets the start position for the video to match the start position in the playlist
       *
       */
      function get_current_video_position() {
        current_video_position = playlist_position - video_ranges[current_video_index];
      }
      
      
      // fetch the playlist
      my_player.catalog.getPlaylist(playlist_id, function(error, playlist){
        if (error) {
          console.log('There was an error retrieving the playlist: ', error);
        }
        
        // load the playlist into the player 
        // the -1 argument prevents the first video from being loaded into the player
        my_player.catalog.load(playlist, -1);
      
        // turn on auto-advance
        my_player.playlist.autoadvance(0);
      
        // turn on replay
        my_player.playlist.repeat(true);
      
        // get the video data from the playlist
        video_data = my_player.playlist();
        
        // get the duration of the playlist and the video ranges
        get_playlist_duration();
        console.log(logger, 'playlist duration: ' + playlist_duration);
        
        
        
        // get the start position in the playlist
        get_playlist_position();
        console.log(logger, 'playlist position: ' + playlist_position);
        
        // get the index of the video where the start position is
        get_current_video_index();
        console.log(logger, 'video index: ' + current_video_index);
        console.log(logger, 'video: ' + video_data[current_video_index].name);
        
        
        // get start position in the video
        get_current_video_position();
        console.log(logger, 'video position:' + current_video_position);
        
        
        // set the start video as the current one
        my_player.playlist.currentItem(current_video_index);
      
        // wait for video to load
        // my_player.on('loadedmetadata', function() {
          // seek to the start point
          my_player.currentTime(current_video_position);
          console.log(logger, 'set position to ' + current_video_position);
          
          // start the video
          my_player.play();
        // }
      });
      });

    Page last updated on 12 Jun 2020