Files
workinf_Blender_Wasm/web/tests/e2e/ffmpeg-movie-probe-production.spec.ts
mes123456 f3e21c6b98
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions
chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-10 11:18:01 +08:00

47 lines
3.3 KiB
TypeScript

import { expect, test } from "@playwright/test";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
const root = path.resolve(import.meta.dirname, "../../..");
const fixture = fs.readFileSync(path.join(root, "tests/files/web/media/sequencer-probe.mp4"));
const sourceSha256 = crypto.createHash("sha256").update(fixture).digest("hex");
test("WBV2-P1128-000 probes and decodes a movie through the local ffmpeg.wasm Worker", async ({ page }) => {
test.setTimeout(120_000);
await page.goto("/");
const result = await page.evaluate(async ({ bytes, sourceSha256 }) => {
const [{ probeSequencerCodec, probeSequencerMovieCodecWithFallback }, cache, { probeMovieWithFFmpeg }] = await Promise.all([
import("/src/sequencer/SequencerCodecProbe.ts"),
import("/src/sequencer/SequencerMediaProxyCache.ts"),
import("/src/sequencer/FFmpegMovieProbe.ts"),
]);
const source = Uint8Array.from(bytes).buffer;
const request = { schemaVersion: 1 as const, stripType: "MOVIE" as const, mimeType: "video/mp4", byteLength: source.byteLength, sourceSha256 };
const browser = await probeSequencerCodec(request, source);
const automatic = await probeSequencerMovieCodecWithFallback(request, source);
const capability = await probeMovieWithFFmpeg(request, source);
const frame = await cache.generateInitialSequencerMovieProxyFrame(request, capability, { kind: "MOVIE_RGBA8_FRAME", width: 8, height: 8, colorSpace: "SRGB8", alphaMode: "STRAIGHT" }, source);
const corrupt = new Uint8Array(source.slice(0));
corrupt.fill(0, 0, Math.min(32, corrupt.length));
const corruptHash = Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256", corrupt)), (value) => value.toString(16).padStart(2, "0")).join("");
const corruptResult = await probeSequencerMovieCodecWithFallback({ ...request, sourceSha256: corruptHash }, corrupt.buffer);
const cancellation = new AbortController();
cancellation.abort();
const cancelled = await probeSequencerMovieCodecWithFallback(request, source, cancellation.signal).then(() => false).catch((error) => error?.name === "AbortError");
const running = new AbortController();
const pending = probeSequencerMovieCodecWithFallback(request, source, running.signal);
running.abort();
const cancelledDuringProbe = await pending.then(() => false).catch((error) => error?.name === "AbortError");
return { browser, automatic, capability, frameBytes: frame.data.byteLength, frameManifest: frame.manifest, corrupt: { status: corruptResult.status, reason: corruptResult.reason }, cancelled, cancelledDuringProbe };
}, { bytes: Array.from(fixture), sourceSha256 });
expect(result.automatic).toMatchObject({ status: "READY", backend: result.browser.status === "READY" ? "HTML_MEDIA" : "FFMPEG_WASM", decoded: { width: 16, height: 16, durationMicros: 1_000_000 } });
expect(result.capability).toMatchObject({ status: "READY", backend: "FFMPEG_WASM", decoded: { width: 16, height: 16, durationMicros: 1_000_000 } });
expect(result.frameBytes).toBe(8 * 8 * 4);
expect(result.frameManifest.decodeCapability).toEqual(result.capability);
expect(result.corrupt).toEqual({ status: "BLOCKED", reason: "DECODE_FAILED" });
expect(result.cancelled).toBe(true);
expect(result.cancelledDuringProbe).toBe(true);
});