Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run 2 html video side by side at the same time JS

I would like to play 2 html video exactly at the same time (side-by-side).

I made a button which has a click EventListener on it. This listener trigger the 2 <video> tag to play it, but I think there is 150 ms a delay at the second play trigger.

index.html

<section>
    <video src="source1" id="video1"></video>
    <video src="source2" id="video2"></video>
    <button id="play">Play</button>
</section>

and here is the basic script.js file.

    const $video1 = document.getElementById('video1');
    const $video2 = document.getElementById('video2');
    const $play = document.getElementById('play');

    const playVideo = () => {
        $video1.play();
        $video2.play();
    };

    $play.addEventListener('click', playVideo);

These 2 videos are almost the same, except the first video size is about 12MB and the other one is around 20MB

What I tried:

Tried to add a console.time('video') that could logs the delay between each play function call, but that can be different in each environment.

like image 443
cs.matyi Avatar asked Jan 22 '26 06:01

cs.matyi


2 Answers

The only way I'm aware of about playing video in sync is to emit a custom event to sync the video in requestAnimationFrame:

var videos = {
    a: Popcorn("#a"),
    b: Popcorn("#b"),
  },
  scrub = $("#scrub"),
  loadCount = 0,
  events = "play pause timeupdate seeking".split(/\s+/g);

// iterate both media sources
Popcorn.forEach(videos, function(media, type) {

  // when each is ready... 
  media.on("canplayall", function() {

    // trigger a custom "sync" event
    this.emit("sync");

    // set the max value of the "scrubber"
    scrub.attr("max", this.duration());

    // Listen for the custom sync event...    
  }).on("sync", function() {

    // Once both items are loaded, sync events
    if (++loadCount == 2) {

      // Iterate all events and trigger them on the video B
      // whenever they occur on the video A
      events.forEach(function(event) {

        videos.a.on(event, function() {

          // Avoid overkill events, trigger timeupdate manually
          if (event === "timeupdate") {

            if (!this.media.paused) {
              return;
            }
            videos.b.emit("timeupdate");

            // update scrubber
            scrub.val(this.currentTime());

            return;
          }

          if (event === "seeking") {
            videos.b.currentTime(this.currentTime());
          }

          if (event === "play" || event === "pause") {
            videos.b[event]();
          }
        });
      });
    }
  });
});

scrub.bind("change", function() {
  var val = this.value;
  videos.a.currentTime(val);
  videos.b.currentTime(val);
});

// With requestAnimationFrame, we can ensure that as 
// frequently as the browser would allow, 
// the video is resync'ed.
function sync() {
  if (videos.b.media.readyState === 4) {
    videos.b.currentTime(
      videos.a.currentTime()
    );
  }
  requestAnimationFrame(sync);
}

sync();
html{font-family:arial;}
<script src="https://static.bocoup.com/js/popcorn.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<video height="180" width="300" id="a" controls> 
<source src="https://videos.mozilla.org/serv/webmademovies/popcorntest.mp4"></source>
<source src="https://videos.mozilla.org/serv/webmademovies/popcorntest.ogv"></source>
<source src="https://videos.mozilla.org/serv/webmademovies/popcorntest.webm"></source>
</video>
<video height="180" width="300" id="b"> 
<source src="https://videos.mozilla.org/serv/webmademovies/popcorntest.mp4"></source>
<source src="https://videos.mozilla.org/serv/webmademovies/popcorntest.ogv"></source>
<source src="https://videos.mozilla.org/serv/webmademovies/popcorntest.webm"></source>
</video>

<input type="range" value="0" id="scrub" />

Ref: https://bocoup.com/blog/html5-video-synchronizing-playback-of-two-videos

like image 104
Mosè Raguzzini Avatar answered Jan 24 '26 21:01

Mosè Raguzzini


UPDATE

Both of the answers was correct. What I didn't know, that one of the video file has sound, and the other don't. That caused the 150ms delay.

Solved it with ffmpeg. Create an .mp3 file with the sound (and play it with <audio>), and 2 .mp4 files without sound. They are playing exactly at the same time now.

like image 45
cs.matyi Avatar answered Jan 24 '26 21:01

cs.matyi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!