0

Let's say I have a canvas:

<canvas height="500" width="500"></canvas>

I can capture a video from it using captureStream.

So if I have a video element, I can pass it the captured stream and see whatever I draw mirrored in the video:

<video autoplay height="500" width="500"></video>


const video = document.querySelector("video");
const canvas = document.querySelector("canvas");

const stream = canvas.captureStream(25);
video.srcObject = stream;
video.play();

I can also derive an OffscreenCanvas from this canvas, and transfer to another frame

const iframe = document.querySelector("iframe");
const offscreen = canvas.transferControlToOffscreen();

iframe.contentWindow.postMessage(
  {
    type: "canvasTransfer",
    canvas: offscreen
  },
  "*",
  [offscreen]
);

And perform the drawing operation from within a sandboxed iframe.

This seems to work fine in chrome but in firefox captureStream fails and I get following error:

[Exception... "Component not initialized"  nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)"  location: "JS frame :: https://2rlmz5.csb.app/src/index.js :: $csb$eval :: line 16"  data: no]

Is there a known resolution ? Any help is highly appreciated.

Codesandbox

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
lorefnon
  • 12,875
  • 6
  • 61
  • 93

1 Answers1

3

There is an open bug in Firefox related to this. As for now, in Firefox, the captureStream will throw if the canvas context is not initialized. A getContext call, before invoking captureStream, fixes that error:

const canvas = document.querySelector("canvas");

canvas.getContext('2d');

const stream = canvas.captureStream(25);
<canvas height="500" width="500"></canvas>

But, the problem here is that the transferControlToOffscreen does not work if the canvas context is initialized, and vice-versa if transferControlToOffscreen was invoked first, then canvas context can be initialized only in offscreen.
Thus, the only resolution is to wait for that bug to be fixed.

n--
  • 3,563
  • 4
  • 9
  • One ugly workaround would be to regularily send ImageBitmaps from the OffscreenCanvas to the main window, paint these on an ImageBitmapRenderer context and capture the MediaStream from its canvas. – Kaiido Oct 13 '22 at 02:06
  • POC: https://jsfiddle.net/9ug4k8am/ (unrelated, but this fiddle exposes a new bug in FF where `fillStyle` is ignored, I'll leave it broken for posterity...) – Kaiido Oct 13 '22 at 02:13
  • Oh wow, open since 7 years. Thanks a lot for your explanation and the workaround. – lorefnon Oct 13 '22 at 05:56