在 Javascript 中同步图形与视频的运动
我想在浏览器(使用Chrome)上构建一个小型应用程序,该应用程序将嵌入式视频与某些图形同步。我从这里汲取了灵感 https://www.youtube.com/watch -0UI 进行小测试。
在这里,我试图以同步的方式播放视频并“移动”矩形的位置:
<!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>
不幸的是,运行此操作时,我看到变量“ M”会正确递增(查看控制台中的值),但是矩形没有移动。我在做什么错?
@vc.one的答案后更新
。略有修改是,矩形现在以同步到进度栏的方式移动到视频下方。这种方法似乎可以工作,但是看起来矩形遵循进度栏以某种延迟,尤其是在快速拖动时。如何提高本守则的响应能力? (我也开放使用其他平台/程序)
<!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>
使用setInterval使用工作版本的更新:
在进行了一些试验之后,我再次尝试使用setInterval尝试过,并且我认为,就同步速度而言,我认为更好的是有关:
<!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>
我认为的主要区别是,使用SetInterval One可以更好地控制该函数的频率(例如,我设置了30毫秒),而对于TimeUpdate,我没有发现这种可能性。但是我不确定缺点。请对您对此解决方案的看法发表任何评论...(对于那些相交的情况,setInterval也有限制更新频率, https://www.w3schools.com/jsref/met_win_setinterval.asp ,即10 ms)
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 )
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
元素提供自己的唯一 ID 以直接访问它。timeupdate
事件根据视频时间移动形状。尝试这样的操作(ps:注意
rect id="myrect"
与svg id="mysvgrect"
):<rect>
element its own unique ID to directly access it.timeupdate
event to move the shape against video time.Try something like this (ps: notice the
rect id="myrect"
vssvg id="mysvgrect"
) :