Skip to content
Advertisement

Video is not drawn on canvas when autoplay is false on Chromium

The following code works fine on Firefox whether autoplay is true or false but not on Chromium. How can I fix it?

EDIT 1: I found out that I can begin with autoplay = true and then in onloadeddata pause the video with video.pause().

EDIT 2: Another interesting thing was found. You can set video.currentTime to, for example 5, to capture the 5th second and if the duration of your video is less than, again for example 5s, the last frame will be drawn on the canvas. And then you can set it back to zero inonloadeddata event. It is good because in most cases the first seconds are black.

let inputFile = document.getElementById("files");
let container = document.getElementById("container");
inputFile.addEventListener("change", inputFileEventHandler);

function inputFileEventHandler() {
  for (const file of inputFile.files) {
    let canvas = document.createElement("canvas");
    canvas.style.border = "1px solid gray";
    canvas.style.padding = "16px";

    let video = document.createElement("video");
    video.style.width = "250px";
    video.style.height = "auto";
    video.style.border = "1px solid gray";
    video.style.padding = "16px";
    video.autoplay = false;
    video.src = URL.createObjectURL(file);

    container.append(video);
    container.append(canvas);

    video.onloadeddata = () => {
      canvas.getContext("2d").drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
    }
  }
}
<!DOCTYPE html>
<html>
  <body>
    <input type="file" id="files" name="files" multiple>
    <div id="container"></div>    
  </body>
</html>

Advertisement

Answer

I have no idea what is the problem

Seems like preload: auto helps, but I’m not sure

Handling multiple events at once makes it work, but not always

let inputFile = document.getElementById("files");
let container = document.getElementById("container");
inputFile.addEventListener("change", inputFileEventHandler);

const events = `abort
canplay
canplaythrough
durationchange
loadeddata
suspend`.split('n')

function inputFileEventHandler() {

  for (const file of inputFile.files) {
    const video = document.createElement("video");
    video.style.width = "250px";
    video.style.height = "auto";
    video.style.border = "1px solid gray";
    video.style.padding = "16px";
    video.autoplay = false;
    video.preload = 'auto';
    video.src = URL.createObjectURL(file);
    container.append(video);

    for (const event of events) {
      const canvas = document.createElement("canvas");
      canvas.style.border = "1px solid gray";
      canvas.style.padding = "16px";
      container.append(canvas);


      video.addEventListener(event, () => {
        console.log(event)
        const ctx = canvas.getContext("2d")
        ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
        ctx.font = "24px serif";
        ctx.fillText(event, 10, 50);
      })
    }
  }
}
<!DOCTYPE html>
<html>

<body>
  <input type="file" id="files" name="files" multiple>
  <div id="container"></div>
</body>

</html>
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement