perf(studio-server): coordinate cancelable thumbnail generation (#2720)

* perf(studio): schedule adaptive timeline thumbnails

* perf(studio): bound thumbnail decoding resources

* perf(studio): virtualize timeline thumbnail media

* perf(studio): prioritize timeline thumbnail work

* perf(studio-server): coordinate cancelable thumbnail generation

---------

Co-authored-by: Codex <codex@local>
This commit is contained in:
Miguel Ángel
2026-08-05 20:41:35 -07:00
committed by GitHub
co-authored by Codex
parent 27d113e56c
commit 96861cbafc
59 changed files with 3537 additions and 879 deletions
+18 -5
View File
@@ -32,6 +32,7 @@ import {
consumeFileWriteReceipt,
getMimeType,
type PreviewApiAdapter,
thumbnailDeviceScaleFactor,
type ResolvedProject,
type RenderJobState,
type BackgroundRemovalRender,
@@ -571,9 +572,18 @@ export function createStudioServer(options: StudioServerOptions): StudioServer {
);
}
let page: import("puppeteer-core").Page | null = null;
const closePage = () => void page?.close().catch(() => {});
opts.signal.addEventListener("abort", closePage, { once: true });
try {
page = await session.browser.newPage();
await page.setViewport({ width: opts.width || 1920, height: opts.height || 1080 });
if (opts.signal.aborted) return null;
const width = opts.width || 1920;
const height = opts.height || 1080;
await page.setViewport({
width,
height,
deviceScaleFactor: thumbnailDeviceScaleFactor(opts),
});
await page.goto(opts.previewUrl, { waitUntil: "domcontentloaded", timeout: 10000 });
await page
.waitForFunction(
@@ -621,12 +631,15 @@ export function createStudioServer(options: StudioServerOptions): StudioServer {
)) as Buffer;
return screenshot;
} catch (err) {
console.warn(
"[Studio] Thumbnail generation failed:",
err instanceof Error ? err.message : err,
);
if (!opts.signal.aborted) {
console.warn(
"[Studio] Thumbnail generation failed:",
err instanceof Error ? err.message : err,
);
}
return null;
} finally {
opts.signal.removeEventListener("abort", closePage);
await page?.close().catch(() => {});
}
},