fix: only read back frames from canvas if the OS is linux, work around not necessary for other OS' line win or darwin

This commit is contained in:
Theodor Peifer
2026-04-14 23:39:13 +02:00
parent 6d449a46c4
commit d12f3980f9
2 changed files with 30 additions and 20 deletions
+5 -1
View File
@@ -187,8 +187,12 @@ export class FrameRenderer {
this.compositeCanvas = document.createElement("canvas");
this.compositeCanvas.width = this.config.width;
this.compositeCanvas.height = this.config.height;
// On Linux, getImageData() is called frequently causing frequent CPU readback
const isLinux = (await window.electronAPI.getPlatform()) === "linux";
this.compositeCtx = this.compositeCanvas.getContext("2d", {
willReadFrequently: false,
willReadFrequently: isLinux,
});
if (!this.compositeCtx) {
+25 -19
View File
@@ -111,6 +111,8 @@ export class VideoExporter {
this.cancelled = false;
this.fatalEncoderError = null;
const platform = await window.electronAPI.getPlatform();
try {
const streamingDecoder = new StreamingVideoDecoder();
this.streamingDecoder = streamingDecoder;
@@ -237,25 +239,29 @@ export class VideoExporter {
const canvas = renderer.getCanvas();
// Read raw pixels from the canvas instead of passing
// the canvas directly to VideoFrame. On some Linux
// systems the GPU shared-image path (EGL/Ozone) fails
// silently, producing empty frames.
const canvasCtx = canvas.getContext("2d")!;
const imageData = canvasCtx.getImageData(0, 0, canvas.width, canvas.height);
const exportFrame = new VideoFrame(imageData.data.buffer, {
format: "RGBA",
codedWidth: canvas.width,
codedHeight: canvas.height,
timestamp,
duration: frameDuration,
colorSpace: {
primaries: "bt709",
transfer: "iec61966-2-1",
matrix: "rgb",
fullRange: true,
},
});
let exportFrame: VideoFrame;
// On some Linux systems the GPU shared-image path (EGL/Ozone) fails
// silently, producing empty frames, so we force a CPU readback instead.
if (platform === "linux") {
const canvasCtx = canvas.getContext("2d")!;
const imageData = canvasCtx.getImageData(0, 0, canvas.width, canvas.height);
exportFrame = new VideoFrame(imageData.data.buffer, {
format: "RGBA",
codedWidth: canvas.width,
codedHeight: canvas.height,
timestamp,
duration: frameDuration,
colorSpace: {
primaries: "bt709",
transfer: "iec61966-2-1",
matrix: "rgb",
fullRange: true,
},
});
} else {
exportFrame = new VideoFrame(canvas, { timestamp, duration: frameDuration });
}
while (
this.encoder &&