HTML Video - timeline action


#1

HI, i was wondering if it was possible to add a listener to a where in the time line a video is then add class to another element...i.e i have a looping mp4 (duration 13 secs)...every at 10 secs add class to another div (then the css class will loop every 13 secs)

Thanks in advance for you thoughts


#2

That would be the timeupdate event... e.g. if you have a video element and say 10 progress marks like this

<video id="my-video" src="./myvideo.mp4" controls></video>

<div>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
  <span class="progress"></span>
</div>

you can toggle a given class depending on the video's currentTime like so:

const video = document.getElementById('my-video')
const progressMarks = [...document.querySelectorAll('.progress')]

video.addEventListener('timeupdate', ({ target }) => {
  const progress = target.currentTime / target.duration * 10

  progressMarks.forEach((mark, index) => {
    mark.classList.toggle('active', progress >= index)
  })
})

#3

Thanks, however not as comprehensive as your suggestion :slight_smile: somewhere on the lines of:

document.getElementById('my-video')
If my-video play position = 10 secs
$('.div').addClass('animate');

as the video is in a loop, id just need to fire the addclass once (at 10 secs) for the 13 sec clip...then i could use my css duration (13 secs) to sync with the video for every 10 secs


#4

You'd still listen to timeupdate all the way... then you could do something like

video.addEventListener('timeupdate', ({ target }) => {
  if (target.currentTime === 10000) {
    // add some class somewhere
  }
})

I'd be careful with that... what if the video pauses due to buffer underrun? Not to mention user interaction...


#6

Ok, time to expose my incompetence...your original script worked as i could see it firing ....but why wouldn't this work?....it seems logical

 <script>
video = document.getElementById("my-video" )
video.addEventListener('timeupdate', ({ target }) => {
  if (target.currentTime === 5000) {
 document.getElementById("demo").innerHTML = "Good day!";
  }
})  </script>

#7

Yes indeed, that should work... can you post the full code including markup, or better yet set up a fiddle?


#8

<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>

<body>
  <video loop autoplay id="my-video">
  
    <source src="http://techslides.com/demos/sample-videos/small.mp4" type="video/mp4" />
    
	</video>
<p id="demo">Good Evening!</p>

</body>
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
 <script>
video = document.getElementById("my-video" )
video.addEventListener('timeupdate', ({ target }) => {
  if (target.currentTime === 5000) {
 document.getElementById("demo").innerHTML = "Good day!";
  }
})  </script>
</html>

#9

Whoops... the currentTime is actually in seconds, not milliseconds. ^^ Furthermore, the event doesn't necessarily fire at exactly 5s... so it should be

if (target.currentTime >= 5) { /* ... */ }

Sorry for the confusion!


#10

Thanks...sorry for not getting back to you...got a little side tracked.....i had a go at looping through the css animation to match the video timeline and unfortunately, as you flagged up before, i did lose sync after a while..........so...rethinking, using your initial code, is it possible to add a class/toggle each of the progress child divs when the video hits 1.48 secs (rather than splitting into 10ths)?

<div id="progress">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>

#11

Sure... actually, putting the fixed value of 10 in the code wasn't ideal indeed; better would be progressMarks.length, so that the JS stays agnostic about how many marks there actually are and you can change the markup at any time without having to adjust the JS:

const video = document.getElementById('my-video')
const progressMarks = [...document.getElementById('progress').children]

video.addEventListener('timeupdate', ({ target }) => {
  const progress = target.currentTime / target.duration * progressMarks.length

  progressMarks.forEach((mark, index) => {
    mark.classList.toggle('active', progress >= index)
  })
})

#12

cheers, but to assign each of the child divs to fire at the 1,48 secs position?


#13

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.