HTMLtemplate webm intro => loop => outro

Hi all

I’m new to using vidoe in a HTML template.
i have it working with alpha which is nice.
with this ffmpeg command i make the clips

ffmpeg.exe -i .\test3.mov -f webm -c:v libvpx -b:v 10M -acodec libvorbis -auto-alt-ref 0 test3.webm

but i was wondering if anyone has a example off the following, or some hints :wink:

@play()
start a intro clip => seamless going into a looping clip looping forever /waiting for stop

and then
@stop()
or go directly to the outro clip (produced so it can start anywhere in the loop)
or wait for the loop clip to reach it’s end an then start the outro clip

thanks

1 Like

Make one clip stitched toghether, then:

    let _loop = document.getElementById('loop');

    function checkLoop()
    {
        if (_loop.currentTime > 33)
        {
            _loop.currentTime = 5;
            _loop.play();
        }
    }
    _loop.addEventListener("timeupdate", checkLoop, false);

and in stop()

        _loop.currentTime = 35.7;
        _loop.play();

You’ll want to have every frame as a keyframe:
-g 1 -keyint_min 1 -force_key_frames 1

You can then seek to a frame with something like:

function seekFrame(fr) {
	bgvid.currentTime = (fr*40)/1000; // 25fps/1000 = 40
}

I actually play videos using rAF as a timer (i.e. the video is always paused and I just seek to frames in it).

@hreinnbeck Do you recommend using 25fps video? Is that better for performance?
I usually use 50p videos or sequences for all the graphics.

That’s just ripped out of a project that was delivered with 25p video assets, I usually do everything at 50. Another thing to note with my rAF solution of playing is that 1) it will be frame accurate for Caspar output (since it takes over rAF) and 2) it’s the only way of reliably getting time for video in browsers (timeupdate is not guaranteeed to fire rapidly enough).

1 Like

Oh! so that’s not just a thing over here.

Good to know! That answers some other questions

with seek command can we add transition like mix ?

Thanks for the info all

will play with this later

again thanks soo far

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.