venice-video-harness 2.4.0

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.
Files changed (264) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +598 -0
  4. package/dist/assembly/manifest-builder.d.ts +8 -0
  5. package/dist/assembly/manifest-builder.d.ts.map +1 -0
  6. package/dist/assembly/manifest-builder.js +196 -0
  7. package/dist/assembly/manifest-builder.js.map +1 -0
  8. package/dist/assembly/remotion-scaffold.d.ts +14 -0
  9. package/dist/assembly/remotion-scaffold.d.ts.map +1 -0
  10. package/dist/assembly/remotion-scaffold.js +292 -0
  11. package/dist/assembly/remotion-scaffold.js.map +1 -0
  12. package/dist/assembly/types.d.ts +67 -0
  13. package/dist/assembly/types.d.ts.map +1 -0
  14. package/dist/assembly/types.js +5 -0
  15. package/dist/assembly/types.js.map +1 -0
  16. package/dist/characters/describer.d.ts +32 -0
  17. package/dist/characters/describer.d.ts.map +1 -0
  18. package/dist/characters/describer.js +309 -0
  19. package/dist/characters/describer.js.map +1 -0
  20. package/dist/characters/extractor.d.ts +27 -0
  21. package/dist/characters/extractor.d.ts.map +1 -0
  22. package/dist/characters/extractor.js +274 -0
  23. package/dist/characters/extractor.js.map +1 -0
  24. package/dist/characters/reference-manager.d.ts +95 -0
  25. package/dist/characters/reference-manager.d.ts.map +1 -0
  26. package/dist/characters/reference-manager.js +346 -0
  27. package/dist/characters/reference-manager.js.map +1 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +310 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/config.d.ts +22 -0
  33. package/dist/config.d.ts.map +1 -0
  34. package/dist/config.js +66 -0
  35. package/dist/config.js.map +1 -0
  36. package/dist/editing/aligner.d.ts +44 -0
  37. package/dist/editing/aligner.d.ts.map +1 -0
  38. package/dist/editing/aligner.js +201 -0
  39. package/dist/editing/aligner.js.map +1 -0
  40. package/dist/editing/edl.d.ts +45 -0
  41. package/dist/editing/edl.d.ts.map +1 -0
  42. package/dist/editing/edl.js +133 -0
  43. package/dist/editing/edl.js.map +1 -0
  44. package/dist/editing/overlays.d.ts +97 -0
  45. package/dist/editing/overlays.d.ts.map +1 -0
  46. package/dist/editing/overlays.js +41 -0
  47. package/dist/editing/overlays.js.map +1 -0
  48. package/dist/editing/packer.d.ts +52 -0
  49. package/dist/editing/packer.d.ts.map +1 -0
  50. package/dist/editing/packer.js +170 -0
  51. package/dist/editing/packer.js.map +1 -0
  52. package/dist/editing/providers/whisper-cpp.d.ts +32 -0
  53. package/dist/editing/providers/whisper-cpp.d.ts.map +1 -0
  54. package/dist/editing/providers/whisper-cpp.js +239 -0
  55. package/dist/editing/providers/whisper-cpp.js.map +1 -0
  56. package/dist/editing/render.d.ts +36 -0
  57. package/dist/editing/render.d.ts.map +1 -0
  58. package/dist/editing/render.js +227 -0
  59. package/dist/editing/render.js.map +1 -0
  60. package/dist/editing/self-eval.d.ts +48 -0
  61. package/dist/editing/self-eval.d.ts.map +1 -0
  62. package/dist/editing/self-eval.js +293 -0
  63. package/dist/editing/self-eval.js.map +1 -0
  64. package/dist/editing/silence.d.ts +76 -0
  65. package/dist/editing/silence.d.ts.map +1 -0
  66. package/dist/editing/silence.js +189 -0
  67. package/dist/editing/silence.js.map +1 -0
  68. package/dist/editing/types.d.ts +178 -0
  69. package/dist/editing/types.d.ts.map +1 -0
  70. package/dist/editing/types.js +13 -0
  71. package/dist/editing/types.js.map +1 -0
  72. package/dist/index.d.ts +6 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +5 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/interactive.d.ts +12 -0
  77. package/dist/interactive.d.ts.map +1 -0
  78. package/dist/interactive.js +78 -0
  79. package/dist/interactive.js.map +1 -0
  80. package/dist/mini-drama/assembler.d.ts +61 -0
  81. package/dist/mini-drama/assembler.d.ts.map +1 -0
  82. package/dist/mini-drama/assembler.js +466 -0
  83. package/dist/mini-drama/assembler.js.map +1 -0
  84. package/dist/mini-drama/audio-mix.d.ts +65 -0
  85. package/dist/mini-drama/audio-mix.d.ts.map +1 -0
  86. package/dist/mini-drama/audio-mix.js +118 -0
  87. package/dist/mini-drama/audio-mix.js.map +1 -0
  88. package/dist/mini-drama/cli.d.ts +3 -0
  89. package/dist/mini-drama/cli.d.ts.map +1 -0
  90. package/dist/mini-drama/cli.js +2869 -0
  91. package/dist/mini-drama/cli.js.map +1 -0
  92. package/dist/mini-drama/fcpxml-export.d.ts +2 -0
  93. package/dist/mini-drama/fcpxml-export.d.ts.map +1 -0
  94. package/dist/mini-drama/fcpxml-export.js +5 -0
  95. package/dist/mini-drama/fcpxml-export.js.map +1 -0
  96. package/dist/mini-drama/generation-planner.d.ts +24 -0
  97. package/dist/mini-drama/generation-planner.d.ts.map +1 -0
  98. package/dist/mini-drama/generation-planner.js +304 -0
  99. package/dist/mini-drama/generation-planner.js.map +1 -0
  100. package/dist/mini-drama/location-generator.d.ts +23 -0
  101. package/dist/mini-drama/location-generator.d.ts.map +1 -0
  102. package/dist/mini-drama/location-generator.js +144 -0
  103. package/dist/mini-drama/location-generator.js.map +1 -0
  104. package/dist/mini-drama/music-cues.d.ts +96 -0
  105. package/dist/mini-drama/music-cues.d.ts.map +1 -0
  106. package/dist/mini-drama/music-cues.js +332 -0
  107. package/dist/mini-drama/music-cues.js.map +1 -0
  108. package/dist/mini-drama/panel-fixer.d.ts +12 -0
  109. package/dist/mini-drama/panel-fixer.d.ts.map +1 -0
  110. package/dist/mini-drama/panel-fixer.js +319 -0
  111. package/dist/mini-drama/panel-fixer.js.map +1 -0
  112. package/dist/mini-drama/prompt-builder.d.ts +149 -0
  113. package/dist/mini-drama/prompt-builder.d.ts.map +1 -0
  114. package/dist/mini-drama/prompt-builder.js +722 -0
  115. package/dist/mini-drama/prompt-builder.js.map +1 -0
  116. package/dist/mini-drama/reference-slots.d.ts +31 -0
  117. package/dist/mini-drama/reference-slots.d.ts.map +1 -0
  118. package/dist/mini-drama/reference-slots.js +161 -0
  119. package/dist/mini-drama/reference-slots.js.map +1 -0
  120. package/dist/mini-drama/shot-paths.d.ts +77 -0
  121. package/dist/mini-drama/shot-paths.d.ts.map +1 -0
  122. package/dist/mini-drama/shot-paths.js +101 -0
  123. package/dist/mini-drama/shot-paths.js.map +1 -0
  124. package/dist/mini-drama/storyboard-reference-generator.d.ts +47 -0
  125. package/dist/mini-drama/storyboard-reference-generator.d.ts.map +1 -0
  126. package/dist/mini-drama/storyboard-reference-generator.js +293 -0
  127. package/dist/mini-drama/storyboard-reference-generator.js.map +1 -0
  128. package/dist/mini-drama/subtitle-generator.d.ts +12 -0
  129. package/dist/mini-drama/subtitle-generator.d.ts.map +1 -0
  130. package/dist/mini-drama/subtitle-generator.js +139 -0
  131. package/dist/mini-drama/subtitle-generator.js.map +1 -0
  132. package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts +3 -0
  133. package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts.map +1 -0
  134. package/dist/mini-drama/timeline-export/davinci-fcpxml.js +150 -0
  135. package/dist/mini-drama/timeline-export/davinci-fcpxml.js.map +1 -0
  136. package/dist/mini-drama/timeline-export/fcpxml.d.ts +11 -0
  137. package/dist/mini-drama/timeline-export/fcpxml.d.ts.map +1 -0
  138. package/dist/mini-drama/timeline-export/fcpxml.js +140 -0
  139. package/dist/mini-drama/timeline-export/fcpxml.js.map +1 -0
  140. package/dist/mini-drama/timeline-export/index.d.ts +13 -0
  141. package/dist/mini-drama/timeline-export/index.d.ts.map +1 -0
  142. package/dist/mini-drama/timeline-export/index.js +26 -0
  143. package/dist/mini-drama/timeline-export/index.js.map +1 -0
  144. package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts +3 -0
  145. package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts.map +1 -0
  146. package/dist/mini-drama/timeline-export/premiere-xmeml.js +211 -0
  147. package/dist/mini-drama/timeline-export/premiere-xmeml.js.map +1 -0
  148. package/dist/mini-drama/timeline-export/probe.d.ts +53 -0
  149. package/dist/mini-drama/timeline-export/probe.d.ts.map +1 -0
  150. package/dist/mini-drama/timeline-export/probe.js +89 -0
  151. package/dist/mini-drama/timeline-export/probe.js.map +1 -0
  152. package/dist/mini-drama/timeline-export/types.d.ts +57 -0
  153. package/dist/mini-drama/timeline-export/types.d.ts.map +1 -0
  154. package/dist/mini-drama/timeline-export/types.js +14 -0
  155. package/dist/mini-drama/timeline-export/types.js.map +1 -0
  156. package/dist/mini-drama/video-generator.d.ts +22 -0
  157. package/dist/mini-drama/video-generator.d.ts.map +1 -0
  158. package/dist/mini-drama/video-generator.js +1305 -0
  159. package/dist/mini-drama/video-generator.js.map +1 -0
  160. package/dist/mini-drama/voice-reference.d.ts +42 -0
  161. package/dist/mini-drama/voice-reference.d.ts.map +1 -0
  162. package/dist/mini-drama/voice-reference.js +170 -0
  163. package/dist/mini-drama/voice-reference.js.map +1 -0
  164. package/dist/output/html-renderer.d.ts +2 -0
  165. package/dist/output/html-renderer.d.ts.map +1 -0
  166. package/dist/output/html-renderer.js +37 -0
  167. package/dist/output/html-renderer.js.map +1 -0
  168. package/dist/parsers/fountain-parser.d.ts +34 -0
  169. package/dist/parsers/fountain-parser.d.ts.map +1 -0
  170. package/dist/parsers/fountain-parser.js +71 -0
  171. package/dist/parsers/fountain-parser.js.map +1 -0
  172. package/dist/parsers/pdf-parser.d.ts +24 -0
  173. package/dist/parsers/pdf-parser.d.ts.map +1 -0
  174. package/dist/parsers/pdf-parser.js +237 -0
  175. package/dist/parsers/pdf-parser.js.map +1 -0
  176. package/dist/parsers/scene-extractor.d.ts +41 -0
  177. package/dist/parsers/scene-extractor.d.ts.map +1 -0
  178. package/dist/parsers/scene-extractor.js +400 -0
  179. package/dist/parsers/scene-extractor.js.map +1 -0
  180. package/dist/series/manager.d.ts +64 -0
  181. package/dist/series/manager.d.ts.map +1 -0
  182. package/dist/series/manager.js +282 -0
  183. package/dist/series/manager.js.map +1 -0
  184. package/dist/series/types.d.ts +641 -0
  185. package/dist/series/types.d.ts.map +1 -0
  186. package/dist/series/types.js +304 -0
  187. package/dist/series/types.js.map +1 -0
  188. package/dist/storyboard/assembler.d.ts +134 -0
  189. package/dist/storyboard/assembler.d.ts.map +1 -0
  190. package/dist/storyboard/assembler.js +319 -0
  191. package/dist/storyboard/assembler.js.map +1 -0
  192. package/dist/storyboard/prompt-builder.d.ts +113 -0
  193. package/dist/storyboard/prompt-builder.d.ts.map +1 -0
  194. package/dist/storyboard/prompt-builder.js +578 -0
  195. package/dist/storyboard/prompt-builder.js.map +1 -0
  196. package/dist/storyboard/shot-planner.d.ts +34 -0
  197. package/dist/storyboard/shot-planner.d.ts.map +1 -0
  198. package/dist/storyboard/shot-planner.js +446 -0
  199. package/dist/storyboard/shot-planner.js.map +1 -0
  200. package/dist/user-config.d.ts +15 -0
  201. package/dist/user-config.d.ts.map +1 -0
  202. package/dist/user-config.js +103 -0
  203. package/dist/user-config.js.map +1 -0
  204. package/dist/venice/audio-preflight.d.ts +80 -0
  205. package/dist/venice/audio-preflight.d.ts.map +1 -0
  206. package/dist/venice/audio-preflight.js +142 -0
  207. package/dist/venice/audio-preflight.js.map +1 -0
  208. package/dist/venice/audio.d.ts +88 -0
  209. package/dist/venice/audio.d.ts.map +1 -0
  210. package/dist/venice/audio.js +234 -0
  211. package/dist/venice/audio.js.map +1 -0
  212. package/dist/venice/client.d.ts +86 -0
  213. package/dist/venice/client.d.ts.map +1 -0
  214. package/dist/venice/client.js +375 -0
  215. package/dist/venice/client.js.map +1 -0
  216. package/dist/venice/edit.d.ts +57 -0
  217. package/dist/venice/edit.d.ts.map +1 -0
  218. package/dist/venice/edit.js +100 -0
  219. package/dist/venice/edit.js.map +1 -0
  220. package/dist/venice/generate.d.ts +47 -0
  221. package/dist/venice/generate.d.ts.map +1 -0
  222. package/dist/venice/generate.js +150 -0
  223. package/dist/venice/generate.js.map +1 -0
  224. package/dist/venice/image-bytes.d.ts +26 -0
  225. package/dist/venice/image-bytes.d.ts.map +1 -0
  226. package/dist/venice/image-bytes.js +101 -0
  227. package/dist/venice/image-bytes.js.map +1 -0
  228. package/dist/venice/models.d.ts +143 -0
  229. package/dist/venice/models.d.ts.map +1 -0
  230. package/dist/venice/models.js +984 -0
  231. package/dist/venice/models.js.map +1 -0
  232. package/dist/venice/multi-edit.d.ts +40 -0
  233. package/dist/venice/multi-edit.d.ts.map +1 -0
  234. package/dist/venice/multi-edit.js +97 -0
  235. package/dist/venice/multi-edit.js.map +1 -0
  236. package/dist/venice/provenance.d.ts +66 -0
  237. package/dist/venice/provenance.d.ts.map +1 -0
  238. package/dist/venice/provenance.js +151 -0
  239. package/dist/venice/provenance.js.map +1 -0
  240. package/dist/venice/recipe.d.ts +69 -0
  241. package/dist/venice/recipe.d.ts.map +1 -0
  242. package/dist/venice/recipe.js +103 -0
  243. package/dist/venice/recipe.js.map +1 -0
  244. package/dist/venice/rejection.d.ts +63 -0
  245. package/dist/venice/rejection.d.ts.map +1 -0
  246. package/dist/venice/rejection.js +111 -0
  247. package/dist/venice/rejection.js.map +1 -0
  248. package/dist/venice/seedance-preflight.d.ts +38 -0
  249. package/dist/venice/seedance-preflight.d.ts.map +1 -0
  250. package/dist/venice/seedance-preflight.js +29 -0
  251. package/dist/venice/seedance-preflight.js.map +1 -0
  252. package/dist/venice/types.d.ts +212 -0
  253. package/dist/venice/types.d.ts.map +1 -0
  254. package/dist/venice/types.js +9 -0
  255. package/dist/venice/types.js.map +1 -0
  256. package/dist/venice/video.d.ts +77 -0
  257. package/dist/venice/video.d.ts.map +1 -0
  258. package/dist/venice/video.js +163 -0
  259. package/dist/venice/video.js.map +1 -0
  260. package/dist/venice/voices.d.ts +40 -0
  261. package/dist/venice/voices.d.ts.map +1 -0
  262. package/dist/venice/voices.js +194 -0
  263. package/dist/venice/voices.js.map +1 -0
  264. package/package.json +79 -0
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Builds a shot manifest by scanning scene directories for MP4s,
3
+ * running ffprobe for timing data, and reading video.json for metadata.
4
+ */
5
+ import { readdir, readFile } from 'node:fs/promises';
6
+ import { join, resolve } from 'node:path';
7
+ import { existsSync } from 'node:fs';
8
+ import { execSync } from 'node:child_process';
9
+ const DEFAULT_FPS = 30;
10
+ const DEFAULT_WIDTH = 1280;
11
+ const DEFAULT_HEIGHT = 720;
12
+ /** Map screenplay transition strings to our TransitionType */
13
+ function parseTransition(raw) {
14
+ if (!raw)
15
+ return 'cut';
16
+ const t = raw.toUpperCase().trim();
17
+ if (t.includes('DISSOLVE'))
18
+ return 'dissolve';
19
+ if (t.includes('FADE'))
20
+ return 'fade';
21
+ if (t.includes('WIPE'))
22
+ return 'wipe';
23
+ return 'cut';
24
+ }
25
+ /** Get transition duration in frames based on type */
26
+ function transitionFrames(type, fps) {
27
+ switch (type) {
28
+ case 'cut': return 1;
29
+ case 'fade': return Math.round(fps * 0.5); // 0.5s
30
+ case 'dissolve': return Math.round(fps * 0.75); // 0.75s
31
+ case 'wipe': return Math.round(fps * 0.5);
32
+ default: return 1;
33
+ }
34
+ }
35
+ /** Run ffprobe on an MP4 to get duration, fps, and dimensions */
36
+ function probeVideo(filePath) {
37
+ try {
38
+ const raw = execSync(`ffprobe -v quiet -print_format json -show_format -show_streams -select_streams v "${filePath}"`, { encoding: 'utf-8', timeout: 10000 });
39
+ const data = JSON.parse(raw);
40
+ const stream = data.streams?.[0] ?? {};
41
+ const format = data.format ?? {};
42
+ const duration = parseFloat(format.duration || stream.duration || '0');
43
+ // Parse fps from r_frame_rate (e.g. "24/1")
44
+ let fps = DEFAULT_FPS;
45
+ if (stream.r_frame_rate) {
46
+ const [num, den] = stream.r_frame_rate.split('/').map(Number);
47
+ if (den && den > 0)
48
+ fps = num / den;
49
+ }
50
+ return {
51
+ duration,
52
+ fps,
53
+ width: stream.width || DEFAULT_WIDTH,
54
+ height: stream.height || DEFAULT_HEIGHT,
55
+ };
56
+ }
57
+ catch (err) {
58
+ console.warn(` ffprobe failed for ${filePath}, using defaults`);
59
+ return { duration: 8, fps: DEFAULT_FPS, width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT };
60
+ }
61
+ }
62
+ /** Read video.json metadata for a shot */
63
+ async function readVideoJson(jsonPath) {
64
+ if (!existsSync(jsonPath))
65
+ return null;
66
+ try {
67
+ const raw = await readFile(jsonPath, 'utf-8');
68
+ return JSON.parse(raw);
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ /** Find all scene directories sorted numerically */
75
+ async function findSceneDirs(projectDir) {
76
+ const entries = await readdir(projectDir, { withFileTypes: true });
77
+ const sceneDirs = [];
78
+ for (const entry of entries) {
79
+ if (!entry.isDirectory())
80
+ continue;
81
+ const match = entry.name.match(/^scene-(\d+)$/);
82
+ if (match) {
83
+ sceneDirs.push({
84
+ dir: join(projectDir, entry.name),
85
+ num: parseInt(match[1], 10),
86
+ });
87
+ }
88
+ }
89
+ return sceneDirs.sort((a, b) => a.num - b.num);
90
+ }
91
+ /** Find all shot MP4s in a scene directory, sorted by shot number */
92
+ async function findShotMp4s(sceneDir) {
93
+ const entries = await readdir(sceneDir);
94
+ const shots = [];
95
+ for (const entry of entries) {
96
+ const match = entry.match(/^shot-(\d+)\.mp4$/);
97
+ if (match) {
98
+ shots.push({
99
+ path: join(sceneDir, entry),
100
+ num: parseInt(match[1], 10),
101
+ });
102
+ }
103
+ }
104
+ return shots.sort((a, b) => a.num - b.num);
105
+ }
106
+ export async function buildManifest(project) {
107
+ const targetFps = DEFAULT_FPS;
108
+ const projectDir = resolve(project.outputDir);
109
+ console.log(`Scanning ${projectDir} for scene directories...`);
110
+ const sceneDirs = await findSceneDirs(projectDir);
111
+ if (sceneDirs.length === 0) {
112
+ throw new Error('No scene directories found. Run storyboard generation first.');
113
+ }
114
+ console.log(`Found ${sceneDirs.length} scene(s)`);
115
+ const scenes = [];
116
+ let totalShots = 0;
117
+ for (const { dir: sceneDir, num: sceneNum } of sceneDirs) {
118
+ const mp4s = await findShotMp4s(sceneDir);
119
+ if (mp4s.length === 0) {
120
+ console.log(` Scene ${sceneNum}: no MP4s found, skipping`);
121
+ continue;
122
+ }
123
+ console.log(` Scene ${sceneNum}: ${mp4s.length} shots`);
124
+ // Find the scene data from project state for heading/mood
125
+ const sceneData = project.scenes.find(s => s.number === sceneNum);
126
+ const shots = [];
127
+ for (const mp4 of mp4s) {
128
+ const probe = probeVideo(mp4.path);
129
+ const videoJsonPath = mp4.path.replace(/\.mp4$/, '.video.json');
130
+ const videoMeta = await readVideoJson(videoJsonPath);
131
+ const transition = parseTransition(videoMeta?.transition);
132
+ const durationInFrames = Math.round(probe.duration * targetFps);
133
+ // Build relative path for Remotion public/ dir
134
+ const sceneFolder = `scene-${String(sceneNum).padStart(3, '0')}`;
135
+ const shotFile = `shot-${String(mp4.num).padStart(3, '0')}.mp4`;
136
+ const relativePath = `${sceneFolder}/${shotFile}`;
137
+ shots.push({
138
+ file: relativePath,
139
+ absolutePath: mp4.path,
140
+ sceneNumber: sceneNum,
141
+ shotNumber: mp4.num,
142
+ panelId: videoMeta?.panelId || `S${sceneNum}-P${mp4.num}`,
143
+ durationSec: probe.duration,
144
+ durationInFrames,
145
+ fps: probe.fps,
146
+ width: probe.width,
147
+ height: probe.height,
148
+ transition,
149
+ transitionDurationInFrames: transitionFrames(transition, targetFps),
150
+ characters: videoMeta?.characters || [],
151
+ dialogue: videoMeta?.dialogue,
152
+ cameraMovement: videoMeta?.cameraMovement || '',
153
+ mood: sceneData?.mood,
154
+ });
155
+ totalShots++;
156
+ }
157
+ // Calculate scene duration (sum of shots minus transition overlaps)
158
+ const shotFrames = shots.reduce((sum, s) => sum + s.durationInFrames, 0);
159
+ // Transitions between shots (not before first shot)
160
+ const transitionOverlap = shots
161
+ .slice(1)
162
+ .reduce((sum, s) => sum + s.transitionDurationInFrames, 0);
163
+ const sceneDurationFrames = shotFrames - transitionOverlap;
164
+ scenes.push({
165
+ sceneNumber: sceneNum,
166
+ heading: sceneData?.heading || `Scene ${sceneNum}`,
167
+ mood: sceneData?.mood || 'neutral',
168
+ shots,
169
+ durationInFrames: sceneDurationFrames,
170
+ durationSec: sceneDurationFrames / targetFps,
171
+ });
172
+ }
173
+ // Total duration: sum of all scene durations plus scene-to-scene transitions
174
+ // Between scenes, we use a 1-second fade
175
+ const sceneTransitionFrames = Math.round(targetFps * 1); // 1s between scenes
176
+ const totalSceneFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
177
+ const totalSceneTransitions = Math.max(0, scenes.length - 1) * sceneTransitionFrames;
178
+ const totalDurationInFrames = totalSceneFrames - totalSceneTransitions;
179
+ const manifest = {
180
+ projectName: project.name,
181
+ targetFps,
182
+ targetWidth: DEFAULT_WIDTH,
183
+ targetHeight: DEFAULT_HEIGHT,
184
+ scenes,
185
+ totalDurationInFrames,
186
+ totalDurationSec: totalDurationInFrames / targetFps,
187
+ totalShots,
188
+ createdAt: new Date().toISOString(),
189
+ };
190
+ console.log(`\nManifest built:`);
191
+ console.log(` Scenes: ${scenes.length}`);
192
+ console.log(` Total shots: ${totalShots}`);
193
+ console.log(` Total duration: ${manifest.totalDurationSec.toFixed(1)}s (${totalDurationInFrames} frames @ ${targetFps}fps)`);
194
+ return manifest;
195
+ }
196
+ //# sourceMappingURL=manifest-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-builder.js","sourceRoot":"","sources":["../../src/assembly/manifest-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Scaffolds a complete Remotion project inside the project's output directory.
3
+ * Generates package.json, tsconfig, and all React components from the manifest.
4
+ */
5
+ import type { ShotManifest } from './types.js';
6
+ export interface ScaffoldResult {
7
+ remotionDir: string;
8
+ manifestPath: string;
9
+ entryPoint: string;
10
+ /** The directory to pass as --public-dir (the project output dir with real MP4s) */
11
+ publicDir: string;
12
+ }
13
+ export declare function scaffoldRemotionProject(projectOutputDir: string, manifest: ShotManifest): Promise<ScaffoldResult>;
14
+ //# sourceMappingURL=remotion-scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remotion-scaffold.d.ts","sourceRoot":"","sources":["../../src/assembly/remotion-scaffold.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAoC,MAAM,YAAY,CAAC;AAEjF,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;CACnB;AASD,wBAAsB,uBAAuB,CAC3C,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,CAkCzB"}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Scaffolds a complete Remotion project inside the project's output directory.
3
+ * Generates package.json, tsconfig, and all React components from the manifest.
4
+ */
5
+ import { writeFile, mkdir } from 'node:fs/promises';
6
+ import { join, resolve } from 'node:path';
7
+ import { existsSync } from 'node:fs';
8
+ /** Ensure a directory exists */
9
+ async function ensureDir(dir) {
10
+ if (!existsSync(dir)) {
11
+ await mkdir(dir, { recursive: true });
12
+ }
13
+ }
14
+ export async function scaffoldRemotionProject(projectOutputDir, manifest) {
15
+ const remotionDir = join(projectOutputDir, 'remotion');
16
+ const srcDir = join(remotionDir, 'src');
17
+ // Use the project output dir itself as the public dir --
18
+ // it already contains scene-NNN/shot-NNN.mp4 files in the right structure.
19
+ // Remotion's --public-dir flag will point here.
20
+ const publicDir = resolve(projectOutputDir);
21
+ console.log(`\nScaffolding Remotion project at ${remotionDir}`);
22
+ // Create directory structure
23
+ await ensureDir(srcDir);
24
+ // Write manifest
25
+ const manifestPath = join(remotionDir, 'shot-manifest.json');
26
+ await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
27
+ console.log('Wrote shot-manifest.json');
28
+ // Write all project files
29
+ await writeFile(join(remotionDir, 'package.json'), generatePackageJson(manifest));
30
+ await writeFile(join(remotionDir, 'tsconfig.json'), generateTsConfig());
31
+ await writeFile(join(srcDir, 'index.ts'), generateEntryPoint());
32
+ await writeFile(join(srcDir, 'Root.tsx'), generateRoot(manifest));
33
+ await writeFile(join(srcDir, 'Film.tsx'), generateFilm());
34
+ await writeFile(join(srcDir, 'Scene.tsx'), generateScene());
35
+ await writeFile(join(srcDir, 'types.ts'), generateClientTypes());
36
+ console.log('Wrote Remotion source files');
37
+ return {
38
+ remotionDir,
39
+ manifestPath,
40
+ entryPoint: join(srcDir, 'index.ts'),
41
+ publicDir,
42
+ };
43
+ }
44
+ // ── File generators ──────────────────────────────────────────────────
45
+ function generatePackageJson(manifest) {
46
+ const pkg = {
47
+ name: `${manifest.projectName}-remotion`,
48
+ version: '1.0.0',
49
+ private: true,
50
+ type: 'module',
51
+ scripts: {
52
+ preview: 'npx remotion preview src/index.ts',
53
+ render: `npx remotion render src/index.ts Film --codec=h264 --crf=18`,
54
+ 'render:scene': 'echo "Usage: npm run render:scene -- SceneN"',
55
+ },
56
+ dependencies: {
57
+ '@remotion/cli': '^4.0.0',
58
+ '@remotion/transitions': '^4.0.0',
59
+ '@remotion/renderer': '^4.0.0',
60
+ '@remotion/bundler': '^4.0.0',
61
+ react: '^18.3.0',
62
+ 'react-dom': '^18.3.0',
63
+ remotion: '^4.0.0',
64
+ },
65
+ devDependencies: {
66
+ '@types/react': '^18.3.0',
67
+ typescript: '^5.7.0',
68
+ },
69
+ };
70
+ return JSON.stringify(pkg, null, 2) + '\n';
71
+ }
72
+ function generateTsConfig() {
73
+ const config = {
74
+ compilerOptions: {
75
+ target: 'ES2022',
76
+ module: 'preserve',
77
+ moduleResolution: 'bundler',
78
+ jsx: 'react-jsx',
79
+ strict: true,
80
+ esModuleInterop: true,
81
+ skipLibCheck: true,
82
+ resolveJsonModule: true,
83
+ outDir: 'dist',
84
+ },
85
+ include: ['src/**/*'],
86
+ };
87
+ return JSON.stringify(config, null, 2) + '\n';
88
+ }
89
+ function generateEntryPoint() {
90
+ return `import { registerRoot } from "remotion";
91
+ import { RemotionRoot } from "./Root";
92
+
93
+ registerRoot(RemotionRoot);
94
+ `;
95
+ }
96
+ function generateRoot(manifest) {
97
+ // Build per-scene compositions + full film composition
98
+ const sceneComps = manifest.scenes
99
+ .map((scene) => {
100
+ const id = `Scene${scene.sceneNumber}`;
101
+ return ` <Composition
102
+ id="${id}"
103
+ component={Film}
104
+ durationInFrames={${scene.durationInFrames}}
105
+ fps={${manifest.targetFps}}
106
+ width={${manifest.targetWidth}}
107
+ height={${manifest.targetHeight}}
108
+ defaultProps={{
109
+ scenes: manifest.scenes.filter((s) => s.sceneNumber === ${scene.sceneNumber}),
110
+ fps: ${manifest.targetFps},
111
+ sceneTransitionFrames: SCENE_TRANSITION_FRAMES,
112
+ }}
113
+ />`;
114
+ })
115
+ .join('\n');
116
+ return `import React from "react";
117
+ import { Composition } from "remotion";
118
+ import { Film } from "./Film";
119
+ import manifest from "../shot-manifest.json";
120
+ import type { ShotManifest } from "./types";
121
+
122
+ const typedManifest = manifest as unknown as ShotManifest;
123
+ const SCENE_TRANSITION_FRAMES = ${manifest.targetFps}; // 1s between scenes
124
+
125
+ export const RemotionRoot: React.FC = () => {
126
+ return (
127
+ <>
128
+ <Composition
129
+ id="Film"
130
+ component={Film}
131
+ durationInFrames={${manifest.totalDurationInFrames}}
132
+ fps={${manifest.targetFps}}
133
+ width={${manifest.targetWidth}}
134
+ height={${manifest.targetHeight}}
135
+ defaultProps={{
136
+ scenes: typedManifest.scenes,
137
+ fps: ${manifest.targetFps},
138
+ sceneTransitionFrames: SCENE_TRANSITION_FRAMES,
139
+ }}
140
+ />
141
+ ${sceneComps}
142
+ </>
143
+ );
144
+ };
145
+ `;
146
+ }
147
+ function generateFilm() {
148
+ return `import React from "react";
149
+ import { TransitionSeries, linearTiming } from "@remotion/transitions";
150
+ import { fade } from "@remotion/transitions/fade";
151
+ import { Scene } from "./Scene";
152
+ import type { SceneManifest } from "./types";
153
+
154
+ interface FilmProps {
155
+ scenes: SceneManifest[];
156
+ fps: number;
157
+ sceneTransitionFrames: number;
158
+ }
159
+
160
+ export const Film: React.FC<FilmProps> = ({
161
+ scenes,
162
+ fps,
163
+ sceneTransitionFrames,
164
+ }) => {
165
+ return (
166
+ <TransitionSeries>
167
+ {scenes.map((scene, i) => (
168
+ <React.Fragment key={scene.sceneNumber}>
169
+ <TransitionSeries.Sequence durationInFrames={scene.durationInFrames}>
170
+ <Scene scene={scene} fps={fps} />
171
+ </TransitionSeries.Sequence>
172
+ {i < scenes.length - 1 && (
173
+ <TransitionSeries.Transition
174
+ presentation={fade()}
175
+ timing={linearTiming({
176
+ durationInFrames: sceneTransitionFrames,
177
+ })}
178
+ />
179
+ )}
180
+ </React.Fragment>
181
+ ))}
182
+ </TransitionSeries>
183
+ );
184
+ };
185
+ `;
186
+ }
187
+ function generateScene() {
188
+ return `import React from "react";
189
+ import { AbsoluteFill, OffthreadVideo, staticFile } from "remotion";
190
+ import { TransitionSeries, linearTiming } from "@remotion/transitions";
191
+ import { fade } from "@remotion/transitions/fade";
192
+ import { slide } from "@remotion/transitions/slide";
193
+ import type { SceneManifest, TransitionType } from "./types";
194
+
195
+ interface SceneProps {
196
+ scene: SceneManifest;
197
+ fps: number;
198
+ }
199
+
200
+ function getPresentation(type: TransitionType) {
201
+ switch (type) {
202
+ case "fade":
203
+ case "dissolve":
204
+ return fade();
205
+ case "wipe":
206
+ return slide({ direction: "from-right" });
207
+ case "cut":
208
+ default:
209
+ return fade(); // 1-frame fade = hard cut
210
+ }
211
+ }
212
+
213
+ export const Scene: React.FC<SceneProps> = ({ scene, fps }) => {
214
+ const { shots } = scene;
215
+
216
+ return (
217
+ <TransitionSeries>
218
+ {shots.map((shot, i) => (
219
+ <React.Fragment key={shot.panelId}>
220
+ <TransitionSeries.Sequence durationInFrames={shot.durationInFrames}>
221
+ <AbsoluteFill style={{ backgroundColor: "black" }}>
222
+ <OffthreadVideo
223
+ src={staticFile(shot.file)}
224
+ style={{
225
+ width: "100%",
226
+ height: "100%",
227
+ objectFit: "cover",
228
+ }}
229
+ />
230
+ </AbsoluteFill>
231
+ </TransitionSeries.Sequence>
232
+ {i < shots.length - 1 && (
233
+ <TransitionSeries.Transition
234
+ presentation={getPresentation(shots[i + 1].transition)}
235
+ timing={linearTiming({
236
+ durationInFrames: shots[i + 1].transitionDurationInFrames,
237
+ })}
238
+ />
239
+ )}
240
+ </React.Fragment>
241
+ ))}
242
+ </TransitionSeries>
243
+ );
244
+ };
245
+ `;
246
+ }
247
+ function generateClientTypes() {
248
+ return `/** Shared types for Remotion components -- mirrors assembly/types.ts */
249
+
250
+ export type TransitionType = "cut" | "fade" | "dissolve" | "wipe";
251
+
252
+ export interface ShotManifestEntry {
253
+ file: string;
254
+ sceneNumber: number;
255
+ shotNumber: number;
256
+ panelId: string;
257
+ durationSec: number;
258
+ durationInFrames: number;
259
+ fps: number;
260
+ width: number;
261
+ height: number;
262
+ transition: TransitionType;
263
+ transitionDurationInFrames: number;
264
+ characters: string[];
265
+ dialogue?: { character: string; line: string };
266
+ cameraMovement: string;
267
+ mood?: string;
268
+ }
269
+
270
+ export interface SceneManifest {
271
+ sceneNumber: number;
272
+ heading: string;
273
+ mood: string;
274
+ shots: ShotManifestEntry[];
275
+ durationInFrames: number;
276
+ durationSec: number;
277
+ }
278
+
279
+ export interface ShotManifest {
280
+ projectName: string;
281
+ targetFps: number;
282
+ targetWidth: number;
283
+ targetHeight: number;
284
+ scenes: SceneManifest[];
285
+ totalDurationInFrames: number;
286
+ totalDurationSec: number;
287
+ totalShots: number;
288
+ createdAt: string;
289
+ }
290
+ `;
291
+ }
292
+ //# sourceMappingURL=remotion-scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remotion-scaffold.js","sourceRoot":"","sources":["../../src/assembly/remotion-scaffold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Types for the Remotion assembly pipeline.
3
+ */
4
+ export interface ShotManifestEntry {
5
+ /** Relative path from remotion public/ dir, e.g. "scene-001/shot-001.mp4" */
6
+ file: string;
7
+ /** Absolute path to the source MP4 */
8
+ absolutePath: string;
9
+ /** Scene number */
10
+ sceneNumber: number;
11
+ /** Shot number within scene */
12
+ shotNumber: number;
13
+ /** Panel ID, e.g. "S1-P1" */
14
+ panelId: string;
15
+ /** Duration in seconds (from ffprobe) */
16
+ durationSec: number;
17
+ /** Duration in frames at target FPS */
18
+ durationInFrames: number;
19
+ /** Video FPS (from ffprobe) */
20
+ fps: number;
21
+ /** Video width */
22
+ width: number;
23
+ /** Video height */
24
+ height: number;
25
+ /** Transition type from video.json metadata */
26
+ transition: TransitionType;
27
+ /** Transition duration in frames */
28
+ transitionDurationInFrames: number;
29
+ /** Characters in this shot */
30
+ characters: string[];
31
+ /** Dialogue if present */
32
+ dialogue?: {
33
+ character: string;
34
+ line: string;
35
+ };
36
+ /** Camera movement description */
37
+ cameraMovement: string;
38
+ /** Mood of the scene */
39
+ mood?: string;
40
+ }
41
+ export type TransitionType = 'cut' | 'fade' | 'dissolve' | 'wipe';
42
+ export interface ShotManifest {
43
+ projectName: string;
44
+ targetFps: number;
45
+ targetWidth: number;
46
+ targetHeight: number;
47
+ scenes: SceneManifest[];
48
+ totalDurationInFrames: number;
49
+ totalDurationSec: number;
50
+ totalShots: number;
51
+ createdAt: string;
52
+ }
53
+ export interface SceneManifest {
54
+ sceneNumber: number;
55
+ heading: string;
56
+ mood: string;
57
+ shots: ShotManifestEntry[];
58
+ durationInFrames: number;
59
+ durationSec: number;
60
+ }
61
+ export interface RemotionProjectConfig {
62
+ projectDir: string;
63
+ publicDir: string;
64
+ srcDir: string;
65
+ manifest: ShotManifest;
66
+ }
67
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/assembly/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,cAAc,CAAC;IAC3B,oCAAoC;IACpC,0BAA0B,EAAE,MAAM,CAAC;IACnC,8BAA8B;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;CACxB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Types for the Remotion assembly pipeline.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/assembly/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,32 @@
1
+ import type { CharacterProfile } from "./extractor.js";
2
+ /** Fully synthesized character description ready for prompt injection. */
3
+ export interface CharacterDescription {
4
+ /** Canonical character name. */
5
+ name: string;
6
+ /** 1-2 sentence summary suitable for quick reference. */
7
+ shortDescription: string;
8
+ /**
9
+ * Exhaustive paragraph covering all known physical attributes.
10
+ * Formatted for direct injection into image generation prompts.
11
+ */
12
+ fullDescription: string;
13
+ /** Default wardrobe description (most commonly described outfit). */
14
+ wardrobe: string;
15
+ /**
16
+ * Per-scene wardrobe overrides.
17
+ * Key is the 1-based scene number; value is the wardrobe description
18
+ * specific to that scene. Only populated when distinct wardrobe changes
19
+ * are detected in the screenplay text.
20
+ */
21
+ wardrobeByScene: Map<number, string>;
22
+ }
23
+ /**
24
+ * Transform an array of `CharacterProfile` objects into structured
25
+ * `CharacterDescription` entries. Each description synthesizes scattered
26
+ * physical-description fragments into a coherent, prompt-ready format.
27
+ *
28
+ * @param profiles - Array of profiles from `extractCharacterProfiles`.
29
+ * @returns Array of `CharacterDescription` in the same order as input.
30
+ */
31
+ export declare function buildCharacterDescriptions(profiles: CharacterProfile[]): CharacterDescription[];
32
+ //# sourceMappingURL=describer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describer.d.ts","sourceRoot":"","sources":["../../src/characters/describer.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IAEb,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AA4VD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,oBAAoB,EAAE,CAuCxB"}