Includes compiler snapshots, injection-proof escaping checks, and an ffmpeg integration test on synthetic testsrc/sine inputs that is skipped when ffmpeg is not installed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138YqDj3ttfayRwuMKKrqVj
136 lines
4.3 KiB
TypeScript
136 lines
4.3 KiB
TypeScript
import type { BrandKit, Edl, PlatformProfile } from "@rakazo/contracts";
|
|
import { BrandKitSchema, EdlSchema, PlatformProfileSchema } from "@rakazo/contracts";
|
|
import type { EdlContext } from "./edl.js";
|
|
|
|
/* Synthetic fixtures shared by the unit tests. No real people, places, or platforms. */
|
|
|
|
export function testProfile(overrides: Record<string, unknown> = {}): PlatformProfile {
|
|
return PlatformProfileSchema.parse({
|
|
id: "example-short-vertical",
|
|
name: "Example short vertical",
|
|
kind: "free_social",
|
|
reviewedAt: "2026-09-01",
|
|
video: {
|
|
aspectRatios: ["9:16"],
|
|
width: 1080,
|
|
height: 1920,
|
|
fps: 30,
|
|
codec: "h264",
|
|
maxBitrateKbps: 8000,
|
|
maxFileSizeMb: 500,
|
|
},
|
|
duration: { hardMinMs: 1000, hardMaxMs: 60_000, recommended: [7000, 15_000, 30_000] },
|
|
safeZones: { topPct: 10, bottomPct: 20, leftPct: 5, rightPct: 12 },
|
|
captions: { recommended: true, maxLines: 2 },
|
|
audio: {},
|
|
text: {
|
|
titleMaxChars: 100,
|
|
captionMaxChars: 150,
|
|
hashtagLimit: 3,
|
|
linkPolicy: "bio_only",
|
|
bannedPatterns: [{ pattern: "free\\s+money", reason: "misleading claim" }],
|
|
},
|
|
content: { thresholds: { explicit_nudity: 0.2, violence: 0.5 } },
|
|
disclosure: { aiAlteredLabelRequired: true },
|
|
consent: { requirePerformerConsent: false, requireAgeVerification: false },
|
|
export: {},
|
|
...overrides,
|
|
});
|
|
}
|
|
|
|
export function testPaidProfile(): PlatformProfile {
|
|
return testProfile({
|
|
id: "example-paid-video",
|
|
name: "Example paid video",
|
|
kind: "paid_video",
|
|
video: {
|
|
aspectRatios: ["16:9"],
|
|
width: 1920,
|
|
height: 1080,
|
|
fps: 30,
|
|
codec: "h264",
|
|
maxBitrateKbps: 12_000,
|
|
maxFileSizeMb: 4000,
|
|
},
|
|
duration: { hardMinMs: 1000, hardMaxMs: 3_600_000, recommended: [] },
|
|
safeZones: { topPct: 0, bottomPct: 0, leftPct: 0, rightPct: 0 },
|
|
text: { captionMaxChars: 2000, hashtagLimit: 10, linkPolicy: "allowed" },
|
|
consent: { requirePerformerConsent: true, requireAgeVerification: true },
|
|
disclosure: { aiAlteredLabelRequired: true, ageRestrictedFlag: true },
|
|
});
|
|
}
|
|
|
|
export function testKit(overrides: Partial<BrandKit> = {}): BrandKit {
|
|
return BrandKitSchema.parse({
|
|
name: "Studio Example",
|
|
colors: {
|
|
primary: "#112233",
|
|
secondary: "#445566",
|
|
accent: "#FFAA00",
|
|
text: "#FFFFFF",
|
|
background: "#000000",
|
|
},
|
|
fonts: [{ family: "Example Sans", artifactId: "font-1", role: "caption", license: "OFL" }],
|
|
watermark: { artifactId: "logo-1", position: "top_right", opacity: 0.6, scale: 0.15 },
|
|
captionPresets: [
|
|
{
|
|
id: "clean",
|
|
name: "Clean",
|
|
template: "clean",
|
|
fontFamily: "Example Sans",
|
|
sizePct: 5,
|
|
textColor: "#FFFFFF",
|
|
},
|
|
],
|
|
musicBeds: [{ artifactId: "music-1", title: "Bed", license: "own", commercialUse: true }],
|
|
...overrides,
|
|
});
|
|
}
|
|
|
|
/** Two 16:9 clips of a 10 s asset, 4 s total, on a vertical profile. */
|
|
export function testEdl(overrides: Record<string, unknown> = {}): Edl {
|
|
return EdlSchema.parse({
|
|
edlVersion: 1,
|
|
output: {
|
|
profileId: "example-short-vertical",
|
|
width: 1080,
|
|
height: 1920,
|
|
fps: 30,
|
|
durationTargetMs: 4000,
|
|
durationHardMinMs: 1000,
|
|
durationHardMaxMs: 60_000,
|
|
},
|
|
tracks: {
|
|
video: [
|
|
{ id: "c1", assetId: "asset-a", inMs: 0, outMs: 2000, atMs: 0, reframe: "auto" },
|
|
{ id: "c2", assetId: "asset-a", inMs: 5000, outMs: 7000, atMs: 2000, reframe: "auto" },
|
|
],
|
|
},
|
|
metadata: {},
|
|
...overrides,
|
|
});
|
|
}
|
|
|
|
export function testContext(overrides: Partial<EdlContext> = {}): EdlContext {
|
|
return {
|
|
profile: testProfile(),
|
|
brandKit: testKit(),
|
|
assets: new Map([
|
|
["asset-a", { kind: "video", durationMs: 10_000, width: 1920, height: 1080 }],
|
|
["asset-b", { kind: "video", durationMs: 8000, width: 1920, height: 1080 }],
|
|
["photo-1", { kind: "photo", durationMs: null, width: 4000, height: 3000 }],
|
|
]),
|
|
artifactIds: new Set(["music-1", "music-2", "vo-1"]),
|
|
music: new Map([
|
|
["music-1", { commercialUse: true }],
|
|
["music-2", { commercialUse: false }],
|
|
]),
|
|
markIds: new Set(["mark-1"]),
|
|
personIds: new Set(["person-1"]),
|
|
faceTrackIds: new Set(["track-1"]),
|
|
templateIds: new Set(["intro-minimal", "outro-simple", "lower-third-a"]),
|
|
paidOnly: [],
|
|
...overrides,
|
|
};
|
|
}
|