DocDoeAI / src /video-engine /types.ts
asnannp's picture
deploy: sync backend to Space root (learn-lesson HF cache fix)
65d68f5
Raw History Blame Contribute Delete
4.64 kB
/**
* DocDoe Cinematic Video Engine β€” Strict Type System
*
* These types form the contract between the AI script generator and the
* Remotion-based visual renderer. Keep them narrow and explicit β€” avoid `string`
* wherever a union works.
*
* NO framer-motion in any component that imports from this file.
* All animation must use Remotion's interpolate() / spring() / useCurrentFrame().
*/
// ---------------------------------------------------------------------------
// Scene type union β€” maps every AI-generated scene to a visual template
// ---------------------------------------------------------------------------
export type SceneType =
| "hook" // Opening attention grab β€” large, bold, dramatic
| "explain" // Core teaching content β€” hologram board, keywords, body text
| "keyword" // Vocabulary/definition spotlight β€” big term + meaning chips
| "pyq" // Past year question β€” exam paper style, marks badge, answer reveal
| "quiz" // Interactive check β€” question + choices or blank fill
| "recap" // Summary cards β€” numbered key points
| "mentor"; // Direct-to-camera personal coaching tone β€” warm, close framing
// ---------------------------------------------------------------------------
// Supporting value types
// ---------------------------------------------------------------------------
export type MentorEmotion =
| "explaining"
| "excited"
| "thinking"
| "serious"
| "recap"
| "doubt"
| "study";
export type CameraMotion = "dolly_in" | "dolly_out" | "pan_left" | "pan_right" | "static";
export type VisualHintType = "diagram" | "equation" | "list" | "comparison" | "none";
export type VisualHint = {
type: VisualHintType;
label?: string;
items?: string[];
};
export type SubtitleSegment = {
/** Seconds from scene start */
start: number;
end: number;
text: string;
};
export type ExamFocusData = {
question: string;
answer: string;
marks: number;
exam_year?: number;
/** How many times asked in past papers */
frequency?: number;
};
// ---------------------------------------------------------------------------
// Core scene and plan types
// ---------------------------------------------------------------------------
export type VideoScene = {
scene_id: number;
type: SceneType;
duration_seconds: number;
/** Headline text β€” short, displayed large at top of board */
title: string;
/** Body explanation text β€” 1-3 sentences */
body: string;
/** TTS narration text β€” may differ from body */
voice_text: string;
/** Max 6 keyword chips shown as staggered tags */
keywords: string[];
visual_hint: VisualHint;
subtitle_segments?: SubtitleSegment[];
mentor_emotion?: MentorEmotion;
camera_motion?: CameraMotion;
/** PYQ scene data β€” used when type === "pyq" */
exam_focus?: ExamFocusData;
audio_src?: string;
is_mock_audio?: boolean;
};
export type VideoPlan = {
/** Stable plan identifier (used as Remotion composition key) */
id: string;
title: string;
subject: string;
chapter?: string;
language: string;
duration_minutes: number;
/** Override computed total when provided by backend */
total_duration_seconds?: number;
scenes: VideoScene[];
/** Whether the Nila teacher character is shown */
show_mentor: boolean;
/** Shows "Preview" watermark in top-right corner */
show_preview_watermark?: boolean;
};
// ---------------------------------------------------------------------------
// Engine configuration
// ---------------------------------------------------------------------------
export type VideoEngineConfig = {
fps: number;
width: number;
height: number;
format: "16:9" | "9:16";
};
export const VIDEO_ENGINE_FPS = 30 as const;
export const DEFAULT_CONFIG: VideoEngineConfig = {
fps: VIDEO_ENGINE_FPS,
width: 1920,
height: 1080,
format: "16:9",
} as const;
export const VERTICAL_CONFIG: VideoEngineConfig = {
fps: VIDEO_ENGINE_FPS,
width: 1080,
height: 1920,
format: "9:16",
} as const;
// ---------------------------------------------------------------------------
// Interop helpers β€” adapt existing ExplainerScene β†’ VideoScene
// ---------------------------------------------------------------------------
/** Minimal ExplainerScene fields needed by the interop adapter */
export type LegacySceneInput = {
scene_id: number;
type: string;
duration_seconds: number;
screen_text: string;
voice_text: string;
keywords: string[];
visual_hint: string;
subtitle_segments?: Array<{ start: number; end: number; text: string }>;
mascot_expression?: string | null;
};