Determine video watch time for scheduling ad

We recently added ads at 8 minute fixed intervals to some of our videos, but found the UX was bad for people scanning through videos.

So now we are looking to insert ads after 8 minutes of view time. For example, someone watches 2 minutes, scans forward a few times, then watches another 3 minutes, then goes back and watches the same 3 minutes again. At this point they have watched 8 minutes of video so we want to schedule an ad.

So my question is: what is the best way to track this behaviour from the player? I’ve had a bit of a look around at the example code, but can’t find anything helpful. Has anyone done this before?

We can probably piece something together by listening to various player events but it would be great to get a head start if someone has done something similar.

Hi @digital.licensing , thanks for sharing your question with community. It is an interesting and a vary valid use case.

As you already suspected, this is something that can be built using a combination Bitmovin events and APIs.

  • First step is to find the playback start position when playback starts.

  • Then update the played range as playback progresses.

  • Both above can be done using TimeChanged event

  • Then on specific events like seeking etc., need to start the range measurement again.

  • For VOD listen to Seeked event to start measuring a new range.

  • For Live, a new range should be started on following 2 events

  • Then when needed all the time ranges can be checked to find the total player duration.

I am sharing below sample javascript code which demonstrates this algorithm.

<!DOCTYPE html>
<html lang="en">
  <meta charset="UTF-8">
  <title>Bitmovin Player full customized example</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="" rel="stylesheet" type="text/css"/>
  <link rel="stylesheet" href="" crossorigin="anonymous">
  <!-- Bitmovin Player -->
  <script type="text/javascript" src=""></script>

<div id="my-player"></div>

<script type="text/javascript">
  var addNewPlayedTimeRange = true;
  var playedRanges = [];
  var config =   {
    "key": "YOUR-API-KEY",
    playback: {
      autoplay: true,
      muted: true

  var source = {
    title: "Sintel Test",
    hls: "",

  var container = document.getElementById('my-player');
  var player = new bitmovin.player.Player(container, config);
  player.on('seeked' , onSeeked);
  player.on('timeshifted', onTimeShifted);
  player.on('timechanged' , onTimeChanged);
  player.on('playbackfinished', onPlaybackFinished);
  player.on('dvrwindowexceeded', onDVRWindowExceeded);

  function() {
      console.log('Successfully created Bitmovin Player instance');
  function(reason) {
      console.log('Error while creating Bitmovin Player instance');

  function onSeeked () {

    // add new played range
    var currentTime = player.getCurrentTime();
    addNewPlayedTimeRange = true;

  function onTimeShifted () {

    // add new played range
    var currentTime = player.getCurrentTime();
    addNewPlayedTimeRange = true;

  function onDVRWindowExceeded () {

    // add new played range for live content when playback falls out of dvr window
    addNewPlayedTimeRange = true;

  function onTimeChanged(event) {
    // update played time range
    if (playedRanges.length === 0 || addNewPlayedTimeRange === true) {
      // add new played time range  
      addNewPlayedTimeRangeEntry(event.time, event.time);
      addNewPlayedTimeRange = false;
    } else {
      playedRanges[playedRanges.length - 1].end = event.time;

    // calculate played duration
    console.log ('Played_Duration=' + calculateTotalPlayedDuration());

  function onPlaybackFinished () {
    console.log('onPlaybackFinished : Total_Played_Duration=' + calculateTotalPlayedDuration());

  function addNewPlayedTimeRangeEntry(startTime, endTime) {
    var newRange = {
        start: startTime,
        end: endTime

  function calculateTotalPlayedDuration() {
    var total_played_duration = 0;
    playedRanges.forEach((range) => total_played_duration += (range.end - range.start));
    return total_played_duration;