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,71 @@
1
+ function transcriptWords(transcript) {
2
+ if (Array.isArray(transcript.words))
3
+ return transcript.words;
4
+ const transcripts = transcript.transcripts;
5
+ if (!Array.isArray(transcripts) || transcripts.length === 0)
6
+ return undefined;
7
+ const first = transcripts[0];
8
+ return typeof first === "object" && first !== null
9
+ ? first.words
10
+ : undefined;
11
+ }
12
+ function cueTokens(value) {
13
+ return value
14
+ .normalize("NFKC")
15
+ .toLocaleLowerCase()
16
+ .replace(/[\u2019']/gu, "")
17
+ .split(/[^\p{L}\p{N}]+/gu)
18
+ .filter(Boolean);
19
+ }
20
+ export function timedSpeechWords(transcript) {
21
+ if (typeof transcript !== "object" || transcript === null) {
22
+ throw new Error("elevenlabs.json must contain a JSON object");
23
+ }
24
+ const words = transcriptWords(transcript);
25
+ if (!Array.isArray(words)) {
26
+ throw new Error("elevenlabs.json does not contain timed words");
27
+ }
28
+ const result = [];
29
+ for (const entry of words) {
30
+ if ((entry.type ?? "word") !== "word")
31
+ continue;
32
+ if (typeof entry.text !== "string")
33
+ continue;
34
+ if (typeof entry.start !== "number" || !Number.isFinite(entry.start) || entry.start < 0)
35
+ continue;
36
+ const tokens = cueTokens(entry.text);
37
+ for (const token of tokens)
38
+ result.push({ text: token, start: entry.start });
39
+ }
40
+ return result;
41
+ }
42
+ export function hasTimedSpeechWords(transcript) {
43
+ try {
44
+ return timedSpeechWords(transcript).length > 0;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ function timestampList(matches) {
51
+ return matches.map((seconds) => `${Number(seconds.toFixed(3))}s`).join(", ");
52
+ }
53
+ export function resolveAudioCue(transcript, cue) {
54
+ const query = cueTokens(cue);
55
+ if (query.length === 0)
56
+ throw new Error("Audio cue must contain a word or number");
57
+ const words = timedSpeechWords(transcript);
58
+ const matches = [];
59
+ for (let start = 0; start + query.length <= words.length; start++) {
60
+ const matchesPhrase = query.every((token, offset) => words[start + offset]?.text === token);
61
+ if (matchesPhrase)
62
+ matches.push(words[start].start);
63
+ }
64
+ if (matches.length === 0) {
65
+ throw new Error(`Audio cue "${cue}" was not found in elevenlabs.json. Use audio_seconds for a numeric target.`);
66
+ }
67
+ if (matches.length > 1) {
68
+ throw new Error(`Audio cue "${cue}" is ambiguous; it matches at ${timestampList(matches)}. Use a longer phrase or audio_seconds.`);
69
+ }
70
+ return matches[0];
71
+ }
@@ -0,0 +1,32 @@
1
+ import { extname } from "node:path";
2
+ import { AUDIO_OPTS } from "./ffmpeg.js";
3
+ export function audioOnlyOutputOptions(outputPath) {
4
+ switch (extname(outputPath).toLowerCase()) {
5
+ case ".mp3":
6
+ return ["-c:a", "libmp3lame", "-q:a", "2", "-ac", "2"];
7
+ case ".wav":
8
+ return ["-c:a", "pcm_s16le", "-ac", "2"];
9
+ case ".ogg":
10
+ return ["-c:a", "libvorbis", "-q:a", "5", "-ac", "2"];
11
+ case ".flac":
12
+ return ["-c:a", "flac", "-compression_level", "5", "-ac", "2"];
13
+ case ".webm":
14
+ case ".opus":
15
+ return ["-c:a", "libopus", "-b:a", "160k", "-ac", "2"];
16
+ case ".weba":
17
+ return ["-f", "webm", "-c:a", "libopus", "-b:a", "160k", "-ac", "2"];
18
+ case ".aac":
19
+ case ".m4a":
20
+ return AUDIO_OPTS;
21
+ default:
22
+ throw new Error(`Unsupported target audio format: ${extname(outputPath) || "unknown"}`);
23
+ }
24
+ }
25
+ export function videoAudioOutputOptions(outputPath) {
26
+ const extension = extname(outputPath).toLowerCase();
27
+ if (extension === ".webm")
28
+ return ["-c:a", "libopus", "-b:a", "160k", "-ac", "2"];
29
+ if (extension === ".avi")
30
+ return ["-c:a", "libmp3lame", "-b:a", "192k", "-ac", "2"];
31
+ return AUDIO_OPTS;
32
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,223 @@
1
+ export const AUDIO_SYNC_STRETCH_MIN = 0.25;
2
+ export const AUDIO_SYNC_STRETCH_MAX = 4;
3
+ const EPSILON = 1e-9;
4
+ function requireFinite(name, value) {
5
+ if (!Number.isFinite(value))
6
+ throw new Error(`${name} must be a finite number`);
7
+ }
8
+ function nearlyEqual(left, right) {
9
+ return Math.abs(left - right) <= EPSILON;
10
+ }
11
+ function endpointDerivative(firstInterval, secondInterval, firstSlope, secondSlope) {
12
+ const derivative = ((2 * firstInterval + secondInterval) * firstSlope
13
+ - firstInterval * secondSlope) / (firstInterval + secondInterval);
14
+ if (derivative <= 0)
15
+ return 0;
16
+ if (secondSlope <= 0 && derivative > 3 * firstSlope)
17
+ return 3 * firstSlope;
18
+ return derivative;
19
+ }
20
+ function pchipDerivatives(intervals, slopes) {
21
+ if (slopes.length === 1)
22
+ return [slopes[0], slopes[0]];
23
+ const derivatives = new Array(slopes.length + 1);
24
+ derivatives[0] = endpointDerivative(intervals[0], intervals[1], slopes[0], slopes[1]);
25
+ derivatives[slopes.length] = endpointDerivative(intervals.at(-1), intervals.at(-2), slopes.at(-1), slopes.at(-2));
26
+ for (let index = 1; index < slopes.length; index++) {
27
+ const previousSlope = slopes[index - 1];
28
+ const nextSlope = slopes[index];
29
+ if (previousSlope * nextSlope <= 0) {
30
+ derivatives[index] = 0;
31
+ continue;
32
+ }
33
+ const previousInterval = intervals[index - 1];
34
+ const nextInterval = intervals[index];
35
+ const firstWeight = 2 * nextInterval + previousInterval;
36
+ const secondWeight = nextInterval + 2 * previousInterval;
37
+ derivatives[index] = (firstWeight + secondWeight)
38
+ / (firstWeight / previousSlope + secondWeight / nextSlope);
39
+ }
40
+ return derivatives;
41
+ }
42
+ function segmentDerivative(segment, normalizedTime) {
43
+ const [cubic, quadratic, linear] = segment.coefficients;
44
+ const interval = segment.videoEndSeconds - segment.videoStartSeconds;
45
+ return (3 * cubic * normalizedTime * normalizedTime
46
+ + 2 * quadratic * normalizedTime
47
+ + linear) / interval;
48
+ }
49
+ function derivativeExtrema(segment) {
50
+ const [cubic, quadratic] = segment.coefficients;
51
+ const values = [segmentDerivative(segment, 0), segmentDerivative(segment, 1)];
52
+ if (Math.abs(cubic) <= EPSILON)
53
+ return values;
54
+ const criticalPoint = -quadratic / (3 * cubic);
55
+ if (criticalPoint > 0 && criticalPoint < 1) {
56
+ values.push(segmentDerivative(segment, criticalPoint));
57
+ }
58
+ return values;
59
+ }
60
+ function validateDerivativeBounds(segment, index) {
61
+ const extrema = derivativeExtrema(segment);
62
+ const minimum = Math.min(...extrema);
63
+ const maximum = Math.max(...extrema);
64
+ if (minimum < AUDIO_SYNC_STRETCH_MIN - EPSILON
65
+ || maximum > AUDIO_SYNC_STRETCH_MAX + EPSILON) {
66
+ throw new Error(`Smooth retiming rate in segment ${index + 1} must stay between ${AUDIO_SYNC_STRETCH_MIN} and ${AUDIO_SYNC_STRETCH_MAX}`);
67
+ }
68
+ }
69
+ function normalizedAnchors(input) {
70
+ const anchors = [{ videoSeconds: 0, audioSeconds: 0 }];
71
+ let suppliedStart = false;
72
+ for (const anchor of input.anchors) {
73
+ if (!suppliedStart && anchors.length === 1
74
+ && anchor.videoSeconds === 0 && anchor.audioSeconds === 0) {
75
+ suppliedStart = true;
76
+ continue;
77
+ }
78
+ anchors.push({ ...anchor });
79
+ }
80
+ const finalAnchor = anchors.at(-1);
81
+ if (finalAnchor.videoSeconds !== input.videoDuration
82
+ || finalAnchor.audioSeconds !== input.audioDuration) {
83
+ anchors.push({
84
+ videoSeconds: input.videoDuration,
85
+ audioSeconds: input.audioDuration,
86
+ });
87
+ }
88
+ return anchors;
89
+ }
90
+ export function createAudioSyncPlan(input) {
91
+ requireFinite("videoDuration", input.videoDuration);
92
+ requireFinite("audioDuration", input.audioDuration);
93
+ requireFinite("sourceFps", input.sourceFps);
94
+ if (input.videoDuration <= 0)
95
+ throw new Error("Video duration must be greater than zero");
96
+ if (input.audioDuration <= 0)
97
+ throw new Error("Audio duration must be greater than zero");
98
+ if (input.sourceFps <= 0)
99
+ throw new Error("Source frame rate must be greater than zero");
100
+ for (const [index, anchor] of input.anchors.entries()) {
101
+ requireFinite(`anchors[${index}].videoSeconds`, anchor.videoSeconds);
102
+ requireFinite(`anchors[${index}].audioSeconds`, anchor.audioSeconds);
103
+ if (anchor.videoSeconds < 0 || anchor.videoSeconds > input.videoDuration) {
104
+ throw new Error(`Video anchor ${index + 1} must be within the video duration`);
105
+ }
106
+ if (anchor.audioSeconds < 0 || anchor.audioSeconds > input.audioDuration) {
107
+ throw new Error(`Audio anchor ${index + 1} must be within the audio duration`);
108
+ }
109
+ }
110
+ const anchors = normalizedAnchors(input);
111
+ const frameDuration = 1 / input.sourceFps;
112
+ const intervals = [];
113
+ const slopes = [];
114
+ for (let index = 0; index < anchors.length - 1; index++) {
115
+ const current = anchors[index];
116
+ const next = anchors[index + 1];
117
+ const videoInterval = next.videoSeconds - current.videoSeconds;
118
+ const audioInterval = next.audioSeconds - current.audioSeconds;
119
+ if (videoInterval <= EPSILON || audioInterval <= EPSILON) {
120
+ throw new Error("Audio-sync anchors must be strictly increasing on both clocks");
121
+ }
122
+ if (videoInterval + EPSILON < frameDuration || audioInterval + EPSILON < frameDuration) {
123
+ throw new Error(`Audio-sync anchor intervals must be at least one source frame (${frameDuration.toFixed(6)}s)`);
124
+ }
125
+ const durationFactor = audioInterval / videoInterval;
126
+ if (durationFactor < AUDIO_SYNC_STRETCH_MIN - EPSILON
127
+ || durationFactor > AUDIO_SYNC_STRETCH_MAX + EPSILON) {
128
+ throw new Error(`Segment duration factor must be between ${AUDIO_SYNC_STRETCH_MIN} and ${AUDIO_SYNC_STRETCH_MAX}`);
129
+ }
130
+ intervals.push(videoInterval);
131
+ slopes.push(durationFactor);
132
+ }
133
+ if (anchors.every((anchor) => nearlyEqual(anchor.videoSeconds, anchor.audioSeconds))) {
134
+ throw new Error("Audio-sync map is a no-op");
135
+ }
136
+ const derivatives = pchipDerivatives(intervals, slopes);
137
+ const segments = slopes.map((durationFactor, index) => {
138
+ const start = anchors[index];
139
+ const end = anchors[index + 1];
140
+ const interval = intervals[index];
141
+ const startDerivative = derivatives[index];
142
+ const endDerivative = derivatives[index + 1];
143
+ const coefficients = [
144
+ 2 * start.audioSeconds - 2 * end.audioSeconds
145
+ + interval * (startDerivative + endDerivative),
146
+ -3 * start.audioSeconds + 3 * end.audioSeconds
147
+ - interval * (2 * startDerivative + endDerivative),
148
+ interval * startDerivative,
149
+ start.audioSeconds,
150
+ ];
151
+ const segment = {
152
+ videoStartSeconds: start.videoSeconds,
153
+ videoEndSeconds: end.videoSeconds,
154
+ audioStartSeconds: start.audioSeconds,
155
+ audioEndSeconds: end.audioSeconds,
156
+ durationFactor,
157
+ startDerivative,
158
+ endDerivative,
159
+ coefficients,
160
+ };
161
+ validateDerivativeBounds(segment, index);
162
+ return segment;
163
+ });
164
+ return {
165
+ videoDuration: input.videoDuration,
166
+ audioDuration: input.audioDuration,
167
+ sourceFps: input.sourceFps,
168
+ frameDuration,
169
+ anchors,
170
+ segments,
171
+ };
172
+ }
173
+ function findSegment(plan, videoSeconds) {
174
+ return plan.segments.find((segment) => videoSeconds <= segment.videoEndSeconds + EPSILON)
175
+ ?? plan.segments.at(-1);
176
+ }
177
+ export function evaluateAudioSyncMap(plan, videoSeconds) {
178
+ requireFinite("videoSeconds", videoSeconds);
179
+ if (videoSeconds < -EPSILON || videoSeconds > plan.videoDuration + EPSILON) {
180
+ throw new Error("Video timestamp must be within the planned video duration");
181
+ }
182
+ const clamped = Math.min(plan.videoDuration, Math.max(0, videoSeconds));
183
+ const segment = findSegment(plan, clamped);
184
+ const interval = segment.videoEndSeconds - segment.videoStartSeconds;
185
+ const normalizedTime = (clamped - segment.videoStartSeconds) / interval;
186
+ const [cubic, quadratic, linear, constant] = segment.coefficients;
187
+ return ((cubic * normalizedTime + quadratic) * normalizedTime + linear)
188
+ * normalizedTime + constant;
189
+ }
190
+ export function evaluateAudioSyncDerivative(plan, videoSeconds) {
191
+ requireFinite("videoSeconds", videoSeconds);
192
+ if (videoSeconds < -EPSILON || videoSeconds > plan.videoDuration + EPSILON) {
193
+ throw new Error("Video timestamp must be within the planned video duration");
194
+ }
195
+ const clamped = Math.min(plan.videoDuration, Math.max(0, videoSeconds));
196
+ const segment = findSegment(plan, clamped);
197
+ const interval = segment.videoEndSeconds - segment.videoStartSeconds;
198
+ return segmentDerivative(segment, (clamped - segment.videoStartSeconds) / interval);
199
+ }
200
+ function filterNumber(value) {
201
+ return Number(value.toFixed(12)).toString();
202
+ }
203
+ function setptsPolynomial(segment) {
204
+ const sourceTime = "((PTS-STARTPTS)*TB)";
205
+ const start = filterNumber(segment.videoStartSeconds);
206
+ const interval = filterNumber(segment.videoEndSeconds - segment.videoStartSeconds);
207
+ const normalizedTime = `((${sourceTime}-${start})/${interval})`;
208
+ const [cubic, quadratic, linear, constant] = segment.coefficients.map(filterNumber);
209
+ return `(((${cubic}*${normalizedTime}+${quadratic})*${normalizedTime}+${linear})*${normalizedTime}+${constant})/TB`;
210
+ }
211
+ export function buildAudioSyncSetptsExpression(plan) {
212
+ let expression = setptsPolynomial(plan.segments.at(-1));
213
+ for (let index = plan.segments.length - 2; index >= 0; index--) {
214
+ const boundary = filterNumber(plan.segments[index].videoEndSeconds);
215
+ expression = `if(lte((PTS-STARTPTS)*TB,${boundary}),${setptsPolynomial(plan.segments[index])},${expression})`;
216
+ }
217
+ return expression;
218
+ }
219
+ export function buildAudioSyncVideoFilter(plan) {
220
+ const fps = filterNumber(plan.sourceFps);
221
+ const duration = filterNumber(plan.audioDuration);
222
+ return `[0:v:0]setpts='${buildAudioSyncSetptsExpression(plan)}',fps=fps=${fps},tpad=stop_mode=clone:stop_duration=${duration},trim=duration=${duration}[vout]`;
223
+ }
@@ -0,0 +1,31 @@
1
+ export const AUDIO_TRIM_EPSILON_SECONDS = 0.05;
2
+ function expectedAudioTrimDuration(sourceDuration, mode, trimStart, trimEnd, cutStart, cutEnd) {
3
+ if (mode === "keep") {
4
+ const start = trimStart ?? 0;
5
+ const end = trimEnd ?? sourceDuration;
6
+ if (start >= sourceDuration - AUDIO_TRIM_EPSILON_SECONDS) {
7
+ throw new Error(`trim_start ${start} must be before audio duration ${sourceDuration.toFixed(3)}`);
8
+ }
9
+ if (end > sourceDuration + AUDIO_TRIM_EPSILON_SECONDS) {
10
+ throw new Error(`trim_end ${end} exceeds audio duration ${sourceDuration.toFixed(3)}`);
11
+ }
12
+ return Math.min(end, sourceDuration) - start;
13
+ }
14
+ const start = cutStart ?? 0;
15
+ const end = cutEnd ?? sourceDuration;
16
+ if (start >= sourceDuration - AUDIO_TRIM_EPSILON_SECONDS) {
17
+ throw new Error(`cut_start ${start} must be before audio duration ${sourceDuration.toFixed(3)}`);
18
+ }
19
+ if (end > sourceDuration + AUDIO_TRIM_EPSILON_SECONDS) {
20
+ throw new Error(`cut_end ${end} exceeds audio duration ${sourceDuration.toFixed(3)}`);
21
+ }
22
+ return sourceDuration - (Math.min(end, sourceDuration) - start);
23
+ }
24
+ export function validateAudioTrimRange(sourceDuration, mode, trimStart, trimEnd, cutStart, cutEnd) {
25
+ if (!Number.isFinite(sourceDuration) || sourceDuration <= 0)
26
+ throw new Error("Audio file has no usable duration");
27
+ const duration = expectedAudioTrimDuration(sourceDuration, mode, trimStart, trimEnd, cutStart, cutEnd);
28
+ if (duration <= AUDIO_TRIM_EPSILON_SECONDS)
29
+ throw new Error("Trim would produce an empty audio file");
30
+ return duration;
31
+ }
@@ -0,0 +1,31 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ const contexts = new AsyncLocalStorage();
3
+ export function currentBookContext() {
4
+ return contexts.getStore();
5
+ }
6
+ function activeBookContext() {
7
+ const context = contexts.getStore();
8
+ if (!context)
9
+ throw new Error("A book context is required for this operation");
10
+ return context;
11
+ }
12
+ export function activeBookEngine() {
13
+ return activeBookContext().engine;
14
+ }
15
+ /**
16
+ * Tool and job code often holds `scopedBookEngine` rather than a concrete
17
+ * engine. Storing that proxy as a context's engine would make every property
18
+ * read resolve back to itself, so nested contexts inherit the enclosing book's
19
+ * concrete engine instead.
20
+ */
21
+ function concreteEngine(engine) {
22
+ return engine === scopedBookEngine ? activeBookEngine() : engine;
23
+ }
24
+ export async function withBookContext(context, operation) {
25
+ return contexts.run({ ...context, engine: concreteEngine(context.engine) }, operation);
26
+ }
27
+ export const scopedBookEngine = new Proxy({}, {
28
+ get(_target, property) {
29
+ return Reflect.get(activeBookEngine(), property);
30
+ },
31
+ });