HTML5 video analytics

I recently helped out an MSc student who, as part of his research into the ‘flipped’ classroom, wanted to look at how students interact with video ‘lectures’. HTML5 allows you to record when events (such as the user clicking play, pause, seek, etc) happen so I wrote some JavaScript that recorded these events and the times that they occurred.

The HTML5 video link is as follows:

<video id="videoplayer" width="600" height="480" controls="controls" type="video/mp4" onplay="javascript: countPlay();" onpause="javascript: countPause();" onseeking="javascript: countSeek();">
  <source id="video_id_here" type="video/mp4" src="video_file_here.mp4" /> 
        </video>
<script src="video_analytics.js" type="text/javascript"></script>

A timer is set up on the user entering the page

var time = Math.round(new Date().getTime()/1000); <!--this gets the time the page was opened-->

and the timing of every video event is then recorded (by adding the time into an array). In addition, the time of each event in the video playback is recorded (again to an array). The timings of play, pause and seek events are also recorded separately, in case they are useful. One thing to note is that seek events where the user drags the play head along the timeline (rather than clicking on the timeline) record multiple events, so the code disregards any seek events that are recorded within a second of the previously recorded value (deciding on a second was pretty arbitrary, but it cuts out some uneccesary data).

The code is as follows (it includes some validation that the user has input their details – this was so we could track different users and can be deleted if not required):

<!-- the various functions called in the video player -->
<!--create some variables-->   
var fileName;   
var vfile = document.getElementById('videoplayer');
var vsrc = vfile.getElementsByTagName('source')[0];   
var videoID = vsrc.id;      
var userNameSet = new Boolean();   
userNameSet = false;   

function getUserName(){    
var userName = document.getElementById('username').value;    
userNameSet = true;    
fileName = videoID+'-'+userName+'-'+fullDate;       
}         

var eventCount = 0;  //stores how many times any event happens   
var eventArray = new Array(); //an array to store which type of event occured   
var eventTime = new Array(); //an array to store the actual time that any event occurs   
var eventVideoTime = new Array(); //an array to store the playback time any video event occurs      

var playCount = 0;    //stores how many times play has been hit   
var playTime = new Array();  //an array to store the playback time that play was hit   
var playEventTime = new Array();  //an array to store the actual time that play was hit 
     
var pauseCount = 0;   //stores how many times pause has been hit   
var pauseTime = new Array(); //an array to store the playback time that pause was hit   
var pauseEventTime = new Array();  //an array to store the actual time that play was hit
      
var seekCount=0;  //stores how many times seek has been hit   
var seekTime = new Array(); //an array to store the playback time that seek was hit   
var seekEventTime = new Array();  //an array to store the actual time that seek was hit             

function countPlay(){        // this function adds times to the count of events and the count of plays        
if (userNameSet == false){vfile.pause();    
alert("Please input your username");}       
else{         
eventCount++;     
eventArray[eventCount] = "Play,"; //records that this was a play event     
eventTime[eventCount] = ((Math.round(new Date().getTime()/1000)-time)); <!-- gets time in seconds user has been on page when event occured and adds it to event array  -->     
eventVideoTime[eventCount] = Math.round(videoplayer.currentTime*100)/100; <!-- gets current time from video player, rounds it to 2dp and adds it to event array -->         
playCount++;  //adds one to a count everytime play is pressed     
playEventTime[playCount] = eventTime[eventCount]; <!-- gets actual time play was hit and stores it in  play array -->     
playTime[playCount] = eventVideoTime[eventCount]; <!-- gets current time from video player, rounds it to 2dp and adds it to play array -->         
}    
}      

function countPause(){   <!-- as above but for pause button -->        
eventCount++;     
eventArray[eventCount] = "Pause,";     
eventTime[eventCount] = ((Math.round(new Date().getTime()/1000)-time));     
eventVideoTime[eventCount] = Math.round(videoplayer.currentTime*100)/100;         
pauseCount++;     pauseEventTime[pauseCount] = eventTime[eventCount];     
pauseTime[pauseCount] = eventVideoTime[eventCount];         
}        

function countSeek(){  <!-- as for play and pause except if there is less than 1 sec ond between events it isn't included, diue to multiple results when drag is used -->      
seekCount++;   
var seekPageTime = ((Math.round(new Date().getTime()/1000)-time)); <!-- gets time in seconds user has been on page when event occured and stores it in variable  -->     
if (seekCount==1){           <!-- if first time seek has been hit values are stored as for play and pause above-->        
eventCount++;     
eventArray[eventCount] = "Seek,";     
eventTime[eventCount] = seekPageTime;     
eventVideoTime[eventCount] = Math.round(videoplayer.currentTime*100)/100;          
seekEventTime[seekCount] = seekPageTime;          
seekTime[seekCount] = eventVideoTime[eventCount];    
}       
else{
var counter = seekEventTime.length-1; //get length of seek events array       
if  ((seekPageTime - seekEventTime[(seekEventTime.length-1)]) >= 1 || (seekEventTime[(seekEventTime.length-1)])- seekPageTime >=1) <!-- if current value varies by more than 1 second from last stored value    
{     
counter++;     
seekEventTime[counter] = seekPageTime;     
seekTime[counter] = Math.round(videoplayer.currentTime*100)/100;               
eventCount++;     
eventArray[eventCount] = "Seek,";     
eventTime[eventCount] = ((Math.round(new Date().getTime()/1000)-time)); <!-- gets actual time event occured -->     
eventVideoTime[eventCount] = seekTime[counter]; <!-- gets current time from video player, rounds it to 2dp and adds it to array -->          
}    
}    
}

The code executes on the user leaving the page (using ‘onbeforeunload’) and outputs all of the recorded data, via a php file, to a csv file, which allows it to be analysed using Excel. The following graph, output from Excel, shows a plot of a user viewing a video with time elapsed shown on the x axis and video playback time on the y axis:

video_times

Play events are shown by a rising line, seek events by a steep rising or falling line and pause events by a flat line, so this user started watching the video at about 13 seconds on the page, got about 10 seconds into the video and then did a seek to about 36 seconds in, paused at around 75 seconds on the video timeline and did a seek back to 10 seconds and then another to 160 seconds. After playing the video for about 10 seconds they then seeked back to around 55 seconds on the timeline before leaving the page after 63 seconds.

The idea here is that, by recording students’ interactions with individual videos, we can analyse the data and look for patterns, for example, we can look for sections in the video where students go back and watch the material more than once, perhaps suggesting content that they find difficult, or parts that they choose to skip over.

Advertisements
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s