More FE changes
This commit is contained in:
parent
f114ada255
commit
a48eb945e0
48 changed files with 4127 additions and 1751 deletions
|
|
@ -1,46 +1,66 @@
|
|||
export const APP_URL = process.env.APP_URL ?? 'http://host.docker.internal:3001';
|
||||
export const DASHBOARD_PATH = '/dashboard';
|
||||
function requiredEnv(name: string): string {
|
||||
const value = process.env[name];
|
||||
if (!value) {
|
||||
throw new Error(`${name} is required`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const AUTH_STATE_PATH = 'auth.json';
|
||||
export const OUTPUT_DIR = 'output';
|
||||
function requiredNumberEnv(name: string): number {
|
||||
const value = Number(requiredEnv(name));
|
||||
if (!Number.isFinite(value)) {
|
||||
throw new Error(`${name} must be a finite number`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const aspect = process.env.ASPECT ?? '16x9';
|
||||
export const APP_URL = requiredEnv("APP_URL");
|
||||
export const DASHBOARD_PATH = "/dashboard";
|
||||
|
||||
export const AUTH_STATE_PATH = "auth.json";
|
||||
export const OUTPUT_DIR = "output";
|
||||
|
||||
const aspect = requiredEnv("ASPECT");
|
||||
if (aspect !== "16x9" && aspect !== "9x16") {
|
||||
throw new Error("ASPECT must be '16x9' or '9x16'");
|
||||
}
|
||||
export const VIEWPORT =
|
||||
aspect === '9x16' ? { width: 1080, height: 1920 } : { width: 1920, height: 1080 };
|
||||
export const CAPTURE_SCALE = Math.max(1, Number(process.env.CAPTURE_SCALE ?? 1));
|
||||
aspect === "9x16"
|
||||
? { width: 1080, height: 1920 }
|
||||
: { width: 1920, height: 1080 };
|
||||
export const CAPTURE_SCALE = Math.max(1, requiredNumberEnv("CAPTURE_SCALE"));
|
||||
export const VIDEO_SIZE = {
|
||||
width: VIEWPORT.width,
|
||||
height: VIEWPORT.height,
|
||||
};
|
||||
export const WEBM_BITRATE = process.env.WEBM_BITRATE ?? (CAPTURE_SCALE > 1 ? '18M' : '8M');
|
||||
export const WEBM_BITRATE = requiredEnv("WEBM_BITRATE");
|
||||
|
||||
// Cold-open prompt. Punchy version of the user's intent, short enough to type
|
||||
// on camera without making the opening scene drag.
|
||||
export const PROMPT_TEXT =
|
||||
process.env.PROMPT_TEXT ?? 'Flats or terraces <£450k, 35 min to Manchester, low crime';
|
||||
export const PROMPT_TEXT = requiredEnv("PROMPT_TEXT");
|
||||
|
||||
// Filters returned by the AI stub. Keys MUST match real feature names from
|
||||
// /api/features (verified against the running server's schema).
|
||||
export const STUBBED_FILTERS: Record<string, [number, number] | string[]> = {
|
||||
'Property type': ['Flats/Maisonettes', 'Terraced'],
|
||||
'Estimated current price': [175000, 450000],
|
||||
'Serious crime per 1k residents (avg/yr)': [0, 55],
|
||||
'Noise (dB)': [50, 68],
|
||||
"Property type": ["Flats/Maisonettes", "Terraced"],
|
||||
"Estimated current price": [175000, 450000],
|
||||
"Serious crime per 1k residents (avg/yr)": [0, 55],
|
||||
"Noise (dB)": [50, 68],
|
||||
};
|
||||
|
||||
// Travel-time filters returned by the AI stub. Slug matches the real
|
||||
// /api/travel-destinations?mode=transit response.
|
||||
export const STUBBED_TRAVEL_TIME_FILTERS: {
|
||||
mode: 'transit' | 'car' | 'bicycle' | 'walking';
|
||||
mode: "transit" | "car" | "bicycle" | "walking";
|
||||
slug: string;
|
||||
label: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
}[] = [
|
||||
{
|
||||
mode: 'transit',
|
||||
slug: 'manchester',
|
||||
label: 'Manchester city centre',
|
||||
mode: "transit",
|
||||
slug: "manchester",
|
||||
label: "Manchester city centre",
|
||||
max: 35,
|
||||
},
|
||||
];
|
||||
|
|
@ -55,7 +75,7 @@ export const TT_DRAG_TO_MIN = 20;
|
|||
|
||||
// Cold-open zoom: how aggressively to magnify the AI box.
|
||||
// 2.4 fills most of the viewport with the prompt card without blowing up text.
|
||||
export const AI_ZOOM_SCALE = Number(process.env.AI_ZOOM_SCALE ?? 2.4);
|
||||
export const AI_ZOOM_SCALE = requiredNumberEnv("AI_ZOOM_SCALE");
|
||||
|
||||
// Initial map view used while we navigate. The AI scene zooms in on the
|
||||
// sidebar so this only matters once we zoom out.
|
||||
|
|
@ -67,13 +87,18 @@ export const INITIAL_MAP_VIEW = {
|
|||
|
||||
// Verification guard only. The renderer does not use this as an editing cap:
|
||||
// if the storyboard needs more than 15 seconds to avoid jumps, keep the frames.
|
||||
export const MAX_DURATION_S = Number(process.env.MAX_DURATION_S ?? 45);
|
||||
export const MIN_DURATION_S = Number(process.env.MIN_DURATION_S ?? 10);
|
||||
export const MAX_DURATION_S = requiredNumberEnv("MAX_DURATION_S");
|
||||
export const MIN_DURATION_S = requiredNumberEnv("MIN_DURATION_S");
|
||||
|
||||
// Target fps of the FINAL output.
|
||||
export const OUTPUT_FPS = Number(process.env.OUTPUT_FPS ?? 50);
|
||||
export const OUTPUT_FPS = requiredNumberEnv("OUTPUT_FPS");
|
||||
|
||||
// Frames of head-room kept in front of sceneStart when trimming. Shared by
|
||||
// the video trim and the narration manifest so cue offsets line up with the
|
||||
// trimmed timeline.
|
||||
export const LEAD_IN_S = 0.12;
|
||||
|
||||
// Brand strings for the outro card.
|
||||
export const BRAND_NAME = 'Perfect Postcode';
|
||||
export const BRAND_TAGLINE = 'Find where you actually want to live.';
|
||||
export const BRAND_URL = 'https://perfect-postcode.co.uk';
|
||||
export const BRAND_NAME = "Perfect Postcode";
|
||||
export const BRAND_TAGLINE = "Find where you actually want to live.";
|
||||
export const BRAND_URL = "https://perfect-postcode.co.uk";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue