videobook 0.0.0-stage → 0.2.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 (565) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/LICENSE +21 -0
  3. package/README.md +195 -2
  4. package/bin/videobook.js +7 -0
  5. package/dist/acestep/client.js +203 -0
  6. package/dist/acestep/config.js +62 -0
  7. package/dist/acestep/errors.js +8 -0
  8. package/dist/acestep/process.js +175 -0
  9. package/dist/alive-captions/analyze.js +117 -0
  10. package/dist/alive-captions/audio.js +179 -0
  11. package/dist/alive-captions/frames.js +59 -0
  12. package/dist/alive-captions/model.js +37 -0
  13. package/dist/alive-captions/schema.js +49 -0
  14. package/dist/alive-captions/track.js +9 -0
  15. package/dist/api-key.js +33 -0
  16. package/dist/app-state.js +56 -0
  17. package/dist/app.js +257 -0
  18. package/dist/archive-b2.js +332 -0
  19. package/dist/archive-store.js +169 -0
  20. package/dist/artifact-label.js +36 -0
  21. package/dist/artifact-refs.js +49 -0
  22. package/dist/asset-tag-extraction.js +169 -0
  23. package/dist/asset-tags.js +228 -0
  24. package/dist/asset-usage.js +23 -0
  25. package/dist/audio-cue.js +71 -0
  26. package/dist/audio-encoding.js +32 -0
  27. package/dist/audio-sync-request.js +1 -0
  28. package/dist/audio-sync.js +223 -0
  29. package/dist/audio-trim-range.js +31 -0
  30. package/dist/book-context.js +31 -0
  31. package/dist/book-manager.js +374 -0
  32. package/dist/catalog-gc.js +26 -0
  33. package/dist/chain-executor.js +815 -0
  34. package/dist/chain-generation.js +115 -0
  35. package/dist/chain-plan.js +746 -0
  36. package/dist/chain-step-review.js +60 -0
  37. package/dist/character-name.js +25 -0
  38. package/dist/chat-generation-routing.js +73 -0
  39. package/dist/chat-generation-settings.js +78 -0
  40. package/dist/chat-models.js +44 -0
  41. package/dist/chat-prompt-rewrite.js +67 -0
  42. package/dist/chat-router.js +628 -0
  43. package/dist/chat-view-actions.js +49 -0
  44. package/dist/cli/args.js +242 -0
  45. package/dist/cli/config-command.js +103 -0
  46. package/dist/cli/doctor-command.js +289 -0
  47. package/dist/cli/entry.js +2 -0
  48. package/dist/cli/key-report.js +16 -0
  49. package/dist/cli/main.js +104 -0
  50. package/dist/cli/mcp-command.js +88 -0
  51. package/dist/cli/mcp-relay.js +51 -0
  52. package/dist/cli/open-browser.js +14 -0
  53. package/dist/cli/run-command.js +231 -0
  54. package/dist/cli/serve-command.js +62 -0
  55. package/dist/cli/setup-command.js +60 -0
  56. package/dist/cli/stdio-guard.js +8 -0
  57. package/dist/cold-open-model.js +7 -0
  58. package/dist/cold-open.js +79 -0
  59. package/dist/command-reference.js +95 -0
  60. package/dist/content-store.js +74 -0
  61. package/dist/cost.js +8 -0
  62. package/dist/crop-geometry.js +23 -0
  63. package/dist/dancing-workflow.js +447 -0
  64. package/dist/data-home.js +44 -0
  65. package/dist/diagnostics.js +109 -0
  66. package/dist/dialog-quality.js +34 -0
  67. package/dist/downloads-dest.js +56 -0
  68. package/dist/editing-moments.js +194 -0
  69. package/dist/elevenlabs-audio-extension.js +66 -0
  70. package/dist/engine.js +54 -0
  71. package/dist/env-file.js +91 -0
  72. package/dist/env-secrets.js +148 -0
  73. package/dist/ffmpeg-binary.js +12 -0
  74. package/dist/ffmpeg.js +425 -0
  75. package/dist/ffprobe-binary.js +77 -0
  76. package/dist/forget-asset.js +216 -0
  77. package/dist/frame-utils.js +27 -0
  78. package/dist/generation-credit-error.js +11 -0
  79. package/dist/generation-input-mentions.js +117 -0
  80. package/dist/generation-input-policy.js +68 -0
  81. package/dist/generation-reference-mentions.js +97 -0
  82. package/dist/goal-characters.js +49 -0
  83. package/dist/goal-plan-v3.js +273 -0
  84. package/dist/goal-plan.js +220 -0
  85. package/dist/goal-planner-prompt.js +28 -0
  86. package/dist/goal-prompt-budget.js +4 -0
  87. package/dist/goal-reference-images.js +25 -0
  88. package/dist/goal-state.js +261 -0
  89. package/dist/goal-stills.js +153 -0
  90. package/dist/goal-store.js +144 -0
  91. package/dist/goal-styles.js +144 -0
  92. package/dist/goal-v3-runtime.js +157 -0
  93. package/dist/guides/character_schema_guide.md +70 -0
  94. package/dist/guides/gpt_image_2_5_prompting_guide.md +21 -0
  95. package/dist/guides/grok_imagine_prompting_guide.md +72 -0
  96. package/dist/guides/image_reproduction_guide.md +84 -0
  97. package/dist/guides/kling_3_0_prompting_guide.md +136 -0
  98. package/dist/guides/nano_banana_pro_prompting_guide.md +28 -0
  99. package/dist/guides/seedance_2_prompting_guide.md +172 -0
  100. package/dist/http-access.js +49 -0
  101. package/dist/http-byte-range.js +31 -0
  102. package/dist/hydration.js +56 -0
  103. package/dist/image-compress.js +77 -0
  104. package/dist/image-edit-default.js +1 -0
  105. package/dist/image-edit-models.js +41 -0
  106. package/dist/image-edit-settings.js +11 -0
  107. package/dist/image-region-edit.js +32 -0
  108. package/dist/image-subject-map.js +523 -0
  109. package/dist/image.js +46 -0
  110. package/dist/index.js +12 -0
  111. package/dist/job-deadline.js +60 -0
  112. package/dist/jobs/_alibaba-upload.js +30 -0
  113. package/dist/jobs/_audio-chunks.js +31 -0
  114. package/dist/jobs/_download-into-asset.js +15 -0
  115. package/dist/jobs/_fal-shared.js +22 -0
  116. package/dist/jobs/_fal-upload.js +35 -0
  117. package/dist/jobs/_image-edit-adapter.js +213 -0
  118. package/dist/jobs/_kie-poll.js +119 -0
  119. package/dist/jobs/_kie-upload.js +32 -0
  120. package/dist/jobs/_lease.js +163 -0
  121. package/dist/jobs/_persist-output.js +19 -0
  122. package/dist/jobs/_storage-retry.js +21 -0
  123. package/dist/jobs/_transcribe.js +245 -0
  124. package/dist/jobs/_translate-transcript.js +270 -0
  125. package/dist/jobs/analyze-alive-captions.js +10 -0
  126. package/dist/jobs/analyze-editing-moments.js +104 -0
  127. package/dist/jobs/analyze-jokes.js +143 -0
  128. package/dist/jobs/analyze-keyword-placement.js +155 -0
  129. package/dist/jobs/analyze-music.js +14 -0
  130. package/dist/jobs/analyze-video.js +282 -0
  131. package/dist/jobs/apply-cuts.js +83 -0
  132. package/dist/jobs/apply-sfx.js +107 -0
  133. package/dist/jobs/archive-clip.js +458 -0
  134. package/dist/jobs/assemble-goal.js +98 -0
  135. package/dist/jobs/audio-boost.js +71 -0
  136. package/dist/jobs/audio-mix.js +161 -0
  137. package/dist/jobs/backfill-asset-tags.js +144 -0
  138. package/dist/jobs/burn-watermark.js +316 -0
  139. package/dist/jobs/change-video-speed.js +176 -0
  140. package/dist/jobs/clean-video-audio.js +207 -0
  141. package/dist/jobs/cold-open.js +166 -0
  142. package/dist/jobs/combine-goal.js +108 -0
  143. package/dist/jobs/complete-provider-task.js +185 -0
  144. package/dist/jobs/copy-library-asset.js +33 -0
  145. package/dist/jobs/cost-estimate-assessment.js +113 -0
  146. package/dist/jobs/crop-image.js +47 -0
  147. package/dist/jobs/crop-video.js +71 -0
  148. package/dist/jobs/describe-image.js +181 -0
  149. package/dist/jobs/detect-scenes.js +33 -0
  150. package/dist/jobs/doctor-fix.js +100 -0
  151. package/dist/jobs/download-video.js +427 -0
  152. package/dist/jobs/enqueue-search-index.js +24 -0
  153. package/dist/jobs/even-split.js +122 -0
  154. package/dist/jobs/export-sequence.js +365 -0
  155. package/dist/jobs/extend-audio.js +229 -0
  156. package/dist/jobs/extract-audio.js +72 -0
  157. package/dist/jobs/extract-frame.js +58 -0
  158. package/dist/jobs/extract-notebook-audio.js +82 -0
  159. package/dist/jobs/extract-notebook-frame.js +93 -0
  160. package/dist/jobs/extract-video-clip.js +8 -0
  161. package/dist/jobs/extract-video-poster.js +55 -0
  162. package/dist/jobs/extract-waveform.js +25 -0
  163. package/dist/jobs/finish-goal.js +255 -0
  164. package/dist/jobs/forget-asset.js +11 -0
  165. package/dist/jobs/generate-acestep-cover.js +219 -0
  166. package/dist/jobs/generate-media.js +70 -0
  167. package/dist/jobs/image-subjects.js +1059 -0
  168. package/dist/jobs/index.js +18 -0
  169. package/dist/jobs/inject-first-frame.js +175 -0
  170. package/dist/jobs/isolate-vocals.js +69 -0
  171. package/dist/jobs/kie-paygate.js +177 -0
  172. package/dist/jobs/label-music-sections.js +5 -0
  173. package/dist/jobs/osg-placement.js +135 -0
  174. package/dist/jobs/pad-video.js +72 -0
  175. package/dist/jobs/plan-goal.js +97 -0
  176. package/dist/jobs/post-record.js +21 -0
  177. package/dist/jobs/post-to-x.js +21 -0
  178. package/dist/jobs/prepare-search-reference.js +190 -0
  179. package/dist/jobs/prepare-temporal-search.js +16 -0
  180. package/dist/jobs/process-audio.js +67 -0
  181. package/dist/jobs/process-image.js +58 -0
  182. package/dist/jobs/process-upload.js +166 -0
  183. package/dist/jobs/process-video.js +438 -0
  184. package/dist/jobs/register-all.js +161 -0
  185. package/dist/jobs/relayout-notebook.js +78 -0
  186. package/dist/jobs/remove-sound.js +299 -0
  187. package/dist/jobs/render-project.js +380 -0
  188. package/dist/jobs/render-qr-outro.js +138 -0
  189. package/dist/jobs/render-timeline.js +283 -0
  190. package/dist/jobs/repair-search-indexes.js +42 -0
  191. package/dist/jobs/replace-video-audio.js +64 -0
  192. package/dist/jobs/restore-archive-clip.js +53 -0
  193. package/dist/jobs/reverse-video.js +53 -0
  194. package/dist/jobs/rewrite-script.js +173 -0
  195. package/dist/jobs/run-notebook.js +3335 -0
  196. package/dist/jobs/semantic-index.js +797 -0
  197. package/dist/jobs/smooth-scene-concat.js +257 -0
  198. package/dist/jobs/splice-video.js +280 -0
  199. package/dist/jobs/split-video.js +127 -0
  200. package/dist/jobs/suggest-cuts.js +149 -0
  201. package/dist/jobs/suggest-sfx.js +135 -0
  202. package/dist/jobs/sync-video-to-audio.js +329 -0
  203. package/dist/jobs/tag-asset.js +266 -0
  204. package/dist/jobs/task-failure.js +16 -0
  205. package/dist/jobs/timewarp-video.js +152 -0
  206. package/dist/jobs/transcribe-video-audio.js +117 -0
  207. package/dist/jobs/transcribe.js +35 -0
  208. package/dist/jobs/translate-transcript.js +55 -0
  209. package/dist/jobs/trim-audio.js +133 -0
  210. package/dist/jobs/trim-video.js +291 -0
  211. package/dist/jobs/xai-paygate.js +26 -0
  212. package/dist/keyword-placement-cache.js +74 -0
  213. package/dist/lazy-render.js +142 -0
  214. package/dist/library-browse.js +78 -0
  215. package/dist/lightning-defaults.js +206 -0
  216. package/dist/load-env.js +12 -0
  217. package/dist/local-search-models.js +206 -0
  218. package/dist/local-upload.js +318 -0
  219. package/dist/logger.js +69 -0
  220. package/dist/media/adapters/alibaba.js +20 -0
  221. package/dist/media/adapters/elevenlabs.js +58 -0
  222. package/dist/media/adapters/fal.js +45 -0
  223. package/dist/media/adapters/index.js +26 -0
  224. package/dist/media/adapters/kie.js +120 -0
  225. package/dist/media/adapters/pending.js +21 -0
  226. package/dist/media/adapters/types.js +5 -0
  227. package/dist/media/adapters/xai.js +18 -0
  228. package/dist/media/catalog.js +236 -0
  229. package/dist/media/complete.js +191 -0
  230. package/dist/media/cost.js +45 -0
  231. package/dist/media/descriptor.js +157 -0
  232. package/dist/media/endpoints.js +11 -0
  233. package/dist/media/frame-options.js +18 -0
  234. package/dist/media/insert-video-timing.js +17 -0
  235. package/dist/media/json-schema.js +75 -0
  236. package/dist/media/legacy-task-types.js +129 -0
  237. package/dist/media/listing.js +24 -0
  238. package/dist/media/model-id.js +14 -0
  239. package/dist/media/preview.js +86 -0
  240. package/dist/media/prompt-dialects.js +65 -0
  241. package/dist/media/ref-fields.js +106 -0
  242. package/dist/media/refs.js +131 -0
  243. package/dist/media/request.js +188 -0
  244. package/dist/media/types.js +6 -0
  245. package/dist/media/wire.js +161 -0
  246. package/dist/media-library.js +535 -0
  247. package/dist/media-output-path.js +33 -0
  248. package/dist/multyculty-workflow.js +757 -0
  249. package/dist/notebook-action-catalog.js +608 -0
  250. package/dist/notebook-cell-outputs.js +726 -0
  251. package/dist/notebook-credit-retry.js +45 -0
  252. package/dist/notebook-fixtures.js +8 -0
  253. package/dist/notebook-generation-contract.js +77 -0
  254. package/dist/notebook-generation-controls.js +145 -0
  255. package/dist/notebook-goal-layout.js +40 -0
  256. package/dist/notebook-graph.js +37 -0
  257. package/dist/notebook-image-edit.js +84 -0
  258. package/dist/notebook-initial-generation-prompt.js +222 -0
  259. package/dist/notebook-live-analysis.js +941 -0
  260. package/dist/notebook-media-ops.js +579 -0
  261. package/dist/notebook-mutations.js +20 -0
  262. package/dist/notebook-placement.js +41 -0
  263. package/dist/notebook-provider-failure.js +87 -0
  264. package/dist/notebook-published-post.js +26 -0
  265. package/dist/notebook-reference-resolver.js +227 -0
  266. package/dist/notebook-relayout.js +270 -0
  267. package/dist/notebook-run-plan.js +519 -0
  268. package/dist/notebook-shots.js +162 -0
  269. package/dist/notebook-workflow.js +856 -0
  270. package/dist/one-password.js +200 -0
  271. package/dist/openai-intelligence.js +99 -0
  272. package/dist/original-media-file.js +12 -0
  273. package/dist/osg-assets.js +36 -0
  274. package/dist/osg-placement-cache.js +64 -0
  275. package/dist/osg-settings.js +27 -0
  276. package/dist/paid-tools.js +22 -0
  277. package/dist/platform-guidance.js +26 -0
  278. package/dist/posts/dropbox-auth.js +91 -0
  279. package/dist/posts/dropbox-upload.js +132 -0
  280. package/dist/posts/icloud-drive.js +134 -0
  281. package/dist/posts/icloud-status.js +64 -0
  282. package/dist/posts/post-contract.js +2 -0
  283. package/dist/posts/post-copy-format.js +43 -0
  284. package/dist/posts/post-copy.js +193 -0
  285. package/dist/posts/post-folder.js +18 -0
  286. package/dist/posts/post-metrics.js +119 -0
  287. package/dist/posts/post-store.js +340 -0
  288. package/dist/posts/x-post-target.js +43 -0
  289. package/dist/preview-payload.js +90 -0
  290. package/dist/prompt-surfaces.js +22 -0
  291. package/dist/provider-prompt-transform.js +77 -0
  292. package/dist/provider-status-link.js +21 -0
  293. package/dist/provider-task-record.js +78 -0
  294. package/dist/provider-task-status.js +47 -0
  295. package/dist/provider-usage.js +294 -0
  296. package/dist/queue.js +810 -0
  297. package/dist/reference-video-duration.js +17 -0
  298. package/dist/remotion/BlurFillVideo.js +51 -0
  299. package/dist/remotion/KeywordGraphicsOverlay.js +68 -0
  300. package/dist/remotion/OsgOverlay.js +30 -0
  301. package/dist/remotion/QrOutroComposition.js +47 -0
  302. package/dist/remotion/RenderComposition.js +11 -0
  303. package/dist/remotion/browser.js +59 -0
  304. package/dist/remotion/constants.js +35 -0
  305. package/dist/remotion/index.js +66 -0
  306. package/dist/remotion/keyword-graphics.js +151 -0
  307. package/dist/remotion/keyword-placement.js +182 -0
  308. package/dist/remotion/osg-spec.js +198 -0
  309. package/dist/remotion/public/qr-outro-impact.wav +0 -0
  310. package/dist/remotion/qr-outro-audio.js +1 -0
  311. package/dist/remotion/qr-outro-spec.js +211 -0
  312. package/dist/remotion/shared-bundle.js +37 -0
  313. package/dist/remotion/subtitles/AliveCaptions.js +83 -0
  314. package/dist/remotion/subtitles/Highlight.js +58 -0
  315. package/dist/remotion/subtitles/Impact.js +67 -0
  316. package/dist/remotion/subtitles/SubtitleOverlay.js +9 -0
  317. package/dist/remotion/subtitles/alive-layout.js +321 -0
  318. package/dist/remotion/subtitles/alive-types.js +17 -0
  319. package/dist/remotion/subtitles/chunker.js +68 -0
  320. package/dist/remotion/subtitles/segments.js +42 -0
  321. package/dist/remotion/subtitles/styles.js +4 -0
  322. package/dist/remotion/subtitles/types.js +1 -0
  323. package/dist/remotion/util.js +18 -0
  324. package/dist/remotion-cancellation.js +15 -0
  325. package/dist/rename-helpers.js +204 -0
  326. package/dist/rhythm/analyze.js +128 -0
  327. package/dist/rhythm/contract.js +14 -0
  328. package/dist/rhythm/draft-model.js +19 -0
  329. package/dist/rhythm/energy.js +133 -0
  330. package/dist/rhythm/fft.js +44 -0
  331. package/dist/rhythm/model.js +71 -0
  332. package/dist/rhythm/music-analysis.js +124 -0
  333. package/dist/rhythm/music-draft.js +261 -0
  334. package/dist/rhythm/onset.js +101 -0
  335. package/dist/rhythm/run-worker.js +51 -0
  336. package/dist/rhythm/score.js +47 -0
  337. package/dist/rhythm/section-labels.js +168 -0
  338. package/dist/rhythm/sequence-rhythm.js +67 -0
  339. package/dist/rhythm/synthesize.js +103 -0
  340. package/dist/rhythm/timing.js +98 -0
  341. package/dist/rhythm/track.js +320 -0
  342. package/dist/rhythm/visual-fit.js +4 -0
  343. package/dist/rhythm/worker.js +25 -0
  344. package/dist/scene-detect.js +200 -0
  345. package/dist/scene-transition.js +12 -0
  346. package/dist/scheduled-posts.js +200 -0
  347. package/dist/search-index-coverage.js +13 -0
  348. package/dist/search-index-media.js +71 -0
  349. package/dist/search-reference-store.js +60 -0
  350. package/dist/search-scoring.js +17 -0
  351. package/dist/serve.js +125 -0
  352. package/dist/server-lock.js +143 -0
  353. package/dist/server.js +42 -0
  354. package/dist/srt.js +16 -0
  355. package/dist/tag-backfill-state.js +121 -0
  356. package/dist/tag-settings.js +30 -0
  357. package/dist/tag-vocabulary.js +237 -0
  358. package/dist/test-queue-cleanup.js +1 -0
  359. package/dist/time-parse.js +50 -0
  360. package/dist/timeline-helpers.js +554 -0
  361. package/dist/timewarp.js +87 -0
  362. package/dist/tools/_image-inputs.js +9 -0
  363. package/dist/tools/_media-refs.js +84 -0
  364. package/dist/tools/_shared.js +59 -0
  365. package/dist/tools/_suggest-shared.js +279 -0
  366. package/dist/tools/add-timeline-audio.js +73 -0
  367. package/dist/tools/alive-captions.js +157 -0
  368. package/dist/tools/analyze-jokes.js +56 -0
  369. package/dist/tools/analyze-video.js +66 -0
  370. package/dist/tools/animate-keywords.js +217 -0
  371. package/dist/tools/api-status.js +42 -0
  372. package/dist/tools/application-commands.js +34 -0
  373. package/dist/tools/apply-cuts.js +112 -0
  374. package/dist/tools/apply-sfx.js +152 -0
  375. package/dist/tools/apply-watermark.js +670 -0
  376. package/dist/tools/archive-clip.js +74 -0
  377. package/dist/tools/asset-history.js +61 -0
  378. package/dist/tools/asset-manifest.js +24 -0
  379. package/dist/tools/asset-tags.js +151 -0
  380. package/dist/tools/assign-slot.js +97 -0
  381. package/dist/tools/audio-boost.js +107 -0
  382. package/dist/tools/audio-mix.js +121 -0
  383. package/dist/tools/book-usage.js +16 -0
  384. package/dist/tools/chain.js +136 -0
  385. package/dist/tools/change-video-speed.js +105 -0
  386. package/dist/tools/chat-history.js +5 -0
  387. package/dist/tools/chat.js +848 -0
  388. package/dist/tools/clean-video-audio.js +97 -0
  389. package/dist/tools/clear-failed-tasks.js +66 -0
  390. package/dist/tools/cold-open.js +114 -0
  391. package/dist/tools/command-plan.js +1680 -0
  392. package/dist/tools/commands.js +1666 -0
  393. package/dist/tools/concat-images.js +236 -0
  394. package/dist/tools/connect-service.js +55 -0
  395. package/dist/tools/copy-file-to-clipboard.js +58 -0
  396. package/dist/tools/create-character.js +114 -0
  397. package/dist/tools/create-qart.js +253 -0
  398. package/dist/tools/create-qr-outro.js +149 -0
  399. package/dist/tools/create-qrbtf.js +215 -0
  400. package/dist/tools/create-watermark.js +97 -0
  401. package/dist/tools/crop-asset.js +18 -0
  402. package/dist/tools/crop-image.js +120 -0
  403. package/dist/tools/crop-video.js +97 -0
  404. package/dist/tools/delete-asset.js +104 -0
  405. package/dist/tools/describe-image.js +69 -0
  406. package/dist/tools/detect-scenes.js +44 -0
  407. package/dist/tools/doctor.js +126 -0
  408. package/dist/tools/download-video.js +114 -0
  409. package/dist/tools/duplicate-asset.js +184 -0
  410. package/dist/tools/edit-timeline.js +59 -0
  411. package/dist/tools/editing-moments.js +105 -0
  412. package/dist/tools/estimate-cost.js +171 -0
  413. package/dist/tools/even-split.js +295 -0
  414. package/dist/tools/export-asset-file.js +22 -0
  415. package/dist/tools/export-asset.js +140 -0
  416. package/dist/tools/export-sequence.js +250 -0
  417. package/dist/tools/export-to-downloads.js +54 -0
  418. package/dist/tools/export-transcript-srt.js +79 -0
  419. package/dist/tools/extend-audio.js +100 -0
  420. package/dist/tools/extract-audio.js +174 -0
  421. package/dist/tools/extract-frame.js +108 -0
  422. package/dist/tools/extract-notebook-audio.js +173 -0
  423. package/dist/tools/extract-notebook-frame.js +160 -0
  424. package/dist/tools/extract-video-clip.js +101 -0
  425. package/dist/tools/generate-media.js +157 -0
  426. package/dist/tools/generation-payload.js +48 -0
  427. package/dist/tools/get-timeline.js +12 -0
  428. package/dist/tools/get-watermark-config.js +38 -0
  429. package/dist/tools/goal.js +644 -0
  430. package/dist/tools/image-subjects.js +711 -0
  431. package/dist/tools/index.js +323 -0
  432. package/dist/tools/inject-first-frame.js +154 -0
  433. package/dist/tools/invert-image.js +70 -0
  434. package/dist/tools/isolate-vocals.js +66 -0
  435. package/dist/tools/list-assets.js +98 -0
  436. package/dist/tools/list-cell-generations.js +225 -0
  437. package/dist/tools/list-elevenlabs-voices.js +163 -0
  438. package/dist/tools/log-wrapper.js +29 -0
  439. package/dist/tools/make-cover-song.js +95 -0
  440. package/dist/tools/mark-asset-seen.js +23 -0
  441. package/dist/tools/media-library.js +245 -0
  442. package/dist/tools/move-timeline-audio.js +35 -0
  443. package/dist/tools/music-analysis.js +60 -0
  444. package/dist/tools/music-draft.js +29 -0
  445. package/dist/tools/pad-video.js +87 -0
  446. package/dist/tools/post-record.js +83 -0
  447. package/dist/tools/post.js +168 -0
  448. package/dist/tools/prompt-history.js +164 -0
  449. package/dist/tools/provider-key-status.js +248 -0
  450. package/dist/tools/qrbtf-render.js +849 -0
  451. package/dist/tools/read-asset-metadata.js +26 -0
  452. package/dist/tools/read-file-at-commit.js +29 -0
  453. package/dist/tools/read-transcript.js +41 -0
  454. package/dist/tools/reconcile-project-work.js +1452 -0
  455. package/dist/tools/recover-asset.js +28 -0
  456. package/dist/tools/remove-sound.js +72 -0
  457. package/dist/tools/remove-timeline-audio.js +34 -0
  458. package/dist/tools/remove-timeline-slot.js +40 -0
  459. package/dist/tools/rename-all.js +434 -0
  460. package/dist/tools/rename-asset.js +34 -0
  461. package/dist/tools/render-settings.js +47 -0
  462. package/dist/tools/render-timeline.js +120 -0
  463. package/dist/tools/render.js +384 -0
  464. package/dist/tools/reorder-character-images.js +45 -0
  465. package/dist/tools/replace-video-audio.js +133 -0
  466. package/dist/tools/restore-archive-clips.js +209 -0
  467. package/dist/tools/restore-asset-version.js +37 -0
  468. package/dist/tools/retry-generation.js +54 -0
  469. package/dist/tools/reverse-video.js +74 -0
  470. package/dist/tools/rewrite-prompt.js +388 -0
  471. package/dist/tools/rewrite-script.js +67 -0
  472. package/dist/tools/schema-from-apicity.js +66 -0
  473. package/dist/tools/search-archive.js +150 -0
  474. package/dist/tools/semantic-search.js +1214 -0
  475. package/dist/tools/sequence-rhythm.js +43 -0
  476. package/dist/tools/set-character-metadata.js +84 -0
  477. package/dist/tools/set-env-secret.js +40 -0
  478. package/dist/tools/set-osg.js +143 -0
  479. package/dist/tools/show-folder.js +37 -0
  480. package/dist/tools/smooth-scene-concat.js +122 -0
  481. package/dist/tools/splice-video.js +149 -0
  482. package/dist/tools/split-video.js +202 -0
  483. package/dist/tools/suggest-cuts.js +45 -0
  484. package/dist/tools/suggest-sfx.js +43 -0
  485. package/dist/tools/sync-video-to-audio.js +115 -0
  486. package/dist/tools/tag-backfill.js +177 -0
  487. package/dist/tools/timewarp-video.js +85 -0
  488. package/dist/tools/tool-def.js +1 -0
  489. package/dist/tools/tool-json-schema.js +116 -0
  490. package/dist/tools/transcribe.js +90 -0
  491. package/dist/tools/translate-subtitles.js +59 -0
  492. package/dist/tools/trim-audio.js +139 -0
  493. package/dist/tools/trim-video.js +168 -0
  494. package/dist/tools/update-script.js +25 -0
  495. package/dist/tools/update-timeline-audio.js +40 -0
  496. package/dist/tools/upload-file.js +41 -0
  497. package/dist/tools/verify-x-mentions.js +141 -0
  498. package/dist/tools/video-editing-command-contract.js +291 -0
  499. package/dist/tools/video-source-reference.js +30 -0
  500. package/dist/tools/video-time-input.js +18 -0
  501. package/dist/tools/videobook-domain.js +2021 -0
  502. package/dist/tools/wait-for-asset-ready.js +143 -0
  503. package/dist/tools/workspace-actions.js +54 -0
  504. package/dist/transcript-projection.js +202 -0
  505. package/dist/transcript-srt.js +33 -0
  506. package/dist/upload.js +76 -0
  507. package/dist/usage-providers.js +25 -0
  508. package/dist/video-analysis-projection.js +46 -0
  509. package/dist/video-poster.js +33 -0
  510. package/dist/video-proxy.js +99 -0
  511. package/dist/vision-regions.js +111 -0
  512. package/dist/voice-actions.js +90 -0
  513. package/dist/voice-audio.js +55 -0
  514. package/dist/voice-config.js +122 -0
  515. package/dist/voice-continuation.js +54 -0
  516. package/dist/voice-contract.js +1 -0
  517. package/dist/voice-http.js +145 -0
  518. package/dist/voice-reply-progress.js +55 -0
  519. package/dist/voice-session.js +992 -0
  520. package/dist/watermark-badge.js +259 -0
  521. package/dist/watermark-config.js +111 -0
  522. package/dist/watermark-handle-position.js +55 -0
  523. package/dist/watermark-platform.js +15 -0
  524. package/dist/watermark-timing.js +16 -0
  525. package/dist/workspace-action-catalog.js +315 -0
  526. package/dist/workspace-action-contract.js +21 -0
  527. package/dist/workspace-action-groups.js +98 -0
  528. package/dist/workspace-action-surfaces.js +7 -0
  529. package/dist/x/account.js +88 -0
  530. package/dist/x/authenticated-handle.js +30 -0
  531. package/dist/x/oauth-flow.js +191 -0
  532. package/dist/x/post-contract.js +1 -0
  533. package/dist/x/post-metadata.js +44 -0
  534. package/dist/x/post-to-x.js +456 -0
  535. package/dist/x/published-post-cell.js +90 -0
  536. package/dist/x/x-tokens.js +69 -0
  537. package/dist/ytdlp-binary.js +65 -0
  538. package/dist/zod-slots.js +334 -0
  539. package/package.json +84 -4
  540. package/ui/assets/alive-captions-BWb5nLKj.css +1 -0
  541. package/ui/assets/alive-captions-DPEr1nKM.js +1 -0
  542. package/ui/assets/confirm-bodies-D8ouHXKy.js +1 -0
  543. package/ui/assets/confirm-bodies-DrMhaXC6.css +1 -0
  544. package/ui/assets/fullscreen-B7nw4YbE.js +1 -0
  545. package/ui/assets/goal-ui-DK-xTCK0.js +2 -0
  546. package/ui/assets/goal-ui-DXdUM2KF.css +1 -0
  547. package/ui/assets/index-DzPAnCUj.css +1 -0
  548. package/ui/assets/index-kS1905s5.js +37 -0
  549. package/ui/assets/inspector-MlzQbTVo.js +1 -0
  550. package/ui/assets/jobs-ui-CoinOWx0.js +1 -0
  551. package/ui/assets/music-video-Cbe80kmQ.js +1 -0
  552. package/ui/assets/music-video-DPaiKKEq.css +1 -0
  553. package/ui/assets/ui-Oirr9VOf.css +1 -0
  554. package/ui/assets/ui-xo_Y1yQg.js +2 -0
  555. package/ui/assets/vendor-D2rfiZ5j.css +1 -0
  556. package/ui/assets/vendor-DfTCWgKm.js +19 -0
  557. package/ui/assets/vendor-flow-BXbeWxW7.js +7 -0
  558. package/ui/assets/vendor-flow-BnuhLJ6X.css +1 -0
  559. package/ui/assets/vendor-icons-CGqhCIXV.js +1 -0
  560. package/ui/assets/vendor-mcp-BTlEJcHV.js +67 -0
  561. package/ui/assets/vendor-react-Dj7D1fD4.js +9 -0
  562. package/ui/assets/vendor-remotion-CH1HXrlc.js +95 -0
  563. package/ui/assets/videobook-Qlp9HQFu.js +20 -0
  564. package/ui/favicon.svg +8 -0
  565. package/ui/index.html +126 -0
@@ -0,0 +1,144 @@
1
+ export const GOAL_STYLE_IDS = ["source", "cinematic", "ig-influencer"];
2
+ const styles = {
3
+ source: {
4
+ id: "source", label: "Match source", summary: "Keep the look, camera and lighting of the source screenshot.",
5
+ briefKeywords: [], defaults: { imageModel: "nano-banana-2-1", imageResolution: "2K", videoResolution: "720p" },
6
+ planner: "Infer the visual style, framing, lighting and camera from the scene reference. Preserve that look. Identify the scene screenshot, character references and prop references from the actual images and brief. Reference images are not necessarily people. Remove social-media interface overlays from generated pictures.",
7
+ fragments: {
8
+ frame: "Match the source scene's framing, lighting and visual style; remove interface overlays",
9
+ storyboard: "Keep the approved scene's visual style, people and props",
10
+ ending: "Keep the approved scene's visual style",
11
+ video: "Match the approved scene's camera and lighting; natural ambient sound",
12
+ revise: "Preserve the selected image's visual style",
13
+ },
14
+ banned: [], options: [],
15
+ },
16
+ cinematic: {
17
+ id: "cinematic", label: "Cinematic", summary: "Photographic live-action with natural proportions, textures and motion.",
18
+ briefKeywords: ["cinematic"], defaults: {},
19
+ planner: "Photographic live-action. Natural proportions, real skin and material textures, practical light. Restrained expressions and plausible motion. Comedy comes from situations and timing; avoid cartoon rendering, caricature, rubbery movement and exaggerated features.",
20
+ fragments: {
21
+ frame: "Photographic live-action, natural proportions, real textures",
22
+ storyboard: "Photographic live-action, natural proportions, real textures",
23
+ ending: "Photographic live-action, natural proportions, real textures",
24
+ video: "Live-action, natural motion, restrained expressions",
25
+ revise: "Photographic live-action, natural proportions, real textures",
26
+ },
27
+ banned: [], options: [],
28
+ },
29
+ "ig-influencer": {
30
+ id: "ig-influencer", label: "IG Influencer", summary: "Hyper-realistic, candid iPhone footage with natural skin and light.",
31
+ briefKeywords: ["ig influencer", "instagram influencer", "influencer", "insta reel", "instagram reel"],
32
+ defaults: { aspectRatio: "9:16", imageModel: "sunburst", imageResolution: "2K", videoResolution: "720p" },
33
+ planner: "Use a hyper-realistic Instagram phone-camera register: real-world activity in present tense, one location per shot, candid framing with slight imperfection, light grain, unretouched skin with visible pores and texture. Use the selected iPhone camera and lighting; natural daylight or soft indoor light by default. No HDR crunch or beautify. No captions or on-screen text inside pictures or video; storyboard notes go below pictures. Avoid cinematic, masterpiece, editorial, Portra, Cinestill and all film-stock vocabulary. Match the delivery: address the camera for selfies, be caught mid-action when filmed by a friend, hold framing steady on a tripod, or show the reflection for a mirror shot. Make the selected content format explicit in the four beats. Sound is ambient room or street sound with an optional short spoken line.",
34
+ fragments: {
35
+ frame: "hyper-realistic, skin pores, light grain",
36
+ storyboard: "hyper-realistic, skin pores, light grain",
37
+ ending: "hyper-realistic, skin pores",
38
+ video: "hyper-realistic skin pores, natural motion, handheld micro-shake, ambient sound",
39
+ revise: "hyper-realistic, skin pores",
40
+ },
41
+ banned: ["cinematic", "masterpiece", "editorial", "Portra", "Cinestill"],
42
+ options: [
43
+ {
44
+ key: "format", label: "Content format", default: "day-in-the-life",
45
+ choices: [
46
+ { value: "grwm", label: "GRWM", prompt: "GRWM", briefKeywords: ["grwm", "get ready with me"], beats: "skincare, outfit, final look, mirror check" },
47
+ { value: "ootd", label: "OOTD", prompt: "OOTD", briefKeywords: ["ootd", "outfit of the day"], beats: "reveal, details, walk, turn" },
48
+ { value: "day-in-the-life", label: "Day in the life", prompt: "day-in-the-life", briefKeywords: ["day in the life", "vlog"], beats: "arrive, begin activity, react, finish" },
49
+ { value: "travel-reel", label: "Travel reel", prompt: "travel", briefKeywords: ["travel reel"], beats: "arrive, explore, discover, farewell" },
50
+ { value: "cafe", label: "Café", prompt: "café", briefKeywords: ["brunch", "cafe", "café"], beats: "order, receive drink, taste, smile" },
51
+ { value: "gym", label: "Gym", prompt: "gym", briefKeywords: ["gym"], beats: "warm up, exercise, effort, recover" },
52
+ { value: "skincare", label: "Skincare", prompt: "skincare", briefKeywords: ["skincare"], beats: "cleanse, apply, massage, reveal" },
53
+ { value: "haul", label: "Haul", prompt: "haul", briefKeywords: ["haul"], beats: "unpack, show item, try on, react" },
54
+ { value: "storytime", label: "Storytime", prompt: "storytime", briefKeywords: ["storytime"], beats: "hook, explain, react, conclude" },
55
+ ],
56
+ },
57
+ {
58
+ key: "delivery", label: "Delivery", default: "selfie-to-camera",
59
+ choices: [
60
+ { value: "selfie-to-camera", label: "Selfie to camera", prompt: "selfie", briefKeywords: ["selfie", "front camera"] },
61
+ { value: "filmed-by-friend", label: "Filmed by a friend", prompt: "friend-filmed", briefKeywords: ["filmed by"] },
62
+ { value: "tripod", label: "Tripod", prompt: "tripod", briefKeywords: ["tripod"] },
63
+ { value: "mirror", label: "Mirror", prompt: "mirror", briefKeywords: ["mirror"] },
64
+ ],
65
+ },
66
+ {
67
+ key: "camera", label: "Camera", default: "iphone-front",
68
+ choices: [
69
+ { value: "iphone-front", label: "iPhone front camera", prompt: "iPhone front", briefKeywords: ["front camera", "iphone front"] },
70
+ { value: "iphone-main", label: "iPhone main camera", prompt: "iPhone main", briefKeywords: ["main camera", "iphone main"] },
71
+ ],
72
+ },
73
+ {
74
+ key: "light", label: "Light", default: "soft-daylight",
75
+ choices: [
76
+ { value: "soft-daylight", label: "Soft daylight", prompt: "soft daylight", briefKeywords: ["soft daylight", "natural daylight"] },
77
+ { value: "golden-hour", label: "Golden hour", prompt: "golden hour", briefKeywords: ["golden hour"] },
78
+ { value: "indoor-warm", label: "Warm indoor light", prompt: "warm indoor", briefKeywords: ["warm indoor", "indoor warm"] },
79
+ { value: "night-flash", label: "Night flash", prompt: "night flash", briefKeywords: ["night out", "flash"] },
80
+ ],
81
+ },
82
+ ],
83
+ },
84
+ };
85
+ export function goalStyle(id) {
86
+ return styles[id];
87
+ }
88
+ export function resolveGoalStyleOptions(id, partial = {}) {
89
+ const style = goalStyle(id);
90
+ for (const key of Object.keys(partial)) {
91
+ if (!style.options.some(option => option.key === key))
92
+ throw new Error(`Unknown ${style.label} option: ${key}`);
93
+ }
94
+ const resolved = {};
95
+ for (const option of style.options) {
96
+ const fallback = option.key === "camera" && resolved.delivery !== "selfie-to-camera" ? "iphone-main" : option.default;
97
+ const value = partial[option.key] ?? fallback;
98
+ if (!option.choices.some(choice => choice.value === value)) {
99
+ throw new Error(`Invalid ${style.label} ${option.label}: ${value}. Choose ${option.choices.map(choice => choice.value).join(", ")}.`);
100
+ }
101
+ resolved[option.key] = value;
102
+ }
103
+ return resolved;
104
+ }
105
+ export function goalStyleFragment(selection, stage) {
106
+ const style = goalStyle(selection.id);
107
+ const options = resolveGoalStyleOptions(selection.id, selection.options);
108
+ let fragment = style.fragments[stage];
109
+ if (!fragment)
110
+ return "";
111
+ if (stage === "video" && options.delivery === "tripod")
112
+ fragment = fragment.replace("handheld micro-shake", "steady framing");
113
+ const pieces = style.options.map(option => option.choices.find(choice => choice.value === options[option.key]).prompt);
114
+ return `${pieces.length ? `${pieces.join(", ")}: ` : ""}${fragment}.`;
115
+ }
116
+ export function goalStyleSummary(selection) {
117
+ const style = goalStyle(selection.id);
118
+ const options = resolveGoalStyleOptions(selection.id, selection.options);
119
+ return [style.label, ...style.options.map(option => option.choices.find(choice => choice.value === options[option.key]).label)].join(" · ");
120
+ }
121
+ export function goalStylesEqual(left, right) {
122
+ if (left.id !== right.id)
123
+ return false;
124
+ const a = resolveGoalStyleOptions(left.id, left.options);
125
+ const b = resolveGoalStyleOptions(right.id, right.options);
126
+ return Object.keys(a).every(key => a[key] === b[key]);
127
+ }
128
+ function firstKeyword(brief, keywords) {
129
+ return Math.min(...keywords.map(keyword => {
130
+ const pattern = keyword.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&").replace(/[ -]+/gu, "[\\s-]+");
131
+ const match = new RegExp(`(^|[^\\p{L}\\p{N}_-])${pattern}(?=$|[^\\p{L}\\p{N}_-])`, "iu").exec(brief);
132
+ return match ? match.index + match[1].length : Infinity;
133
+ }));
134
+ }
135
+ export function goalBriefStyle(brief) {
136
+ const style = GOAL_STYLE_IDS.map(id => ({ style: goalStyle(id), index: firstKeyword(brief, goalStyle(id).briefKeywords) }))
137
+ .filter(match => Number.isFinite(match.index)).sort((left, right) => left.index - right.index)[0]?.style ?? goalStyle("source");
138
+ const partial = Object.fromEntries(style.options.flatMap(option => {
139
+ const choice = option.choices.map(candidate => ({ value: candidate.value, index: firstKeyword(brief, candidate.briefKeywords) }))
140
+ .filter(match => Number.isFinite(match.index)).sort((left, right) => left.index - right.index)[0];
141
+ return choice ? [[option.key, choice.value]] : [];
142
+ }));
143
+ return { id: style.id, options: resolveGoalStyleOptions(style.id, partial) };
144
+ }
@@ -0,0 +1,157 @@
1
+ import { join } from "node:path";
2
+ import { v7 as uuidv7 } from "uuid";
3
+ import { findPrimaryMediaFile, nextHorizontalSlotFrom } from "videobook-engine";
4
+ import { notebookGridTag, notebookOccupiedSlots } from "videobook-engine/notebook-grid";
5
+ import { scanNotebookMentions } from "videobook-engine/notebook-mentions";
6
+ import { probeVideo } from "./ffmpeg.js";
7
+ import { closestGoalAspectRatio, compileGoalV3Steps } from "./goal-plan-v3.js";
8
+ import { captureFrame } from "./notebook-media-ops.js";
9
+ import { EXTRACT_FRAME_OUTPUT_ROLE } from "./notebook-cell-outputs.js";
10
+ import { mutateNotebook } from "./notebook-mutations.js";
11
+ import { slotRight } from "./notebook-placement.js";
12
+ import { notebookCellFingerprint } from "./jobs/run-notebook.js";
13
+ import { queue } from "./queue.js";
14
+ import { resolveNotebookPromptReferences } from "./notebook-reference-resolver.js";
15
+ import { assessToolCallEstimate } from "./jobs/cost-estimate-assessment.js";
16
+ const GOAL_MEDIA_HELP = "Mention the reference images or videos in the brief, for example /goal @a1 @a2 as ...";
17
+ function mediaKind(kind, cellType) {
18
+ if (kind === "image" || cellType === "image" || cellType === "generate_image")
19
+ return "image";
20
+ if (kind === "video" || kind === "final" || ["video", "generate_video", "concat", "splice", "split_video"].includes(cellType))
21
+ return "video";
22
+ return null;
23
+ }
24
+ export async function resolveGoalMediaReferences(engine, document, brief) {
25
+ if (scanNotebookMentions(brief).length === 0)
26
+ throw new Error(GOAL_MEDIA_HELP);
27
+ const resolved = resolveNotebookPromptReferences({ engine, document, prompt: brief, requireMedia: true });
28
+ if (resolved.unresolved.length > 0)
29
+ throw new Error(resolved.unresolved[0].message);
30
+ const references = [];
31
+ const seen = new Set();
32
+ for (const reference of resolved.resolved) {
33
+ if (seen.has(reference.artifactId))
34
+ continue;
35
+ const artifact = engine.artifacts.get(reference.artifactId);
36
+ const cell = document.cells.find(candidate => candidate.id === reference.cellId);
37
+ const kind = artifact.ok && cell ? mediaKind(artifact.value.kind, cell.type) : null;
38
+ if (!artifact.ok || !cell || !kind)
39
+ throw new Error(`${reference.mention} is not an image or video`);
40
+ const manifest = await engine.files.manifest(reference.artifactId);
41
+ const file = manifest.ok ? findPrimaryMediaFile(manifest.value.files, kind === "image" ? "image" : "video") : null;
42
+ if (!manifest.ok || !file)
43
+ throw new Error(`${reference.mention} has no readable media`);
44
+ seen.add(reference.artifactId);
45
+ references.push({
46
+ kind,
47
+ artifactId: reference.artifactId,
48
+ cellId: cell.id,
49
+ address: notebookGridTag(cell.slot),
50
+ label: artifact.value.label || cell.label || reference.mention,
51
+ objectHash: file.objectHash,
52
+ });
53
+ }
54
+ if (references.length === 0)
55
+ throw new Error(GOAL_MEDIA_HELP);
56
+ return references;
57
+ }
58
+ async function frameImageFile(engine, artifactId) {
59
+ const manifest = await engine.files.manifest(artifactId);
60
+ if (!manifest.ok)
61
+ throw new Error(manifest.error.message);
62
+ const file = findPrimaryMediaFile(manifest.value.files, "image");
63
+ if (!file)
64
+ throw new Error("The scene frame has no image file");
65
+ return { path: join(manifest.value.path, file.name), objectHash: file.objectHash };
66
+ }
67
+ async function insertSceneFrameCell(engine, notebookId, video, artifactId, atSeconds) {
68
+ const placed = { cell: null };
69
+ const runId = uuidv7();
70
+ const result = await mutateNotebook(engine, notebookId, "goal_scene_frame", (notebook) => {
71
+ const anchor = notebook.cells.find(cell => cell.id === video.cellId);
72
+ if (!anchor)
73
+ throw new Error(`${video.address} was removed`);
74
+ const cell = engine.notebooks.createCell({
75
+ type: "image",
76
+ label: `Frame at ${atSeconds}s`,
77
+ slot: nextHorizontalSlotFrom(slotRight(anchor.slot), notebookOccupiedSlots(notebook.cells)),
78
+ outputArtifactId: artifactId,
79
+ inputs: { mediaRole: EXTRACT_FRAME_OUTPUT_ROLE, frameMode: "time", timestampSeconds: atSeconds, atSeconds, sourceCellId: anchor.id, state: "completed" },
80
+ });
81
+ placed.cell = cell;
82
+ const completedAt = new Date().toISOString();
83
+ return {
84
+ ...notebook,
85
+ cells: [...notebook.cells, cell],
86
+ edges: [...notebook.edges, engine.notebooks.createEdge({ source: anchor.id, target: cell.id, targetInput: "segment" })],
87
+ execution: {
88
+ ...(notebook.execution ?? {}),
89
+ [cell.id]: { fingerprint: notebookCellFingerprint(notebook, cell), status: "completed", runId, outputArtifactId: artifactId, completedAt, updatedAt: completedAt, tool: "ffmpeg" },
90
+ },
91
+ };
92
+ }, { sourceCellId: video.cellId, runId }, { artifactId });
93
+ if (!result.ok)
94
+ throw new Error(result.error.message);
95
+ if (!placed.cell)
96
+ throw new Error("The scene frame could not be placed");
97
+ return placed.cell;
98
+ }
99
+ export async function captureGoalSceneFrame(engine, notebookId, references) {
100
+ const video = references.find(reference => reference.kind === "video");
101
+ if (!video)
102
+ return null;
103
+ const captured = await captureFrame(engine, video.artifactId, { role: "time", timestampSeconds: 1, title: `${video.address} · scene frame` });
104
+ const file = await frameImageFile(engine, captured.artifactId);
105
+ const probe = await probeVideo(file.path);
106
+ await queue.enqueue(`process-image-${captured.artifactId}`, {
107
+ type: "process_image", assetId: captured.artifactId, bookId: engine.book.get().bookId, extension: ".jpg",
108
+ provenance: { origin: "extract_frame", sourceArtifactId: video.artifactId, frameMode: "time", atSeconds: captured.atSeconds },
109
+ });
110
+ const cell = await insertSceneFrameCell(engine, notebookId, video, captured.artifactId, captured.atSeconds);
111
+ return {
112
+ reference: {
113
+ kind: "image", artifactId: captured.artifactId, cellId: cell.id, address: notebookGridTag(cell.slot),
114
+ label: cell.label ?? "Scene frame", objectHash: file.objectHash,
115
+ },
116
+ seconds: captured.atSeconds,
117
+ aspectRatio: closestGoalAspectRatio(probe.width, probe.height),
118
+ };
119
+ }
120
+ function estimateInput(engine, plan, step) {
121
+ const images = (step.id === "video" ? plan.video.imageRefs : plan.scene.imageRefs).map(reference => reference.artifactId);
122
+ const videos = step.id === "video" ? plan.video.videoRefs.map(reference => reference.artifactId) : [];
123
+ return {
124
+ book_id: engine.book.get().bookId,
125
+ ...step.params,
126
+ refs: { image: images, video: videos },
127
+ ...(step.id === "video" && images.length + videos.length > 0 ? { mode: "r2v" } : {}),
128
+ };
129
+ }
130
+ export async function estimateGoalV3(engine, plan) {
131
+ const [scene, video] = compileGoalV3Steps(plan);
132
+ const priced = await Promise.all([scene, video].map(async (step) => {
133
+ const estimate = await assessToolCallEstimate(engine, step.tool, estimateInput(engine, plan, step));
134
+ return { usd: estimate.available ? estimate.usd ?? null : null, warnings: estimate.warnings };
135
+ }));
136
+ const frame = priced[0];
137
+ const videos = priced[1];
138
+ const storyboards = { usd: 0, warnings: [] };
139
+ const parts = [frame, storyboards, videos];
140
+ return {
141
+ frame,
142
+ storyboards,
143
+ videos,
144
+ total: {
145
+ usd: parts.every(part => part.usd !== null) ? parts.reduce((sum, part) => sum + (part.usd ?? 0), 0) : null,
146
+ warnings: [...new Set(parts.flatMap(part => part.warnings))],
147
+ },
148
+ };
149
+ }
150
+ export function goalMediaCharacters(references) {
151
+ return references.filter(reference => reference.kind === "image").map(reference => ({
152
+ artifactId: reference.artifactId,
153
+ cellId: reference.cellId,
154
+ address: reference.address,
155
+ label: reference.label,
156
+ }));
157
+ }
@@ -0,0 +1,70 @@
1
+ # Character extraction guide
2
+
3
+ You are an expert visual analyst. Look at the photograph and emit a structured **character profile** that downstream image-generation models can use to re-render this same identity across different garments, poses, and scenes.
4
+
5
+ Return ONLY a JSON object matching the schema below. Do NOT wrap it in markdown fences or prose.
6
+
7
+ ## Subject kinds
8
+
9
+ Pick exactly one `subject_kind` from this 4-way set, based on what the photograph shows:
10
+
11
+ - `female` — a human female-presenting subject.
12
+ - `male` — a human male-presenting subject.
13
+ - `animal` — a non-human living subject (cat, dog, horse, bird, etc.).
14
+ - `other` — anything else: an object, sculpture, doll, paper figure, mascot costume, abstract form, etc.
15
+
16
+ The schema branches on this field. **Fill the human field set OR the freeform `other` field — never both.**
17
+
18
+ ## Field rules — `female` / `male`
19
+
20
+ For human subjects, fill every required field with **concrete visual descriptors**. Image generators reproduce what they can render — anatomical structure, color, texture, geometry. They don't reproduce vibes from vague adjectives.
21
+
22
+ - ✅ "hooded almond-shaped hazel eyes with thick lower lashes"
23
+ - ❌ "kind, intelligent eyes"
24
+ - ✅ "shoulder-length wavy chestnut hair, side-parted, slight frizz at the temples"
25
+ - ❌ "messy brown hair"
26
+
27
+ **Body measurements (`bust`, `waist`, `hips`) are the primary signal for re-rendering body shape consistently.** The `bust` field is the chest/bust geometry field: for `male` describe chest width, pectoral shape, and ribcage taper; for `female` describe bust size, cup estimate, distribution, and placement. Estimate concrete shape descriptors from the photograph — exact numeric measurements aren't usually possible, but chest width, cup size, waist taper, and hip width almost always are. Face / hair / eyes / skin remain useful but are **secondary** to body measurements.
28
+
29
+ If a detail isn't visible, give the best plausible reading. Never write "unknown" — pick a concrete descriptor.
30
+
31
+ ## Field rules — `animal` / `other`
32
+
33
+ For animal and other subjects, fill **only** the freeform `other` field — a single dense description that downstream models can use to re-render the same subject. Pack it with concrete visual detail.
34
+
35
+ - For `animal`: species, breed, color, coat/fur length and texture, body proportions, distinguishing markings, eye color, ear/tail shape. Example: `"white domestic longhair cat, slender long-bodied build, fluffy medium-long silky fur, heterochromatic blue and golden eyes, pointed ears, plumed tail"`.
36
+ - For `other`: what the subject is, materials, surface texture, color, structural form, distinguishing features. Example: `"origami paper man, folded white cardstock with sharp creases, blank flat face, articulated arms and legs, ~30cm tall"`.
37
+
38
+ Do not fill the human fields (`age`, `ethnicity`, `height`, `build`, `bust`, `waist`, `hips`, `face`, `hair`, `eyes`, `skin`) for `animal` or `other`. Leave them out of the JSON.
39
+
40
+ ## Schema
41
+
42
+ ```json
43
+ {
44
+ "name": "string — optional, leave blank or omit (the user fills this in)",
45
+ "subject_kind": "string — REQUIRED. One of: 'female', 'male', 'animal', 'other'.",
46
+
47
+ // Required ONLY when subject_kind is 'female' or 'male' — omit otherwise.
48
+ "age": "string — e.g. 'early 20s', 'mid-30s', '47'",
49
+ "ethnicity": "string — e.g. 'East Asian', 'Black / West African heritage', 'Latina', 'White / Northern European'",
50
+ "height": "string — height estimate, include a numeric estimate when possible (e.g. 'tall, ~6'0\" / 183cm')",
51
+ "build": "string — body build, e.g. 'lean athletic', 'slender', 'stocky compact'",
52
+ "bust": "string — chest/bust size + shape. For 'male': chest width, pectoral fullness, ribcage taper. For 'female': cup size estimate + distribution.",
53
+ "waist": "string — waist shape and taper",
54
+ "hips": "string — hip shape and width",
55
+ "face": "string — face structure. 1-2 sentences.",
56
+ "hair": "string — color, length, texture, density, hairline; describe the reference hairstyle itself. 1 sentence.",
57
+ "eyes": "string — color, shape, lash density, brow shape. 1 sentence.",
58
+ "skin": "string — skin tone and texture. 1 sentence.",
59
+
60
+ // Required ONLY when subject_kind is 'animal' or 'other' — omit for 'female'/'male'.
61
+ "other": "string — a single dense freeform description packed with concrete visual detail. 1-3 sentences."
62
+ }
63
+ ```
64
+
65
+ ## Constraints
66
+
67
+ - Each descriptive field is at most 2 short sentences (3 for `other`).
68
+ - Total JSON must be under 2000 characters.
69
+ - Do NOT include a `name` value — leave it empty or omit the key. The name is user-owned.
70
+ - Do NOT speculate about profession, mood beyond the photo, or relationships.
@@ -0,0 +1,21 @@
1
+ ---
2
+ source: "https://developers.openai.com/api/docs/guides/image-generation"
3
+ models: "GPT Image 2.5 Sunburst and Flare"
4
+ ---
5
+
6
+ # GPT Image 2.5 Prompting Guide
7
+
8
+ Sunburst is the default for precise image editing. Flare is available for fast everyday generation. Both support text prompts and reference images.
9
+
10
+ Describe the subject, composition, setting, lighting, style, and intended use in clear language. Put essential constraints first. Quote any exact text that must appear and describe its placement and typography.
11
+
12
+ For edits, state what must change and what must remain: identity, pose, framing, colors, layout, or background. Refer to multiple inputs by their order, such as image 1 and image 2, and describe the role of each. Preserve the user's reference order and requested visual details.
13
+
14
+ Videobook uses Kie's GPT Image 2.5 endpoints. Supported controls come from Apicity:
15
+
16
+ - Up to 16 optional reference images; no references selects text-to-image.
17
+ - Aspect ratio: auto, 1:1, 3:2, 2:3, 4:3, 3:4, 16:9, 9:16, 21:9, 27:16, 16:27, 9:8, or 8:9.
18
+ - Resolution: 1K, 2K, or 4K. Ratios 27:16, 16:27, 9:8, and 8:9 require 1K.
19
+ - Background: transparent, opaque, or auto.
20
+
21
+ Use only controls exposed by the selected provider. Keep aspect ratio, resolution, and background in their structured fields instead of adding API parameter names to the visual prompt. Do not add quality or NSFW-checker parameters to these Kie requests.
@@ -0,0 +1,72 @@
1
+ ---
2
+ source: "docs.x.ai/docs/guides/image-generation, docs.x.ai/docs/guides/video-generation, grokimagineai.net/prompt-guide, genaintel.com/guides/how-to-prompt-grok-imagine"
3
+ type: reference
4
+ date_added: 2026-02-14
5
+ ---
6
+
7
+ # Grok Imagine Prompting Guide
8
+
9
+ ## Summary
10
+
11
+ Grok Imagine is xAI's multimodal generation system built on the Aurora model, an autoregressive mixture-of-experts network trained on interleaved text and image data. It supports text-to-image, image editing, text-to-video, image-to-video, and video editing. Aurora excels at photorealistic rendering and precise instruction following. Grok Imagine responds best to natural language scene descriptions rather than keyword lists — write prompts like scene direction, not tag stacking.
12
+
13
+ ## Key Takeaways
14
+
15
+ - Prompts should read as natural scene descriptions, not keyword lists — the model interprets context intelligently
16
+ - **Text-to-video formula:** Subject + Movement + Scene + Shot, Style
17
+ - **Image-to-video formula:** Subject + Motion, Background + Motion, Camera + Motion
18
+ - **Five-part structure for images:** Scene (what's happening) + Style (aesthetic) + Mood (emotional direction) + Lighting (time/quality) + Camera (shot type/lens/focus)
19
+ - Place the main subject and action first — the model weights the opening of the prompt most heavily
20
+ - Image-to-video prompts should reduce static element descriptions since the model expands from the input image
21
+ - Negative prompts are ignored by the model — use explicit positive descriptions instead
22
+ - Camera movement commands understood: zoom, pan, tilt, surround, aerial, follow, handheld, lens switching
23
+ - Use "Shot Switch" to separate distinct camera angles in multi-shot sequences
24
+ - Select "unfixed lens" when including camera movement in video generation
25
+ - Intensity modifiers (quickly, violently, with large amplitude, powerfully, wildly) specify motion the model cannot infer from static images
26
+ - Iterative refinement works best when adjusting one variable per iteration (lighting OR camera OR mood)
27
+ - Batch generation supports up to 10 images per request for same-prompt variations
28
+
29
+ ## Style Keywords
30
+
31
+ - **Realism:** photoreal detail, natural lighting, documentary feel
32
+ - **Anime:** vibrant cel-shading, expressive linework
33
+ - **Painterly:** oil-painting texture, impressionist glow
34
+ - **Cinematic:** volumetric lighting, film grain, dynamic shadows
35
+ - **Surreal:** dreamlike distortion, ethereal glow
36
+ - **Graphic Novel:** inked outlines, bold contrasts, neon lines
37
+ - Also supports: pencil sketch, pop art, watercolor, impressionism
38
+
39
+ ## Composition Control
40
+
41
+ - Wide establishing shots for scale and context
42
+ - Low-angle shots for heroic or imposing framing
43
+ - Close-ups for emotion and texture
44
+ - Over-the-shoulder for conversation and tension
45
+ - Shallow depth of field for subject isolation
46
+
47
+ ## Emotion-Driven Language
48
+
49
+ The model responds strongly to atmospheric vocabulary: nostalgic, melancholic, electric, tense, dreamlike. Emotional tone shapes the entire output more than technical descriptors alone.
50
+
51
+ ## Technical Parameters
52
+
53
+ ### Image Generation
54
+ - **Aspect ratios:** 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 2:1, 1:2, auto
55
+ - **Resolution:** 1K or 2K
56
+ - **Batch size:** up to 10 images per request
57
+ - **Pricing:** flat per-image (not token-based)
58
+
59
+ ### Video Generation
60
+ - **Duration:** 1–15 seconds (generation), up to 8.7 seconds (editing)
61
+ - **Resolution:** 480p or 720p
62
+ - **Aspect ratios:** 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3
63
+ - **Lens type:** fixed or unfixed (unfixed required for camera movement)
64
+
65
+ ## Common Mistakes
66
+
67
+ - Tag stacking instead of natural language (produces generic results)
68
+ - Weak verbs — use "surges," "unfurls," "erupts" instead of "standing," "sitting"
69
+ - Missing time-of-day or weather cues
70
+ - Vague aesthetic directions without specific style anchors
71
+ - Conflicting adjective overload
72
+ - Contradicting the input image in image-to-video prompts
@@ -0,0 +1,84 @@
1
+ # Image Reproduction Prompt Guide
2
+
3
+ Your output is fed directly into an image generator. Produce a prompt that — if given to a capable model with no other context — would reproduce the image as closely as possible in subject, framing, light, and feel.
4
+
5
+ ## Output shape
6
+
7
+ Return a JSON object with these fields:
8
+
9
+ ```json
10
+ {
11
+ "prompt": "single paragraph prompt, no line breaks, fed directly to an image model",
12
+ "shot": "shot size + camera angle in standard cinematography terms — see rules below",
13
+ "pose": "pure body pose of any human figure(s) — body geometry only, see rules below"
14
+ }
15
+ ```
16
+
17
+ ## Rules for the `shot` field
18
+
19
+ Format: `"<size>, <angle>"`. Always include both, comma-separated, lowercase.
20
+
21
+ **Size** — pick exactly one (terms from standard cinematography):
22
+
23
+ - `extreme close-up` (ECU/XCU) — a single feature fills the frame (eyes, mouth, hands, a detail)
24
+ - `close-up` (CU) — head fills the frame
25
+ - `medium close-up` (MCU) — head and shoulders, roughly chest-up
26
+ - `medium shot` (MS) — waist up
27
+ - `medium long shot` (MLS) — knees up (also called American shot / cowboy shot)
28
+ - `long shot` (LS) — full figure head to toe, roughly fills frame height
29
+ - `extreme long shot` (ELS/EWS) — figure small inside a dominant environment
30
+
31
+ **Angle** — pick exactly one:
32
+
33
+ - `eye-level` — camera at subject's eye height
34
+ - `low-angle` — camera below subject, looking up
35
+ - `high-angle` — camera above subject, looking down
36
+ - `overhead` — straight down, bird's-eye
37
+ - `dutch` — camera tilted, horizon askew
38
+
39
+ Examples: `"medium close-up, eye-level"`, `"long shot, low-angle"`, `"extreme close-up, overhead"`.
40
+
41
+ If there is no human or recognisable subject (pure landscape, abstract texture), still emit the closest size and angle for the dominant element.
42
+
43
+ ## Rules for the `pose` field
44
+
45
+ Only emit `pose` when the image contains one or more human figures. Describe the body's geometry only:
46
+
47
+ - Weight distribution and stance (e.g. weight on right leg, left foot crossed in front on the ball, contrapposto, kneeling, seated cross-legged, walking mid-stride).
48
+ - Rotation of hips, torso, shoulders, and head relative to camera (e.g. hips three-quarters away, torso twisted back over right shoulder, head turned further than shoulders into three-quarter view).
49
+ - Spine curvature (S-curve, arched, slumped, neutral).
50
+ - Arm and leg positions, including elbow/knee bend and where the hands rest or what they grip.
51
+
52
+ For close-ups where part of the body is out of frame, also describe the **implied posture** suggested by what's visible — what the off-frame body must be doing for the in-frame parts to make sense (e.g. "leaning forward with folded arms resting on a flat surface at chest height", "seated at a table with elbows on the surface", "lying prone with chin propped on hands"). Make this implied-posture clause one sentence at the end of the field.
53
+
54
+ Do NOT mention clothing, hair, facial features, identity, expression, props, setting, or lighting in this field — those belong in `prompt`. Keep it to body geometry a pose-skeleton extractor would care about.
55
+
56
+ ## Rules for the `prompt` field
57
+
58
+ 1. **One paragraph.** No line breaks, no lists, no labels. Continuous prose.
59
+ 2. **Order matters.** Start with subject + action, then composition/framing, then lighting, then camera, then palette, then style/medium, then mood, then post-processing. A reader following the prompt top to bottom should build the image in the right order.
60
+ 3. **Be specific and visual.** "Warm golden-hour key light from camera-right at a low angle, long hard shadows raking across the wall" — not "nice lighting."
61
+ 4. **Name what you can see.** If the light is clearly a window, say window. If it's a rim light, say rim. If it's a ring-light catchlight, say so. Don't invent details you can't see, but don't be vague about what's obvious.
62
+ 5. **Estimate technical parameters** when the image signals them: lens compression (long-lens flattening vs wide-lens distortion), depth of field, shutter artifacts, film stock hints (Portra pastels, Ektachrome greens, Cinestill halation).
63
+ 6. **Match the medium.** A painting gets brush/medium vocabulary, not lens talk. A 3D render gets render-engine/material vocabulary. A photo gets camera/lens/film vocabulary.
64
+ 7. **Mood last.** End on the emotional register so the model weighs subject and craft before feel.
65
+ 8. **No filler.** Drop "a beautiful image of," "stunning," "masterpiece," etc. Describe, don't adjectivize.
66
+ 9. **Do not reference the source.** Don't say "recreate this image" or "in the style of the attached photo." The prompt stands alone.
67
+
68
+ ## Register: authentic photo vs editorial vs non-photo
69
+
70
+ Before writing the prompt, decide what the image *actually is*. Picking the wrong register is the single biggest source of bad reproductions.
71
+
72
+ - **Authentic / phone / social snapshot** — candid framing, imperfect focus, available (non-studio) light, slight clutter, non-posed subject, visible compression or upload artifacts, unretouched skin. This is the default for most user images. Use phone-capture vocabulary, drawn freely from this list as appropriate: *authentic iPhone photo, casual snapshot, handheld, mild grain, subtle facial imperfections, natural under-eye shadows, slight uneven skin tone, very subtle motion softness, no beauty filter, no skin smoothing, unedited skin, slight ISO noise, tiny chromatic aberration around highlights, mild Instagram-upload compression artifacts, slight shadow banding, very subtle sensor noise, slightly lifted blacks from auto-HDR, ordinary daylight / ordinary indoor light*. **Do not** say "editorial photograph", "35mm Portra/Cinestill", "masterpiece", "cinematic", "shot on Arri", or name pro film stocks.
73
+ - **Editorial / studio / film** — controlled light, intentional framing, pro retouching, shallow studio bokeh, obvious film look. Only then use film-stock / lens / grade vocabulary (Portra, Cinestill, halation, teal-orange grade, etc.).
74
+ - **Painting, illustration, 3D render** — use medium vocabulary (brushwork, ink, cel, Unreal Engine 5, PBR, octane). Never mix camera/lens/film talk into a painting.
75
+
76
+ If in doubt, default to **authentic photo**. Most source images are phone captures, and "editorial/cinematic" vocabulary is what makes reproductions look staged and fake.
77
+
78
+ ## Example (authentic phone snapshot — for calibration, not for output)
79
+
80
+ Subject: a pale pink pet pig sitting upright on the back of a small red scooter in daytime traffic, secured with a rope harness, shot from a neighboring car window.
81
+
82
+ Bad: "a cinematic editorial photograph of a pig on a scooter, masterpiece, 35mm Portra, shallow depth of field"
83
+
84
+ Good: "A large pale pink pig sits upright on the rear seat of a small red scooter behind a helmeted rider, held in place with a loose rope harness, rolling through mid-afternoon urban traffic; framed through the open window of a neighboring car with a sliver of the car's door visible in the lower foreground and parked white sedans and low concrete shopfronts receding into the background. Composition is centered on the pig, handheld and slightly tilted, medium telephoto compression flattening the street behind. Ordinary overhead midday daylight, soft overall with a gentle warm cast off the asphalt and no hard shadows. Shot on iPhone at roughly equivalent 50–70mm, deep focus, very slight motion softness from the moving cars. Palette of dusty pink, tomato red, warm grey asphalt, and pale sky. Authentic iPhone photo, mild grain, tiny chromatic aberration around highlights, subtle sensor noise, mild Instagram-upload compression, slightly lifted blacks, no beauty filter, no skin smoothing, unedited. Humorous and surreal but matter-of-fact."