I would like to build a small application running on browser ( using Chrome ) that synchronizes an embedded video with some graphics. I took inspiration from here https://www.youtube.com/watch?v=_AD2ciZ-0UI for a small test.
Here I am trying to play the video and "move" the position of a rectangle accordingly, in a synced way:
<!DOCTYPE html>
<html>
<body>
<video id="myvideo" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="myrect" viewBox="0 0 200 200" > <rect x=10 y=8 width=5 height=20
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
<script>
var m = 10 ;
var myvideo = document.getElementById('myvideo')
var rect = document.getElementById('myrect');
myvideo.addEventListener('play', function() {
timerID=window.setInterval(function (){
m=parseInt(myvideo.currentTime);
console.log(m);
rect.setAttribute('x',m);
},100)
})
</script>
</body>
</html>
Unluckily, when running this I see that the variable "m" gets incremented correctly (looking at the values in the Console), but the rectangle is not moving. What am I doing wrong ?
UPDATE AFTER ANSWER OF @VC.ONE .
Here is a working version from @vc.one , slighly modified. The slight modification is that the rectangle now moves below the video in a way synced to the progress bar. This method seems to work, but it looks that the rectangle follows the progress bar with some delay, especially when this is dragged fast. How to improve the responsiveness of this code ? ( I am also open to use other platforms/programs )
<!DOCTYPE html>
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div>
<video id="myvideo" width="720" controls>
<source src="mov_bbb.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=4 y=0 width=5 height=15
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
</div>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
myvideo.addEventListener('timeupdate', function() { moveShape() } );
myvideo.addEventListener('play', function() { handle_Play() } );
function moveShape()
{
speed = 188/myvideo.duration ;
m = 4 + ( speed * (myvideo.currentTime) );
rect.style.x = m; //# direct access to "x" Style
//rect.setAttribute('x', m); //# alt way to access same "x" Style
}
function handle_Play()
{
//# if needed (may clog the console with constant messages every 100 ms)
//timerID = window.setInterval( doTimer(), 100);
}
function doTimer()
{
m = parseInt( myvideo.currentTime );
console.log("video secs : " + m);
}
</script>
</body>
</html>
UPDATE WITH A WORKING VERSION USING setInterval :
After some trials I tried again with setInterval, and kind of works better I think, as far as synchronization speed is concerned :
<!DOCTYPE html>
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<div>
<video id="myvideo" width="720" controls>
<source src="video.mp4" type="video/mp4"></source>
</video>
<svg id="mysvgrect" viewBox="0 0 200 200" > <rect id="myrect" x=4 y=0 width=5 height=15
fill-opacity=0.0
style="stroke-width:0.5;stroke:rgb(0,0,0)"/> </svg>
</div>
<script>
var timerID;
var m = 10;
var speed = 0;
const rect = document.getElementById('myrect');
const myvideo = document.getElementById('myvideo');
setInterval(function () {
speed = 188/myvideo.duration ;
m = 4 + ( speed * (myvideo.currentTime) );
rect.style.x = m; // will get you a lot more updates.
}, 30);
</script>
</body>
</html>
The main difference I think is that with setInterval one has more control on how frequently the function is called ( here e.g. I set up 30 ms), whereas with timeupdate I did not find this possibility. But I am not sure about the drawbacks. Please leave any comments on what you think about this solution... ( for those intereseted, also setInterval has a limit to the update frequency, https://www.w3schools.com/jsref/met_win_setinterval.asp , i.e. 10 ms )