HTML5 Video - How to do a seamless play and/or loop of several videos?

11,294

After trying various things I have finally been able to create what seems to be a working solution. I haven't tested this on older browsers or other OSes, but this works on latest versions of Chrome, IE, Firefox and Opera. (Although some more feedback of whether this works on other systems would be appreciated)

The idea is to have all 3 videos output frames to HTML5 canvas. The original videos are hidden and preloaded in advance to avoid pause between loading.

Here is the code:

var playCounter = 0;
var clipArray = [];

var $video1 = $("#video1");
var $video2 = $("#video2");
var $video3 = $("#video3");

$video1.attr("src", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4");
$video2.attr("src", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4");
$video3.attr("src", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4");

var timerID;

var $canvas = $("#myCanvas");
var ctx = $canvas[0].getContext("2d");

function stopTimer() {
  window.clearInterval(timerID);
}

$('#startPlayback').click(function() {
  stopTimer();
  playCounter = $('#playbackNum').val();
  clipArray = [];

  // addd element to the end of the array
  clipArray.push(1);
  for (var i = 0; i < playCounter; i++) {
    clipArray.push(2);
  }
  clipArray.push(3);

  $video2[0].load();
  $video3[0].load();

  $video1[0].play();
});

function drawImage(video) {
  //last 2 params are video width and height
  ctx.drawImage(video, 0, 0, 640, 360);
}

// copy the 1st video frame to canvas as soon as it is loaded
$video1.one("loadeddata", function() {
  drawImage($video1[0]);
});

// copy video frame to canvas every 30 milliseconds
$video1.on("play", function() {
  timerID = window.setInterval(function() {
    drawImage($video1[0]);
  }, 30);
});
$video2.on("play", function() {
  timerID = window.setInterval(function() {
    drawImage($video2[0]);
  }, 30);
});
$video3.on("play", function() {
  timerID = window.setInterval(function() {
    drawImage($video3[0]);
  }, 30);
});

function onVideoEnd() {
  //stop copying frames to canvas for the current video element
  stopTimer();

  // remove 1st element of the array
  clipArray.shift();

  //IE fix
  if (!this.paused) this.pause();

  if (clipArray.length > 0) {
    if (clipArray[0] === 1) {
      $video1[0].play();
    }
    if (clipArray[0] === 2) {
      $video2[0].play();
    }
    if (clipArray[0] === 3) {
      $video3[0].play();
    }
  } else {
    // in case of last video, make sure to load 1st video so that it would start from the 1st frame 
    $video1[0].load();
  }
}

$video1.on("ended", onVideoEnd);
$video2.on("ended", onVideoEnd);
$video3.on("ended", onVideoEnd);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div id="border">
  <video id="video1" width="640" height="360" hidden>
            <source type="video/mp4">
            Your browser does not support playing this Video
        </video>
  <video id="video2" width="640" height="360" hidden>
            <source type="video/mp4">
            Your browser does not support playing this Video
        </video>
  <video id="video3" width="640" height="360" hidden>
            <source type="video/mp4">
            Your browser does not support playing this Video
        </video>
  <div>
    <canvas id="myCanvas" width="640" height="360"> </canvas>
  </div>
  <div role="controls">
    <div>
      <label>
           Times the middle video will repeat itself:
      </label>
    </div>
    <div>
      <input id="playbackNum" value="1" />
    </div>
    <p>
      <button id="startPlayback">Start</button>
    </p>
  </div>
</div>

Please note, the code is not very pretty and would benefit from some cleanup and optimization, but at least this should show the way to work around the problem and implement a seamless playback of several videos in HTML5. Also make sure to include jQuery source file in html file location for the code to work.

Share:
11,294

Related videos on Youtube

Tanuki
Author by

Tanuki

Updated on September 16, 2022

Comments

  • Tanuki
    Tanuki over 1 year

    How can I reliably play several videos one after another seamlessly? As there is a small pause or flicker between playing 2 videos.

    In my particular example I have 3 videos. I need to play all 3 of them seamlessly one after another, and I also need to loop middle video an arbitrary number of times (say 2 or 3). All of that needs to happen seamlessly and consistently across different browsers.

    I've been trying everything under the moon, from starting video playback on video end, to using several video tags and hiding and replacing them, I even tried to implement this in Flash, but alas nothing works, and the same problem happens in current Flash as well.

    I've seen this (or similar) question asked many times but I haven't seen a reliable solution yet.

    Does anyone know a solution to this?

  • Tanuki
    Tanuki over 8 years
    Hi, thank you for the answer, but have you actually tried this yourself? I've seen a couple VideoJS answers that still haven't solved this. Also, if you know how to solve this with VideoJS, can you point me in a specific direction? As I know nothing about VideoJS.
  • myselfmiqdad
    myselfmiqdad over 8 years
    Yes, I have worked with videoJS playlists. an example I have bookmarked is this github.com/jgallen23/videojs-playLists/blob/master/example/… there is also a playlist plugin for video js github.com/brightcove/videojs-playlist
  • Tanuki
    Tanuki over 8 years
    Ok, the 1st one doesn't work out of the box. I've removed poster images code and replaced online videos with my own links, but there still is a quick flicker (of loading animation mind you) in between the videos. It might be because of poster images, but I am very averse to the idea of having to create and load a picture of every video I want to play. Guess I will have to dig down deeper into this to see if that is possible in VideoJS at all. Still, thank you for the link, perhaps I will find the light at the end of this tunnel.
  • Zade
    Zade about 7 years
    Do you have a URL where we can see this in action?
  • totymedli
    totymedli almost 6 years
    I created a video player with all the common controls in native JS based on this answer.
  • foba
    foba over 4 years
    If you try doing this with really short clips with audio it sounds/looks choppy. I might try finding a solution to this but if someone else does in the meantime that would be great!
  • Tanuki
    Tanuki over 4 years
    Yes, I also found later that this solution doesnt work 100% for short clips. In some cases it would look jittery no matter what I did. I think I tried everything I could think of back then, but nothing really solved the problem. I am not sure how big people at youtube or say pluralsight can play back videos so consistently well. I am very surprised this question suddenly started gaining traction after 2 years since I posted it. But if anyone is looking at this now, please note that this is not a 100% working solution. Although if anyone can provide a fully working solution that would be great!
  • Will
    Will about 4 years
    smart solution. but not the best on mobile (IOS safari)