HTMLtemplate webm intro => loop => outro

I used two video tags for that effect so the loop keeps playing while fading out and the outro fades in a couple of frames earlier.

Again thank you all love the community

I came up with this anyone seeing trouble in this

    <script>
    let loop = false
    let playHead = {
    	pos: 0,
    	loopPos: 0,
    	loop: {
    		in: 100,
    		out: 400
    	},
    	end: 500
    	}
    

    function play () {
    	TweenMax.to(playHead, 1, {pos:playHead.loop.in, ease:Linear.easeNone, onUpdate: updatePlayHead, onComplete:loopstart})
		let myPlayer1 = document.getElementById('myPlayer1')
    	TweenMax.to(myPlayer1, 1, {opacity: 1})
   		let myPlayer2 = document.getElementById('myPlayer2')
    	TweenMax.to(myPlayer2, 1, {opacity: 1})
    }

    function stop () {
    	loop = false
    	TweenMax.to(playHead, 1, {pos:playHead.end, onUpdate: updatePlayHead})
    	TweenMax.to(myPlayer1, 1, {opacity: 0})
    	TweenMax.to(myPlayer2, 1, {opacity: 0})
    }

    function loopstart () {
    	loop = true
    	playHead.pos = playHead.loop.in
    	seek(playHead.pos)
    }

    function update () {
        
    }

    function updatePlayHead () {
    	seek(playHead.pos) 
    }


    function seek (frame) {
    	let myPlayer1 = document.getElementById('myPlayer1')
    	let myPlayer2 = document.getElementById('myPlayer2')
    	myPlayer1.currentTime = (frame * 20)/1000;
    	myPlayer2.currentTime = (frame * 20)/1000;
    }
    
    function hearthBeat() {
    	window.requestAnimationFrame(hearthBeat)
    	if (loop) {
    		playHead.pos++
    		seek(playHead.pos)
    		if (playHead.pos === playHead.loop.out) {
    			playHead.pos = playHead.loop.in
    		}
    	}
    }

    window.requestAnimationFrame(hearthBeat)
    </script>
    <style>
    	#myPlayer1{
    		opacity: 0
    	}
    	#myPlayer2{
    		opacity: 0
    	}
    </style>

You’ll want rAF at the end.

Do let myPlayer1 = document.getElementById('myPlayer1') etc… outside of the functions and only once.

Don’t count the frames, check currentTime

Thanks @hreinnbeck

You’ll want rAF at the end.

Yep i understand why

Do let myPlayer1 = document.getElementById(‘myPlayer1’) etc… outside of the functions and only once.

true i understand

Don’t count the frames, check currentTime

i guess you mean this part

if (playHead.pos === playHead.loop.out) {
playHead.pos = playHead.loop.in
}

it seems too work nicely.
Where do you see the problem?
What could go wrong?

You can’t be sure that the video has actually presented (displayed/rendered) the frame. The closest thing to being sure of that is to check currenttime. I’d also have that as >= just to be sure you don’t miss a frame and then it just plays till the end.

May I also recommend using a can play event listener if you are using a HTML <video> element. This combined with a Promise and an on error function can make for an asynchronous video load and error handling fallback.

How do you seek to the next correct time-accurate frame without counting frames? I’m lost.
I understand rAF throttles down the execution so every frame would take more than 20ms to update in some cases.

Just check this: https://casparcg.net/webm/

1 Like

Nice example thanks !

i totally get what you are doing.

in my case i am using 2 clips driven by the same var now (2 club logo’s that can be chosen)

i guess your solutions plays all the frame’s nicely but can get out off sync when a frame from one player is late.

where my idea skips a frame (in a dirty way) when a frame is late leaving the 2 clips in sync

very nice solution though !!

I am curious why this video is being loaded as one element. Why wouldn’t the intro, loop and outro be three separate elements that can be loaded and adjusted independently from each other? Then you wouldn’t need to do the frame checks but instead set the loop video to loop=true and call it a day. Just a thought :slight_smile:

It’s a lot more performant and it easily allows to finish loops before going into outro (which I consider a hallmark of professional graphics).

At least in my line of thoughts, the goal is to load all the elements at the same time and not to worry if something gets left behind, but I’m actually not sure the seeked video frames get loaded faster than a new video.

Since there is no debating that the download time for one video is better than three and @hreinnbeck is right when he says loading one video makes playing out a loop easier (You may need a setTimeout or a has ended event listener to play out the next video).
I just want to offer these last few points. Separating the videos lets you load different intro and outros dynamically from one template. For example, I use one template called full-video.html and that loads an intro wipe, video to playout full, and then an outro wipe all specified by the client. As I mentioned above you could then add a default fallback video if the new intro or outro fails. Then one step further, if the default video fails, the template can remove itself from the server and report the error to the client.

The performance issue is more with having multiple video elements rather than loading (this seems to matter even more when running CEF with gpu acceleration enabled).

Every template is different, I often have elements that animate in and out of the loops so you can’t easily have different videos and turn them on/off, fade in/out etc.

But the most important part of my example is demonstrating the seek and seekExact methods (which also work well with GSAP and similar ways of animating) and having a single event loop (newFrame/rAF) driving everything.

i’m testing it on chrome but video isn’t playing…
after digging i found that video is playing but browser isn’t updating current frame

Chrome version >78? It seems to have some issues.

ohh right !!
thanks

do you have any idea for adding mix effect in loop and outro etc as rrebuffo suggest for achieving this he is using two video tags but you are suggesting for best performance use only one video tag

second i wanna ask on page refresh video tag is showing black screen then loading first frame of video
so how can we avoid this black flashing on refresh

Not sure what you mean with mix effects, my example is purposefully very different in the intro/loop/outro to show that it is frame accurate. A real video would be with animation into the loop and out of it.

You’ll want “background:transparent;” on the video tag.

yeah i get it !

sorry my question is off the topic
what i wanna say is while looping video when we play outro than instead of waiting for loop end and then play outro we quickly have to play outro without any wait so video will show jump from some looping frame to outro start
so do you have any idea for avoiding this jump and that’s why i was asking for something like mix effect etc

Just use two video elements and disable enable-gpu in your config if you have performance issues. I had to do that and discussed it here.

1 Like