diffusionstudio / core

The Video Creation Engine: Edit videos with code, featuring the fastest WebCodecs renderer for in-browser video processing.
https://examples.diffusion.studio/
Mozilla Public License 2.0
269 stars 19 forks source link

Flushing error while exporting via CanvasEncoder #12

Closed Martinusius closed 1 month ago

Martinusius commented 1 month ago

I copied the example code from here to record a canvas. This is the full code I'm using:

import { CanvasEncoder } from "@diffusionstudio/core";

// Make sure to assign video dimensions
const canvas = new OffscreenCanvas(1920, 1080);

const encoder = new CanvasEncoder(canvas);

const ctx = canvas.getContext("2d")!;

for (let i = 0; i < 90; i++) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // background
  ctx.fillStyle = "blue";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // text
  ctx.fillStyle = "white";
  ctx.font = "50px serif"; // animated Hello World
  ctx.fillText("Hello world", 10 + i * 20, 10 + i * 12);

  // Encode the current canvas state
  await encoder.encodeVideo();
}

const blob = await encoder.export();

However the call to encoder.export() seems to fail: image

I'm using Chrome Version 128.0.6613.86 on Windows.

Any idea why this is happening or how to fix it?

k9p5 commented 1 month ago

Something might get blocked by your browser, perhaps this can be fixed by switching to an incognito window (with no plugins). I just tested the script resulting in the following video

https://github.com/user-attachments/assets/a9cf102d-7adb-4107-8f80-5662e77a81c1

k9p5 commented 1 month ago

Please make sure the video encoder is green on this page: https://diffusion-studio-public.s3.eu-central-1.amazonaws.com/html/feature-detect.html

Martinusius commented 1 month ago

Something might get blocked by your browser, perhaps this can be fixed by switching to an incognito window (with no plugins). I just tested the script resulting in the following video

result.mp4

Tried Chrome incognito and also tried running it in Edge. The issue still persists.

Please make sure the video encoder is green on this page: https://diffusion-studio-public.s3.eu-central-1.amazonaws.com/html/feature-detect.html

Yes, it is green.

Will try on a different device soon.

Martinusius commented 1 month ago

Same error on a different Windows device.

k9p5 commented 1 month ago

Then it must be a windows related issue since I only tested the encoder on MacOs, I'll see what I can find out. In the past I had a similar issue by encoding frames to fast on windows. Something you could try is to wait 100 ms between every frame.

See https://issues.chromium.org/issues/40944632 for reference

k9p5 commented 1 month ago

I just notice it might be this exact bug. In the issue I also wrote that decreasing the video size e.g. to 640p or encoding fewer frames can help

Martinusius commented 1 month ago

I'm literally going crazy. It doesn't work on a single Windows machine of mine but for some reason it does work on my Android.

I hosted the packaged and built code here in case you want to try running EXACTLY the same thing as me.

Martinusius commented 1 month ago

Then it must be a windows related issue since I only tested the encoder on MacOs, I'll see what I can find out. In the past I had a similar issue by encoding frames to fast on windows. Something you could try is to wait 100 ms between every frame.

See https://issues.chromium.org/issues/40944632 for reference

I guess it just doesn't work on Windows then. I tried adding the delay but unfortunately no success.

Martinusius commented 1 month ago

I just notice it might be this exact bug. In the issue I also wrote that decreasing the video size e.g. to 640p or encoding fewer frames can help

I now tried 30 frames of size 320x180 with a 200ms delay. Still nothing.

k9p5 commented 1 month ago

What the Google engineers suggested is to limit the encoder queue size, this is what the gpuBatchSize argument is for:

const encoder = new CanvasEncoder(canvas, { gpuBatchSize: 1});

This should limit the queue size to 1

Martinusius commented 1 month ago

What the Google engineers suggested is to limit the encoder queue size, this is what the gpuBatchSize argument is for:

const encoder = new CanvasEncoder(canvas, { gpuBatchSize: 1});

This should limit the queue size to 1

Same thing. RIP Windows I guess.

Martinusius commented 1 month ago

Okay, nevermind. I now just added an empty AudioBuffer and it suddenly seems to work. Damn!

await encoder.encodeAudio(
  new AudioBuffer({ length: 44100, numberOfChannels: 2, sampleRate: 44100 })
);
k9p5 commented 1 month ago

All right that should be easy to fix thanks! Weird that this is a windows specific issue

k9p5 commented 1 month ago

Just published a fix for windows, the api also changed a bit:

import { CanvasEncoder } from '@diffusionstudio/core';

const encoder = new CanvasEncoder(canvas);

const blob = await encoder.blob()

If you need audio you now have to need to pass audio: true to the constructor:

const encoder = new CanvasEncoder(canvas, { audio: true });
k9p5 commented 1 month ago

Since I switched the audio encoder from webcodecs to opuslib (wasm) it should also now work in all browsers