133 lines
4.9 KiB
JavaScript
133 lines
4.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import ts from "typescript";
|
|
|
|
const root = path.resolve(import.meta.dirname, "../../..");
|
|
const sourcePath = path.join(root, "web/protocol/sequencer-export.ts");
|
|
const source = fs.readFileSync(sourcePath, "utf8").replace('import type { ErrorCode } from "./error";\n', "");
|
|
const transpiled = ts.transpileModule(source, {
|
|
compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 },
|
|
fileName: sourcePath,
|
|
reportDiagnostics: true,
|
|
});
|
|
assert.deepEqual(transpiled.diagnostics, []);
|
|
const finalExport = await import("data:text/javascript;base64," + Buffer.from(transpiled.outputText).toString("base64"));
|
|
const golden = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M11-12/sequencer-final-export.json"), "utf8"));
|
|
|
|
const request = (overrides = {}) => ({
|
|
schemaVersion: 1,
|
|
timelineId: "sequencer:scene:SequencerScene",
|
|
timelineRevision: 1,
|
|
sourceBlendSha256: golden.sourceBlendSha256,
|
|
frameStart: 1,
|
|
frameEnd: 250,
|
|
fpsNumerator: 24000,
|
|
fpsDenominator: 1001,
|
|
width: 1920,
|
|
height: 1080,
|
|
container: "MPEG4",
|
|
videoCodec: "H264",
|
|
audioCodec: "AAC",
|
|
...overrides,
|
|
});
|
|
|
|
test("M11-12 requires the declared server export capability", async () => {
|
|
const blocked = await finalExport.routeSequencerFinalExport(request(), {
|
|
serverExportAvailable: false,
|
|
browserVideoEncoderAvailable: false,
|
|
});
|
|
assert.deepEqual(blocked, golden.withoutServer);
|
|
|
|
const routed = await finalExport.routeSequencerFinalExport(request(), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: false,
|
|
});
|
|
assert.deepEqual(routed, golden.withServer);
|
|
});
|
|
|
|
test("M11-12 never treats browser VideoEncoder detection as local final-export support", async () => {
|
|
for (const serverExportAvailable of [false, true]) {
|
|
const withoutEncoder = await finalExport.routeSequencerFinalExport(request(), {
|
|
serverExportAvailable,
|
|
browserVideoEncoderAvailable: false,
|
|
});
|
|
const withEncoder = await finalExport.routeSequencerFinalExport(request(), {
|
|
serverExportAvailable,
|
|
browserVideoEncoderAvailable: true,
|
|
});
|
|
assert.equal(withoutEncoder.route, "SERVER_EXPORT");
|
|
assert.equal(withEncoder.route, "SERVER_EXPORT");
|
|
assert.equal(withoutEncoder.localEncoding, "BLOCKED");
|
|
assert.equal(withEncoder.localEncoding, "BLOCKED");
|
|
assert.equal(withEncoder.browserVideoEncoderDetected, true);
|
|
assert.deepEqual(
|
|
{ ...withEncoder, browserVideoEncoderDetected: false },
|
|
withoutEncoder,
|
|
);
|
|
}
|
|
});
|
|
|
|
test("M11-12 hashes settings and source revision into deterministic request identities", async () => {
|
|
const baseline = await finalExport.routeSequencerFinalExport(request(), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: false,
|
|
});
|
|
assert.equal(baseline.settingsSha256, golden.settingsSha256);
|
|
assert.equal(baseline.requestSha256, golden.requestSha256);
|
|
assert.deepEqual(
|
|
await finalExport.routeSequencerFinalExport({ ...request(), container: "MPEG4" }, {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: false,
|
|
}),
|
|
baseline,
|
|
);
|
|
|
|
const revisionDrift = await finalExport.routeSequencerFinalExport(request({ timelineRevision: 2 }), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: false,
|
|
});
|
|
assert.equal(revisionDrift.settingsSha256, baseline.settingsSha256);
|
|
assert.notEqual(revisionDrift.requestSha256, baseline.requestSha256);
|
|
|
|
const settingsDrift = await finalExport.routeSequencerFinalExport(request({ width: 1280 }), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: false,
|
|
});
|
|
assert.notEqual(settingsDrift.settingsSha256, baseline.settingsSha256);
|
|
assert.notEqual(settingsDrift.requestSha256, baseline.requestSha256);
|
|
});
|
|
|
|
test("M11-12 rejects undeclared, malformed, and over-budget export requests", async () => {
|
|
await assert.rejects(
|
|
finalExport.routeSequencerFinalExport({ ...request(), localEncoding: "READY" }, {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: true,
|
|
}),
|
|
{ code: "SEQUENCER_EXPORT_REQUEST_INVALID" },
|
|
);
|
|
await assert.rejects(
|
|
finalExport.routeSequencerFinalExport(request({ container: "WEBM", videoCodec: "H264" }), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: true,
|
|
}),
|
|
{ code: "SEQUENCER_EXPORT_REQUEST_INVALID" },
|
|
);
|
|
await assert.rejects(
|
|
finalExport.routeSequencerFinalExport(request({ frameStart: -1_000_000, frameEnd: 1_000_000 }), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: true,
|
|
}),
|
|
{ code: "SEQUENCER_EXPORT_REQUEST_INVALID" },
|
|
);
|
|
await assert.rejects(
|
|
finalExport.routeSequencerFinalExport(request(), {
|
|
serverExportAvailable: true,
|
|
browserVideoEncoderAvailable: true,
|
|
codecName: "h264",
|
|
}),
|
|
{ code: "SEQUENCER_EXPORT_REQUEST_INVALID" },
|
|
);
|
|
});
|