-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtransition.ts
More file actions
70 lines (65 loc) · 2 KB
/
Copy pathtransition.ts
File metadata and controls
70 lines (65 loc) · 2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* Subset of ffmpeg's `xfade` transition kinds. Chosen to cover the common
* consumer-editor transition palette without overwhelming the agent with 40+
* obscure options. Each one maps 1:1 to an `xfade` `transition=<name>` value.
*/
export type TransitionKind =
| 'fade'
| 'fadeblack'
| 'fadewhite'
| 'dissolve'
| 'wipeleft'
| 'wiperight'
| 'wipeup'
| 'wipedown'
| 'slideleft'
| 'slideright'
| 'circleopen'
| 'circleclose';
export interface TransitionArgs {
inputA: string;
inputB: string;
output: string;
kind: TransitionKind;
/** How long the transition takes (seconds). */
durationSec: number;
/** When the transition starts in clip A (seconds). Usually `durationA - durationSec`. */
offsetSec: number;
/**
* Whether both inputs have audio streams. When true we wire an
* `acrossfade` alongside the video xfade; when false we drop audio
* entirely from the output. Mixed-audio inputs are explicitly out of
* scope for v0 — surface the constraint at the tool layer.
*/
hasAudio: boolean;
}
export function buildTransitionArgs(args: TransitionArgs): string[] {
const { inputA, inputB, output, kind, durationSec, offsetSec, hasAudio } = args;
const videoFilter = `[0:v][1:v]xfade=transition=${kind}:duration=${durationSec}:offset=${offsetSec}[v]`;
const audioFilter = hasAudio ? `;[0:a][1:a]acrossfade=d=${durationSec}[a]` : '';
const filterComplex = `${videoFilter}${audioFilter}`;
const mappings = hasAudio ? ['-map', '[v]', '-map', '[a]'] : ['-map', '[v]'];
// Re-encoding is unavoidable for xfade (it blends frames). Audio is
// re-encoded too when acrossfade is in play. libx264 + aac are the safe
// defaults; -pix_fmt yuv420p ensures broad player compatibility.
return [
'-y',
'-i',
inputA,
'-i',
inputB,
'-filter_complex',
filterComplex,
...mappings,
'-c:v',
'libx264',
'-preset',
'fast',
'-crf',
'23',
'-pix_fmt',
'yuv420p',
...(hasAudio ? ['-c:a', 'aac'] : []),
output,
];
}