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,446 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Shot Planner -- breaks a Scene into an ordered sequence of camera shots.
3
+ //
4
+ // Analyses the scene's action beats, dialogue exchanges, and emotional
5
+ // cues to produce a cinematically sensible shot list that a prompt builder
6
+ // can turn into image-generation prompts.
7
+ // ---------------------------------------------------------------------------
8
+ // ---- Lens mapping ---------------------------------------------------------
9
+ const LENS_BY_SHOT_TYPE = {
10
+ "extreme-wide": "14mm ultra-wide",
11
+ wide: "24mm wide",
12
+ "medium-wide": "35mm standard",
13
+ medium: "50mm standard",
14
+ "medium-close-up": "50mm standard",
15
+ "close-up": "85mm portrait",
16
+ "extreme-close-up": "100mm macro",
17
+ insert: "100mm macro",
18
+ };
19
+ // ---- Keyword sets for heuristic classification ----------------------------
20
+ const EMOTIONAL_KEYWORDS = new Set([
21
+ "tears",
22
+ "crying",
23
+ "cries",
24
+ "weeps",
25
+ "sobbing",
26
+ "screams",
27
+ "whispers",
28
+ "trembles",
29
+ "shaking",
30
+ "heartbreak",
31
+ "anguish",
32
+ "devastated",
33
+ "shock",
34
+ "stunned",
35
+ "gasps",
36
+ "smiles",
37
+ "laughs",
38
+ "grins",
39
+ "kisses",
40
+ "embraces",
41
+ "holds",
42
+ "hugs",
43
+ "love",
44
+ "fear",
45
+ "terror",
46
+ "horror",
47
+ "rage",
48
+ "fury",
49
+ "anger",
50
+ "joy",
51
+ "elation",
52
+ ]);
53
+ const ACTION_KEYWORDS = new Set([
54
+ "runs",
55
+ "chases",
56
+ "fights",
57
+ "punches",
58
+ "kicks",
59
+ "ducks",
60
+ "jumps",
61
+ "climbs",
62
+ "crashes",
63
+ "explodes",
64
+ "fires",
65
+ "shoots",
66
+ "falls",
67
+ "leaps",
68
+ "dives",
69
+ "rolls",
70
+ "sprints",
71
+ "charges",
72
+ "tackles",
73
+ "slams",
74
+ "breaks",
75
+ "smashes",
76
+ "throws",
77
+ "dodges",
78
+ ]);
79
+ const INSERT_KEYWORDS = new Set([
80
+ "letter",
81
+ "note",
82
+ "phone",
83
+ "screen",
84
+ "photo",
85
+ "photograph",
86
+ "document",
87
+ "newspaper",
88
+ "headline",
89
+ "clock",
90
+ "watch",
91
+ "ring",
92
+ "key",
93
+ "gun",
94
+ "weapon",
95
+ "knife",
96
+ "blood",
97
+ "hand",
98
+ "envelope",
99
+ "map",
100
+ "badge",
101
+ "wallet",
102
+ "glass",
103
+ "bottle",
104
+ "pill",
105
+ "syringe",
106
+ "book",
107
+ "diary",
108
+ "mirror",
109
+ "sign",
110
+ ]);
111
+ const DISSOLVE_KEYWORDS = new Set([
112
+ "later",
113
+ "hours pass",
114
+ "time passes",
115
+ "morning",
116
+ "sunset",
117
+ "dawn",
118
+ "dusk",
119
+ "next day",
120
+ "the following",
121
+ "weeks",
122
+ "months",
123
+ "years",
124
+ ]);
125
+ const MATCH_CUT_KEYWORDS = new Set([
126
+ "match cut",
127
+ "smash cut",
128
+ "match on",
129
+ ]);
130
+ // ---- Helpers --------------------------------------------------------------
131
+ /**
132
+ * Check whether a text block contains any word from a keyword set.
133
+ */
134
+ function containsKeyword(text, keywords) {
135
+ const lower = text.toLowerCase();
136
+ for (const kw of keywords) {
137
+ if (lower.includes(kw))
138
+ return true;
139
+ }
140
+ return false;
141
+ }
142
+ /**
143
+ * Extract potential object insert subjects from an action line.
144
+ */
145
+ function findInsertSubjects(text) {
146
+ const lower = text.toLowerCase();
147
+ const found = [];
148
+ for (const kw of INSERT_KEYWORDS) {
149
+ if (lower.includes(kw)) {
150
+ found.push(kw);
151
+ }
152
+ }
153
+ return found;
154
+ }
155
+ /**
156
+ * Determine the default transition OUT for a shot based on surrounding text.
157
+ */
158
+ function inferTransitionOut(actionText, isLastInScene) {
159
+ if (containsKeyword(actionText, MATCH_CUT_KEYWORDS))
160
+ return "MATCH CUT";
161
+ if (containsKeyword(actionText, DISSOLVE_KEYWORDS))
162
+ return "DISSOLVE";
163
+ if (isLastInScene)
164
+ return undefined; // scene boundary handled externally
165
+ return "CUT";
166
+ }
167
+ /**
168
+ * Infer whether a scene heading indicates an exterior location.
169
+ * Parses the heading for INT/EXT prefixes.
170
+ */
171
+ function isExterior(heading) {
172
+ const upper = heading.toUpperCase().trim();
173
+ // EXT. or EXT/INT. -- exterior establishing shots
174
+ return upper.startsWith("EXT.") || upper.startsWith("EXT/INT");
175
+ }
176
+ /**
177
+ * Split action text into discrete beats (paragraphs or sentences that
178
+ * represent distinct visual moments).
179
+ */
180
+ function splitActionBeats(actionLines) {
181
+ // Each element of the action array is already a paragraph from the parser.
182
+ // If a single paragraph is very long, split on sentence boundaries.
183
+ const beats = [];
184
+ for (const paragraph of actionLines) {
185
+ const trimmed = paragraph.trim();
186
+ if (!trimmed)
187
+ continue;
188
+ // If the paragraph is short enough, treat it as one beat.
189
+ if (trimmed.length < 200) {
190
+ beats.push(trimmed);
191
+ continue;
192
+ }
193
+ // Split long paragraphs on sentence boundaries.
194
+ const sentences = trimmed
195
+ .split(/(?<=[.!?])\s+(?=[A-Z])/)
196
+ .map((s) => s.trim())
197
+ .filter(Boolean);
198
+ if (sentences.length > 1) {
199
+ beats.push(...sentences);
200
+ }
201
+ else {
202
+ beats.push(trimmed);
203
+ }
204
+ }
205
+ return beats.length > 0 ? beats : [];
206
+ }
207
+ /**
208
+ * Extract character names mentioned in an action beat. Matches known
209
+ * scene characters by checking for their names (case-insensitive) in
210
+ * the beat text.
211
+ */
212
+ function findCharactersInBeat(beat, knownCharacters) {
213
+ const upperBeat = beat.toUpperCase();
214
+ return knownCharacters.filter((c) => upperBeat.includes(c.toUpperCase()));
215
+ }
216
+ // ---- Dialogue grouping ----------------------------------------------------
217
+ /**
218
+ * Group sequential dialogue lines into exchanges. An exchange is a
219
+ * contiguous block of dialogue lines between 2 or more speakers.
220
+ * A single-speaker monologue becomes its own exchange.
221
+ */
222
+ function groupDialogueExchanges(dialogue) {
223
+ if (dialogue.length === 0)
224
+ return [];
225
+ const speakers = new Set(dialogue.map((d) => d.character));
226
+ // Single speaker -- each line is its own exchange.
227
+ if (speakers.size === 1) {
228
+ return dialogue.map((d) => [d]);
229
+ }
230
+ // Multiple speakers -- group into contiguous exchanges. Start a new
231
+ // exchange when the set of active speakers grows large (3+) and the
232
+ // current group is already substantial.
233
+ const exchanges = [];
234
+ let current = [];
235
+ for (const line of dialogue) {
236
+ current.push(line);
237
+ const currentSpeakers = new Set(current.map((d) => d.character));
238
+ if (currentSpeakers.size >= 3 && current.length >= 6) {
239
+ exchanges.push(current);
240
+ current = [];
241
+ }
242
+ }
243
+ if (current.length > 0) {
244
+ exchanges.push(current);
245
+ }
246
+ return exchanges;
247
+ }
248
+ // ---- Core planning --------------------------------------------------------
249
+ /**
250
+ * Plan a sequence of camera shots for a given scene.
251
+ *
252
+ * The planner follows classical cinematographic conventions:
253
+ *
254
+ * 1. Every scene opens with an establishing shot (extreme-wide or wide).
255
+ * 2. Action beats get wide-to-medium coverage with dynamic camera movement.
256
+ * 3. Dialogue exchanges are covered with a two-shot opener followed by
257
+ * over-the-shoulder singles alternating between speakers.
258
+ * 4. Emotional moments receive close-ups or extreme close-ups.
259
+ * 5. Important objects mentioned in action text receive insert shots.
260
+ * 6. Transitions default to CUT; DISSOLVE is used for time passages and
261
+ * MATCH CUT where the screenplay indicates one.
262
+ */
263
+ export function planShots(scene) {
264
+ const shots = [];
265
+ let shotCounter = 0;
266
+ const push = (partial) => {
267
+ shotCounter++;
268
+ shots.push({ shotNumber: shotCounter, ...partial });
269
+ };
270
+ const exterior = isExterior(scene.heading);
271
+ // ---- 1. Establishing shot ------------------------------------------------
272
+ push({
273
+ type: exterior ? "extreme-wide" : "wide",
274
+ angle: "eye-level",
275
+ movement: exterior ? "crane" : "dolly-in",
276
+ lens: exterior
277
+ ? LENS_BY_SHOT_TYPE["extreme-wide"]
278
+ : LENS_BY_SHOT_TYPE["wide"],
279
+ characters: scene.characters.slice(0, 3),
280
+ action: `Establishing shot: ${scene.heading}`,
281
+ transitionIn: "CUT",
282
+ notes: `Establish location: ${scene.location}, ${scene.timeOfDay}.`,
283
+ });
284
+ // ---- 2. Action beats -----------------------------------------------------
285
+ if (scene.action.length > 0) {
286
+ const beats = splitActionBeats(scene.action);
287
+ for (let i = 0; i < beats.length; i++) {
288
+ const beat = beats[i];
289
+ const beatCharacters = findCharactersInBeat(beat, scene.characters);
290
+ const isLast = i === beats.length - 1 && scene.dialogue.length === 0;
291
+ // Emotional beat
292
+ if (containsKeyword(beat, EMOTIONAL_KEYWORDS)) {
293
+ const focus = beatCharacters[0];
294
+ push({
295
+ type: "close-up",
296
+ angle: "eye-level",
297
+ movement: "dolly-in",
298
+ lens: LENS_BY_SHOT_TYPE["close-up"],
299
+ characters: beatCharacters,
300
+ focusCharacter: focus,
301
+ action: beat,
302
+ transitionOut: inferTransitionOut(beat, isLast),
303
+ notes: "Emotional beat -- close-up to capture performance.",
304
+ });
305
+ continue;
306
+ }
307
+ // Insert shot for important objects
308
+ const insertSubjects = findInsertSubjects(beat);
309
+ if (insertSubjects.length > 0) {
310
+ push({
311
+ type: "insert",
312
+ angle: "high-angle",
313
+ movement: "static",
314
+ lens: LENS_BY_SHOT_TYPE["insert"],
315
+ characters: [],
316
+ action: `Insert: ${insertSubjects.join(", ")} -- ${beat}`,
317
+ transitionOut: inferTransitionOut(beat, isLast),
318
+ notes: `Insert shot of: ${insertSubjects.join(", ")}.`,
319
+ });
320
+ // Reaction shot if characters are present
321
+ if (beatCharacters.length > 0) {
322
+ push({
323
+ type: "medium-close-up",
324
+ angle: "eye-level",
325
+ movement: "static",
326
+ lens: LENS_BY_SHOT_TYPE["medium-close-up"],
327
+ characters: beatCharacters,
328
+ focusCharacter: beatCharacters[0],
329
+ action: `Reaction to ${insertSubjects.join(", ")}`,
330
+ transitionOut: inferTransitionOut(beat, isLast),
331
+ notes: "Reaction shot following insert.",
332
+ });
333
+ }
334
+ continue;
335
+ }
336
+ // Physical action beat
337
+ if (containsKeyword(beat, ACTION_KEYWORDS)) {
338
+ push({
339
+ type: beatCharacters.length > 2 ? "wide" : "medium-wide",
340
+ angle: "eye-level",
341
+ movement: "tracking",
342
+ lens: beatCharacters.length > 2
343
+ ? LENS_BY_SHOT_TYPE["wide"]
344
+ : LENS_BY_SHOT_TYPE["medium-wide"],
345
+ characters: beatCharacters,
346
+ focusCharacter: beatCharacters[0],
347
+ action: beat,
348
+ transitionOut: inferTransitionOut(beat, isLast),
349
+ notes: "Action coverage with tracking camera.",
350
+ });
351
+ continue;
352
+ }
353
+ // Default action beat
354
+ push({
355
+ type: beatCharacters.length > 2 ? "medium-wide" : "medium",
356
+ angle: "eye-level",
357
+ movement: "static",
358
+ lens: beatCharacters.length > 2
359
+ ? LENS_BY_SHOT_TYPE["medium-wide"]
360
+ : LENS_BY_SHOT_TYPE["medium"],
361
+ characters: beatCharacters,
362
+ focusCharacter: beatCharacters[0],
363
+ action: beat,
364
+ transitionOut: inferTransitionOut(beat, isLast),
365
+ notes: "Standard coverage.",
366
+ });
367
+ }
368
+ }
369
+ // ---- 3. Dialogue coverage ------------------------------------------------
370
+ if (scene.dialogue.length > 0) {
371
+ const exchanges = groupDialogueExchanges(scene.dialogue);
372
+ for (const exchange of exchanges) {
373
+ const speakers = [...new Set(exchange.map((d) => d.character))];
374
+ // Two-shot opener for conversations with 2+ speakers
375
+ if (speakers.length >= 2) {
376
+ push({
377
+ type: "medium",
378
+ angle: "eye-level",
379
+ movement: "static",
380
+ lens: LENS_BY_SHOT_TYPE["medium"],
381
+ characters: speakers.slice(0, 2),
382
+ action: `Two-shot: ${speakers[0]} and ${speakers[1]} in conversation.`,
383
+ dialogue: exchange[0].text,
384
+ transitionOut: "CUT",
385
+ notes: "Two-shot opener for dialogue exchange.",
386
+ });
387
+ }
388
+ // OTS singles for each line
389
+ for (let i = 0; i < exchange.length; i++) {
390
+ const line = exchange[i];
391
+ const otherSpeaker = speakers.find((s) => s !== line.character);
392
+ const isEmotionalLine = containsKeyword(line.text + (line.parenthetical ?? ""), EMOTIONAL_KEYWORDS);
393
+ const isLastLine = i === exchange.length - 1 &&
394
+ exchange === exchanges[exchanges.length - 1];
395
+ if (isEmotionalLine) {
396
+ push({
397
+ type: "close-up",
398
+ angle: "eye-level",
399
+ movement: "dolly-in",
400
+ lens: LENS_BY_SHOT_TYPE["close-up"],
401
+ characters: [line.character],
402
+ focusCharacter: line.character,
403
+ action: line.parenthetical
404
+ ? `${line.character} (${line.parenthetical})`
405
+ : `${line.character} speaks with intensity.`,
406
+ dialogue: line.text,
407
+ transitionOut: inferTransitionOut(line.text, isLastLine),
408
+ notes: "Emotional close-up during dialogue.",
409
+ });
410
+ }
411
+ else {
412
+ const shotCharacters = otherSpeaker
413
+ ? [line.character, otherSpeaker]
414
+ : [line.character];
415
+ push({
416
+ type: "medium-close-up",
417
+ angle: "eye-level",
418
+ movement: "static",
419
+ lens: LENS_BY_SHOT_TYPE["medium-close-up"],
420
+ characters: shotCharacters,
421
+ focusCharacter: line.character,
422
+ action: otherSpeaker
423
+ ? `OTS ${otherSpeaker}, favoring ${line.character}.`
424
+ : `Single on ${line.character}.`,
425
+ dialogue: line.text,
426
+ transitionOut: inferTransitionOut(line.text, isLastLine),
427
+ notes: otherSpeaker
428
+ ? `Over-the-shoulder from ${otherSpeaker}'s perspective.`
429
+ : "Single shot -- no reverse needed.",
430
+ });
431
+ }
432
+ }
433
+ }
434
+ }
435
+ // ---- 4. Wire up transition chains ----------------------------------------
436
+ for (let i = 0; i < shots.length; i++) {
437
+ if (i > 0 && !shots[i].transitionIn) {
438
+ shots[i].transitionIn = shots[i - 1].transitionOut ?? "CUT";
439
+ }
440
+ if (!shots[i].transitionOut && i < shots.length - 1) {
441
+ shots[i].transitionOut = "CUT";
442
+ }
443
+ }
444
+ return shots;
445
+ }
446
+ //# sourceMappingURL=shot-planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shot-planner.js","sourceRoot":"","sources":["../../src/storyboard/shot-planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface UserConfig {
2
+ apiKey?: string;
3
+ workspace?: string;
4
+ }
5
+ export declare function getConfigDir(): string;
6
+ export declare function getConfigPath(): string;
7
+ export declare function readUserConfig(): Promise<UserConfig>;
8
+ export declare function writeUserConfig(config: UserConfig): Promise<void>;
9
+ export declare function updateUserConfig(patch: Partial<UserConfig>): Promise<UserConfig>;
10
+ export declare function hydrateEnvironmentFromUserConfig(): Promise<void>;
11
+ export declare function getDefaultSetupWorkspace(): string;
12
+ export declare function getWorkspaceDir(override?: string): Promise<string>;
13
+ export declare function maskApiKey(apiKey?: string): string;
14
+ export declare function validateVeniceApiKey(apiKey: string): Promise<void>;
15
+ //# sourceMappingURL=user-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-config.d.ts","sourceRoot":"","sources":["../src/user-config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,wBAAgB,YAAY,IAAI,MAAM,CAQrC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC,CAY1D;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAcvE;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAOtF;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,IAAI,CAAC,CAItE;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,wBAAsB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIxE;AAED,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAaxE"}
@@ -0,0 +1,103 @@
1
+ import { chmod, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
2
+ import { homedir, platform } from 'node:os';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ function expandHome(value) {
5
+ if (value === '~')
6
+ return homedir();
7
+ if (value.startsWith('~/'))
8
+ return join(homedir(), value.slice(2));
9
+ return value;
10
+ }
11
+ export function getConfigDir() {
12
+ const override = process.env.VENICE_VIDEO_CONFIG_DIR;
13
+ if (override)
14
+ return resolve(expandHome(override));
15
+ if (platform() === 'darwin')
16
+ return join(homedir(), 'Library', 'Application Support', 'venice-video');
17
+ if (platform() === 'win32') {
18
+ return join(process.env.APPDATA ?? join(homedir(), 'AppData', 'Roaming'), 'venice-video');
19
+ }
20
+ return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), '.config'), 'venice-video');
21
+ }
22
+ export function getConfigPath() {
23
+ return join(getConfigDir(), 'config.json');
24
+ }
25
+ export async function readUserConfig() {
26
+ try {
27
+ const raw = await readFile(getConfigPath(), 'utf-8');
28
+ const parsed = JSON.parse(raw);
29
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
30
+ throw new Error('configuration root must be a JSON object');
31
+ }
32
+ return parsed;
33
+ }
34
+ catch (error) {
35
+ if (error.code === 'ENOENT')
36
+ return {};
37
+ throw new Error(`Could not read Venice Video config at ${getConfigPath()}: ${error.message}`);
38
+ }
39
+ }
40
+ export async function writeUserConfig(config) {
41
+ const configPath = getConfigPath();
42
+ await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });
43
+ const temporaryPath = `${configPath}.${process.pid}.tmp`;
44
+ try {
45
+ await writeFile(temporaryPath, `${JSON.stringify(config, null, 2)}\n`, {
46
+ encoding: 'utf-8',
47
+ mode: 0o600,
48
+ });
49
+ await rename(temporaryPath, configPath);
50
+ if (platform() !== 'win32')
51
+ await chmod(configPath, 0o600);
52
+ }
53
+ finally {
54
+ await rm(temporaryPath, { force: true }).catch(() => undefined);
55
+ }
56
+ }
57
+ export async function updateUserConfig(patch) {
58
+ const next = { ...(await readUserConfig()), ...patch };
59
+ for (const key of Object.keys(next)) {
60
+ if (next[key] === undefined || next[key] === '')
61
+ delete next[key];
62
+ }
63
+ await writeUserConfig(next);
64
+ return next;
65
+ }
66
+ export async function hydrateEnvironmentFromUserConfig() {
67
+ if (process.env.VENICE_API_KEY)
68
+ return;
69
+ const stored = (await readUserConfig()).apiKey;
70
+ if (stored)
71
+ process.env.VENICE_API_KEY = stored;
72
+ }
73
+ export function getDefaultSetupWorkspace() {
74
+ return join(homedir(), 'VeniceVideos');
75
+ }
76
+ export async function getWorkspaceDir(override) {
77
+ const config = await readUserConfig();
78
+ const selected = override ?? process.env.VENICE_VIDEO_WORKSPACE ?? config.workspace ?? resolve('output');
79
+ return resolve(expandHome(selected));
80
+ }
81
+ export function maskApiKey(apiKey) {
82
+ if (!apiKey)
83
+ return '(not configured)';
84
+ if (apiKey.length <= 8)
85
+ return '••••••••';
86
+ return `${apiKey.slice(0, 4)}••••${apiKey.slice(-4)}`;
87
+ }
88
+ export async function validateVeniceApiKey(apiKey) {
89
+ const response = await fetch('https://api.venice.ai/api/v1/models?type=video', {
90
+ headers: { Authorization: `Bearer ${apiKey}` },
91
+ signal: AbortSignal.timeout(15_000),
92
+ });
93
+ if (!response.ok) {
94
+ let detail = '';
95
+ try {
96
+ const body = await response.json();
97
+ detail = body.error?.message ? `: ${body.error.message}` : '';
98
+ }
99
+ catch { /* status is enough */ }
100
+ throw new Error(`Venice rejected the API key (HTTP ${response.status})${detail}`);
101
+ }
102
+ }
103
+ //# sourceMappingURL=user-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-config.js","sourceRoot":"","sources":["../src/user-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ export declare class WanAudioTooShortError extends Error {
2
+ readonly model: string;
3
+ readonly audioPath: string;
4
+ readonly durationSec: number;
5
+ readonly minSec: number;
6
+ constructor(info: {
7
+ model: string;
8
+ audioPath: string;
9
+ durationSec: number;
10
+ minSec: number;
11
+ });
12
+ }
13
+ /**
14
+ * Probe an audio file's duration in seconds via ffprobe.
15
+ *
16
+ * Throws if ffprobe is not on PATH or the file cannot be read.
17
+ */
18
+ export declare function probeAudioDurationSec(audioPath: string): Promise<number>;
19
+ /**
20
+ * Pad an audio file with TRAILING silence to exactly `targetSec` seconds.
21
+ *
22
+ * Writes the padded variant to `outPath`, leaving the source file untouched.
23
+ * The caller decides where to put it — convention is `audio/dialogue-padded/`
24
+ * so the original short clip remains usable for non-Wan placements.
25
+ *
26
+ * Pads to exactly `targetSec` (no slack). Less padding = less held-pose
27
+ * visual time after the speech ends.
28
+ */
29
+ export declare function padAudioWithTrailingSilence(opts: {
30
+ inputPath: string;
31
+ outputPath: string;
32
+ targetSec: number;
33
+ }): Promise<{
34
+ outputPath: string;
35
+ paddedFromSec: number;
36
+ toSec: number;
37
+ }>;
38
+ export interface PadAudioForModelOptions {
39
+ /** Model id from the registry. `minAudioInputSec` drives the target. */
40
+ model: string;
41
+ /** Path to the source audio file. */
42
+ audioPath: string;
43
+ /**
44
+ * Directory where padded variants land. Defaults to `<input dir>/padded/`.
45
+ * The original file is never modified.
46
+ */
47
+ paddedDir?: string;
48
+ /**
49
+ * Override the target seconds. Defaults to the model's `minAudioInputSec`.
50
+ */
51
+ targetSec?: number;
52
+ }
53
+ /**
54
+ * Ensure an audio file meets a model's minimum-duration requirement.
55
+ *
56
+ * - If the model has no `minAudioInputSec` or the clip already qualifies,
57
+ * returns the original path unmodified.
58
+ * - Otherwise, pads with trailing silence and returns the padded path.
59
+ *
60
+ * Throws `WanAudioTooShortError` only if the model declares a minimum AND
61
+ * padding is explicitly disabled (`paddedDir: null` is reserved for that
62
+ * future variant; today we always pad rather than throw, because callers
63
+ * have already paid for the TTS and want the render).
64
+ */
65
+ export declare function padAudioForModel(opts: PadAudioForModelOptions): Promise<{
66
+ outputPath: string;
67
+ padded: boolean;
68
+ durationSec: number;
69
+ }>;
70
+ /**
71
+ * Assert an audio file is long enough for a given model.
72
+ *
73
+ * Use this when callers want to reject short audio explicitly rather than
74
+ * silently padding it.
75
+ */
76
+ export declare function assertAudioMeetsModelMin(opts: {
77
+ model: string;
78
+ audioPath: string;
79
+ }): Promise<void>;
80
+ //# sourceMappingURL=audio-preflight.d.ts.map