Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display same video in multiple <video> tags

I have a video (let's call it composite video) composed by multiple other videos concatenated using some pattern. For example, see the screenshot of the videos below, composed by two and four other videos, respectively:

2-videos example

4-videos example

However, I need to display it differently: One main, larger, video and N-1 video thumbnails, where N is the total number of videos. Here are this other display corresponding to the videos above:

Main video + 1 thumbnail

Main video + 3 thumbnails

To display the main I'm using a combination of HTML and CSS to position the video I want in the larger div. It runs smoothly, no matter the number of videos in the composite videos.

To display the thumbnails, I'm using <canvas> to draw the parts I want:

video.addEventListener('play', function() {
  (function loop() {
    drawThumbnails();
    setTimeout(loop, 1000 / 30); // drawing at 30fps
  })();
}, false);

function drawThumbnails() {
  for (var i = thumbs.length - 1; i >= 0; i--) {
    drawThumbnail(thumbs[i]);
  };
}

function drawThumbnail(thumb) {
  var thumbNumber = Number(thumb.id.match(/\d+/g));
  var canvasContext = thumb.getContext('2d');
  var thumbCoordinates = getVideoCoordinates(thumbNumber);
  var srcX = thumbCoordinates.column * videoWidth;
  var srcY = thumbCoordinates.row * videoHeight;

  canvasContext.drawImage(
      video, srcX, srcY, videoWidth, videoHeight, // Source
      0, 0, thumb.width, thumb.height); // Destination
}

It was working well for 3 (sometimes 4) videos. However, as the number of videos in the composite video increases, the videos in the thumbnails start to freeze and run not in a smooth way. This is probably happening because there's too much image processing being done at the same time.

I think the proper way to do it is, somehow, using <video> and methods specific for videos, not for images. I've also tried to use the same src in the multiple <video> tags (one for each thumbnail) and add eventListeners to play/pause the videos in the thumbnails once the main video is played/paused. That's not very efficient, particularly because videos can get out of sync sometimes, when seeking/buffering.

Is there a way of using only one video in multiple <video> tags and use only one of them (in my case, the one that contains the main video) to control all the others? In case there's no way of doing that, is there an alternative approach for my problem?

Thanks a lot,

P.S. Having multiple, separated, videos is not an option in my situation. It would take a very long time to process the input video and divide it in multiple videos.

like image 413
Amaury Medeiros Avatar asked Jan 29 '16 20:01

Amaury Medeiros


People also ask

How to embed video in HTML?

To embed a video in an HTML page, use the <iframe> element. The source attribute included the video URL. For the dimensions of the video player, set the width and height of the video appropriately. The Video URL is the video embed link.

How does video tag works?

The <video> tag is used to embed video content in a document, such as a movie clip or other video streams. The <video> tag contains one or more <source> tags with different video sources. The browser will choose the first source it supports.


2 Answers

You can certainly reference the same video across multiple video elements. Cloning the original and appending them as thumbnail videos might alleviate some of the tedium.

Iterating over the thumbnails and .play()ing them should be fine so long as you set their currentTime with that of the main video prior to playing, to minimize drift. There may be some need to wait for canplay to fire on the main video and/or the thumbnails depending on the exact experience you're looking to deliver.

If each thumbnail is given a parent container you could possibly position the video element serving as your thumbnail such that only the portion of the video you care to see is visible, clipping the rest.

FWIW, CSS masking might be of interest to you as a performance optimization if it helps the compositing performance.

You will need to manually coordinate playing/pausing all of the video elements, but that should be easy enough to do with a facade object that handle the play pause of all the "linked" video elements.

like image 115
mczepiel Avatar answered Oct 16 '22 08:10

mczepiel


I know I'm posting late, and you may have already found an answer. However, if anyone else comes across this question, here is my answer:

You can use multiple video elements with the same source. The way to do it is with css.

.wrapper {
    height: /*height of one video*/;
    width: /*width of one video*/;
    overflow: hidden;
}
video {
    position: relative;
    top: /*height offset*/;
    left: /*width offset*/;
}

And HTML

<div class="wrapper">
    <video src="myvideo.mp4"></video>
</div>

So, if I was doing the top right video, and each one was 250px by 250px, I would set my wrapper height and width to 250px and my video top to 0px and my video left to 250px

like image 1
jlynch630 Avatar answered Oct 16 '22 09:10

jlynch630