video-editing 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3569 @@
1
+ import { z } from 'zod';
2
+
3
+ type TokenType = "word" | "spacing" | "audio_event";
4
+ /** A single ElevenLabs Scribe token (word-level, verbatim). */
5
+ interface ScribeWord {
6
+ type?: TokenType;
7
+ text?: string;
8
+ start: number | null;
9
+ end: number | null;
10
+ speaker_id?: string | null;
11
+ [extra: string]: unknown;
12
+ }
13
+ interface ScribeTranscript {
14
+ language_code?: string;
15
+ text?: string;
16
+ words: ScribeWord[];
17
+ [extra: string]: unknown;
18
+ }
19
+ /** One KEEP segment in SOURCE seconds. Gaps between ranges are the cuts. */
20
+ interface EdlRange {
21
+ source: string;
22
+ start: number;
23
+ end: number;
24
+ beat?: string;
25
+ quote?: string;
26
+ reason?: string;
27
+ /** Optional per-range grade override (preset name | raw ffmpeg filter | "auto"). */
28
+ grade?: string;
29
+ }
30
+ interface EdlOverlay {
31
+ [k: string]: unknown;
32
+ }
33
+ interface Edl {
34
+ version: number;
35
+ sources: Record<string, string>;
36
+ /** "none" | preset name | raw ffmpeg filter | "auto" */
37
+ grade: string;
38
+ ranges: EdlRange[];
39
+ overlays: EdlOverlay[];
40
+ total_duration_s: number;
41
+ /** Optional explicit subtitle path. */
42
+ subtitles?: string;
43
+ /** Set once the amplitude silence-trim pass has rewritten the ranges. */
44
+ desilenced?: boolean;
45
+ }
46
+ interface SourceJson {
47
+ created: string;
48
+ source: string;
49
+ stem: string;
50
+ job_dir: string;
51
+ duration_s: number;
52
+ stored_width: number;
53
+ stored_height: number;
54
+ display_width: number;
55
+ display_height: number;
56
+ rotation: number;
57
+ probe: FfprobeResult;
58
+ }
59
+ interface FfprobeStream {
60
+ index?: number;
61
+ codec_type?: string;
62
+ codec_name?: string;
63
+ width?: number;
64
+ height?: number;
65
+ r_frame_rate?: string;
66
+ avg_frame_rate?: string;
67
+ duration?: string;
68
+ color_transfer?: string;
69
+ side_data_list?: Array<Record<string, unknown>>;
70
+ tags?: Record<string, string>;
71
+ [extra: string]: unknown;
72
+ }
73
+ interface FfprobeResult {
74
+ streams?: FfprobeStream[];
75
+ format?: {
76
+ duration?: string;
77
+ size?: string;
78
+ format_name?: string;
79
+ [k: string]: unknown;
80
+ };
81
+ [extra: string]: unknown;
82
+ }
83
+ interface CutBoundary {
84
+ index: number;
85
+ output_time_s: number;
86
+ removed_source_gap_s: number;
87
+ source_before: number;
88
+ source_after: number;
89
+ }
90
+ type RenderMode = "preview" | "draft" | "final";
91
+ interface ReviewIssue {
92
+ where?: string;
93
+ range_index?: number | null;
94
+ severity?: "error" | "warning" | "info";
95
+ problem?: string;
96
+ fix?: string;
97
+ }
98
+ interface ReviewJson {
99
+ verdict?: "clean" | "needs-fixes";
100
+ issues?: ReviewIssue[];
101
+ confidence?: string;
102
+ }
103
+ interface Warning {
104
+ id: string;
105
+ severity: string;
106
+ output_time_s: number;
107
+ range_index: number | null | undefined;
108
+ problem: string;
109
+ fix: string;
110
+ }
111
+ interface VerifyJoinFinding {
112
+ index: number;
113
+ output_time_s: number;
114
+ duplicated_phrase?: string;
115
+ gap_s?: number;
116
+ severity: "error" | "warning" | "info";
117
+ detail: string;
118
+ }
119
+ interface VerifyResult {
120
+ verdict: "clean" | "needs-fixes";
121
+ mode: "full" | "joins";
122
+ joins: VerifyJoinFinding[];
123
+ confidence: string;
124
+ }
125
+
126
+ interface RunResult {
127
+ code: number;
128
+ stdout: string;
129
+ stderr: string;
130
+ }
131
+ interface RunOptions {
132
+ /** Capture stdout/stderr into strings (default: inherit to the terminal). */
133
+ capture?: boolean;
134
+ /** Write merged stdout+stderr to this file path. */
135
+ stdoutPath?: string;
136
+ cwd?: string;
137
+ /** Throw on non-zero exit (default true). */
138
+ check?: boolean;
139
+ /** Echo the command (default true) — mirrors the Python "+ <cmd>" trace. */
140
+ echo?: boolean;
141
+ }
142
+ declare function shown(cmd: string[]): string;
143
+ declare class CommandError extends Error {
144
+ code: number;
145
+ result: RunResult;
146
+ constructor(message: string, code: number, result: RunResult);
147
+ }
148
+ /** Run a command, streaming or capturing output. Async. */
149
+ declare function run(cmd: string[], opts?: RunOptions): Promise<RunResult>;
150
+ /** Synchronous run (used by a few hot paths / parity tooling). */
151
+ declare function runSync(cmd: string[], opts?: {
152
+ check?: boolean;
153
+ echo?: boolean;
154
+ }): RunResult;
155
+ /** ffprobe -of json, parsed. Mirrors cli.py ffprobe(). */
156
+ declare function ffprobe(path: string): Promise<FfprobeResult>;
157
+ declare function videoStream(probe: FfprobeResult): FfprobeStream;
158
+ declare function mediaDuration(path: string): Promise<number>;
159
+ /** Assert ffmpeg + ffprobe are on PATH. */
160
+ declare function requireFfmpeg(): void;
161
+
162
+ declare function configDir(): string;
163
+ declare function configEnvPath(): string;
164
+ interface KeyOptions {
165
+ /** explicit --api-key value (highest precedence after env var miss) */
166
+ apiKey?: string;
167
+ /** extra .env path to check (e.g. for tests) */
168
+ envPath?: string;
169
+ }
170
+ /** Resolve the ElevenLabs API key or throw with a clear message. */
171
+ declare function loadApiKey(opts?: KeyOptions): string;
172
+
173
+ declare function slugify(value: string): string;
174
+ declare function isoNow(): string;
175
+ /** Round to `ndigits` using round-half-to-even (Python's round()). */
176
+ declare function pyRound(x: number, ndigits?: number): number;
177
+ /** Format like Python f"{x:.<prec>f}" (fixed-point, round-half-even-ish). */
178
+ declare function pyFixed(x: number, prec: number): string;
179
+ /** Python f"{x:0<width>.<prec>f}" — zero-padded fixed width incl. sign/dot. */
180
+ declare function pyFixedPad(x: number, width: number, prec: number): string;
181
+ /** Python f"{x:<width>.<prec>f}" — space-padded (right-aligned). */
182
+ declare function pySpacePad(x: number, width: number, prec: number): string;
183
+
184
+ declare function rotationDegrees(stream: FfprobeStream): number;
185
+ /** Returns [displayWidth, displayHeight, rotation] accounting for rotation flags. */
186
+ declare function displayedDimensions(stream: FfprobeStream): [number, number, number];
187
+
188
+ declare const DEFAULT_EDIT_ROOT: string;
189
+ declare const VIDEO_EXTS: Set<string>;
190
+ declare function defaultJobDir(source: string): string;
191
+ declare function transcriptPath(jobDir: string, stem: string): string;
192
+ declare function initJob(source: string, jobDir: string | null, opts?: {
193
+ force?: boolean;
194
+ }): Promise<string>;
195
+ declare function loadJob(jobDir: string): SourceJson;
196
+ declare function sourceFromJob(jobDir: string): string;
197
+ interface ResolvedJob {
198
+ jobDir: string;
199
+ source: string;
200
+ stem: string;
201
+ }
202
+ /** Resolve a job from a --source or --job-dir argument. */
203
+ declare function resolveJob(args: {
204
+ source?: string;
205
+ jobDir?: string;
206
+ }, opts?: {
207
+ forceJob?: boolean;
208
+ }): Promise<ResolvedJob>;
209
+
210
+ declare function ensureVerticalMaster(jobDir: string, source: string, opts?: {
211
+ force?: boolean;
212
+ }): Promise<string>;
213
+
214
+ interface TranscribeOptions {
215
+ editDir: string;
216
+ language?: string;
217
+ numSpeakers?: number;
218
+ noHeal?: boolean;
219
+ force?: boolean;
220
+ apiKey?: string;
221
+ verbose?: boolean;
222
+ }
223
+ /**
224
+ * Transcribe a single video. Returns the path to the transcript JSON.
225
+ * Cached: returns the existing path immediately if the transcript already
226
+ * exists (unless `force`). Mirrors transcribe_one().
227
+ */
228
+ declare function transcribeOne(video: string, opts: TranscribeOptions): Promise<string>;
229
+
230
+ interface BatchOptions {
231
+ workers?: number;
232
+ language?: string;
233
+ numSpeakers?: number;
234
+ editDir?: string;
235
+ apiKey?: string;
236
+ }
237
+ interface BatchResult {
238
+ videos: string[];
239
+ cached: string[];
240
+ transcribed: string[];
241
+ errors: Array<{
242
+ video: string;
243
+ message: string;
244
+ }>;
245
+ }
246
+ /**
247
+ * Batch transcription. Returns a summary of which files were cached,
248
+ * transcribed, and which failed. Mirrors transcribe_batch.main().
249
+ */
250
+ declare function transcribeBatch(videosDir: string, opts?: BatchOptions): Promise<BatchResult>;
251
+
252
+ /**
253
+ * Screen a single transcript and return the report text exactly as
254
+ * flag_takes.py prints it to stdout (this is what gets written to flags.txt).
255
+ */
256
+ declare function screenTakes(transcriptPath: string, opts?: {
257
+ offset?: number;
258
+ longToken?: number;
259
+ gap?: number;
260
+ }): string;
261
+
262
+ interface PackTranscriptsOptions {
263
+ silenceThreshold?: number;
264
+ output?: string;
265
+ }
266
+ declare function packTranscripts(editDir: string, opts?: PackTranscriptsOptions): {
267
+ path: string;
268
+ content: string;
269
+ };
270
+
271
+ declare const PRESETS: Record<string, string>;
272
+ /** Return the ffmpeg filter string for a preset name. Empty string for 'none'.
273
+ * Throws (like Python's KeyError) for unknown presets. */
274
+ declare function getPreset(name: string): string;
275
+ interface GradeStats {
276
+ y_mean: number;
277
+ y_range: number;
278
+ sat_mean: number;
279
+ }
280
+ /** Pure decision logic — mirrors auto_grade_for_clip's decision rules exactly.
281
+ * Bounded to ±8% on any axis, NO color shift. Unit-testable without ffmpeg. */
282
+ declare function decideGradeFilter(stats: GradeStats): string;
283
+ /** Analyze a clip and return the computed auto-grade `eq=...` filter string
284
+ * (or "" for passthrough). Bounded to ±8% on any axis, NO color shift.
285
+ *
286
+ * Probes the clip duration via ffprobe (matching Python's default behavior),
287
+ * samples frames via ffmpeg signalstats, then applies the bounded decision
288
+ * rules. Equivalent to Python's auto_grade_for_clip(video)[0]. */
289
+ declare function autoGradeForClip(input: string): Promise<string>;
290
+
291
+ interface RenderOptions {
292
+ preview?: boolean;
293
+ draft?: boolean;
294
+ buildSubtitles?: boolean;
295
+ noSubtitles?: boolean;
296
+ noLoudnorm?: boolean;
297
+ }
298
+ /** Render a video from an EDL. Mirrors render.py main(). */
299
+ declare function render(edlPath: string, output: string, opts?: RenderOptions): Promise<void>;
300
+
301
+ /**
302
+ * Compute a windowed-RMS envelope of length `samples` from raw Int16 PCM.
303
+ *
304
+ * Pure port of the math in Python's compute_envelope() (after WAV parsing):
305
+ * - convert to float32 / 32768
306
+ * - window = max(1, floor(n / samples))
307
+ * - reshape to (-1, window) over the usable prefix, RMS per window
308
+ * - pad with zeros / truncate to `samples`
309
+ * - normalize by max so values land in [0, 1]
310
+ *
311
+ * Returns all-zeros of length `samples` for empty input.
312
+ */
313
+ declare function computeEnvelope(pcm: Int16Array, samples: number): number[];
314
+ interface TimelineViewOptions {
315
+ /** Number of frames in the filmstrip (default 10). */
316
+ nFrames?: number;
317
+ /** Path to a transcript.json for word labels + silence shading. */
318
+ transcript?: string;
319
+ }
320
+ /**
321
+ * Render a filmstrip + waveform composite PNG for [start, end] of `video` to
322
+ * `output`. Faithful port of render_timeline() in timeline_view.py.
323
+ *
324
+ * The caller must pass `end < duration`; we clamp `end` to the media duration
325
+ * internally (same defensive behavior as the Python EOF guard) to avoid the
326
+ * end-window-at-EOF failure.
327
+ */
328
+ declare function timelineView(video: string, start: number, end: number, output: string, opts?: TimelineViewOptions): Promise<void>;
329
+
330
+ interface VerifyOptions {
331
+ full?: boolean;
332
+ windowS?: number;
333
+ gapThresholdS?: number;
334
+ apiKey?: string;
335
+ }
336
+ interface TimedWord {
337
+ text: string;
338
+ norm: string;
339
+ start: number;
340
+ end: number;
341
+ }
342
+ interface DupSpan {
343
+ /** The full matched text (abandoned take + keeper). */
344
+ text: string;
345
+ /** The repeated n-gram length in tokens. 2 = a bare two-word repeat (often
346
+ * emphasis / a spelled acronym like "WW" → "דבל יו דבל יו" / a spoken number),
347
+ * >= 3 = a restarted clause (the strong retake fingerprint). */
348
+ n: number;
349
+ }
350
+ /**
351
+ * ALL near-adjacent repeated phrases (the retake fingerprint), left to right.
352
+ * Reports the longest match at each position and skips past it, so a stumbly
353
+ * source with several within-window stutters surfaces every one (not just the
354
+ * first). Intentional rhetorical repeats ("X? Y X?") also match — the editor
355
+ * adjudicates those. Each span carries its n-gram length so callers can weight
356
+ * a 3+-word clause restart (almost always a real retake) above a bare 2-word
357
+ * repeat (frequently a spelled acronym / number / emphasis, not a retake).
358
+ */
359
+ declare function duplicatedSpans(words: TimedWord[]): DupSpan[];
360
+ /** ALL near-adjacent repeated phrases as plain text (back-compat). */
361
+ declare function duplicatedPhrases(words: TimedWord[]): string[];
362
+ /** First near-adjacent duplicate (back-compat helper). */
363
+ declare function duplicatedPhrase(words: TimedWord[]): string | null;
364
+ /** Largest inter-word gap that straddles `joinOffset` (window-relative seconds). */
365
+ declare function straddlingGap(words: TimedWord[], joinOffset: number): number;
366
+ declare function verify(jobDir: string, opts?: VerifyOptions): Promise<VerifyResult>;
367
+
368
+ interface SilenceInterval {
369
+ start: number;
370
+ end: number;
371
+ }
372
+ interface DesilenceOptions {
373
+ /** Silence threshold in dB (ffmpeg silencedetect `noise`). Default -39. */
374
+ noiseDb: number;
375
+ /** Minimum silence length (s) to act on — also silencedetect `d`. Default 0.30. */
376
+ minSilence: number;
377
+ /** Total air (s) to leave where an internal silence is cut. Default 0.13. */
378
+ targetGap: number;
379
+ /** Air kept BEFORE speech resumes at a cut / leading edge. Default 0.05. */
380
+ leadKeep: number;
381
+ /** Air kept AFTER speech ends at a cut / trailing edge. Default 0.08. */
382
+ trailKeep: number;
383
+ /** Drop any resulting sub-range shorter than this (s). Default 0.10. */
384
+ minSegment: number;
385
+ }
386
+ declare const DEFAULT_DESILENCE: DesilenceOptions;
387
+ /** ffmpeg argv for an amplitude silence scan. No video, null muxer; the report
388
+ * lands on stderr. Pure (no execution). */
389
+ declare function silenceDetectArgs(source: string, noiseDb: number, minSilenceS: number): string[];
390
+ /** Parse `silence_start:` / `silence_end:` pairs out of ffmpeg stderr.
391
+ * A dangling silence_start (silence runs to EOF) is closed at `sourceDurationS`
392
+ * when provided (>0), otherwise dropped. */
393
+ declare function parseSilenceDetect(stderr: string, sourceDurationS?: number): SilenceInterval[];
394
+ /** Tighten ONE keep-range against the detected silences: excise internal
395
+ * silences >= minSilence (leaving trailKeep + leadKeep of air) and trim silent
396
+ * leading/trailing edges. Returns 1..N sub-ranges, all inside [start,end],
397
+ * inheriting source/grade/beat/quote. Pure. */
398
+ declare function tightenRange(range: EdlRange, silences: SilenceInterval[], opts?: DesilenceOptions, words?: SilenceInterval[]): EdlRange[];
399
+ /** Tighten every range against per-source silence maps, protecting intra-word
400
+ * splits with per-source word tokens. Pure. */
401
+ declare function tightenRanges(ranges: EdlRange[], silencesBySource: Record<string, SilenceInterval[]>, opts?: DesilenceOptions, wordsBySource?: Record<string, SilenceInterval[]>): EdlRange[];
402
+ /** Load word-token spans per EDL source from the job's transcripts/ dir. Tries
403
+ * transcripts/<sourceName>.json, then falls back to the lone transcript when a
404
+ * single-source job names its transcript by stem (the common case). */
405
+ declare function loadWordsBySource(edl: Edl, editDir: string): Record<string, SilenceInterval[]>;
406
+ /** Run silencedetect on a source and return the silence intervals. */
407
+ declare function detectSilences(source: string, noiseDb: number, minSilenceS: number, sourceDurationS: number): Promise<SilenceInterval[]>;
408
+ interface DesilenceStats {
409
+ rangesBefore: number;
410
+ rangesAfter: number;
411
+ durationBefore: number;
412
+ durationAfter: number;
413
+ removedS: number;
414
+ }
415
+ /** Detect silences for every source referenced by the EDL, tighten all ranges,
416
+ * and return a new EDL (with updated total_duration_s + a `desilenced` marker)
417
+ * plus stats. Does NOT write anything. */
418
+ declare function desilenceEdl(edl: Edl, editDir: string, opts?: DesilenceOptions): Promise<{
419
+ edl: Edl;
420
+ stats: DesilenceStats;
421
+ }>;
422
+
423
+ declare function loadWords(tpath: string, opts?: {
424
+ includeEvents?: boolean;
425
+ }): ScribeWord[];
426
+ declare function writeWordDump(tpath: string, outPath: string, gapThreshold?: number): void;
427
+ declare function writeCoverage(jobDir: string, source: string, tpath: string): Promise<string>;
428
+ declare function writeTranscriptArtifacts(jobDir: string, source: string, tpath: string): Promise<void>;
429
+ declare function ensureTranscribed(jobDir: string, source: string, stem: string, opts?: {
430
+ language?: string;
431
+ numSpeakers?: number;
432
+ noHeal?: boolean;
433
+ force?: boolean;
434
+ apiKey?: string;
435
+ }): Promise<string>;
436
+ declare function edlPath(jobDir: string): string;
437
+ declare function readEdl(jobDir: string): Edl | null;
438
+ declare function cutBoundaries(ranges: Edl["ranges"]): CutBoundary[];
439
+ declare function writeBoundaries(jobDir: string): string | null;
440
+ declare function generateQcImages(jobDir: string, opts?: {
441
+ preview?: string;
442
+ maxImages?: number;
443
+ }): Promise<string | null>;
444
+ declare function writeWarningsFromReview(jobDir: string): string;
445
+ declare function artifactPaths(jobDir: string, stem: string): Record<string, string>;
446
+ declare function writeAgentManifest(jobDir: string, source: string, stem: string, mode: string): string;
447
+ declare function statusPayload(jobDir: string): Promise<Record<string, unknown>>;
448
+
449
+ declare function learnedEditingGuardrails(jobDir: string, stem: string): string;
450
+ declare function agentizePrompt(text: string, jobDir: string, stem: string): string;
451
+ declare function writeVideoEditingPrompt(jobDir: string, stem: string, templateName: string, outName: string): string;
452
+ interface SilencePromptOptions {
453
+ minGap: number;
454
+ targetGap: number;
455
+ leadPad: number;
456
+ trailPad: number;
457
+ }
458
+ declare function writeSilencePrompt(jobDir: string, stem: string, opts: SilencePromptOptions): string;
459
+
460
+ /** Who put an item into the timeline, and in which authoring round. Required on
461
+ * every item; defaults to {round:null, changeId:null, actor:"agent"}. */
462
+ declare const provenanceSchema: z.ZodDefault<z.ZodObject<{
463
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
464
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
465
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
466
+ }, "strict", z.ZodTypeAny, {
467
+ round: number | null;
468
+ changeId: string | null;
469
+ actor: "agent" | "user";
470
+ }, {
471
+ round?: number | null | undefined;
472
+ changeId?: string | null | undefined;
473
+ actor?: "agent" | "user" | undefined;
474
+ }>>;
475
+ type Provenance = z.infer<typeof provenanceSchema>;
476
+ /** Anchor to a phrase in a source's word-level transcript. `resolved` is a
477
+ * cache: trusted only while the source's transcriptHash still matches. */
478
+ declare const wordsAnchorSchema: z.ZodObject<{
479
+ type: z.ZodLiteral<"words">;
480
+ source: z.ZodString;
481
+ phrase: z.ZodString;
482
+ /** 1-based occurrence index when the phrase appears more than once. */
483
+ occurrence: z.ZodOptional<z.ZodNumber>;
484
+ /** Cached resolution in SOURCE seconds. */
485
+ resolved: z.ZodOptional<z.ZodObject<{
486
+ start: z.ZodNumber;
487
+ end: z.ZodNumber;
488
+ }, "strict", z.ZodTypeAny, {
489
+ start: number;
490
+ end: number;
491
+ }, {
492
+ start: number;
493
+ end: number;
494
+ }>>;
495
+ /** Collapse the span to one instant (phrase start or end). */
496
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
497
+ }, "strict", z.ZodTypeAny, {
498
+ type: "words";
499
+ source: string;
500
+ phrase: string;
501
+ occurrence?: number | undefined;
502
+ resolved?: {
503
+ start: number;
504
+ end: number;
505
+ } | undefined;
506
+ edge?: "start" | "end" | undefined;
507
+ }, {
508
+ type: "words";
509
+ source: string;
510
+ phrase: string;
511
+ occurrence?: number | undefined;
512
+ resolved?: {
513
+ start: number;
514
+ end: number;
515
+ } | undefined;
516
+ edge?: "start" | "end" | undefined;
517
+ }>;
518
+ /** Anchor to explicit SOURCE seconds. */
519
+ declare const sourceAnchorSchema: z.ZodObject<{
520
+ type: z.ZodLiteral<"source">;
521
+ source: z.ZodString;
522
+ start: z.ZodNumber;
523
+ end: z.ZodNumber;
524
+ }, "strict", z.ZodTypeAny, {
525
+ type: "source";
526
+ start: number;
527
+ end: number;
528
+ source: string;
529
+ }, {
530
+ type: "source";
531
+ start: number;
532
+ end: number;
533
+ source: string;
534
+ }>;
535
+ /** Symbolic OUTPUT-time anchor. Numeric output seconds are deliberately not
536
+ * representable: output time shifts under desilence/re-cuts, so authored docs
537
+ * may only say start/end/full or "after that other item". */
538
+ declare const outputAnchorSchema: z.ZodObject<{
539
+ type: z.ZodLiteral<"output">;
540
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
541
+ after: z.ZodString;
542
+ }, "strict", z.ZodTypeAny, {
543
+ after: string;
544
+ }, {
545
+ after: string;
546
+ }>]>;
547
+ durationS: z.ZodOptional<z.ZodNumber>;
548
+ }, "strict", z.ZodTypeAny, {
549
+ type: "output";
550
+ at: "start" | "end" | "full" | {
551
+ after: string;
552
+ };
553
+ durationS?: number | undefined;
554
+ }, {
555
+ type: "output";
556
+ at: "start" | "end" | "full" | {
557
+ after: string;
558
+ };
559
+ durationS?: number | undefined;
560
+ }>;
561
+ declare const anchorSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
562
+ type: z.ZodLiteral<"words">;
563
+ source: z.ZodString;
564
+ phrase: z.ZodString;
565
+ /** 1-based occurrence index when the phrase appears more than once. */
566
+ occurrence: z.ZodOptional<z.ZodNumber>;
567
+ /** Cached resolution in SOURCE seconds. */
568
+ resolved: z.ZodOptional<z.ZodObject<{
569
+ start: z.ZodNumber;
570
+ end: z.ZodNumber;
571
+ }, "strict", z.ZodTypeAny, {
572
+ start: number;
573
+ end: number;
574
+ }, {
575
+ start: number;
576
+ end: number;
577
+ }>>;
578
+ /** Collapse the span to one instant (phrase start or end). */
579
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
580
+ }, "strict", z.ZodTypeAny, {
581
+ type: "words";
582
+ source: string;
583
+ phrase: string;
584
+ occurrence?: number | undefined;
585
+ resolved?: {
586
+ start: number;
587
+ end: number;
588
+ } | undefined;
589
+ edge?: "start" | "end" | undefined;
590
+ }, {
591
+ type: "words";
592
+ source: string;
593
+ phrase: string;
594
+ occurrence?: number | undefined;
595
+ resolved?: {
596
+ start: number;
597
+ end: number;
598
+ } | undefined;
599
+ edge?: "start" | "end" | undefined;
600
+ }>, z.ZodObject<{
601
+ type: z.ZodLiteral<"source">;
602
+ source: z.ZodString;
603
+ start: z.ZodNumber;
604
+ end: z.ZodNumber;
605
+ }, "strict", z.ZodTypeAny, {
606
+ type: "source";
607
+ start: number;
608
+ end: number;
609
+ source: string;
610
+ }, {
611
+ type: "source";
612
+ start: number;
613
+ end: number;
614
+ source: string;
615
+ }>, z.ZodObject<{
616
+ type: z.ZodLiteral<"output">;
617
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
618
+ after: z.ZodString;
619
+ }, "strict", z.ZodTypeAny, {
620
+ after: string;
621
+ }, {
622
+ after: string;
623
+ }>]>;
624
+ durationS: z.ZodOptional<z.ZodNumber>;
625
+ }, "strict", z.ZodTypeAny, {
626
+ type: "output";
627
+ at: "start" | "end" | "full" | {
628
+ after: string;
629
+ };
630
+ durationS?: number | undefined;
631
+ }, {
632
+ type: "output";
633
+ at: "start" | "end" | "full" | {
634
+ after: string;
635
+ };
636
+ durationS?: number | undefined;
637
+ }>]>;
638
+ type WordsAnchor = z.infer<typeof wordsAnchorSchema>;
639
+ type SourceAnchor = z.infer<typeof sourceAnchorSchema>;
640
+ type OutputAnchor = z.infer<typeof outputAnchorSchema>;
641
+ type Anchor = z.infer<typeof anchorSchema>;
642
+ declare const timelineSourceSchema: z.ZodObject<{
643
+ /** Path (absolute or job-dir-relative) to the media file. */
644
+ path: z.ZodString;
645
+ durationS: z.ZodOptional<z.ZodNumber>;
646
+ /** "sha256:<hex>" of the transcript JSON this doc's cached anchor
647
+ * resolutions were computed against. */
648
+ transcriptHash: z.ZodOptional<z.ZodString>;
649
+ }, "strict", z.ZodTypeAny, {
650
+ path: string;
651
+ durationS?: number | undefined;
652
+ transcriptHash?: string | undefined;
653
+ }, {
654
+ path: string;
655
+ durationS?: number | undefined;
656
+ transcriptHash?: string | undefined;
657
+ }>;
658
+ declare const settingsSchema: z.ZodDefault<z.ZodObject<{
659
+ canvas: z.ZodDefault<z.ZodObject<{
660
+ w: z.ZodNumber;
661
+ h: z.ZodNumber;
662
+ }, "strict", z.ZodTypeAny, {
663
+ w: number;
664
+ h: number;
665
+ }, {
666
+ w: number;
667
+ h: number;
668
+ }>>;
669
+ /** "none" | preset name | raw ffmpeg filter | "auto" (same as EDL grade),
670
+ * or a declarative {preset, intensity?} grade for the composition path. */
671
+ grade: z.ZodDefault<z.ZodUnion<[z.ZodString, z.ZodObject<{
672
+ preset: z.ZodString;
673
+ intensity: z.ZodOptional<z.ZodNumber>;
674
+ }, "strict", z.ZodTypeAny, {
675
+ preset: string;
676
+ intensity?: number | undefined;
677
+ }, {
678
+ preset: string;
679
+ intensity?: number | undefined;
680
+ }>]>>;
681
+ loudnorm: z.ZodDefault<z.ZodBoolean>;
682
+ /** Optional DesilenceOptions subset; merged over DEFAULT_DESILENCE. */
683
+ desilence: z.ZodOptional<z.ZodObject<{
684
+ noiseDb: z.ZodOptional<z.ZodNumber>;
685
+ minSilence: z.ZodOptional<z.ZodNumber>;
686
+ targetGap: z.ZodOptional<z.ZodNumber>;
687
+ leadKeep: z.ZodOptional<z.ZodNumber>;
688
+ trailKeep: z.ZodOptional<z.ZodNumber>;
689
+ minSegment: z.ZodOptional<z.ZodNumber>;
690
+ }, "strict", z.ZodTypeAny, {
691
+ noiseDb?: number | undefined;
692
+ minSilence?: number | undefined;
693
+ targetGap?: number | undefined;
694
+ leadKeep?: number | undefined;
695
+ trailKeep?: number | undefined;
696
+ minSegment?: number | undefined;
697
+ }, {
698
+ noiseDb?: number | undefined;
699
+ minSilence?: number | undefined;
700
+ targetGap?: number | undefined;
701
+ leadKeep?: number | undefined;
702
+ trailKeep?: number | undefined;
703
+ minSegment?: number | undefined;
704
+ }>>;
705
+ }, "strict", z.ZodTypeAny, {
706
+ canvas: {
707
+ w: number;
708
+ h: number;
709
+ };
710
+ grade: string | {
711
+ preset: string;
712
+ intensity?: number | undefined;
713
+ };
714
+ loudnorm: boolean;
715
+ desilence?: {
716
+ noiseDb?: number | undefined;
717
+ minSilence?: number | undefined;
718
+ targetGap?: number | undefined;
719
+ leadKeep?: number | undefined;
720
+ trailKeep?: number | undefined;
721
+ minSegment?: number | undefined;
722
+ } | undefined;
723
+ }, {
724
+ canvas?: {
725
+ w: number;
726
+ h: number;
727
+ } | undefined;
728
+ grade?: string | {
729
+ preset: string;
730
+ intensity?: number | undefined;
731
+ } | undefined;
732
+ loudnorm?: boolean | undefined;
733
+ desilence?: {
734
+ noiseDb?: number | undefined;
735
+ minSilence?: number | undefined;
736
+ targetGap?: number | undefined;
737
+ leadKeep?: number | undefined;
738
+ trailKeep?: number | undefined;
739
+ minSegment?: number | undefined;
740
+ } | undefined;
741
+ }>>;
742
+ declare const cutRangeSchema: z.ZodObject<{
743
+ id: z.ZodString;
744
+ source: z.ZodString;
745
+ start: z.ZodNumber;
746
+ end: z.ZodNumber;
747
+ beat: z.ZodOptional<z.ZodString>;
748
+ quote: z.ZodOptional<z.ZodString>;
749
+ reason: z.ZodOptional<z.ZodString>;
750
+ /** Optional per-range grade override (kept for v1 EDL round-trips). */
751
+ grade: z.ZodOptional<z.ZodString>;
752
+ provenance: z.ZodDefault<z.ZodObject<{
753
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
754
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
755
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
756
+ }, "strict", z.ZodTypeAny, {
757
+ round: number | null;
758
+ changeId: string | null;
759
+ actor: "agent" | "user";
760
+ }, {
761
+ round?: number | null | undefined;
762
+ changeId?: string | null | undefined;
763
+ actor?: "agent" | "user" | undefined;
764
+ }>>;
765
+ }, "strict", z.ZodTypeAny, {
766
+ start: number;
767
+ end: number;
768
+ source: string;
769
+ id: string;
770
+ provenance: {
771
+ round: number | null;
772
+ changeId: string | null;
773
+ actor: "agent" | "user";
774
+ };
775
+ grade?: string | undefined;
776
+ beat?: string | undefined;
777
+ quote?: string | undefined;
778
+ reason?: string | undefined;
779
+ }, {
780
+ start: number;
781
+ end: number;
782
+ source: string;
783
+ id: string;
784
+ grade?: string | undefined;
785
+ beat?: string | undefined;
786
+ quote?: string | undefined;
787
+ reason?: string | undefined;
788
+ provenance?: {
789
+ round?: number | null | undefined;
790
+ changeId?: string | null | undefined;
791
+ actor?: "agent" | "user" | undefined;
792
+ } | undefined;
793
+ }>;
794
+ declare const captionOverrideSchema: z.ZodObject<{
795
+ id: z.ZodString;
796
+ anchor: z.ZodObject<{
797
+ type: z.ZodLiteral<"words">;
798
+ source: z.ZodString;
799
+ phrase: z.ZodString;
800
+ /** 1-based occurrence index when the phrase appears more than once. */
801
+ occurrence: z.ZodOptional<z.ZodNumber>;
802
+ /** Cached resolution in SOURCE seconds. */
803
+ resolved: z.ZodOptional<z.ZodObject<{
804
+ start: z.ZodNumber;
805
+ end: z.ZodNumber;
806
+ }, "strict", z.ZodTypeAny, {
807
+ start: number;
808
+ end: number;
809
+ }, {
810
+ start: number;
811
+ end: number;
812
+ }>>;
813
+ /** Collapse the span to one instant (phrase start or end). */
814
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
815
+ }, "strict", z.ZodTypeAny, {
816
+ type: "words";
817
+ source: string;
818
+ phrase: string;
819
+ occurrence?: number | undefined;
820
+ resolved?: {
821
+ start: number;
822
+ end: number;
823
+ } | undefined;
824
+ edge?: "start" | "end" | undefined;
825
+ }, {
826
+ type: "words";
827
+ source: string;
828
+ phrase: string;
829
+ occurrence?: number | undefined;
830
+ resolved?: {
831
+ start: number;
832
+ end: number;
833
+ } | undefined;
834
+ edge?: "start" | "end" | undefined;
835
+ }>;
836
+ op: z.ZodEnum<["replace-text", "hide", "break-line", "style"]>;
837
+ text: z.ZodOptional<z.ZodString>;
838
+ /** op:"style" — per-word color (hex or simple CSS color name). */
839
+ color: z.ZodOptional<z.ZodString>;
840
+ /** op:"style" — per-word animated emphasis at the word's onset. */
841
+ emphasis: z.ZodOptional<z.ZodEnum<["pop", "highlight"]>>;
842
+ provenance: z.ZodDefault<z.ZodObject<{
843
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
844
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
845
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
846
+ }, "strict", z.ZodTypeAny, {
847
+ round: number | null;
848
+ changeId: string | null;
849
+ actor: "agent" | "user";
850
+ }, {
851
+ round?: number | null | undefined;
852
+ changeId?: string | null | undefined;
853
+ actor?: "agent" | "user" | undefined;
854
+ }>>;
855
+ }, "strict", z.ZodTypeAny, {
856
+ anchor: {
857
+ type: "words";
858
+ source: string;
859
+ phrase: string;
860
+ occurrence?: number | undefined;
861
+ resolved?: {
862
+ start: number;
863
+ end: number;
864
+ } | undefined;
865
+ edge?: "start" | "end" | undefined;
866
+ };
867
+ id: string;
868
+ provenance: {
869
+ round: number | null;
870
+ changeId: string | null;
871
+ actor: "agent" | "user";
872
+ };
873
+ op: "replace-text" | "hide" | "break-line" | "style";
874
+ text?: string | undefined;
875
+ color?: string | undefined;
876
+ emphasis?: "pop" | "highlight" | undefined;
877
+ }, {
878
+ anchor: {
879
+ type: "words";
880
+ source: string;
881
+ phrase: string;
882
+ occurrence?: number | undefined;
883
+ resolved?: {
884
+ start: number;
885
+ end: number;
886
+ } | undefined;
887
+ edge?: "start" | "end" | undefined;
888
+ };
889
+ id: string;
890
+ op: "replace-text" | "hide" | "break-line" | "style";
891
+ text?: string | undefined;
892
+ provenance?: {
893
+ round?: number | null | undefined;
894
+ changeId?: string | null | undefined;
895
+ actor?: "agent" | "user" | undefined;
896
+ } | undefined;
897
+ color?: string | undefined;
898
+ emphasis?: "pop" | "highlight" | undefined;
899
+ }>;
900
+ declare const zoomSchema: z.ZodObject<{
901
+ id: z.ZodString;
902
+ anchor: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
903
+ type: z.ZodLiteral<"words">;
904
+ source: z.ZodString;
905
+ phrase: z.ZodString;
906
+ /** 1-based occurrence index when the phrase appears more than once. */
907
+ occurrence: z.ZodOptional<z.ZodNumber>;
908
+ /** Cached resolution in SOURCE seconds. */
909
+ resolved: z.ZodOptional<z.ZodObject<{
910
+ start: z.ZodNumber;
911
+ end: z.ZodNumber;
912
+ }, "strict", z.ZodTypeAny, {
913
+ start: number;
914
+ end: number;
915
+ }, {
916
+ start: number;
917
+ end: number;
918
+ }>>;
919
+ /** Collapse the span to one instant (phrase start or end). */
920
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
921
+ }, "strict", z.ZodTypeAny, {
922
+ type: "words";
923
+ source: string;
924
+ phrase: string;
925
+ occurrence?: number | undefined;
926
+ resolved?: {
927
+ start: number;
928
+ end: number;
929
+ } | undefined;
930
+ edge?: "start" | "end" | undefined;
931
+ }, {
932
+ type: "words";
933
+ source: string;
934
+ phrase: string;
935
+ occurrence?: number | undefined;
936
+ resolved?: {
937
+ start: number;
938
+ end: number;
939
+ } | undefined;
940
+ edge?: "start" | "end" | undefined;
941
+ }>, z.ZodObject<{
942
+ type: z.ZodLiteral<"source">;
943
+ source: z.ZodString;
944
+ start: z.ZodNumber;
945
+ end: z.ZodNumber;
946
+ }, "strict", z.ZodTypeAny, {
947
+ type: "source";
948
+ start: number;
949
+ end: number;
950
+ source: string;
951
+ }, {
952
+ type: "source";
953
+ start: number;
954
+ end: number;
955
+ source: string;
956
+ }>, z.ZodObject<{
957
+ type: z.ZodLiteral<"output">;
958
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
959
+ after: z.ZodString;
960
+ }, "strict", z.ZodTypeAny, {
961
+ after: string;
962
+ }, {
963
+ after: string;
964
+ }>]>;
965
+ durationS: z.ZodOptional<z.ZodNumber>;
966
+ }, "strict", z.ZodTypeAny, {
967
+ type: "output";
968
+ at: "start" | "end" | "full" | {
969
+ after: string;
970
+ };
971
+ durationS?: number | undefined;
972
+ }, {
973
+ type: "output";
974
+ at: "start" | "end" | "full" | {
975
+ after: string;
976
+ };
977
+ durationS?: number | undefined;
978
+ }>]>;
979
+ onCut: z.ZodDefault<z.ZodEnum<["clip", "drop", "error"]>>;
980
+ rect: z.ZodObject<{
981
+ x: z.ZodNumber;
982
+ y: z.ZodNumber;
983
+ w: z.ZodNumber;
984
+ h: z.ZodNumber;
985
+ }, "strict", z.ZodTypeAny, {
986
+ w: number;
987
+ h: number;
988
+ x: number;
989
+ y: number;
990
+ }, {
991
+ w: number;
992
+ h: number;
993
+ x: number;
994
+ y: number;
995
+ }>;
996
+ scale: z.ZodNumber;
997
+ /** Ramp target: when present, the zoom animates from the base rect/scale
998
+ * to `to` over the zoom window (`ease` shapes the ramp). */
999
+ to: z.ZodOptional<z.ZodObject<{
1000
+ rect: z.ZodOptional<z.ZodObject<{
1001
+ x: z.ZodNumber;
1002
+ y: z.ZodNumber;
1003
+ w: z.ZodNumber;
1004
+ h: z.ZodNumber;
1005
+ }, "strict", z.ZodTypeAny, {
1006
+ w: number;
1007
+ h: number;
1008
+ x: number;
1009
+ y: number;
1010
+ }, {
1011
+ w: number;
1012
+ h: number;
1013
+ x: number;
1014
+ y: number;
1015
+ }>>;
1016
+ scale: z.ZodOptional<z.ZodNumber>;
1017
+ }, "strict", z.ZodTypeAny, {
1018
+ rect?: {
1019
+ w: number;
1020
+ h: number;
1021
+ x: number;
1022
+ y: number;
1023
+ } | undefined;
1024
+ scale?: number | undefined;
1025
+ }, {
1026
+ rect?: {
1027
+ w: number;
1028
+ h: number;
1029
+ x: number;
1030
+ y: number;
1031
+ } | undefined;
1032
+ scale?: number | undefined;
1033
+ }>>;
1034
+ ease: z.ZodDefault<z.ZodObject<{
1035
+ in: z.ZodNumber;
1036
+ out: z.ZodNumber;
1037
+ }, "strict", z.ZodTypeAny, {
1038
+ in: number;
1039
+ out: number;
1040
+ }, {
1041
+ in: number;
1042
+ out: number;
1043
+ }>>;
1044
+ provenance: z.ZodDefault<z.ZodObject<{
1045
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
1046
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
1047
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
1048
+ }, "strict", z.ZodTypeAny, {
1049
+ round: number | null;
1050
+ changeId: string | null;
1051
+ actor: "agent" | "user";
1052
+ }, {
1053
+ round?: number | null | undefined;
1054
+ changeId?: string | null | undefined;
1055
+ actor?: "agent" | "user" | undefined;
1056
+ }>>;
1057
+ }, "strict", z.ZodTypeAny, {
1058
+ anchor: {
1059
+ type: "words";
1060
+ source: string;
1061
+ phrase: string;
1062
+ occurrence?: number | undefined;
1063
+ resolved?: {
1064
+ start: number;
1065
+ end: number;
1066
+ } | undefined;
1067
+ edge?: "start" | "end" | undefined;
1068
+ } | {
1069
+ type: "source";
1070
+ start: number;
1071
+ end: number;
1072
+ source: string;
1073
+ } | {
1074
+ type: "output";
1075
+ at: "start" | "end" | "full" | {
1076
+ after: string;
1077
+ };
1078
+ durationS?: number | undefined;
1079
+ };
1080
+ id: string;
1081
+ provenance: {
1082
+ round: number | null;
1083
+ changeId: string | null;
1084
+ actor: "agent" | "user";
1085
+ };
1086
+ onCut: "error" | "drop" | "clip";
1087
+ rect: {
1088
+ w: number;
1089
+ h: number;
1090
+ x: number;
1091
+ y: number;
1092
+ };
1093
+ scale: number;
1094
+ ease: {
1095
+ in: number;
1096
+ out: number;
1097
+ };
1098
+ to?: {
1099
+ rect?: {
1100
+ w: number;
1101
+ h: number;
1102
+ x: number;
1103
+ y: number;
1104
+ } | undefined;
1105
+ scale?: number | undefined;
1106
+ } | undefined;
1107
+ }, {
1108
+ anchor: {
1109
+ type: "words";
1110
+ source: string;
1111
+ phrase: string;
1112
+ occurrence?: number | undefined;
1113
+ resolved?: {
1114
+ start: number;
1115
+ end: number;
1116
+ } | undefined;
1117
+ edge?: "start" | "end" | undefined;
1118
+ } | {
1119
+ type: "source";
1120
+ start: number;
1121
+ end: number;
1122
+ source: string;
1123
+ } | {
1124
+ type: "output";
1125
+ at: "start" | "end" | "full" | {
1126
+ after: string;
1127
+ };
1128
+ durationS?: number | undefined;
1129
+ };
1130
+ id: string;
1131
+ rect: {
1132
+ w: number;
1133
+ h: number;
1134
+ x: number;
1135
+ y: number;
1136
+ };
1137
+ scale: number;
1138
+ provenance?: {
1139
+ round?: number | null | undefined;
1140
+ changeId?: string | null | undefined;
1141
+ actor?: "agent" | "user" | undefined;
1142
+ } | undefined;
1143
+ onCut?: "error" | "drop" | "clip" | undefined;
1144
+ to?: {
1145
+ rect?: {
1146
+ w: number;
1147
+ h: number;
1148
+ x: number;
1149
+ y: number;
1150
+ } | undefined;
1151
+ scale?: number | undefined;
1152
+ } | undefined;
1153
+ ease?: {
1154
+ in: number;
1155
+ out: number;
1156
+ } | undefined;
1157
+ }>;
1158
+ /** Entrance/exit animation for an overlay (rendered as GSAP fromTo tweens at
1159
+ * the overlay's output start/end). */
1160
+ declare const overlayFxSchema: z.ZodObject<{
1161
+ preset: z.ZodEnum<["fade", "pop", "slide-up", "slide-down", "scale-in"]>;
1162
+ durationS: z.ZodNumber;
1163
+ }, "strict", z.ZodTypeAny, {
1164
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1165
+ durationS: number;
1166
+ }, {
1167
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1168
+ durationS: number;
1169
+ }>;
1170
+ declare const overlaySchema: z.ZodObject<{
1171
+ id: z.ZodString;
1172
+ kind: z.ZodEnum<["text", "title-card", "image", "sticker"]>;
1173
+ anchor: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1174
+ type: z.ZodLiteral<"words">;
1175
+ source: z.ZodString;
1176
+ phrase: z.ZodString;
1177
+ /** 1-based occurrence index when the phrase appears more than once. */
1178
+ occurrence: z.ZodOptional<z.ZodNumber>;
1179
+ /** Cached resolution in SOURCE seconds. */
1180
+ resolved: z.ZodOptional<z.ZodObject<{
1181
+ start: z.ZodNumber;
1182
+ end: z.ZodNumber;
1183
+ }, "strict", z.ZodTypeAny, {
1184
+ start: number;
1185
+ end: number;
1186
+ }, {
1187
+ start: number;
1188
+ end: number;
1189
+ }>>;
1190
+ /** Collapse the span to one instant (phrase start or end). */
1191
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
1192
+ }, "strict", z.ZodTypeAny, {
1193
+ type: "words";
1194
+ source: string;
1195
+ phrase: string;
1196
+ occurrence?: number | undefined;
1197
+ resolved?: {
1198
+ start: number;
1199
+ end: number;
1200
+ } | undefined;
1201
+ edge?: "start" | "end" | undefined;
1202
+ }, {
1203
+ type: "words";
1204
+ source: string;
1205
+ phrase: string;
1206
+ occurrence?: number | undefined;
1207
+ resolved?: {
1208
+ start: number;
1209
+ end: number;
1210
+ } | undefined;
1211
+ edge?: "start" | "end" | undefined;
1212
+ }>, z.ZodObject<{
1213
+ type: z.ZodLiteral<"source">;
1214
+ source: z.ZodString;
1215
+ start: z.ZodNumber;
1216
+ end: z.ZodNumber;
1217
+ }, "strict", z.ZodTypeAny, {
1218
+ type: "source";
1219
+ start: number;
1220
+ end: number;
1221
+ source: string;
1222
+ }, {
1223
+ type: "source";
1224
+ start: number;
1225
+ end: number;
1226
+ source: string;
1227
+ }>, z.ZodObject<{
1228
+ type: z.ZodLiteral<"output">;
1229
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
1230
+ after: z.ZodString;
1231
+ }, "strict", z.ZodTypeAny, {
1232
+ after: string;
1233
+ }, {
1234
+ after: string;
1235
+ }>]>;
1236
+ durationS: z.ZodOptional<z.ZodNumber>;
1237
+ }, "strict", z.ZodTypeAny, {
1238
+ type: "output";
1239
+ at: "start" | "end" | "full" | {
1240
+ after: string;
1241
+ };
1242
+ durationS?: number | undefined;
1243
+ }, {
1244
+ type: "output";
1245
+ at: "start" | "end" | "full" | {
1246
+ after: string;
1247
+ };
1248
+ durationS?: number | undefined;
1249
+ }>]>;
1250
+ onCut: z.ZodDefault<z.ZodEnum<["clip", "drop", "error"]>>;
1251
+ layout: z.ZodDefault<z.ZodObject<{
1252
+ x: z.ZodDefault<z.ZodNumber>;
1253
+ y: z.ZodDefault<z.ZodNumber>;
1254
+ align: z.ZodDefault<z.ZodEnum<["left", "center", "right"]>>;
1255
+ safeArea: z.ZodDefault<z.ZodBoolean>;
1256
+ }, "strict", z.ZodTypeAny, {
1257
+ x: number;
1258
+ y: number;
1259
+ align: "center" | "left" | "right";
1260
+ safeArea: boolean;
1261
+ }, {
1262
+ x?: number | undefined;
1263
+ y?: number | undefined;
1264
+ align?: "center" | "left" | "right" | undefined;
1265
+ safeArea?: boolean | undefined;
1266
+ }>>;
1267
+ text: z.ZodOptional<z.ZodString>;
1268
+ style: z.ZodDefault<z.ZodObject<{
1269
+ preset: z.ZodOptional<z.ZodString>;
1270
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
1271
+ preset: z.ZodOptional<z.ZodString>;
1272
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
1273
+ preset: z.ZodOptional<z.ZodString>;
1274
+ }, z.ZodTypeAny, "passthrough">>>;
1275
+ durationS: z.ZodOptional<z.ZodNumber>;
1276
+ asset: z.ZodOptional<z.ZodObject<{
1277
+ ref: z.ZodString;
1278
+ }, "strict", z.ZodTypeAny, {
1279
+ ref: string;
1280
+ }, {
1281
+ ref: string;
1282
+ }>>;
1283
+ /** Entrance/exit presets (image/sticker overlays). */
1284
+ enter: z.ZodOptional<z.ZodObject<{
1285
+ preset: z.ZodEnum<["fade", "pop", "slide-up", "slide-down", "scale-in"]>;
1286
+ durationS: z.ZodNumber;
1287
+ }, "strict", z.ZodTypeAny, {
1288
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1289
+ durationS: number;
1290
+ }, {
1291
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1292
+ durationS: number;
1293
+ }>>;
1294
+ exit: z.ZodOptional<z.ZodObject<{
1295
+ preset: z.ZodEnum<["fade", "pop", "slide-up", "slide-down", "scale-in"]>;
1296
+ durationS: z.ZodNumber;
1297
+ }, "strict", z.ZodTypeAny, {
1298
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1299
+ durationS: number;
1300
+ }, {
1301
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1302
+ durationS: number;
1303
+ }>>;
1304
+ /** Size as canvas fractions (w of canvas width, h of canvas height). */
1305
+ size: z.ZodOptional<z.ZodObject<{
1306
+ w: z.ZodOptional<z.ZodNumber>;
1307
+ h: z.ZodOptional<z.ZodNumber>;
1308
+ }, "strict", z.ZodTypeAny, {
1309
+ w?: number | undefined;
1310
+ h?: number | undefined;
1311
+ }, {
1312
+ w?: number | undefined;
1313
+ h?: number | undefined;
1314
+ }>>;
1315
+ /** Stacking order (CSS z-index); temporal lanes stay non-overlapping. */
1316
+ z: z.ZodOptional<z.ZodNumber>;
1317
+ provenance: z.ZodDefault<z.ZodObject<{
1318
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
1319
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
1320
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
1321
+ }, "strict", z.ZodTypeAny, {
1322
+ round: number | null;
1323
+ changeId: string | null;
1324
+ actor: "agent" | "user";
1325
+ }, {
1326
+ round?: number | null | undefined;
1327
+ changeId?: string | null | undefined;
1328
+ actor?: "agent" | "user" | undefined;
1329
+ }>>;
1330
+ }, "strict", z.ZodTypeAny, {
1331
+ anchor: {
1332
+ type: "words";
1333
+ source: string;
1334
+ phrase: string;
1335
+ occurrence?: number | undefined;
1336
+ resolved?: {
1337
+ start: number;
1338
+ end: number;
1339
+ } | undefined;
1340
+ edge?: "start" | "end" | undefined;
1341
+ } | {
1342
+ type: "source";
1343
+ start: number;
1344
+ end: number;
1345
+ source: string;
1346
+ } | {
1347
+ type: "output";
1348
+ at: "start" | "end" | "full" | {
1349
+ after: string;
1350
+ };
1351
+ durationS?: number | undefined;
1352
+ };
1353
+ kind: "text" | "title-card" | "image" | "sticker";
1354
+ id: string;
1355
+ provenance: {
1356
+ round: number | null;
1357
+ changeId: string | null;
1358
+ actor: "agent" | "user";
1359
+ };
1360
+ style: {
1361
+ preset?: string | undefined;
1362
+ } & {
1363
+ [k: string]: unknown;
1364
+ };
1365
+ onCut: "error" | "drop" | "clip";
1366
+ layout: {
1367
+ x: number;
1368
+ y: number;
1369
+ align: "center" | "left" | "right";
1370
+ safeArea: boolean;
1371
+ };
1372
+ text?: string | undefined;
1373
+ size?: {
1374
+ w?: number | undefined;
1375
+ h?: number | undefined;
1376
+ } | undefined;
1377
+ durationS?: number | undefined;
1378
+ asset?: {
1379
+ ref: string;
1380
+ } | undefined;
1381
+ enter?: {
1382
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1383
+ durationS: number;
1384
+ } | undefined;
1385
+ exit?: {
1386
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1387
+ durationS: number;
1388
+ } | undefined;
1389
+ z?: number | undefined;
1390
+ }, {
1391
+ anchor: {
1392
+ type: "words";
1393
+ source: string;
1394
+ phrase: string;
1395
+ occurrence?: number | undefined;
1396
+ resolved?: {
1397
+ start: number;
1398
+ end: number;
1399
+ } | undefined;
1400
+ edge?: "start" | "end" | undefined;
1401
+ } | {
1402
+ type: "source";
1403
+ start: number;
1404
+ end: number;
1405
+ source: string;
1406
+ } | {
1407
+ type: "output";
1408
+ at: "start" | "end" | "full" | {
1409
+ after: string;
1410
+ };
1411
+ durationS?: number | undefined;
1412
+ };
1413
+ kind: "text" | "title-card" | "image" | "sticker";
1414
+ id: string;
1415
+ text?: string | undefined;
1416
+ size?: {
1417
+ w?: number | undefined;
1418
+ h?: number | undefined;
1419
+ } | undefined;
1420
+ durationS?: number | undefined;
1421
+ provenance?: {
1422
+ round?: number | null | undefined;
1423
+ changeId?: string | null | undefined;
1424
+ actor?: "agent" | "user" | undefined;
1425
+ } | undefined;
1426
+ style?: z.objectInputType<{
1427
+ preset: z.ZodOptional<z.ZodString>;
1428
+ }, z.ZodTypeAny, "passthrough"> | undefined;
1429
+ onCut?: "error" | "drop" | "clip" | undefined;
1430
+ layout?: {
1431
+ x?: number | undefined;
1432
+ y?: number | undefined;
1433
+ align?: "center" | "left" | "right" | undefined;
1434
+ safeArea?: boolean | undefined;
1435
+ } | undefined;
1436
+ asset?: {
1437
+ ref: string;
1438
+ } | undefined;
1439
+ enter?: {
1440
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1441
+ durationS: number;
1442
+ } | undefined;
1443
+ exit?: {
1444
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
1445
+ durationS: number;
1446
+ } | undefined;
1447
+ z?: number | undefined;
1448
+ }>;
1449
+ declare const audioSchema: z.ZodObject<{
1450
+ id: z.ZodString;
1451
+ kind: z.ZodEnum<["music", "sfx"]>;
1452
+ asset: z.ZodObject<{
1453
+ ref: z.ZodString;
1454
+ }, "strict", z.ZodTypeAny, {
1455
+ ref: string;
1456
+ }, {
1457
+ ref: string;
1458
+ }>;
1459
+ anchor: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
1460
+ type: z.ZodLiteral<"words">;
1461
+ source: z.ZodString;
1462
+ phrase: z.ZodString;
1463
+ /** 1-based occurrence index when the phrase appears more than once. */
1464
+ occurrence: z.ZodOptional<z.ZodNumber>;
1465
+ /** Cached resolution in SOURCE seconds. */
1466
+ resolved: z.ZodOptional<z.ZodObject<{
1467
+ start: z.ZodNumber;
1468
+ end: z.ZodNumber;
1469
+ }, "strict", z.ZodTypeAny, {
1470
+ start: number;
1471
+ end: number;
1472
+ }, {
1473
+ start: number;
1474
+ end: number;
1475
+ }>>;
1476
+ /** Collapse the span to one instant (phrase start or end). */
1477
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
1478
+ }, "strict", z.ZodTypeAny, {
1479
+ type: "words";
1480
+ source: string;
1481
+ phrase: string;
1482
+ occurrence?: number | undefined;
1483
+ resolved?: {
1484
+ start: number;
1485
+ end: number;
1486
+ } | undefined;
1487
+ edge?: "start" | "end" | undefined;
1488
+ }, {
1489
+ type: "words";
1490
+ source: string;
1491
+ phrase: string;
1492
+ occurrence?: number | undefined;
1493
+ resolved?: {
1494
+ start: number;
1495
+ end: number;
1496
+ } | undefined;
1497
+ edge?: "start" | "end" | undefined;
1498
+ }>, z.ZodObject<{
1499
+ type: z.ZodLiteral<"source">;
1500
+ source: z.ZodString;
1501
+ start: z.ZodNumber;
1502
+ end: z.ZodNumber;
1503
+ }, "strict", z.ZodTypeAny, {
1504
+ type: "source";
1505
+ start: number;
1506
+ end: number;
1507
+ source: string;
1508
+ }, {
1509
+ type: "source";
1510
+ start: number;
1511
+ end: number;
1512
+ source: string;
1513
+ }>, z.ZodObject<{
1514
+ type: z.ZodLiteral<"output">;
1515
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
1516
+ after: z.ZodString;
1517
+ }, "strict", z.ZodTypeAny, {
1518
+ after: string;
1519
+ }, {
1520
+ after: string;
1521
+ }>]>;
1522
+ durationS: z.ZodOptional<z.ZodNumber>;
1523
+ }, "strict", z.ZodTypeAny, {
1524
+ type: "output";
1525
+ at: "start" | "end" | "full" | {
1526
+ after: string;
1527
+ };
1528
+ durationS?: number | undefined;
1529
+ }, {
1530
+ type: "output";
1531
+ at: "start" | "end" | "full" | {
1532
+ after: string;
1533
+ };
1534
+ durationS?: number | undefined;
1535
+ }>]>;
1536
+ gainDb: z.ZodDefault<z.ZodNumber>;
1537
+ duckToSpeech: z.ZodDefault<z.ZodBoolean>;
1538
+ fadeOutS: z.ZodOptional<z.ZodNumber>;
1539
+ provenance: z.ZodDefault<z.ZodObject<{
1540
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
1541
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
1542
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
1543
+ }, "strict", z.ZodTypeAny, {
1544
+ round: number | null;
1545
+ changeId: string | null;
1546
+ actor: "agent" | "user";
1547
+ }, {
1548
+ round?: number | null | undefined;
1549
+ changeId?: string | null | undefined;
1550
+ actor?: "agent" | "user" | undefined;
1551
+ }>>;
1552
+ }, "strict", z.ZodTypeAny, {
1553
+ anchor: {
1554
+ type: "words";
1555
+ source: string;
1556
+ phrase: string;
1557
+ occurrence?: number | undefined;
1558
+ resolved?: {
1559
+ start: number;
1560
+ end: number;
1561
+ } | undefined;
1562
+ edge?: "start" | "end" | undefined;
1563
+ } | {
1564
+ type: "source";
1565
+ start: number;
1566
+ end: number;
1567
+ source: string;
1568
+ } | {
1569
+ type: "output";
1570
+ at: "start" | "end" | "full" | {
1571
+ after: string;
1572
+ };
1573
+ durationS?: number | undefined;
1574
+ };
1575
+ kind: "music" | "sfx";
1576
+ id: string;
1577
+ provenance: {
1578
+ round: number | null;
1579
+ changeId: string | null;
1580
+ actor: "agent" | "user";
1581
+ };
1582
+ asset: {
1583
+ ref: string;
1584
+ };
1585
+ gainDb: number;
1586
+ duckToSpeech: boolean;
1587
+ fadeOutS?: number | undefined;
1588
+ }, {
1589
+ anchor: {
1590
+ type: "words";
1591
+ source: string;
1592
+ phrase: string;
1593
+ occurrence?: number | undefined;
1594
+ resolved?: {
1595
+ start: number;
1596
+ end: number;
1597
+ } | undefined;
1598
+ edge?: "start" | "end" | undefined;
1599
+ } | {
1600
+ type: "source";
1601
+ start: number;
1602
+ end: number;
1603
+ source: string;
1604
+ } | {
1605
+ type: "output";
1606
+ at: "start" | "end" | "full" | {
1607
+ after: string;
1608
+ };
1609
+ durationS?: number | undefined;
1610
+ };
1611
+ kind: "music" | "sfx";
1612
+ id: string;
1613
+ asset: {
1614
+ ref: string;
1615
+ };
1616
+ provenance?: {
1617
+ round?: number | null | undefined;
1618
+ changeId?: string | null | undefined;
1619
+ actor?: "agent" | "user" | undefined;
1620
+ } | undefined;
1621
+ gainDb?: number | undefined;
1622
+ duckToSpeech?: boolean | undefined;
1623
+ fadeOutS?: number | undefined;
1624
+ }>;
1625
+ type CutRange = z.infer<typeof cutRangeSchema>;
1626
+ type CaptionOverride = z.infer<typeof captionOverrideSchema>;
1627
+ type ZoomItem = z.infer<typeof zoomSchema>;
1628
+ type OverlayItem = z.infer<typeof overlaySchema>;
1629
+ type OverlayFx = z.infer<typeof overlayFxSchema>;
1630
+ type AudioItem = z.infer<typeof audioSchema>;
1631
+ type TimelineSource = z.infer<typeof timelineSourceSchema>;
1632
+ type TimelineSettings = z.infer<typeof settingsSchema>;
1633
+ declare const timelineV2Schema: z.ZodObject<{
1634
+ version: z.ZodLiteral<2>;
1635
+ id: z.ZodString;
1636
+ sources: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodObject<{
1637
+ /** Path (absolute or job-dir-relative) to the media file. */
1638
+ path: z.ZodString;
1639
+ durationS: z.ZodOptional<z.ZodNumber>;
1640
+ /** "sha256:<hex>" of the transcript JSON this doc's cached anchor
1641
+ * resolutions were computed against. */
1642
+ transcriptHash: z.ZodOptional<z.ZodString>;
1643
+ }, "strict", z.ZodTypeAny, {
1644
+ path: string;
1645
+ durationS?: number | undefined;
1646
+ transcriptHash?: string | undefined;
1647
+ }, {
1648
+ path: string;
1649
+ durationS?: number | undefined;
1650
+ transcriptHash?: string | undefined;
1651
+ }>>, Record<string, {
1652
+ path: string;
1653
+ durationS?: number | undefined;
1654
+ transcriptHash?: string | undefined;
1655
+ }>, Record<string, {
1656
+ path: string;
1657
+ durationS?: number | undefined;
1658
+ transcriptHash?: string | undefined;
1659
+ }>>;
1660
+ settings: z.ZodDefault<z.ZodObject<{
1661
+ canvas: z.ZodDefault<z.ZodObject<{
1662
+ w: z.ZodNumber;
1663
+ h: z.ZodNumber;
1664
+ }, "strict", z.ZodTypeAny, {
1665
+ w: number;
1666
+ h: number;
1667
+ }, {
1668
+ w: number;
1669
+ h: number;
1670
+ }>>;
1671
+ /** "none" | preset name | raw ffmpeg filter | "auto" (same as EDL grade),
1672
+ * or a declarative {preset, intensity?} grade for the composition path. */
1673
+ grade: z.ZodDefault<z.ZodUnion<[z.ZodString, z.ZodObject<{
1674
+ preset: z.ZodString;
1675
+ intensity: z.ZodOptional<z.ZodNumber>;
1676
+ }, "strict", z.ZodTypeAny, {
1677
+ preset: string;
1678
+ intensity?: number | undefined;
1679
+ }, {
1680
+ preset: string;
1681
+ intensity?: number | undefined;
1682
+ }>]>>;
1683
+ loudnorm: z.ZodDefault<z.ZodBoolean>;
1684
+ /** Optional DesilenceOptions subset; merged over DEFAULT_DESILENCE. */
1685
+ desilence: z.ZodOptional<z.ZodObject<{
1686
+ noiseDb: z.ZodOptional<z.ZodNumber>;
1687
+ minSilence: z.ZodOptional<z.ZodNumber>;
1688
+ targetGap: z.ZodOptional<z.ZodNumber>;
1689
+ leadKeep: z.ZodOptional<z.ZodNumber>;
1690
+ trailKeep: z.ZodOptional<z.ZodNumber>;
1691
+ minSegment: z.ZodOptional<z.ZodNumber>;
1692
+ }, "strict", z.ZodTypeAny, {
1693
+ noiseDb?: number | undefined;
1694
+ minSilence?: number | undefined;
1695
+ targetGap?: number | undefined;
1696
+ leadKeep?: number | undefined;
1697
+ trailKeep?: number | undefined;
1698
+ minSegment?: number | undefined;
1699
+ }, {
1700
+ noiseDb?: number | undefined;
1701
+ minSilence?: number | undefined;
1702
+ targetGap?: number | undefined;
1703
+ leadKeep?: number | undefined;
1704
+ trailKeep?: number | undefined;
1705
+ minSegment?: number | undefined;
1706
+ }>>;
1707
+ }, "strict", z.ZodTypeAny, {
1708
+ canvas: {
1709
+ w: number;
1710
+ h: number;
1711
+ };
1712
+ grade: string | {
1713
+ preset: string;
1714
+ intensity?: number | undefined;
1715
+ };
1716
+ loudnorm: boolean;
1717
+ desilence?: {
1718
+ noiseDb?: number | undefined;
1719
+ minSilence?: number | undefined;
1720
+ targetGap?: number | undefined;
1721
+ leadKeep?: number | undefined;
1722
+ trailKeep?: number | undefined;
1723
+ minSegment?: number | undefined;
1724
+ } | undefined;
1725
+ }, {
1726
+ canvas?: {
1727
+ w: number;
1728
+ h: number;
1729
+ } | undefined;
1730
+ grade?: string | {
1731
+ preset: string;
1732
+ intensity?: number | undefined;
1733
+ } | undefined;
1734
+ loudnorm?: boolean | undefined;
1735
+ desilence?: {
1736
+ noiseDb?: number | undefined;
1737
+ minSilence?: number | undefined;
1738
+ targetGap?: number | undefined;
1739
+ leadKeep?: number | undefined;
1740
+ trailKeep?: number | undefined;
1741
+ minSegment?: number | undefined;
1742
+ } | undefined;
1743
+ }>>;
1744
+ cut: z.ZodDefault<z.ZodObject<{
1745
+ ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
1746
+ id: z.ZodString;
1747
+ source: z.ZodString;
1748
+ start: z.ZodNumber;
1749
+ end: z.ZodNumber;
1750
+ beat: z.ZodOptional<z.ZodString>;
1751
+ quote: z.ZodOptional<z.ZodString>;
1752
+ reason: z.ZodOptional<z.ZodString>;
1753
+ /** Optional per-range grade override (kept for v1 EDL round-trips). */
1754
+ grade: z.ZodOptional<z.ZodString>;
1755
+ provenance: z.ZodDefault<z.ZodObject<{
1756
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
1757
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
1758
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
1759
+ }, "strict", z.ZodTypeAny, {
1760
+ round: number | null;
1761
+ changeId: string | null;
1762
+ actor: "agent" | "user";
1763
+ }, {
1764
+ round?: number | null | undefined;
1765
+ changeId?: string | null | undefined;
1766
+ actor?: "agent" | "user" | undefined;
1767
+ }>>;
1768
+ }, "strict", z.ZodTypeAny, {
1769
+ start: number;
1770
+ end: number;
1771
+ source: string;
1772
+ id: string;
1773
+ provenance: {
1774
+ round: number | null;
1775
+ changeId: string | null;
1776
+ actor: "agent" | "user";
1777
+ };
1778
+ grade?: string | undefined;
1779
+ beat?: string | undefined;
1780
+ quote?: string | undefined;
1781
+ reason?: string | undefined;
1782
+ }, {
1783
+ start: number;
1784
+ end: number;
1785
+ source: string;
1786
+ id: string;
1787
+ grade?: string | undefined;
1788
+ beat?: string | undefined;
1789
+ quote?: string | undefined;
1790
+ reason?: string | undefined;
1791
+ provenance?: {
1792
+ round?: number | null | undefined;
1793
+ changeId?: string | null | undefined;
1794
+ actor?: "agent" | "user" | undefined;
1795
+ } | undefined;
1796
+ }>, "many">>;
1797
+ }, "strict", z.ZodTypeAny, {
1798
+ ranges: {
1799
+ start: number;
1800
+ end: number;
1801
+ source: string;
1802
+ id: string;
1803
+ provenance: {
1804
+ round: number | null;
1805
+ changeId: string | null;
1806
+ actor: "agent" | "user";
1807
+ };
1808
+ grade?: string | undefined;
1809
+ beat?: string | undefined;
1810
+ quote?: string | undefined;
1811
+ reason?: string | undefined;
1812
+ }[];
1813
+ }, {
1814
+ ranges?: {
1815
+ start: number;
1816
+ end: number;
1817
+ source: string;
1818
+ id: string;
1819
+ grade?: string | undefined;
1820
+ beat?: string | undefined;
1821
+ quote?: string | undefined;
1822
+ reason?: string | undefined;
1823
+ provenance?: {
1824
+ round?: number | null | undefined;
1825
+ changeId?: string | null | undefined;
1826
+ actor?: "agent" | "user" | undefined;
1827
+ } | undefined;
1828
+ }[] | undefined;
1829
+ }>>;
1830
+ captions: z.ZodDefault<z.ZodObject<{
1831
+ enabled: z.ZodDefault<z.ZodBoolean>;
1832
+ preset: z.ZodDefault<z.ZodEnum<["grouped", "opus-karaoke"]>>;
1833
+ style: z.ZodDefault<z.ZodObject<{
1834
+ /** Max words per grouped cue (preset "grouped" only). */
1835
+ maxWords: z.ZodOptional<z.ZodNumber>;
1836
+ /** Inter-word gap (seconds) that ends a phrase — a hard cue boundary
1837
+ * (preset "grouped" only). */
1838
+ gapBreakS: z.ZodOptional<z.ZodNumber>;
1839
+ /** Seconds each cue's display start is shifted EARLIER (clamped to the
1840
+ * previous cue's end / the segment's outStart). */
1841
+ leadS: z.ZodOptional<z.ZodNumber>;
1842
+ /** Max seconds a cue is held past its last word to bridge the gap to the
1843
+ * next cue (never past the segment's outEnd). */
1844
+ holdS: z.ZodOptional<z.ZodNumber>;
1845
+ /** Per-word highlight sweep within grouped cues (karaoke-style). */
1846
+ karaoke: z.ZodOptional<z.ZodBoolean>;
1847
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
1848
+ /** Max words per grouped cue (preset "grouped" only). */
1849
+ maxWords: z.ZodOptional<z.ZodNumber>;
1850
+ /** Inter-word gap (seconds) that ends a phrase — a hard cue boundary
1851
+ * (preset "grouped" only). */
1852
+ gapBreakS: z.ZodOptional<z.ZodNumber>;
1853
+ /** Seconds each cue's display start is shifted EARLIER (clamped to the
1854
+ * previous cue's end / the segment's outStart). */
1855
+ leadS: z.ZodOptional<z.ZodNumber>;
1856
+ /** Max seconds a cue is held past its last word to bridge the gap to the
1857
+ * next cue (never past the segment's outEnd). */
1858
+ holdS: z.ZodOptional<z.ZodNumber>;
1859
+ /** Per-word highlight sweep within grouped cues (karaoke-style). */
1860
+ karaoke: z.ZodOptional<z.ZodBoolean>;
1861
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
1862
+ /** Max words per grouped cue (preset "grouped" only). */
1863
+ maxWords: z.ZodOptional<z.ZodNumber>;
1864
+ /** Inter-word gap (seconds) that ends a phrase — a hard cue boundary
1865
+ * (preset "grouped" only). */
1866
+ gapBreakS: z.ZodOptional<z.ZodNumber>;
1867
+ /** Seconds each cue's display start is shifted EARLIER (clamped to the
1868
+ * previous cue's end / the segment's outStart). */
1869
+ leadS: z.ZodOptional<z.ZodNumber>;
1870
+ /** Max seconds a cue is held past its last word to bridge the gap to the
1871
+ * next cue (never past the segment's outEnd). */
1872
+ holdS: z.ZodOptional<z.ZodNumber>;
1873
+ /** Per-word highlight sweep within grouped cues (karaoke-style). */
1874
+ karaoke: z.ZodOptional<z.ZodBoolean>;
1875
+ }, z.ZodTypeAny, "passthrough">>>;
1876
+ overrides: z.ZodDefault<z.ZodArray<z.ZodObject<{
1877
+ id: z.ZodString;
1878
+ anchor: z.ZodObject<{
1879
+ type: z.ZodLiteral<"words">;
1880
+ source: z.ZodString;
1881
+ phrase: z.ZodString;
1882
+ /** 1-based occurrence index when the phrase appears more than once. */
1883
+ occurrence: z.ZodOptional<z.ZodNumber>;
1884
+ /** Cached resolution in SOURCE seconds. */
1885
+ resolved: z.ZodOptional<z.ZodObject<{
1886
+ start: z.ZodNumber;
1887
+ end: z.ZodNumber;
1888
+ }, "strict", z.ZodTypeAny, {
1889
+ start: number;
1890
+ end: number;
1891
+ }, {
1892
+ start: number;
1893
+ end: number;
1894
+ }>>;
1895
+ /** Collapse the span to one instant (phrase start or end). */
1896
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
1897
+ }, "strict", z.ZodTypeAny, {
1898
+ type: "words";
1899
+ source: string;
1900
+ phrase: string;
1901
+ occurrence?: number | undefined;
1902
+ resolved?: {
1903
+ start: number;
1904
+ end: number;
1905
+ } | undefined;
1906
+ edge?: "start" | "end" | undefined;
1907
+ }, {
1908
+ type: "words";
1909
+ source: string;
1910
+ phrase: string;
1911
+ occurrence?: number | undefined;
1912
+ resolved?: {
1913
+ start: number;
1914
+ end: number;
1915
+ } | undefined;
1916
+ edge?: "start" | "end" | undefined;
1917
+ }>;
1918
+ op: z.ZodEnum<["replace-text", "hide", "break-line", "style"]>;
1919
+ text: z.ZodOptional<z.ZodString>;
1920
+ /** op:"style" — per-word color (hex or simple CSS color name). */
1921
+ color: z.ZodOptional<z.ZodString>;
1922
+ /** op:"style" — per-word animated emphasis at the word's onset. */
1923
+ emphasis: z.ZodOptional<z.ZodEnum<["pop", "highlight"]>>;
1924
+ provenance: z.ZodDefault<z.ZodObject<{
1925
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
1926
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
1927
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
1928
+ }, "strict", z.ZodTypeAny, {
1929
+ round: number | null;
1930
+ changeId: string | null;
1931
+ actor: "agent" | "user";
1932
+ }, {
1933
+ round?: number | null | undefined;
1934
+ changeId?: string | null | undefined;
1935
+ actor?: "agent" | "user" | undefined;
1936
+ }>>;
1937
+ }, "strict", z.ZodTypeAny, {
1938
+ anchor: {
1939
+ type: "words";
1940
+ source: string;
1941
+ phrase: string;
1942
+ occurrence?: number | undefined;
1943
+ resolved?: {
1944
+ start: number;
1945
+ end: number;
1946
+ } | undefined;
1947
+ edge?: "start" | "end" | undefined;
1948
+ };
1949
+ id: string;
1950
+ provenance: {
1951
+ round: number | null;
1952
+ changeId: string | null;
1953
+ actor: "agent" | "user";
1954
+ };
1955
+ op: "replace-text" | "hide" | "break-line" | "style";
1956
+ text?: string | undefined;
1957
+ color?: string | undefined;
1958
+ emphasis?: "pop" | "highlight" | undefined;
1959
+ }, {
1960
+ anchor: {
1961
+ type: "words";
1962
+ source: string;
1963
+ phrase: string;
1964
+ occurrence?: number | undefined;
1965
+ resolved?: {
1966
+ start: number;
1967
+ end: number;
1968
+ } | undefined;
1969
+ edge?: "start" | "end" | undefined;
1970
+ };
1971
+ id: string;
1972
+ op: "replace-text" | "hide" | "break-line" | "style";
1973
+ text?: string | undefined;
1974
+ provenance?: {
1975
+ round?: number | null | undefined;
1976
+ changeId?: string | null | undefined;
1977
+ actor?: "agent" | "user" | undefined;
1978
+ } | undefined;
1979
+ color?: string | undefined;
1980
+ emphasis?: "pop" | "highlight" | undefined;
1981
+ }>, "many">>;
1982
+ }, "strict", z.ZodTypeAny, {
1983
+ preset: "grouped" | "opus-karaoke";
1984
+ style: {
1985
+ maxWords?: number | undefined;
1986
+ gapBreakS?: number | undefined;
1987
+ leadS?: number | undefined;
1988
+ holdS?: number | undefined;
1989
+ karaoke?: boolean | undefined;
1990
+ } & {
1991
+ [k: string]: unknown;
1992
+ };
1993
+ enabled: boolean;
1994
+ overrides: {
1995
+ anchor: {
1996
+ type: "words";
1997
+ source: string;
1998
+ phrase: string;
1999
+ occurrence?: number | undefined;
2000
+ resolved?: {
2001
+ start: number;
2002
+ end: number;
2003
+ } | undefined;
2004
+ edge?: "start" | "end" | undefined;
2005
+ };
2006
+ id: string;
2007
+ provenance: {
2008
+ round: number | null;
2009
+ changeId: string | null;
2010
+ actor: "agent" | "user";
2011
+ };
2012
+ op: "replace-text" | "hide" | "break-line" | "style";
2013
+ text?: string | undefined;
2014
+ color?: string | undefined;
2015
+ emphasis?: "pop" | "highlight" | undefined;
2016
+ }[];
2017
+ }, {
2018
+ preset?: "grouped" | "opus-karaoke" | undefined;
2019
+ style?: z.objectInputType<{
2020
+ /** Max words per grouped cue (preset "grouped" only). */
2021
+ maxWords: z.ZodOptional<z.ZodNumber>;
2022
+ /** Inter-word gap (seconds) that ends a phrase — a hard cue boundary
2023
+ * (preset "grouped" only). */
2024
+ gapBreakS: z.ZodOptional<z.ZodNumber>;
2025
+ /** Seconds each cue's display start is shifted EARLIER (clamped to the
2026
+ * previous cue's end / the segment's outStart). */
2027
+ leadS: z.ZodOptional<z.ZodNumber>;
2028
+ /** Max seconds a cue is held past its last word to bridge the gap to the
2029
+ * next cue (never past the segment's outEnd). */
2030
+ holdS: z.ZodOptional<z.ZodNumber>;
2031
+ /** Per-word highlight sweep within grouped cues (karaoke-style). */
2032
+ karaoke: z.ZodOptional<z.ZodBoolean>;
2033
+ }, z.ZodTypeAny, "passthrough"> | undefined;
2034
+ enabled?: boolean | undefined;
2035
+ overrides?: {
2036
+ anchor: {
2037
+ type: "words";
2038
+ source: string;
2039
+ phrase: string;
2040
+ occurrence?: number | undefined;
2041
+ resolved?: {
2042
+ start: number;
2043
+ end: number;
2044
+ } | undefined;
2045
+ edge?: "start" | "end" | undefined;
2046
+ };
2047
+ id: string;
2048
+ op: "replace-text" | "hide" | "break-line" | "style";
2049
+ text?: string | undefined;
2050
+ provenance?: {
2051
+ round?: number | null | undefined;
2052
+ changeId?: string | null | undefined;
2053
+ actor?: "agent" | "user" | undefined;
2054
+ } | undefined;
2055
+ color?: string | undefined;
2056
+ emphasis?: "pop" | "highlight" | undefined;
2057
+ }[] | undefined;
2058
+ }>>;
2059
+ zooms: z.ZodDefault<z.ZodArray<z.ZodObject<{
2060
+ id: z.ZodString;
2061
+ anchor: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2062
+ type: z.ZodLiteral<"words">;
2063
+ source: z.ZodString;
2064
+ phrase: z.ZodString;
2065
+ /** 1-based occurrence index when the phrase appears more than once. */
2066
+ occurrence: z.ZodOptional<z.ZodNumber>;
2067
+ /** Cached resolution in SOURCE seconds. */
2068
+ resolved: z.ZodOptional<z.ZodObject<{
2069
+ start: z.ZodNumber;
2070
+ end: z.ZodNumber;
2071
+ }, "strict", z.ZodTypeAny, {
2072
+ start: number;
2073
+ end: number;
2074
+ }, {
2075
+ start: number;
2076
+ end: number;
2077
+ }>>;
2078
+ /** Collapse the span to one instant (phrase start or end). */
2079
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
2080
+ }, "strict", z.ZodTypeAny, {
2081
+ type: "words";
2082
+ source: string;
2083
+ phrase: string;
2084
+ occurrence?: number | undefined;
2085
+ resolved?: {
2086
+ start: number;
2087
+ end: number;
2088
+ } | undefined;
2089
+ edge?: "start" | "end" | undefined;
2090
+ }, {
2091
+ type: "words";
2092
+ source: string;
2093
+ phrase: string;
2094
+ occurrence?: number | undefined;
2095
+ resolved?: {
2096
+ start: number;
2097
+ end: number;
2098
+ } | undefined;
2099
+ edge?: "start" | "end" | undefined;
2100
+ }>, z.ZodObject<{
2101
+ type: z.ZodLiteral<"source">;
2102
+ source: z.ZodString;
2103
+ start: z.ZodNumber;
2104
+ end: z.ZodNumber;
2105
+ }, "strict", z.ZodTypeAny, {
2106
+ type: "source";
2107
+ start: number;
2108
+ end: number;
2109
+ source: string;
2110
+ }, {
2111
+ type: "source";
2112
+ start: number;
2113
+ end: number;
2114
+ source: string;
2115
+ }>, z.ZodObject<{
2116
+ type: z.ZodLiteral<"output">;
2117
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
2118
+ after: z.ZodString;
2119
+ }, "strict", z.ZodTypeAny, {
2120
+ after: string;
2121
+ }, {
2122
+ after: string;
2123
+ }>]>;
2124
+ durationS: z.ZodOptional<z.ZodNumber>;
2125
+ }, "strict", z.ZodTypeAny, {
2126
+ type: "output";
2127
+ at: "start" | "end" | "full" | {
2128
+ after: string;
2129
+ };
2130
+ durationS?: number | undefined;
2131
+ }, {
2132
+ type: "output";
2133
+ at: "start" | "end" | "full" | {
2134
+ after: string;
2135
+ };
2136
+ durationS?: number | undefined;
2137
+ }>]>;
2138
+ onCut: z.ZodDefault<z.ZodEnum<["clip", "drop", "error"]>>;
2139
+ rect: z.ZodObject<{
2140
+ x: z.ZodNumber;
2141
+ y: z.ZodNumber;
2142
+ w: z.ZodNumber;
2143
+ h: z.ZodNumber;
2144
+ }, "strict", z.ZodTypeAny, {
2145
+ w: number;
2146
+ h: number;
2147
+ x: number;
2148
+ y: number;
2149
+ }, {
2150
+ w: number;
2151
+ h: number;
2152
+ x: number;
2153
+ y: number;
2154
+ }>;
2155
+ scale: z.ZodNumber;
2156
+ /** Ramp target: when present, the zoom animates from the base rect/scale
2157
+ * to `to` over the zoom window (`ease` shapes the ramp). */
2158
+ to: z.ZodOptional<z.ZodObject<{
2159
+ rect: z.ZodOptional<z.ZodObject<{
2160
+ x: z.ZodNumber;
2161
+ y: z.ZodNumber;
2162
+ w: z.ZodNumber;
2163
+ h: z.ZodNumber;
2164
+ }, "strict", z.ZodTypeAny, {
2165
+ w: number;
2166
+ h: number;
2167
+ x: number;
2168
+ y: number;
2169
+ }, {
2170
+ w: number;
2171
+ h: number;
2172
+ x: number;
2173
+ y: number;
2174
+ }>>;
2175
+ scale: z.ZodOptional<z.ZodNumber>;
2176
+ }, "strict", z.ZodTypeAny, {
2177
+ rect?: {
2178
+ w: number;
2179
+ h: number;
2180
+ x: number;
2181
+ y: number;
2182
+ } | undefined;
2183
+ scale?: number | undefined;
2184
+ }, {
2185
+ rect?: {
2186
+ w: number;
2187
+ h: number;
2188
+ x: number;
2189
+ y: number;
2190
+ } | undefined;
2191
+ scale?: number | undefined;
2192
+ }>>;
2193
+ ease: z.ZodDefault<z.ZodObject<{
2194
+ in: z.ZodNumber;
2195
+ out: z.ZodNumber;
2196
+ }, "strict", z.ZodTypeAny, {
2197
+ in: number;
2198
+ out: number;
2199
+ }, {
2200
+ in: number;
2201
+ out: number;
2202
+ }>>;
2203
+ provenance: z.ZodDefault<z.ZodObject<{
2204
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
2205
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
2206
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
2207
+ }, "strict", z.ZodTypeAny, {
2208
+ round: number | null;
2209
+ changeId: string | null;
2210
+ actor: "agent" | "user";
2211
+ }, {
2212
+ round?: number | null | undefined;
2213
+ changeId?: string | null | undefined;
2214
+ actor?: "agent" | "user" | undefined;
2215
+ }>>;
2216
+ }, "strict", z.ZodTypeAny, {
2217
+ anchor: {
2218
+ type: "words";
2219
+ source: string;
2220
+ phrase: string;
2221
+ occurrence?: number | undefined;
2222
+ resolved?: {
2223
+ start: number;
2224
+ end: number;
2225
+ } | undefined;
2226
+ edge?: "start" | "end" | undefined;
2227
+ } | {
2228
+ type: "source";
2229
+ start: number;
2230
+ end: number;
2231
+ source: string;
2232
+ } | {
2233
+ type: "output";
2234
+ at: "start" | "end" | "full" | {
2235
+ after: string;
2236
+ };
2237
+ durationS?: number | undefined;
2238
+ };
2239
+ id: string;
2240
+ provenance: {
2241
+ round: number | null;
2242
+ changeId: string | null;
2243
+ actor: "agent" | "user";
2244
+ };
2245
+ onCut: "error" | "drop" | "clip";
2246
+ rect: {
2247
+ w: number;
2248
+ h: number;
2249
+ x: number;
2250
+ y: number;
2251
+ };
2252
+ scale: number;
2253
+ ease: {
2254
+ in: number;
2255
+ out: number;
2256
+ };
2257
+ to?: {
2258
+ rect?: {
2259
+ w: number;
2260
+ h: number;
2261
+ x: number;
2262
+ y: number;
2263
+ } | undefined;
2264
+ scale?: number | undefined;
2265
+ } | undefined;
2266
+ }, {
2267
+ anchor: {
2268
+ type: "words";
2269
+ source: string;
2270
+ phrase: string;
2271
+ occurrence?: number | undefined;
2272
+ resolved?: {
2273
+ start: number;
2274
+ end: number;
2275
+ } | undefined;
2276
+ edge?: "start" | "end" | undefined;
2277
+ } | {
2278
+ type: "source";
2279
+ start: number;
2280
+ end: number;
2281
+ source: string;
2282
+ } | {
2283
+ type: "output";
2284
+ at: "start" | "end" | "full" | {
2285
+ after: string;
2286
+ };
2287
+ durationS?: number | undefined;
2288
+ };
2289
+ id: string;
2290
+ rect: {
2291
+ w: number;
2292
+ h: number;
2293
+ x: number;
2294
+ y: number;
2295
+ };
2296
+ scale: number;
2297
+ provenance?: {
2298
+ round?: number | null | undefined;
2299
+ changeId?: string | null | undefined;
2300
+ actor?: "agent" | "user" | undefined;
2301
+ } | undefined;
2302
+ onCut?: "error" | "drop" | "clip" | undefined;
2303
+ to?: {
2304
+ rect?: {
2305
+ w: number;
2306
+ h: number;
2307
+ x: number;
2308
+ y: number;
2309
+ } | undefined;
2310
+ scale?: number | undefined;
2311
+ } | undefined;
2312
+ ease?: {
2313
+ in: number;
2314
+ out: number;
2315
+ } | undefined;
2316
+ }>, "many">>;
2317
+ overlays: z.ZodDefault<z.ZodArray<z.ZodObject<{
2318
+ id: z.ZodString;
2319
+ kind: z.ZodEnum<["text", "title-card", "image", "sticker"]>;
2320
+ anchor: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2321
+ type: z.ZodLiteral<"words">;
2322
+ source: z.ZodString;
2323
+ phrase: z.ZodString;
2324
+ /** 1-based occurrence index when the phrase appears more than once. */
2325
+ occurrence: z.ZodOptional<z.ZodNumber>;
2326
+ /** Cached resolution in SOURCE seconds. */
2327
+ resolved: z.ZodOptional<z.ZodObject<{
2328
+ start: z.ZodNumber;
2329
+ end: z.ZodNumber;
2330
+ }, "strict", z.ZodTypeAny, {
2331
+ start: number;
2332
+ end: number;
2333
+ }, {
2334
+ start: number;
2335
+ end: number;
2336
+ }>>;
2337
+ /** Collapse the span to one instant (phrase start or end). */
2338
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
2339
+ }, "strict", z.ZodTypeAny, {
2340
+ type: "words";
2341
+ source: string;
2342
+ phrase: string;
2343
+ occurrence?: number | undefined;
2344
+ resolved?: {
2345
+ start: number;
2346
+ end: number;
2347
+ } | undefined;
2348
+ edge?: "start" | "end" | undefined;
2349
+ }, {
2350
+ type: "words";
2351
+ source: string;
2352
+ phrase: string;
2353
+ occurrence?: number | undefined;
2354
+ resolved?: {
2355
+ start: number;
2356
+ end: number;
2357
+ } | undefined;
2358
+ edge?: "start" | "end" | undefined;
2359
+ }>, z.ZodObject<{
2360
+ type: z.ZodLiteral<"source">;
2361
+ source: z.ZodString;
2362
+ start: z.ZodNumber;
2363
+ end: z.ZodNumber;
2364
+ }, "strict", z.ZodTypeAny, {
2365
+ type: "source";
2366
+ start: number;
2367
+ end: number;
2368
+ source: string;
2369
+ }, {
2370
+ type: "source";
2371
+ start: number;
2372
+ end: number;
2373
+ source: string;
2374
+ }>, z.ZodObject<{
2375
+ type: z.ZodLiteral<"output">;
2376
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
2377
+ after: z.ZodString;
2378
+ }, "strict", z.ZodTypeAny, {
2379
+ after: string;
2380
+ }, {
2381
+ after: string;
2382
+ }>]>;
2383
+ durationS: z.ZodOptional<z.ZodNumber>;
2384
+ }, "strict", z.ZodTypeAny, {
2385
+ type: "output";
2386
+ at: "start" | "end" | "full" | {
2387
+ after: string;
2388
+ };
2389
+ durationS?: number | undefined;
2390
+ }, {
2391
+ type: "output";
2392
+ at: "start" | "end" | "full" | {
2393
+ after: string;
2394
+ };
2395
+ durationS?: number | undefined;
2396
+ }>]>;
2397
+ onCut: z.ZodDefault<z.ZodEnum<["clip", "drop", "error"]>>;
2398
+ layout: z.ZodDefault<z.ZodObject<{
2399
+ x: z.ZodDefault<z.ZodNumber>;
2400
+ y: z.ZodDefault<z.ZodNumber>;
2401
+ align: z.ZodDefault<z.ZodEnum<["left", "center", "right"]>>;
2402
+ safeArea: z.ZodDefault<z.ZodBoolean>;
2403
+ }, "strict", z.ZodTypeAny, {
2404
+ x: number;
2405
+ y: number;
2406
+ align: "center" | "left" | "right";
2407
+ safeArea: boolean;
2408
+ }, {
2409
+ x?: number | undefined;
2410
+ y?: number | undefined;
2411
+ align?: "center" | "left" | "right" | undefined;
2412
+ safeArea?: boolean | undefined;
2413
+ }>>;
2414
+ text: z.ZodOptional<z.ZodString>;
2415
+ style: z.ZodDefault<z.ZodObject<{
2416
+ preset: z.ZodOptional<z.ZodString>;
2417
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
2418
+ preset: z.ZodOptional<z.ZodString>;
2419
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
2420
+ preset: z.ZodOptional<z.ZodString>;
2421
+ }, z.ZodTypeAny, "passthrough">>>;
2422
+ durationS: z.ZodOptional<z.ZodNumber>;
2423
+ asset: z.ZodOptional<z.ZodObject<{
2424
+ ref: z.ZodString;
2425
+ }, "strict", z.ZodTypeAny, {
2426
+ ref: string;
2427
+ }, {
2428
+ ref: string;
2429
+ }>>;
2430
+ /** Entrance/exit presets (image/sticker overlays). */
2431
+ enter: z.ZodOptional<z.ZodObject<{
2432
+ preset: z.ZodEnum<["fade", "pop", "slide-up", "slide-down", "scale-in"]>;
2433
+ durationS: z.ZodNumber;
2434
+ }, "strict", z.ZodTypeAny, {
2435
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2436
+ durationS: number;
2437
+ }, {
2438
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2439
+ durationS: number;
2440
+ }>>;
2441
+ exit: z.ZodOptional<z.ZodObject<{
2442
+ preset: z.ZodEnum<["fade", "pop", "slide-up", "slide-down", "scale-in"]>;
2443
+ durationS: z.ZodNumber;
2444
+ }, "strict", z.ZodTypeAny, {
2445
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2446
+ durationS: number;
2447
+ }, {
2448
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2449
+ durationS: number;
2450
+ }>>;
2451
+ /** Size as canvas fractions (w of canvas width, h of canvas height). */
2452
+ size: z.ZodOptional<z.ZodObject<{
2453
+ w: z.ZodOptional<z.ZodNumber>;
2454
+ h: z.ZodOptional<z.ZodNumber>;
2455
+ }, "strict", z.ZodTypeAny, {
2456
+ w?: number | undefined;
2457
+ h?: number | undefined;
2458
+ }, {
2459
+ w?: number | undefined;
2460
+ h?: number | undefined;
2461
+ }>>;
2462
+ /** Stacking order (CSS z-index); temporal lanes stay non-overlapping. */
2463
+ z: z.ZodOptional<z.ZodNumber>;
2464
+ provenance: z.ZodDefault<z.ZodObject<{
2465
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
2466
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
2467
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
2468
+ }, "strict", z.ZodTypeAny, {
2469
+ round: number | null;
2470
+ changeId: string | null;
2471
+ actor: "agent" | "user";
2472
+ }, {
2473
+ round?: number | null | undefined;
2474
+ changeId?: string | null | undefined;
2475
+ actor?: "agent" | "user" | undefined;
2476
+ }>>;
2477
+ }, "strict", z.ZodTypeAny, {
2478
+ anchor: {
2479
+ type: "words";
2480
+ source: string;
2481
+ phrase: string;
2482
+ occurrence?: number | undefined;
2483
+ resolved?: {
2484
+ start: number;
2485
+ end: number;
2486
+ } | undefined;
2487
+ edge?: "start" | "end" | undefined;
2488
+ } | {
2489
+ type: "source";
2490
+ start: number;
2491
+ end: number;
2492
+ source: string;
2493
+ } | {
2494
+ type: "output";
2495
+ at: "start" | "end" | "full" | {
2496
+ after: string;
2497
+ };
2498
+ durationS?: number | undefined;
2499
+ };
2500
+ kind: "text" | "title-card" | "image" | "sticker";
2501
+ id: string;
2502
+ provenance: {
2503
+ round: number | null;
2504
+ changeId: string | null;
2505
+ actor: "agent" | "user";
2506
+ };
2507
+ style: {
2508
+ preset?: string | undefined;
2509
+ } & {
2510
+ [k: string]: unknown;
2511
+ };
2512
+ onCut: "error" | "drop" | "clip";
2513
+ layout: {
2514
+ x: number;
2515
+ y: number;
2516
+ align: "center" | "left" | "right";
2517
+ safeArea: boolean;
2518
+ };
2519
+ text?: string | undefined;
2520
+ size?: {
2521
+ w?: number | undefined;
2522
+ h?: number | undefined;
2523
+ } | undefined;
2524
+ durationS?: number | undefined;
2525
+ asset?: {
2526
+ ref: string;
2527
+ } | undefined;
2528
+ enter?: {
2529
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2530
+ durationS: number;
2531
+ } | undefined;
2532
+ exit?: {
2533
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2534
+ durationS: number;
2535
+ } | undefined;
2536
+ z?: number | undefined;
2537
+ }, {
2538
+ anchor: {
2539
+ type: "words";
2540
+ source: string;
2541
+ phrase: string;
2542
+ occurrence?: number | undefined;
2543
+ resolved?: {
2544
+ start: number;
2545
+ end: number;
2546
+ } | undefined;
2547
+ edge?: "start" | "end" | undefined;
2548
+ } | {
2549
+ type: "source";
2550
+ start: number;
2551
+ end: number;
2552
+ source: string;
2553
+ } | {
2554
+ type: "output";
2555
+ at: "start" | "end" | "full" | {
2556
+ after: string;
2557
+ };
2558
+ durationS?: number | undefined;
2559
+ };
2560
+ kind: "text" | "title-card" | "image" | "sticker";
2561
+ id: string;
2562
+ text?: string | undefined;
2563
+ size?: {
2564
+ w?: number | undefined;
2565
+ h?: number | undefined;
2566
+ } | undefined;
2567
+ durationS?: number | undefined;
2568
+ provenance?: {
2569
+ round?: number | null | undefined;
2570
+ changeId?: string | null | undefined;
2571
+ actor?: "agent" | "user" | undefined;
2572
+ } | undefined;
2573
+ style?: z.objectInputType<{
2574
+ preset: z.ZodOptional<z.ZodString>;
2575
+ }, z.ZodTypeAny, "passthrough"> | undefined;
2576
+ onCut?: "error" | "drop" | "clip" | undefined;
2577
+ layout?: {
2578
+ x?: number | undefined;
2579
+ y?: number | undefined;
2580
+ align?: "center" | "left" | "right" | undefined;
2581
+ safeArea?: boolean | undefined;
2582
+ } | undefined;
2583
+ asset?: {
2584
+ ref: string;
2585
+ } | undefined;
2586
+ enter?: {
2587
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2588
+ durationS: number;
2589
+ } | undefined;
2590
+ exit?: {
2591
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2592
+ durationS: number;
2593
+ } | undefined;
2594
+ z?: number | undefined;
2595
+ }>, "many">>;
2596
+ audio: z.ZodDefault<z.ZodArray<z.ZodObject<{
2597
+ id: z.ZodString;
2598
+ kind: z.ZodEnum<["music", "sfx"]>;
2599
+ asset: z.ZodObject<{
2600
+ ref: z.ZodString;
2601
+ }, "strict", z.ZodTypeAny, {
2602
+ ref: string;
2603
+ }, {
2604
+ ref: string;
2605
+ }>;
2606
+ anchor: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2607
+ type: z.ZodLiteral<"words">;
2608
+ source: z.ZodString;
2609
+ phrase: z.ZodString;
2610
+ /** 1-based occurrence index when the phrase appears more than once. */
2611
+ occurrence: z.ZodOptional<z.ZodNumber>;
2612
+ /** Cached resolution in SOURCE seconds. */
2613
+ resolved: z.ZodOptional<z.ZodObject<{
2614
+ start: z.ZodNumber;
2615
+ end: z.ZodNumber;
2616
+ }, "strict", z.ZodTypeAny, {
2617
+ start: number;
2618
+ end: number;
2619
+ }, {
2620
+ start: number;
2621
+ end: number;
2622
+ }>>;
2623
+ /** Collapse the span to one instant (phrase start or end). */
2624
+ edge: z.ZodOptional<z.ZodEnum<["start", "end"]>>;
2625
+ }, "strict", z.ZodTypeAny, {
2626
+ type: "words";
2627
+ source: string;
2628
+ phrase: string;
2629
+ occurrence?: number | undefined;
2630
+ resolved?: {
2631
+ start: number;
2632
+ end: number;
2633
+ } | undefined;
2634
+ edge?: "start" | "end" | undefined;
2635
+ }, {
2636
+ type: "words";
2637
+ source: string;
2638
+ phrase: string;
2639
+ occurrence?: number | undefined;
2640
+ resolved?: {
2641
+ start: number;
2642
+ end: number;
2643
+ } | undefined;
2644
+ edge?: "start" | "end" | undefined;
2645
+ }>, z.ZodObject<{
2646
+ type: z.ZodLiteral<"source">;
2647
+ source: z.ZodString;
2648
+ start: z.ZodNumber;
2649
+ end: z.ZodNumber;
2650
+ }, "strict", z.ZodTypeAny, {
2651
+ type: "source";
2652
+ start: number;
2653
+ end: number;
2654
+ source: string;
2655
+ }, {
2656
+ type: "source";
2657
+ start: number;
2658
+ end: number;
2659
+ source: string;
2660
+ }>, z.ZodObject<{
2661
+ type: z.ZodLiteral<"output">;
2662
+ at: z.ZodUnion<[z.ZodEnum<["start", "end", "full"]>, z.ZodObject<{
2663
+ after: z.ZodString;
2664
+ }, "strict", z.ZodTypeAny, {
2665
+ after: string;
2666
+ }, {
2667
+ after: string;
2668
+ }>]>;
2669
+ durationS: z.ZodOptional<z.ZodNumber>;
2670
+ }, "strict", z.ZodTypeAny, {
2671
+ type: "output";
2672
+ at: "start" | "end" | "full" | {
2673
+ after: string;
2674
+ };
2675
+ durationS?: number | undefined;
2676
+ }, {
2677
+ type: "output";
2678
+ at: "start" | "end" | "full" | {
2679
+ after: string;
2680
+ };
2681
+ durationS?: number | undefined;
2682
+ }>]>;
2683
+ gainDb: z.ZodDefault<z.ZodNumber>;
2684
+ duckToSpeech: z.ZodDefault<z.ZodBoolean>;
2685
+ fadeOutS: z.ZodOptional<z.ZodNumber>;
2686
+ provenance: z.ZodDefault<z.ZodObject<{
2687
+ round: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
2688
+ changeId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
2689
+ actor: z.ZodDefault<z.ZodEnum<["agent", "user"]>>;
2690
+ }, "strict", z.ZodTypeAny, {
2691
+ round: number | null;
2692
+ changeId: string | null;
2693
+ actor: "agent" | "user";
2694
+ }, {
2695
+ round?: number | null | undefined;
2696
+ changeId?: string | null | undefined;
2697
+ actor?: "agent" | "user" | undefined;
2698
+ }>>;
2699
+ }, "strict", z.ZodTypeAny, {
2700
+ anchor: {
2701
+ type: "words";
2702
+ source: string;
2703
+ phrase: string;
2704
+ occurrence?: number | undefined;
2705
+ resolved?: {
2706
+ start: number;
2707
+ end: number;
2708
+ } | undefined;
2709
+ edge?: "start" | "end" | undefined;
2710
+ } | {
2711
+ type: "source";
2712
+ start: number;
2713
+ end: number;
2714
+ source: string;
2715
+ } | {
2716
+ type: "output";
2717
+ at: "start" | "end" | "full" | {
2718
+ after: string;
2719
+ };
2720
+ durationS?: number | undefined;
2721
+ };
2722
+ kind: "music" | "sfx";
2723
+ id: string;
2724
+ provenance: {
2725
+ round: number | null;
2726
+ changeId: string | null;
2727
+ actor: "agent" | "user";
2728
+ };
2729
+ asset: {
2730
+ ref: string;
2731
+ };
2732
+ gainDb: number;
2733
+ duckToSpeech: boolean;
2734
+ fadeOutS?: number | undefined;
2735
+ }, {
2736
+ anchor: {
2737
+ type: "words";
2738
+ source: string;
2739
+ phrase: string;
2740
+ occurrence?: number | undefined;
2741
+ resolved?: {
2742
+ start: number;
2743
+ end: number;
2744
+ } | undefined;
2745
+ edge?: "start" | "end" | undefined;
2746
+ } | {
2747
+ type: "source";
2748
+ start: number;
2749
+ end: number;
2750
+ source: string;
2751
+ } | {
2752
+ type: "output";
2753
+ at: "start" | "end" | "full" | {
2754
+ after: string;
2755
+ };
2756
+ durationS?: number | undefined;
2757
+ };
2758
+ kind: "music" | "sfx";
2759
+ id: string;
2760
+ asset: {
2761
+ ref: string;
2762
+ };
2763
+ provenance?: {
2764
+ round?: number | null | undefined;
2765
+ changeId?: string | null | undefined;
2766
+ actor?: "agent" | "user" | undefined;
2767
+ } | undefined;
2768
+ gainDb?: number | undefined;
2769
+ duckToSpeech?: boolean | undefined;
2770
+ fadeOutS?: number | undefined;
2771
+ }>, "many">>;
2772
+ }, "strict", z.ZodTypeAny, {
2773
+ audio: {
2774
+ anchor: {
2775
+ type: "words";
2776
+ source: string;
2777
+ phrase: string;
2778
+ occurrence?: number | undefined;
2779
+ resolved?: {
2780
+ start: number;
2781
+ end: number;
2782
+ } | undefined;
2783
+ edge?: "start" | "end" | undefined;
2784
+ } | {
2785
+ type: "source";
2786
+ start: number;
2787
+ end: number;
2788
+ source: string;
2789
+ } | {
2790
+ type: "output";
2791
+ at: "start" | "end" | "full" | {
2792
+ after: string;
2793
+ };
2794
+ durationS?: number | undefined;
2795
+ };
2796
+ kind: "music" | "sfx";
2797
+ id: string;
2798
+ provenance: {
2799
+ round: number | null;
2800
+ changeId: string | null;
2801
+ actor: "agent" | "user";
2802
+ };
2803
+ asset: {
2804
+ ref: string;
2805
+ };
2806
+ gainDb: number;
2807
+ duckToSpeech: boolean;
2808
+ fadeOutS?: number | undefined;
2809
+ }[];
2810
+ id: string;
2811
+ version: 2;
2812
+ sources: Record<string, {
2813
+ path: string;
2814
+ durationS?: number | undefined;
2815
+ transcriptHash?: string | undefined;
2816
+ }>;
2817
+ settings: {
2818
+ canvas: {
2819
+ w: number;
2820
+ h: number;
2821
+ };
2822
+ grade: string | {
2823
+ preset: string;
2824
+ intensity?: number | undefined;
2825
+ };
2826
+ loudnorm: boolean;
2827
+ desilence?: {
2828
+ noiseDb?: number | undefined;
2829
+ minSilence?: number | undefined;
2830
+ targetGap?: number | undefined;
2831
+ leadKeep?: number | undefined;
2832
+ trailKeep?: number | undefined;
2833
+ minSegment?: number | undefined;
2834
+ } | undefined;
2835
+ };
2836
+ cut: {
2837
+ ranges: {
2838
+ start: number;
2839
+ end: number;
2840
+ source: string;
2841
+ id: string;
2842
+ provenance: {
2843
+ round: number | null;
2844
+ changeId: string | null;
2845
+ actor: "agent" | "user";
2846
+ };
2847
+ grade?: string | undefined;
2848
+ beat?: string | undefined;
2849
+ quote?: string | undefined;
2850
+ reason?: string | undefined;
2851
+ }[];
2852
+ };
2853
+ captions: {
2854
+ preset: "grouped" | "opus-karaoke";
2855
+ style: {
2856
+ maxWords?: number | undefined;
2857
+ gapBreakS?: number | undefined;
2858
+ leadS?: number | undefined;
2859
+ holdS?: number | undefined;
2860
+ karaoke?: boolean | undefined;
2861
+ } & {
2862
+ [k: string]: unknown;
2863
+ };
2864
+ enabled: boolean;
2865
+ overrides: {
2866
+ anchor: {
2867
+ type: "words";
2868
+ source: string;
2869
+ phrase: string;
2870
+ occurrence?: number | undefined;
2871
+ resolved?: {
2872
+ start: number;
2873
+ end: number;
2874
+ } | undefined;
2875
+ edge?: "start" | "end" | undefined;
2876
+ };
2877
+ id: string;
2878
+ provenance: {
2879
+ round: number | null;
2880
+ changeId: string | null;
2881
+ actor: "agent" | "user";
2882
+ };
2883
+ op: "replace-text" | "hide" | "break-line" | "style";
2884
+ text?: string | undefined;
2885
+ color?: string | undefined;
2886
+ emphasis?: "pop" | "highlight" | undefined;
2887
+ }[];
2888
+ };
2889
+ zooms: {
2890
+ anchor: {
2891
+ type: "words";
2892
+ source: string;
2893
+ phrase: string;
2894
+ occurrence?: number | undefined;
2895
+ resolved?: {
2896
+ start: number;
2897
+ end: number;
2898
+ } | undefined;
2899
+ edge?: "start" | "end" | undefined;
2900
+ } | {
2901
+ type: "source";
2902
+ start: number;
2903
+ end: number;
2904
+ source: string;
2905
+ } | {
2906
+ type: "output";
2907
+ at: "start" | "end" | "full" | {
2908
+ after: string;
2909
+ };
2910
+ durationS?: number | undefined;
2911
+ };
2912
+ id: string;
2913
+ provenance: {
2914
+ round: number | null;
2915
+ changeId: string | null;
2916
+ actor: "agent" | "user";
2917
+ };
2918
+ onCut: "error" | "drop" | "clip";
2919
+ rect: {
2920
+ w: number;
2921
+ h: number;
2922
+ x: number;
2923
+ y: number;
2924
+ };
2925
+ scale: number;
2926
+ ease: {
2927
+ in: number;
2928
+ out: number;
2929
+ };
2930
+ to?: {
2931
+ rect?: {
2932
+ w: number;
2933
+ h: number;
2934
+ x: number;
2935
+ y: number;
2936
+ } | undefined;
2937
+ scale?: number | undefined;
2938
+ } | undefined;
2939
+ }[];
2940
+ overlays: {
2941
+ anchor: {
2942
+ type: "words";
2943
+ source: string;
2944
+ phrase: string;
2945
+ occurrence?: number | undefined;
2946
+ resolved?: {
2947
+ start: number;
2948
+ end: number;
2949
+ } | undefined;
2950
+ edge?: "start" | "end" | undefined;
2951
+ } | {
2952
+ type: "source";
2953
+ start: number;
2954
+ end: number;
2955
+ source: string;
2956
+ } | {
2957
+ type: "output";
2958
+ at: "start" | "end" | "full" | {
2959
+ after: string;
2960
+ };
2961
+ durationS?: number | undefined;
2962
+ };
2963
+ kind: "text" | "title-card" | "image" | "sticker";
2964
+ id: string;
2965
+ provenance: {
2966
+ round: number | null;
2967
+ changeId: string | null;
2968
+ actor: "agent" | "user";
2969
+ };
2970
+ style: {
2971
+ preset?: string | undefined;
2972
+ } & {
2973
+ [k: string]: unknown;
2974
+ };
2975
+ onCut: "error" | "drop" | "clip";
2976
+ layout: {
2977
+ x: number;
2978
+ y: number;
2979
+ align: "center" | "left" | "right";
2980
+ safeArea: boolean;
2981
+ };
2982
+ text?: string | undefined;
2983
+ size?: {
2984
+ w?: number | undefined;
2985
+ h?: number | undefined;
2986
+ } | undefined;
2987
+ durationS?: number | undefined;
2988
+ asset?: {
2989
+ ref: string;
2990
+ } | undefined;
2991
+ enter?: {
2992
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2993
+ durationS: number;
2994
+ } | undefined;
2995
+ exit?: {
2996
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
2997
+ durationS: number;
2998
+ } | undefined;
2999
+ z?: number | undefined;
3000
+ }[];
3001
+ }, {
3002
+ id: string;
3003
+ version: 2;
3004
+ sources: Record<string, {
3005
+ path: string;
3006
+ durationS?: number | undefined;
3007
+ transcriptHash?: string | undefined;
3008
+ }>;
3009
+ audio?: {
3010
+ anchor: {
3011
+ type: "words";
3012
+ source: string;
3013
+ phrase: string;
3014
+ occurrence?: number | undefined;
3015
+ resolved?: {
3016
+ start: number;
3017
+ end: number;
3018
+ } | undefined;
3019
+ edge?: "start" | "end" | undefined;
3020
+ } | {
3021
+ type: "source";
3022
+ start: number;
3023
+ end: number;
3024
+ source: string;
3025
+ } | {
3026
+ type: "output";
3027
+ at: "start" | "end" | "full" | {
3028
+ after: string;
3029
+ };
3030
+ durationS?: number | undefined;
3031
+ };
3032
+ kind: "music" | "sfx";
3033
+ id: string;
3034
+ asset: {
3035
+ ref: string;
3036
+ };
3037
+ provenance?: {
3038
+ round?: number | null | undefined;
3039
+ changeId?: string | null | undefined;
3040
+ actor?: "agent" | "user" | undefined;
3041
+ } | undefined;
3042
+ gainDb?: number | undefined;
3043
+ duckToSpeech?: boolean | undefined;
3044
+ fadeOutS?: number | undefined;
3045
+ }[] | undefined;
3046
+ settings?: {
3047
+ canvas?: {
3048
+ w: number;
3049
+ h: number;
3050
+ } | undefined;
3051
+ grade?: string | {
3052
+ preset: string;
3053
+ intensity?: number | undefined;
3054
+ } | undefined;
3055
+ loudnorm?: boolean | undefined;
3056
+ desilence?: {
3057
+ noiseDb?: number | undefined;
3058
+ minSilence?: number | undefined;
3059
+ targetGap?: number | undefined;
3060
+ leadKeep?: number | undefined;
3061
+ trailKeep?: number | undefined;
3062
+ minSegment?: number | undefined;
3063
+ } | undefined;
3064
+ } | undefined;
3065
+ cut?: {
3066
+ ranges?: {
3067
+ start: number;
3068
+ end: number;
3069
+ source: string;
3070
+ id: string;
3071
+ grade?: string | undefined;
3072
+ beat?: string | undefined;
3073
+ quote?: string | undefined;
3074
+ reason?: string | undefined;
3075
+ provenance?: {
3076
+ round?: number | null | undefined;
3077
+ changeId?: string | null | undefined;
3078
+ actor?: "agent" | "user" | undefined;
3079
+ } | undefined;
3080
+ }[] | undefined;
3081
+ } | undefined;
3082
+ captions?: {
3083
+ preset?: "grouped" | "opus-karaoke" | undefined;
3084
+ style?: z.objectInputType<{
3085
+ /** Max words per grouped cue (preset "grouped" only). */
3086
+ maxWords: z.ZodOptional<z.ZodNumber>;
3087
+ /** Inter-word gap (seconds) that ends a phrase — a hard cue boundary
3088
+ * (preset "grouped" only). */
3089
+ gapBreakS: z.ZodOptional<z.ZodNumber>;
3090
+ /** Seconds each cue's display start is shifted EARLIER (clamped to the
3091
+ * previous cue's end / the segment's outStart). */
3092
+ leadS: z.ZodOptional<z.ZodNumber>;
3093
+ /** Max seconds a cue is held past its last word to bridge the gap to the
3094
+ * next cue (never past the segment's outEnd). */
3095
+ holdS: z.ZodOptional<z.ZodNumber>;
3096
+ /** Per-word highlight sweep within grouped cues (karaoke-style). */
3097
+ karaoke: z.ZodOptional<z.ZodBoolean>;
3098
+ }, z.ZodTypeAny, "passthrough"> | undefined;
3099
+ enabled?: boolean | undefined;
3100
+ overrides?: {
3101
+ anchor: {
3102
+ type: "words";
3103
+ source: string;
3104
+ phrase: string;
3105
+ occurrence?: number | undefined;
3106
+ resolved?: {
3107
+ start: number;
3108
+ end: number;
3109
+ } | undefined;
3110
+ edge?: "start" | "end" | undefined;
3111
+ };
3112
+ id: string;
3113
+ op: "replace-text" | "hide" | "break-line" | "style";
3114
+ text?: string | undefined;
3115
+ provenance?: {
3116
+ round?: number | null | undefined;
3117
+ changeId?: string | null | undefined;
3118
+ actor?: "agent" | "user" | undefined;
3119
+ } | undefined;
3120
+ color?: string | undefined;
3121
+ emphasis?: "pop" | "highlight" | undefined;
3122
+ }[] | undefined;
3123
+ } | undefined;
3124
+ zooms?: {
3125
+ anchor: {
3126
+ type: "words";
3127
+ source: string;
3128
+ phrase: string;
3129
+ occurrence?: number | undefined;
3130
+ resolved?: {
3131
+ start: number;
3132
+ end: number;
3133
+ } | undefined;
3134
+ edge?: "start" | "end" | undefined;
3135
+ } | {
3136
+ type: "source";
3137
+ start: number;
3138
+ end: number;
3139
+ source: string;
3140
+ } | {
3141
+ type: "output";
3142
+ at: "start" | "end" | "full" | {
3143
+ after: string;
3144
+ };
3145
+ durationS?: number | undefined;
3146
+ };
3147
+ id: string;
3148
+ rect: {
3149
+ w: number;
3150
+ h: number;
3151
+ x: number;
3152
+ y: number;
3153
+ };
3154
+ scale: number;
3155
+ provenance?: {
3156
+ round?: number | null | undefined;
3157
+ changeId?: string | null | undefined;
3158
+ actor?: "agent" | "user" | undefined;
3159
+ } | undefined;
3160
+ onCut?: "error" | "drop" | "clip" | undefined;
3161
+ to?: {
3162
+ rect?: {
3163
+ w: number;
3164
+ h: number;
3165
+ x: number;
3166
+ y: number;
3167
+ } | undefined;
3168
+ scale?: number | undefined;
3169
+ } | undefined;
3170
+ ease?: {
3171
+ in: number;
3172
+ out: number;
3173
+ } | undefined;
3174
+ }[] | undefined;
3175
+ overlays?: {
3176
+ anchor: {
3177
+ type: "words";
3178
+ source: string;
3179
+ phrase: string;
3180
+ occurrence?: number | undefined;
3181
+ resolved?: {
3182
+ start: number;
3183
+ end: number;
3184
+ } | undefined;
3185
+ edge?: "start" | "end" | undefined;
3186
+ } | {
3187
+ type: "source";
3188
+ start: number;
3189
+ end: number;
3190
+ source: string;
3191
+ } | {
3192
+ type: "output";
3193
+ at: "start" | "end" | "full" | {
3194
+ after: string;
3195
+ };
3196
+ durationS?: number | undefined;
3197
+ };
3198
+ kind: "text" | "title-card" | "image" | "sticker";
3199
+ id: string;
3200
+ text?: string | undefined;
3201
+ size?: {
3202
+ w?: number | undefined;
3203
+ h?: number | undefined;
3204
+ } | undefined;
3205
+ durationS?: number | undefined;
3206
+ provenance?: {
3207
+ round?: number | null | undefined;
3208
+ changeId?: string | null | undefined;
3209
+ actor?: "agent" | "user" | undefined;
3210
+ } | undefined;
3211
+ style?: z.objectInputType<{
3212
+ preset: z.ZodOptional<z.ZodString>;
3213
+ }, z.ZodTypeAny, "passthrough"> | undefined;
3214
+ onCut?: "error" | "drop" | "clip" | undefined;
3215
+ layout?: {
3216
+ x?: number | undefined;
3217
+ y?: number | undefined;
3218
+ align?: "center" | "left" | "right" | undefined;
3219
+ safeArea?: boolean | undefined;
3220
+ } | undefined;
3221
+ asset?: {
3222
+ ref: string;
3223
+ } | undefined;
3224
+ enter?: {
3225
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
3226
+ durationS: number;
3227
+ } | undefined;
3228
+ exit?: {
3229
+ preset: "pop" | "fade" | "slide-up" | "slide-down" | "scale-in";
3230
+ durationS: number;
3231
+ } | undefined;
3232
+ z?: number | undefined;
3233
+ }[] | undefined;
3234
+ }>;
3235
+ type TimelineV2 = z.infer<typeof timelineV2Schema>;
3236
+ interface Diagnostic {
3237
+ /** JSON-path-ish location, e.g. "cut.ranges[2].end". */
3238
+ path: string;
3239
+ code: string;
3240
+ message: string;
3241
+ suggestion?: string;
3242
+ context?: unknown;
3243
+ }
3244
+ interface Diagnostics {
3245
+ errors: Diagnostic[];
3246
+ warnings: Diagnostic[];
3247
+ /** Item ids removed by onCut:"drop" policy during compile. */
3248
+ dropped: string[];
3249
+ }
3250
+ interface ParseResult {
3251
+ doc: TimelineV2 | null;
3252
+ errors: Diagnostic[];
3253
+ }
3254
+ /** Parse + shape-validate a raw JSON value into a TimelineV2 (applying
3255
+ * defaults). Returns diagnostics instead of throwing. */
3256
+ declare function parseTimeline(raw: unknown): ParseResult;
3257
+ /** Semantic (beyond-shape) validation. Pure. Capability checks live in
3258
+ * capabilities.ts (checkCapabilities) so the registry stays injectable. */
3259
+ declare function validateTimeline(doc: TimelineV2): {
3260
+ errors: Diagnostic[];
3261
+ warnings: Diagnostic[];
3262
+ };
3263
+
3264
+ type CapabilityStatus = "ready" | "staged" | "none";
3265
+ interface Capability {
3266
+ status: CapabilityStatus;
3267
+ }
3268
+ type FeatureKey = "cut" | "captions.karaoke" | "captions.word-style" | "captions.karaoke-highlight" | "zoom" | "zoom.ramp" | "overlay.text" | "overlay.title-card" | "overlay.image" | "overlay.sticker" | "overlay.enter-exit" | "audio.music" | "audio.sfx" | "grade";
3269
+ declare const CAPABILITIES: Record<string, Capability>;
3270
+ /** The ordered, de-duplicated list of feature keys a doc actually uses. */
3271
+ declare function usesFromDoc(doc: TimelineV2): string[];
3272
+ /** Check used features against a registry (injectable for tests). Unknown
3273
+ * feature keys are treated as status "none". */
3274
+ declare function checkCapabilities(uses: string[], registry?: Record<string, Capability>): {
3275
+ errors: Diagnostic[];
3276
+ warnings: Diagnostic[];
3277
+ };
3278
+
3279
+ interface StreamWord {
3280
+ /** Index in the word stream (word tokens only, sorted by start). */
3281
+ index: number;
3282
+ start: number;
3283
+ end: number;
3284
+ text: string;
3285
+ /** Normalized token used for matching. */
3286
+ norm: string;
3287
+ }
3288
+ interface PhraseMatch {
3289
+ /** 1-based occurrence index in stream order. */
3290
+ occurrence: number;
3291
+ start: number;
3292
+ end: number;
3293
+ words: Array<{
3294
+ start: number;
3295
+ end: number;
3296
+ text: string;
3297
+ }>;
3298
+ /** ±5 words of context around the match. */
3299
+ context: string;
3300
+ /** Stream index of the first matched word. */
3301
+ wordIndex: number;
3302
+ }
3303
+ interface PhraseSuggestion {
3304
+ start: number;
3305
+ end: number;
3306
+ text: string;
3307
+ similarity: number;
3308
+ }
3309
+ type ResolveOutcome = {
3310
+ status: "ok";
3311
+ match: PhraseMatch;
3312
+ matches: PhraseMatch[];
3313
+ } | {
3314
+ status: "ambiguous";
3315
+ candidates: PhraseMatch[];
3316
+ } | {
3317
+ status: "not-found";
3318
+ suggestions: PhraseSuggestion[];
3319
+ };
3320
+ /** Strip leading/trailing non-letter/digit characters and lowercase. Keeps
3321
+ * interior characters (apostrophes, Hebrew letters, gershayim …) intact. */
3322
+ declare function normalizeToken(text: string): string;
3323
+ /** Tokenize a phrase on whitespace, normalize, drop empties. */
3324
+ declare function normalizePhrase(phrase: string): string[];
3325
+ /** Word tokens (type==="word", numeric times) sorted by start, normalized. */
3326
+ declare function wordStream(transcript: ScribeTranscript): StreamWord[];
3327
+ /** All exact (normalized) occurrences of `phrase` in the stream, in order. */
3328
+ declare function findPhrase(stream: StreamWord[], phrase: string): PhraseMatch[];
3329
+ /** Nearest windows of the same token count, ranked by string similarity. */
3330
+ declare function fuzzySuggestions(stream: StreamWord[], phrase: string, limit?: number): PhraseSuggestion[];
3331
+ interface ResolveOptions {
3332
+ /** 1-based occurrence to pick when the phrase repeats. */
3333
+ occurrence?: number;
3334
+ /** Disambiguate by proximity: pick the match whose start is nearest to this
3335
+ * SOURCE time (seconds). */
3336
+ nearS?: number;
3337
+ }
3338
+ /** Resolve a phrase to source time. Exactly one match → ok. Multiple matches
3339
+ * are disambiguated by `occurrence` or `nearS`; otherwise → ambiguous with
3340
+ * every occurrence listed (±5-word context). Zero matches → not-found with
3341
+ * fuzzy suggestions. */
3342
+ declare function resolvePhrase(stream: StreamWord[], phrase: string, opts?: ResolveOptions): ResolveOutcome;
3343
+
3344
+ interface PlanZoomOp {
3345
+ kind: "zoom";
3346
+ itemId: string;
3347
+ rect: {
3348
+ x: number;
3349
+ y: number;
3350
+ w: number;
3351
+ h: number;
3352
+ };
3353
+ scale: number;
3354
+ ease: {
3355
+ in: number;
3356
+ out: number;
3357
+ };
3358
+ /** Seconds relative to the segment's own start. */
3359
+ tIn: number;
3360
+ tOut: number;
3361
+ /** Ramp target (zoom `to`): animate rect/scale base → target over [tIn, tOut]. */
3362
+ toRect?: {
3363
+ x: number;
3364
+ y: number;
3365
+ w: number;
3366
+ h: number;
3367
+ };
3368
+ toScale?: number;
3369
+ }
3370
+ type PlanVideoOp = PlanZoomOp;
3371
+ interface PlanSegment {
3372
+ id: string;
3373
+ source: string;
3374
+ srcStart: number;
3375
+ srcEnd: number;
3376
+ outStart: number;
3377
+ outEnd: number;
3378
+ /** The authored cut range this segment came from (pre-desilence). */
3379
+ rangeId: string;
3380
+ videoOps: PlanVideoOp[];
3381
+ }
3382
+ interface PlanCueWord {
3383
+ /** Offset from the cue's outStart. */
3384
+ t: number;
3385
+ d: number;
3386
+ text: string;
3387
+ /** Per-word color (op:"style" caption override). */
3388
+ color?: string;
3389
+ /** Per-word animated emphasis at the word's onset (op:"style" override). */
3390
+ emphasis?: "pop" | "highlight";
3391
+ }
3392
+ interface PlanCaptionCueEvent {
3393
+ kind: "caption-cue";
3394
+ outStart: number;
3395
+ outEnd: number;
3396
+ words: PlanCueWord[];
3397
+ /** Force a line break after this cue (break-line override). */
3398
+ lineBreakAfter?: boolean;
3399
+ /** Set when the cue came from a caption override. */
3400
+ itemId?: string;
3401
+ /** Per-word highlight sweep within the cue (captions.style.karaoke). */
3402
+ karaoke?: boolean;
3403
+ }
3404
+ interface PlanOverlayEvent {
3405
+ kind: "overlay";
3406
+ itemId: string;
3407
+ outStart: number;
3408
+ outEnd: number;
3409
+ overlay: {
3410
+ kind: OverlayItem["kind"];
3411
+ layout: OverlayItem["layout"];
3412
+ text?: string;
3413
+ style: OverlayItem["style"];
3414
+ asset?: {
3415
+ ref: string;
3416
+ };
3417
+ enter?: OverlayFx;
3418
+ exit?: OverlayFx;
3419
+ size?: {
3420
+ w?: number;
3421
+ h?: number;
3422
+ };
3423
+ z?: number;
3424
+ };
3425
+ }
3426
+ interface PlanAudioEvent {
3427
+ kind: "audio";
3428
+ itemId: string;
3429
+ outStart: number;
3430
+ outEnd: number;
3431
+ audio: {
3432
+ kind: AudioItem["kind"];
3433
+ asset: {
3434
+ ref: string;
3435
+ };
3436
+ gainDb: number;
3437
+ duckToSpeech: boolean;
3438
+ fadeOutS?: number;
3439
+ };
3440
+ }
3441
+ type PlanEvent = PlanCaptionCueEvent | PlanOverlayEvent | PlanAudioEvent;
3442
+ interface Plan {
3443
+ version: 1;
3444
+ fromTimeline: string;
3445
+ timelineHash: string;
3446
+ outputDurationS: number;
3447
+ segments: PlanSegment[];
3448
+ events: PlanEvent[];
3449
+ uses: string[];
3450
+ boundaries: CutBoundary[];
3451
+ }
3452
+ interface CompileCtx {
3453
+ /** Parsed word-level Scribe transcripts by source name. */
3454
+ transcripts?: Record<string, ScribeTranscript | undefined>;
3455
+ /** "sha256:…" hash of each source's transcript file (anchor cache key). */
3456
+ transcriptHashes?: Record<string, string>;
3457
+ /** Amplitude silences by source (from ffmpeg silencedetect). When omitted,
3458
+ * the desilence pass sees no silences and keeps ranges as authored. */
3459
+ silencesBySource?: Record<string, SilenceInterval[]>;
3460
+ /** Word-token spans by source for intra-word split protection. Defaults to
3461
+ * spans derived from `transcripts`. */
3462
+ wordsBySource?: Record<string, SilenceInterval[]>;
3463
+ /** Set false to skip the desilence tighten pass entirely. Default true. */
3464
+ desilence?: boolean;
3465
+ /** Capability registry override (tests). */
3466
+ capabilities?: Record<string, Capability>;
3467
+ /** Existence of referenced asset files by ref (a stat pass gathered by the
3468
+ * caller — see gatherCompileCtx). A ref mapped to false fails compile with
3469
+ * "asset-missing"; refs absent from the map are not checked. */
3470
+ assetsPresent?: Record<string, boolean>;
3471
+ }
3472
+ interface CompileResult {
3473
+ ok: boolean;
3474
+ plan: Plan | null;
3475
+ legacyEdl: Edl | null;
3476
+ diagnostics: Diagnostics;
3477
+ uses: string[];
3478
+ }
3479
+ /** Deterministic content hash of the (defaults-applied) doc: sha256 over a
3480
+ * canonical (recursively key-sorted) JSON encoding. */
3481
+ declare function timelineHash(doc: TimelineV2): string;
3482
+ /** Compile an authored TimelineV2 into a render plan. Pure: never touches the
3483
+ * filesystem; the CLI layer (io.ts) gathers ctx and writes artifacts. */
3484
+ declare function compileTimeline(doc: TimelineV2, ctx?: CompileCtx): CompileResult;
3485
+
3486
+ interface TimelineFromEdlOptions {
3487
+ /** Timeline id; default "tl_<uuid>". */
3488
+ id?: string;
3489
+ /** Known source durations (seconds) by source name. */
3490
+ sourceDurations?: Record<string, number>;
3491
+ /** "sha256:…" transcript hashes by source name. */
3492
+ transcriptHashes?: Record<string, string>;
3493
+ }
3494
+ /** Lift a legacy EDL into a cut-only TimelineV2 document. */
3495
+ declare function timelineFromEdl(edl: Edl, opts?: TimelineFromEdlOptions): TimelineV2;
3496
+
3497
+ /** Vertical 9:16 master geometry — matches ensureVerticalMaster's output. */
3498
+ declare const COMPOSE_WIDTH: 1080;
3499
+ declare const COMPOSE_HEIGHT: 1920;
3500
+ /** Entry HTML file name inside the composition dir. */
3501
+ declare const COMPOSE_ENTRY: "index.html";
3502
+ /** Composition-relative media paths written by the `compose` verb. */
3503
+ declare const COMPOSE_VIDEO_SRC: "media/source.mp4";
3504
+ declare const COMPOSE_AUDIO_SRC: "media/audio.m4a";
3505
+ /** The subset of a compiled plan the composition needs. */
3506
+ type ComposePlan = Pick<Plan, "segments" | "events">;
3507
+ interface ComposeHtmlOptions {
3508
+ /** URL (composition-relative) of the proxy video. Default media/source.mp4. */
3509
+ videoSrc?: string;
3510
+ /** URL (composition-relative) of the CONTINUOUS cut audio — the ffmpeg-cut
3511
+ * track extracted from preview.mp4. Default media/audio.m4a. */
3512
+ audioSrc?: string;
3513
+ /** Declarative color grade (timeline settings.grade object form) — stamped
3514
+ * as data-color-grading on the base track-0 clips. */
3515
+ grade?: {
3516
+ preset: string;
3517
+ intensity?: number;
3518
+ };
3519
+ }
3520
+ /** Element counts as emitted by composeHtml (mirrors its skip rules). */
3521
+ interface ComposeCounts {
3522
+ segments: number;
3523
+ cues: number;
3524
+ zooms: number;
3525
+ overlays: number;
3526
+ }
3527
+ declare function composeCounts(plan: ComposePlan): ComposeCounts;
3528
+ /** Declarative HyperFrames composition markup — see module doc. Pure. */
3529
+ declare function composeHtml(plan: ComposePlan, options?: ComposeHtmlOptions): string;
3530
+
3531
+ declare function timelineJsonPath(jobDir: string): string;
3532
+ declare function planPath(jobDir: string): string;
3533
+ declare function diagnosticsPath(jobDir: string): string;
3534
+ interface LoadedTimeline {
3535
+ doc: TimelineV2 | null;
3536
+ errors: Diagnostic[];
3537
+ raw: unknown;
3538
+ }
3539
+ /** Read + parse <job>/timeline.json. */
3540
+ declare function loadTimeline(jobDir: string): LoadedTimeline;
3541
+ /** Transcript file for a source name. Mirrors silence.ts loadWordsBySource:
3542
+ * transcripts/<name>.json, else the lone transcripts/*.json (single-source
3543
+ * jobs name the transcript by source stem). */
3544
+ declare function transcriptFileForSource(jobDir: string, name: string): string | null;
3545
+ declare function sha256File(path: string): string;
3546
+ interface GatherOptions {
3547
+ /** Skip ffmpeg silence detection (ctx.silencesBySource stays undefined and
3548
+ * the compile desilence pass becomes a no-op tighten). */
3549
+ noDetect?: boolean;
3550
+ }
3551
+ /** Gather the impure CompileCtx inputs for a doc: per-source transcripts +
3552
+ * hashes, and (unless noDetect) ffmpeg silencedetect maps using the doc's
3553
+ * desilence settings — the same detection the legacy desilence flow runs. */
3554
+ declare function gatherCompileCtx(jobDir: string, doc: TimelineV2, opts?: GatherOptions): Promise<CompileCtx>;
3555
+ interface WrittenArtifacts {
3556
+ plan?: string;
3557
+ diagnostics: string;
3558
+ edl?: string;
3559
+ }
3560
+ /** Write resolved/plan.json + resolved/diagnostics.json (+ legacy edl.json on
3561
+ * success). diagnostics.json is always written, also for failed compiles. */
3562
+ declare function writeCompileArtifacts(jobDir: string, result: CompileResult): WrittenArtifacts;
3563
+ /** Update ONLY the captions block of timeline.json (enabled + preset), leaving
3564
+ * every other byte-level detail of the authored doc as-is. */
3565
+ declare function updateCaptionsBlock(jobDir: string, preset: string): {
3566
+ raw: Record<string, unknown>;
3567
+ };
3568
+
3569
+ export { type Anchor, type AudioItem, CAPABILITIES, COMPOSE_AUDIO_SRC, COMPOSE_ENTRY, COMPOSE_HEIGHT, COMPOSE_VIDEO_SRC, COMPOSE_WIDTH, type Capability, type CapabilityStatus, type CaptionOverride, CommandError, type CompileCtx, type CompileResult, type ComposeCounts, type ComposeHtmlOptions, type ComposePlan, type CutBoundary, type CutRange, DEFAULT_DESILENCE, DEFAULT_EDIT_ROOT, type DesilenceOptions, type DesilenceStats, type Diagnostic, type Diagnostics, type Edl, type EdlOverlay, type EdlRange, type FeatureKey, type FfprobeResult, type FfprobeStream, type OutputAnchor, type OverlayItem, PRESETS, type PhraseMatch, type PhraseSuggestion, type Plan, type PlanAudioEvent, type PlanCaptionCueEvent, type PlanCueWord, type PlanEvent, type PlanOverlayEvent, type PlanSegment, type PlanVideoOp, type PlanZoomOp, type Provenance, type RenderMode, type ResolveOutcome, type ReviewIssue, type ReviewJson, type ScribeTranscript, type ScribeWord, type SilenceInterval, type SourceAnchor, type SourceJson, type StreamWord, type TimelineFromEdlOptions, type TimelineSettings, type TimelineSource, type TimelineV2, type TokenType, VIDEO_EXTS, type VerifyJoinFinding, type VerifyResult, type Warning, type WordsAnchor, type ZoomItem, agentizePrompt, artifactPaths, autoGradeForClip, checkCapabilities, compileTimeline, composeCounts, composeHtml, computeEnvelope, configDir, configEnvPath, cutBoundaries, decideGradeFilter, defaultJobDir, desilenceEdl, detectSilences, diagnosticsPath, displayedDimensions, duplicatedPhrase, duplicatedPhrases, duplicatedSpans, edlPath, ensureTranscribed, ensureVerticalMaster, ffprobe, findPhrase, fuzzySuggestions, gatherCompileCtx, generateQcImages, getPreset, initJob, isoNow, learnedEditingGuardrails, loadApiKey, loadJob, loadTimeline, loadWords, loadWordsBySource, mediaDuration, normalizePhrase, normalizeToken, packTranscripts, parseSilenceDetect, parseTimeline, planPath, pyFixed, pyFixedPad, pyRound, pySpacePad, readEdl, render, requireFfmpeg, resolveJob, resolvePhrase, rotationDegrees, run, runSync, screenTakes, sha256File, shown, silenceDetectArgs, slugify, sourceFromJob, statusPayload, straddlingGap, tightenRange, tightenRanges, timelineFromEdl, timelineHash, timelineJsonPath, timelineV2Schema, timelineView, transcribeBatch, transcribeOne, transcriptFileForSource, transcriptPath, updateCaptionsBlock, usesFromDoc, validateTimeline, verify, videoStream, wordStream, writeAgentManifest, writeBoundaries, writeCompileArtifacts, writeCoverage, writeSilencePrompt, writeTranscriptArtifacts, writeVideoEditingPrompt, writeWarningsFromReview, writeWordDump };