user10035093
user10035093

Reputation:

track the time the video was playing in the web page

The problem is to get the total time the video was played. I am using videojs as a JavaScript library. As a caution, currentTime() method is not what we want as total playback time, we also consider that the viewer seeks the movie to an arbitrary playback position, and wants to acquire the time actually played. example) 60 seconds video Viewer watches first 5 seconds then jumps to the 10 seconds point and watches the next 5 seconds. Current time is 15 seconds point, but I hope total watched time is 10 seconds.

In fact, every time viewer play 10%, call API. How can I implement JavaScript?

edit) It may be time consuming to read video, so it is difficult to use new Date(). For example, 5 seconds video may take 10 seconds due to newtwork speed problem. I am considering the following code. As long as you see the console, it works well in most cases, but when you skip the playback position, there is an error in the measurement of the playback rate in rare cases.

<link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
<video id="myPlayer" class="video-js"
    controls preload="auto" width="440" height="264"
    poster="http://vjs.zencdn.net/v/oceans.png">
  <source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4">
</video>
<script src='https://vjs.zencdn.net/7.4.1/video.js'></script>
const player = videojs('myPlayer');
const trackingPoint = 10;
let totalTime = 0;
let tempTotalTime = 0;
let startTime = 0;

player.on('pause', function () {
  totalTime += tempTotalTime;
});

player.on('play', function () {
  startTime = player.currentTime();
});

player.on('timeupdate', function () {
  if (player.paused()) {
    return;
  }
  let currentTime = player.currentTime();
  tempTotalTime = currentTime - startTime;
  let tmptotalTime = totalTime + tempTotalTime;
  let playbackRate = tmptotalTime / player.duration() * 100;
  console.log(Math.floor(playbackRate) + ' %');
});

Upvotes: 1

Views: 8162

Answers (4)

Md.Naimur Rahman
Md.Naimur Rahman

Reputation: 1

Here is how I do it:

<script>
    const video = document.getElementById("videoPlayer");
    const watchTimeDisplay = document.getElementById("watchTime");
    let watchTime = 0;
    let timer = null;

    const startTimer = () => {
      if (!timer) {
        timer = setInterval(() => {
          watchTime++;
          watchTimeDisplay.textContent = watchTime;
        }, 1000);
      }
    };

    const stopTimer = () => {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    };

    // Start counting watch time when the video plays
    video.addEventListener("play", () => {
      startTimer();
    });

    // Stop counting when the video pauses
    video.addEventListener("pause", () => {
      stopTimer();
    });

    // Stop counting during buffering
    video.addEventListener("waiting", () => {
      stopTimer();
    });

    // Resume counting after buffering completes
    video.addEventListener("playing", () => {
      startTimer();
    });

    // Cleanup the timer when the page is closed or reloaded
    window.addEventListener("beforeunload", () => {
      stopTimer();
    });
  </script>

Here you will be even able to track if your video is buffering or not and thus you can stop the timer providing you with a correct duration the video is played. If you want you can set limit so that watchTime doesn't exceed the duration of your video

Upvotes: 0

hapablap
hapablap

Reputation: 409

The following code is based on the previous answers, but I added handling video buffering time, which should be counted as watch time:

const player = videojs('myvideo');

let timer = null;
let totalTime = 0;
let lastPlayerTime = player.currentTime();

player.on('play', startPlaying);
player.on('pause', pausePlaying);

function startPlaying() {
    console.log('played');
    timer = window.setInterval(function() {
        if(lastPlayerTime != player.currentTime()) {
            totalTime += 1;
        }
        lastPlayerTime = player.currentTime();
        console.log(lastPlayerTime);
        console.log(player.currentTime());
        console.log(totalTime);
    }, 1000);
}

function pausePlaying() {
    console.log('stopped');
    if (timer) clearInterval(timer);
}

window.onbeforeunload = function() {
    console.log('stopped');
};

It compares the last tracked player time with the current player time and only counts the seconds if those times differ.

Upvotes: 1

Pourya Kordi
Pourya Kordi

Reputation: 31

this code is fine, but you don't need Date, the interval would act like timer itself so.

let timer = null,
totalTime = 0;

player.on("play", startPlaying);
player.on("pause", pausePlaying);

function startPlaying() {
    console.log('played');
  timer = window.setInterval(function() {
    totalTime += 1;
  }, 1000);
}

function pausePlaying() {
    console.log('stopped');
  if (timer) clearInterval(timer);
}

would return the time video has been watched in seconds, and if you need more accurate result like in milliseconds you could set shorter Intervals (Change the 1000 to 1 so the function would be called every millisecond) but I don't think this method is good for such use cases when you need it to be so much accurate because this won't take into account loading times which is almost guaranteed to be more than a second.

Upvotes: 2

Keno
Keno

Reputation: 2098

You'd want to listen to the play and pause events for your video player. For the former, you'd start an incrementer function which basically adds to the total time the video was played, and pause would clear it.

Here's how I would go about it.

let timer = null,
    totalTime = 0;

let time = new Date();

player.addEventListener("play", startPlaying);
player.addEventListener("pause", pausePlaying);

function startPlaying() {
  timer = window.setInterval(function() {
    totalTime += new Date().getTime() - time.getTime()
  }, 10);
}

function pausePlaying() {
  if (timer) clearInterval(timer);
}

Another alternative:

let isPaused = true;
let time = new Date();
let totalTime = 0;
let t = window.setInterval(function() {
  if(!isPaused) {
    let milisec = new Date()).getTime() - time.getTime();
    totalTime += parseInt(milisec / 1000);
  }
}, 10);

player.addEventListener("play", () => isPaused = false);
player.addEventListener("pause", () => isPaused = true);

Hope this helps!

Upvotes: 1

Related Questions