Reputation: 31
I have two HTML video elements that begin autoplaying on page load and continue looping with no end until the user leaves the page. Both videos are 8 seconds long and I need them to always be in sync with one another, but of course they do get out-of-sync. For the audio, Video 1 plays a full song arrangement and video 2 plays just one instrument in the same song so, to show that they are related, they have to be in sync.
<video id="first-video" autoplay="" muted="" loop="" playsinline="" loading="lazy" src="videos/video-1.mp4"></video>
<video id="second-video" autoplay="" muted="" loop="" playsinline="" loading="lazy" src="videos/video-2.mp4"></video>
There are several solutions in this SO question: Is there a way to keep two videos synchronized in a webpage without plugins?
but when I try to implement, I see no change in quality of sync, they get out of sync just as easily. I am new to JS, but my guess is that there is some method of detecting the first and last frame of a video and then one could use those to start/stop a second video and with the video on "loop" this could go on indefinitely. If anybody can point me in the right direction for that or any other solution, that would be very helpful!
Thank you.
Upvotes: 1
Views: 1943
Reputation: 69
I also faced the challenge of synchronizing multiple videos and found the process to be very complicated. As a result, I created a package called sync-video-player that can synchronize two or more videos. If you're interested in the implementation, feel free to take a look at the code on GitHub:
It's worth noting that this package is relatively new, but I use it actively in my own projects and am committed to maintaining it. If you encounter any issues, please don't hesitate to report them.
Upvotes: -1
Reputation: 949
Assuming both tracks start at the same current time (0) and are playing at the same rate you can constantly change the second video's position to the first video's position. This isn't exact or frame accurate, but should roughly get the job done:
function syncVideos() {
const first = document.getElementById('first-video');
const second = document.getElementById('second-video');
// keep track of if video's seeking to avoid constant changes to position
// don't know if this is really necessary
let isSeeking = false;
second.addEventListener('seeking', () => isSeeking = true);
second.addEventListener('seeked', () => isSeeking = false);
const thresholdMilliseconds = 50; // some ms threshold of difference to avoid excessive seeking
const nudgeOffsetMilliseconds = 5; // just a guess that you may need to assume that seeking won't be instantaneous. I don't know if this is necessary or helpful
// listen for time updates on the first video's position
first.addEventListener('timeupdate', () => {
const deltaMilliseconds = (second.currentTime - first.currentTime) * 1000;
if (Math.abs(delta) >= thresholdMilliseconds) {
if (isSeeking) {
console.warn('not in sync, but currently seeking');
return;
}
console.log(`out of sync by ${deltaMilliseconds}ms. Seeking to ${first.currentTime}`);
// adding a bit of nudge b/c syncing may not be instant. Not an exact science...for that use MSE
second.currentTime = first.currentTime + nudgeOffsetMilliseconds;
}
});
}
syncVideos();
Use MSE (Media Source Extensions), which would probably allow for more accurate seeking and sync. This may help: Playing one of multiple audio tracks in sync with a video
You may want to look for libraries on github. I Haven't looked but searching for "audio mixer" or something may point you somewhere...
Upvotes: 2