@vibeframe/cli 0.27.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 (420) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-lint.log +21 -0
  3. package/.turbo/turbo-test.log +689 -0
  4. package/dist/agent/adapters/claude.d.ts +15 -0
  5. package/dist/agent/adapters/claude.d.ts.map +1 -0
  6. package/dist/agent/adapters/claude.js +119 -0
  7. package/dist/agent/adapters/claude.js.map +1 -0
  8. package/dist/agent/adapters/gemini.d.ts +15 -0
  9. package/dist/agent/adapters/gemini.d.ts.map +1 -0
  10. package/dist/agent/adapters/gemini.js +132 -0
  11. package/dist/agent/adapters/gemini.js.map +1 -0
  12. package/dist/agent/adapters/index.d.ts +27 -0
  13. package/dist/agent/adapters/index.d.ts.map +1 -0
  14. package/dist/agent/adapters/index.js +38 -0
  15. package/dist/agent/adapters/index.js.map +1 -0
  16. package/dist/agent/adapters/ollama.d.ts +20 -0
  17. package/dist/agent/adapters/ollama.d.ts.map +1 -0
  18. package/dist/agent/adapters/ollama.js +186 -0
  19. package/dist/agent/adapters/ollama.js.map +1 -0
  20. package/dist/agent/adapters/openai.d.ts +15 -0
  21. package/dist/agent/adapters/openai.d.ts.map +1 -0
  22. package/dist/agent/adapters/openai.js +92 -0
  23. package/dist/agent/adapters/openai.js.map +1 -0
  24. package/dist/agent/adapters/xai.d.ts +15 -0
  25. package/dist/agent/adapters/xai.d.ts.map +1 -0
  26. package/dist/agent/adapters/xai.js +95 -0
  27. package/dist/agent/adapters/xai.js.map +1 -0
  28. package/dist/agent/index.d.ts +69 -0
  29. package/dist/agent/index.d.ts.map +1 -0
  30. package/dist/agent/index.js +180 -0
  31. package/dist/agent/index.js.map +1 -0
  32. package/dist/agent/memory/index.d.ts +70 -0
  33. package/dist/agent/memory/index.d.ts.map +1 -0
  34. package/dist/agent/memory/index.js +132 -0
  35. package/dist/agent/memory/index.js.map +1 -0
  36. package/dist/agent/prompts/system.d.ts +6 -0
  37. package/dist/agent/prompts/system.d.ts.map +1 -0
  38. package/dist/agent/prompts/system.js +103 -0
  39. package/dist/agent/prompts/system.js.map +1 -0
  40. package/dist/agent/tools/ai-editing.d.ts +15 -0
  41. package/dist/agent/tools/ai-editing.d.ts.map +1 -0
  42. package/dist/agent/tools/ai-editing.js +763 -0
  43. package/dist/agent/tools/ai-editing.js.map +1 -0
  44. package/dist/agent/tools/ai-generation.d.ts +13 -0
  45. package/dist/agent/tools/ai-generation.d.ts.map +1 -0
  46. package/dist/agent/tools/ai-generation.js +973 -0
  47. package/dist/agent/tools/ai-generation.js.map +1 -0
  48. package/dist/agent/tools/ai-pipeline.d.ts +14 -0
  49. package/dist/agent/tools/ai-pipeline.d.ts.map +1 -0
  50. package/dist/agent/tools/ai-pipeline.js +961 -0
  51. package/dist/agent/tools/ai-pipeline.js.map +1 -0
  52. package/dist/agent/tools/ai.d.ts +13 -0
  53. package/dist/agent/tools/ai.d.ts.map +1 -0
  54. package/dist/agent/tools/ai.js +19 -0
  55. package/dist/agent/tools/ai.js.map +1 -0
  56. package/dist/agent/tools/batch.d.ts +6 -0
  57. package/dist/agent/tools/batch.d.ts.map +1 -0
  58. package/dist/agent/tools/batch.js +383 -0
  59. package/dist/agent/tools/batch.js.map +1 -0
  60. package/dist/agent/tools/e2e.test.d.ts +26 -0
  61. package/dist/agent/tools/e2e.test.d.ts.map +1 -0
  62. package/dist/agent/tools/e2e.test.js +397 -0
  63. package/dist/agent/tools/e2e.test.js.map +1 -0
  64. package/dist/agent/tools/export.d.ts +6 -0
  65. package/dist/agent/tools/export.d.ts.map +1 -0
  66. package/dist/agent/tools/export.js +171 -0
  67. package/dist/agent/tools/export.js.map +1 -0
  68. package/dist/agent/tools/filesystem.d.ts +6 -0
  69. package/dist/agent/tools/filesystem.d.ts.map +1 -0
  70. package/dist/agent/tools/filesystem.js +212 -0
  71. package/dist/agent/tools/filesystem.js.map +1 -0
  72. package/dist/agent/tools/index.d.ts +65 -0
  73. package/dist/agent/tools/index.d.ts.map +1 -0
  74. package/dist/agent/tools/index.js +120 -0
  75. package/dist/agent/tools/index.js.map +1 -0
  76. package/dist/agent/tools/integration.test.d.ts +11 -0
  77. package/dist/agent/tools/integration.test.d.ts.map +1 -0
  78. package/dist/agent/tools/integration.test.js +659 -0
  79. package/dist/agent/tools/integration.test.js.map +1 -0
  80. package/dist/agent/tools/media.d.ts +6 -0
  81. package/dist/agent/tools/media.d.ts.map +1 -0
  82. package/dist/agent/tools/media.js +616 -0
  83. package/dist/agent/tools/media.js.map +1 -0
  84. package/dist/agent/tools/project.d.ts +6 -0
  85. package/dist/agent/tools/project.d.ts.map +1 -0
  86. package/dist/agent/tools/project.js +284 -0
  87. package/dist/agent/tools/project.js.map +1 -0
  88. package/dist/agent/tools/timeline.d.ts +6 -0
  89. package/dist/agent/tools/timeline.d.ts.map +1 -0
  90. package/dist/agent/tools/timeline.js +873 -0
  91. package/dist/agent/tools/timeline.js.map +1 -0
  92. package/dist/agent/types.d.ts +59 -0
  93. package/dist/agent/types.d.ts.map +1 -0
  94. package/dist/agent/types.js +5 -0
  95. package/dist/agent/types.js.map +1 -0
  96. package/dist/commands/agent.d.ts +21 -0
  97. package/dist/commands/agent.d.ts.map +1 -0
  98. package/dist/commands/agent.js +290 -0
  99. package/dist/commands/agent.js.map +1 -0
  100. package/dist/commands/ai-analyze.d.ts +106 -0
  101. package/dist/commands/ai-analyze.d.ts.map +1 -0
  102. package/dist/commands/ai-analyze.js +327 -0
  103. package/dist/commands/ai-analyze.js.map +1 -0
  104. package/dist/commands/ai-animated-caption.d.ts +64 -0
  105. package/dist/commands/ai-animated-caption.d.ts.map +1 -0
  106. package/dist/commands/ai-animated-caption.js +272 -0
  107. package/dist/commands/ai-animated-caption.js.map +1 -0
  108. package/dist/commands/ai-audio.d.ts +20 -0
  109. package/dist/commands/ai-audio.d.ts.map +1 -0
  110. package/dist/commands/ai-audio.js +808 -0
  111. package/dist/commands/ai-audio.js.map +1 -0
  112. package/dist/commands/ai-broll.d.ts +15 -0
  113. package/dist/commands/ai-broll.d.ts.map +1 -0
  114. package/dist/commands/ai-broll.js +406 -0
  115. package/dist/commands/ai-broll.js.map +1 -0
  116. package/dist/commands/ai-edit-cli.d.ts +14 -0
  117. package/dist/commands/ai-edit-cli.d.ts.map +1 -0
  118. package/dist/commands/ai-edit-cli.js +579 -0
  119. package/dist/commands/ai-edit-cli.js.map +1 -0
  120. package/dist/commands/ai-edit.d.ts +398 -0
  121. package/dist/commands/ai-edit.d.ts.map +1 -0
  122. package/dist/commands/ai-edit.js +1019 -0
  123. package/dist/commands/ai-edit.js.map +1 -0
  124. package/dist/commands/ai-fill-gaps.d.ts +14 -0
  125. package/dist/commands/ai-fill-gaps.d.ts.map +1 -0
  126. package/dist/commands/ai-fill-gaps.js +451 -0
  127. package/dist/commands/ai-fill-gaps.js.map +1 -0
  128. package/dist/commands/ai-helpers.d.ts +20 -0
  129. package/dist/commands/ai-helpers.d.ts.map +1 -0
  130. package/dist/commands/ai-helpers.js +59 -0
  131. package/dist/commands/ai-helpers.js.map +1 -0
  132. package/dist/commands/ai-highlights.d.ts +127 -0
  133. package/dist/commands/ai-highlights.d.ts.map +1 -0
  134. package/dist/commands/ai-highlights.js +1026 -0
  135. package/dist/commands/ai-highlights.js.map +1 -0
  136. package/dist/commands/ai-image.d.ts +34 -0
  137. package/dist/commands/ai-image.d.ts.map +1 -0
  138. package/dist/commands/ai-image.js +653 -0
  139. package/dist/commands/ai-image.js.map +1 -0
  140. package/dist/commands/ai-motion.d.ts +50 -0
  141. package/dist/commands/ai-motion.d.ts.map +1 -0
  142. package/dist/commands/ai-motion.js +271 -0
  143. package/dist/commands/ai-motion.js.map +1 -0
  144. package/dist/commands/ai-narrate.d.ts +66 -0
  145. package/dist/commands/ai-narrate.d.ts.map +1 -0
  146. package/dist/commands/ai-narrate.js +329 -0
  147. package/dist/commands/ai-narrate.js.map +1 -0
  148. package/dist/commands/ai-review.d.ts +57 -0
  149. package/dist/commands/ai-review.d.ts.map +1 -0
  150. package/dist/commands/ai-review.js +251 -0
  151. package/dist/commands/ai-review.js.map +1 -0
  152. package/dist/commands/ai-script-pipeline-cli.d.ts +9 -0
  153. package/dist/commands/ai-script-pipeline-cli.d.ts.map +1 -0
  154. package/dist/commands/ai-script-pipeline-cli.js +1494 -0
  155. package/dist/commands/ai-script-pipeline-cli.js.map +1 -0
  156. package/dist/commands/ai-script-pipeline.d.ts +259 -0
  157. package/dist/commands/ai-script-pipeline.d.ts.map +1 -0
  158. package/dist/commands/ai-script-pipeline.js +1027 -0
  159. package/dist/commands/ai-script-pipeline.js.map +1 -0
  160. package/dist/commands/ai-suggest-edit.d.ts +14 -0
  161. package/dist/commands/ai-suggest-edit.d.ts.map +1 -0
  162. package/dist/commands/ai-suggest-edit.js +220 -0
  163. package/dist/commands/ai-suggest-edit.js.map +1 -0
  164. package/dist/commands/ai-video-fx.d.ts +14 -0
  165. package/dist/commands/ai-video-fx.d.ts.map +1 -0
  166. package/dist/commands/ai-video-fx.js +395 -0
  167. package/dist/commands/ai-video-fx.js.map +1 -0
  168. package/dist/commands/ai-video.d.ts +15 -0
  169. package/dist/commands/ai-video.d.ts.map +1 -0
  170. package/dist/commands/ai-video.js +785 -0
  171. package/dist/commands/ai-video.js.map +1 -0
  172. package/dist/commands/ai-viral.d.ts +15 -0
  173. package/dist/commands/ai-viral.d.ts.map +1 -0
  174. package/dist/commands/ai-viral.js +519 -0
  175. package/dist/commands/ai-viral.js.map +1 -0
  176. package/dist/commands/ai-visual-fx.d.ts +14 -0
  177. package/dist/commands/ai-visual-fx.d.ts.map +1 -0
  178. package/dist/commands/ai-visual-fx.js +505 -0
  179. package/dist/commands/ai-visual-fx.js.map +1 -0
  180. package/dist/commands/ai.d.ts +38 -0
  181. package/dist/commands/ai.d.ts.map +1 -0
  182. package/dist/commands/ai.js +225 -0
  183. package/dist/commands/ai.js.map +1 -0
  184. package/dist/commands/ai.test.d.ts +2 -0
  185. package/dist/commands/ai.test.d.ts.map +1 -0
  186. package/dist/commands/ai.test.js +554 -0
  187. package/dist/commands/ai.test.js.map +1 -0
  188. package/dist/commands/analyze.d.ts +16 -0
  189. package/dist/commands/analyze.d.ts.map +1 -0
  190. package/dist/commands/analyze.js +247 -0
  191. package/dist/commands/analyze.js.map +1 -0
  192. package/dist/commands/audio.d.ts +18 -0
  193. package/dist/commands/audio.d.ts.map +1 -0
  194. package/dist/commands/audio.js +539 -0
  195. package/dist/commands/audio.js.map +1 -0
  196. package/dist/commands/batch.d.ts +3 -0
  197. package/dist/commands/batch.d.ts.map +1 -0
  198. package/dist/commands/batch.js +366 -0
  199. package/dist/commands/batch.js.map +1 -0
  200. package/dist/commands/batch.test.d.ts +2 -0
  201. package/dist/commands/batch.test.d.ts.map +1 -0
  202. package/dist/commands/batch.test.js +203 -0
  203. package/dist/commands/batch.test.js.map +1 -0
  204. package/dist/commands/detect.d.ts +3 -0
  205. package/dist/commands/detect.d.ts.map +1 -0
  206. package/dist/commands/detect.js +273 -0
  207. package/dist/commands/detect.js.map +1 -0
  208. package/dist/commands/doctor.d.ts +6 -0
  209. package/dist/commands/doctor.d.ts.map +1 -0
  210. package/dist/commands/doctor.js +191 -0
  211. package/dist/commands/doctor.js.map +1 -0
  212. package/dist/commands/edit-cmd.d.ts +26 -0
  213. package/dist/commands/edit-cmd.d.ts.map +1 -0
  214. package/dist/commands/edit-cmd.js +870 -0
  215. package/dist/commands/edit-cmd.js.map +1 -0
  216. package/dist/commands/export.d.ts +39 -0
  217. package/dist/commands/export.d.ts.map +1 -0
  218. package/dist/commands/export.js +730 -0
  219. package/dist/commands/export.js.map +1 -0
  220. package/dist/commands/generate.d.ts +25 -0
  221. package/dist/commands/generate.d.ts.map +1 -0
  222. package/dist/commands/generate.js +1885 -0
  223. package/dist/commands/generate.js.map +1 -0
  224. package/dist/commands/media.d.ts +3 -0
  225. package/dist/commands/media.d.ts.map +1 -0
  226. package/dist/commands/media.js +165 -0
  227. package/dist/commands/media.js.map +1 -0
  228. package/dist/commands/output.d.ts +45 -0
  229. package/dist/commands/output.d.ts.map +1 -0
  230. package/dist/commands/output.js +122 -0
  231. package/dist/commands/output.js.map +1 -0
  232. package/dist/commands/pipeline.d.ts +19 -0
  233. package/dist/commands/pipeline.d.ts.map +1 -0
  234. package/dist/commands/pipeline.js +345 -0
  235. package/dist/commands/pipeline.js.map +1 -0
  236. package/dist/commands/project.d.ts +3 -0
  237. package/dist/commands/project.d.ts.map +1 -0
  238. package/dist/commands/project.js +139 -0
  239. package/dist/commands/project.js.map +1 -0
  240. package/dist/commands/project.test.d.ts +2 -0
  241. package/dist/commands/project.test.d.ts.map +1 -0
  242. package/dist/commands/project.test.js +105 -0
  243. package/dist/commands/project.test.js.map +1 -0
  244. package/dist/commands/sanitize.d.ts +21 -0
  245. package/dist/commands/sanitize.d.ts.map +1 -0
  246. package/dist/commands/sanitize.js +56 -0
  247. package/dist/commands/sanitize.js.map +1 -0
  248. package/dist/commands/schema.d.ts +11 -0
  249. package/dist/commands/schema.d.ts.map +1 -0
  250. package/dist/commands/schema.js +101 -0
  251. package/dist/commands/schema.js.map +1 -0
  252. package/dist/commands/setup.d.ts +6 -0
  253. package/dist/commands/setup.d.ts.map +1 -0
  254. package/dist/commands/setup.js +440 -0
  255. package/dist/commands/setup.js.map +1 -0
  256. package/dist/commands/timeline.d.ts +3 -0
  257. package/dist/commands/timeline.d.ts.map +1 -0
  258. package/dist/commands/timeline.js +469 -0
  259. package/dist/commands/timeline.js.map +1 -0
  260. package/dist/commands/timeline.test.d.ts +2 -0
  261. package/dist/commands/timeline.test.d.ts.map +1 -0
  262. package/dist/commands/timeline.test.js +320 -0
  263. package/dist/commands/timeline.test.js.map +1 -0
  264. package/dist/commands/validate.d.ts +32 -0
  265. package/dist/commands/validate.d.ts.map +1 -0
  266. package/dist/commands/validate.js +63 -0
  267. package/dist/commands/validate.js.map +1 -0
  268. package/dist/config/config.test.d.ts +2 -0
  269. package/dist/config/config.test.d.ts.map +1 -0
  270. package/dist/config/config.test.js +164 -0
  271. package/dist/config/config.test.js.map +1 -0
  272. package/dist/config/index.d.ts +35 -0
  273. package/dist/config/index.d.ts.map +1 -0
  274. package/dist/config/index.js +101 -0
  275. package/dist/config/index.js.map +1 -0
  276. package/dist/config/schema.d.ts +43 -0
  277. package/dist/config/schema.d.ts.map +1 -0
  278. package/dist/config/schema.js +42 -0
  279. package/dist/config/schema.js.map +1 -0
  280. package/dist/engine/index.d.ts +3 -0
  281. package/dist/engine/index.d.ts.map +1 -0
  282. package/dist/engine/index.js +2 -0
  283. package/dist/engine/index.js.map +1 -0
  284. package/dist/engine/project.d.ts +84 -0
  285. package/dist/engine/project.d.ts.map +1 -0
  286. package/dist/engine/project.js +355 -0
  287. package/dist/engine/project.js.map +1 -0
  288. package/dist/engine/project.test.d.ts +2 -0
  289. package/dist/engine/project.test.d.ts.map +1 -0
  290. package/dist/engine/project.test.js +599 -0
  291. package/dist/engine/project.test.js.map +1 -0
  292. package/dist/index.d.ts +7 -0
  293. package/dist/index.d.ts.map +1 -0
  294. package/dist/index.js +131 -0
  295. package/dist/index.js.map +1 -0
  296. package/dist/utils/api-key.d.ts +36 -0
  297. package/dist/utils/api-key.d.ts.map +1 -0
  298. package/dist/utils/api-key.js +211 -0
  299. package/dist/utils/api-key.js.map +1 -0
  300. package/dist/utils/api-key.test.d.ts +2 -0
  301. package/dist/utils/api-key.test.d.ts.map +1 -0
  302. package/dist/utils/api-key.test.js +35 -0
  303. package/dist/utils/api-key.test.js.map +1 -0
  304. package/dist/utils/audio.d.ts +23 -0
  305. package/dist/utils/audio.d.ts.map +1 -0
  306. package/dist/utils/audio.js +79 -0
  307. package/dist/utils/audio.js.map +1 -0
  308. package/dist/utils/exec-safe.d.ts +22 -0
  309. package/dist/utils/exec-safe.d.ts.map +1 -0
  310. package/dist/utils/exec-safe.js +62 -0
  311. package/dist/utils/exec-safe.js.map +1 -0
  312. package/dist/utils/first-run.d.ts +13 -0
  313. package/dist/utils/first-run.d.ts.map +1 -0
  314. package/dist/utils/first-run.js +48 -0
  315. package/dist/utils/first-run.js.map +1 -0
  316. package/dist/utils/provider-resolver.d.ts +15 -0
  317. package/dist/utils/provider-resolver.d.ts.map +1 -0
  318. package/dist/utils/provider-resolver.js +42 -0
  319. package/dist/utils/provider-resolver.js.map +1 -0
  320. package/dist/utils/remotion.d.ts +210 -0
  321. package/dist/utils/remotion.d.ts.map +1 -0
  322. package/dist/utils/remotion.js +731 -0
  323. package/dist/utils/remotion.js.map +1 -0
  324. package/dist/utils/subtitle.d.ts +65 -0
  325. package/dist/utils/subtitle.d.ts.map +1 -0
  326. package/dist/utils/subtitle.js +135 -0
  327. package/dist/utils/subtitle.js.map +1 -0
  328. package/dist/utils/subtitle.test.d.ts +2 -0
  329. package/dist/utils/subtitle.test.d.ts.map +1 -0
  330. package/dist/utils/subtitle.test.js +175 -0
  331. package/dist/utils/subtitle.test.js.map +1 -0
  332. package/dist/utils/tty.d.ts +45 -0
  333. package/dist/utils/tty.d.ts.map +1 -0
  334. package/dist/utils/tty.js +172 -0
  335. package/dist/utils/tty.js.map +1 -0
  336. package/package.json +102 -0
  337. package/src/agent/adapters/claude.ts +143 -0
  338. package/src/agent/adapters/gemini.ts +159 -0
  339. package/src/agent/adapters/index.ts +61 -0
  340. package/src/agent/adapters/ollama.ts +231 -0
  341. package/src/agent/adapters/openai.ts +116 -0
  342. package/src/agent/adapters/xai.ts +119 -0
  343. package/src/agent/index.ts +251 -0
  344. package/src/agent/memory/index.ts +151 -0
  345. package/src/agent/prompts/system.ts +106 -0
  346. package/src/agent/tools/ai-editing.ts +845 -0
  347. package/src/agent/tools/ai-generation.ts +1073 -0
  348. package/src/agent/tools/ai-pipeline.ts +1055 -0
  349. package/src/agent/tools/ai.ts +21 -0
  350. package/src/agent/tools/batch.ts +429 -0
  351. package/src/agent/tools/e2e.test.ts +545 -0
  352. package/src/agent/tools/export.ts +184 -0
  353. package/src/agent/tools/filesystem.ts +237 -0
  354. package/src/agent/tools/index.ts +150 -0
  355. package/src/agent/tools/integration.test.ts +775 -0
  356. package/src/agent/tools/media.ts +697 -0
  357. package/src/agent/tools/project.ts +313 -0
  358. package/src/agent/tools/timeline.ts +951 -0
  359. package/src/agent/types.ts +68 -0
  360. package/src/commands/agent.ts +340 -0
  361. package/src/commands/ai-analyze.ts +429 -0
  362. package/src/commands/ai-animated-caption.ts +390 -0
  363. package/src/commands/ai-audio.ts +941 -0
  364. package/src/commands/ai-broll.ts +490 -0
  365. package/src/commands/ai-edit-cli.ts +658 -0
  366. package/src/commands/ai-edit.ts +1542 -0
  367. package/src/commands/ai-fill-gaps.ts +566 -0
  368. package/src/commands/ai-helpers.ts +65 -0
  369. package/src/commands/ai-highlights.ts +1303 -0
  370. package/src/commands/ai-image.ts +761 -0
  371. package/src/commands/ai-motion.ts +347 -0
  372. package/src/commands/ai-narrate.ts +451 -0
  373. package/src/commands/ai-review.ts +309 -0
  374. package/src/commands/ai-script-pipeline-cli.ts +1710 -0
  375. package/src/commands/ai-script-pipeline.ts +1365 -0
  376. package/src/commands/ai-suggest-edit.ts +264 -0
  377. package/src/commands/ai-video-fx.ts +445 -0
  378. package/src/commands/ai-video.ts +915 -0
  379. package/src/commands/ai-viral.ts +595 -0
  380. package/src/commands/ai-visual-fx.ts +601 -0
  381. package/src/commands/ai.test.ts +627 -0
  382. package/src/commands/ai.ts +307 -0
  383. package/src/commands/analyze.ts +282 -0
  384. package/src/commands/audio.ts +644 -0
  385. package/src/commands/batch.test.ts +279 -0
  386. package/src/commands/batch.ts +440 -0
  387. package/src/commands/detect.ts +329 -0
  388. package/src/commands/doctor.ts +237 -0
  389. package/src/commands/edit-cmd.ts +1014 -0
  390. package/src/commands/export.ts +918 -0
  391. package/src/commands/generate.ts +2146 -0
  392. package/src/commands/media.ts +177 -0
  393. package/src/commands/output.ts +142 -0
  394. package/src/commands/pipeline.ts +398 -0
  395. package/src/commands/project.test.ts +127 -0
  396. package/src/commands/project.ts +149 -0
  397. package/src/commands/sanitize.ts +60 -0
  398. package/src/commands/schema.ts +130 -0
  399. package/src/commands/setup.ts +509 -0
  400. package/src/commands/timeline.test.ts +499 -0
  401. package/src/commands/timeline.ts +529 -0
  402. package/src/commands/validate.ts +77 -0
  403. package/src/config/config.test.ts +197 -0
  404. package/src/config/index.ts +125 -0
  405. package/src/config/schema.ts +82 -0
  406. package/src/engine/index.ts +2 -0
  407. package/src/engine/project.test.ts +702 -0
  408. package/src/engine/project.ts +439 -0
  409. package/src/index.ts +146 -0
  410. package/src/utils/api-key.test.ts +41 -0
  411. package/src/utils/api-key.ts +247 -0
  412. package/src/utils/audio.ts +83 -0
  413. package/src/utils/exec-safe.ts +75 -0
  414. package/src/utils/first-run.ts +52 -0
  415. package/src/utils/provider-resolver.ts +56 -0
  416. package/src/utils/remotion.ts +951 -0
  417. package/src/utils/subtitle.test.ts +227 -0
  418. package/src/utils/subtitle.ts +169 -0
  419. package/src/utils/tty.ts +196 -0
  420. package/tsconfig.json +20 -0
package/dist/index.js ADDED
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ // Debug: Check if script starts at all
3
+ if (process.env.VIBE_DEBUG === "1") {
4
+ console.log("[CLI] Script started, loading modules...");
5
+ }
6
+ import { Command } from "commander";
7
+ import { createRequire } from "module";
8
+ import chalk from "chalk";
9
+ const require = createRequire(import.meta.url);
10
+ const pkg = require("../package.json");
11
+ // Re-export engine for library usage
12
+ export { Project, generateId } from "./engine/index.js";
13
+ import { projectCommand } from "./commands/project.js";
14
+ import { timelineCommand } from "./commands/timeline.js";
15
+ import { generateCommand } from "./commands/generate.js";
16
+ import { editCommand } from "./commands/edit-cmd.js";
17
+ import { analyzeCommand } from "./commands/analyze.js";
18
+ import { audioCommand } from "./commands/audio.js";
19
+ import { pipelineCommand } from "./commands/pipeline.js";
20
+ import { schemaCommand } from "./commands/schema.js";
21
+ import { mediaCommand } from "./commands/media.js";
22
+ import { exportCommand } from "./commands/export.js";
23
+ import { batchCommand } from "./commands/batch.js";
24
+ import { detectCommand } from "./commands/detect.js";
25
+ import { setupCommand } from "./commands/setup.js";
26
+ import { doctorCommand } from "./commands/doctor.js";
27
+ import { agentCommand, startAgent } from "./commands/agent.js";
28
+ import { ApiKeyError } from "./utils/api-key.js";
29
+ import { isFirstRun, showFirstRunBanner } from "./utils/first-run.js";
30
+ import { exitWithError } from "./commands/output.js";
31
+ export { startAgent } from "./commands/agent.js";
32
+ export { loadConfig, saveConfig, isConfigured } from "./config/index.js";
33
+ export { AgentExecutor, ToolRegistry, ConversationMemory } from "./agent/index.js";
34
+ const program = new Command();
35
+ program
36
+ .name("vibe")
37
+ .showSuggestionAfterError(true)
38
+ .description("VibeFrame CLI - AI-First Video Editor")
39
+ .version(pkg.version)
40
+ .option("--json", "Output in JSON format")
41
+ .option("-q, --quiet", "Output only the primary result value (path, URL, or ID)")
42
+ .option("--fields <fields>", "Limit JSON output to specific fields (comma-separated)")
43
+ .configureOutput({
44
+ outputError: (str, write) => {
45
+ write(chalk.red(str.trim()) + "\n");
46
+ write(chalk.dim("Run with --help for full options.\n"));
47
+ },
48
+ })
49
+ .addHelpText("after", `
50
+ Tips:
51
+ vibe setup Configure API keys and preferences
52
+ vibe doctor Check system health and available commands
53
+ vibe schema <command> Show JSON schema for any command (e.g., vibe schema generate.image)
54
+ vibe Start interactive Agent mode (no args)
55
+
56
+ More commands: vibe project|timeline|export|batch|detect|schema --help
57
+ `);
58
+ // Set JSON mode env var before subcommand parsing
59
+ // Also check for first-run and show banner
60
+ program.hook("preAction", async (thisCommand) => {
61
+ const opts = program.opts();
62
+ // --json flag or auto-detect non-TTY stdout
63
+ if (opts.json || (!process.stdout.isTTY && !process.env.VIBE_HUMAN_OUTPUT)) {
64
+ process.env.VIBE_JSON_OUTPUT = "1";
65
+ }
66
+ // --quiet flag
67
+ if (opts.quiet) {
68
+ process.env.VIBE_QUIET_OUTPUT = "1";
69
+ }
70
+ // --fields flag
71
+ if (opts.fields) {
72
+ process.env.VIBE_OUTPUT_FIELDS = opts.fields;
73
+ }
74
+ // Show first-run banner for non-setup/doctor commands
75
+ const cmdName = thisCommand.name();
76
+ const skipBannerCommands = ["setup", "doctor", "help"];
77
+ if (!skipBannerCommands.includes(cmdName) && process.stdin.isTTY) {
78
+ try {
79
+ if (await isFirstRun()) {
80
+ showFirstRunBanner();
81
+ }
82
+ }
83
+ catch {
84
+ // Don't block on first-run check failure
85
+ }
86
+ }
87
+ });
88
+ // Main commands (visible in --help)
89
+ program.addCommand(generateCommand);
90
+ program.addCommand(editCommand);
91
+ program.addCommand(analyzeCommand);
92
+ program.addCommand(audioCommand);
93
+ program.addCommand(pipelineCommand);
94
+ program.addCommand(setupCommand);
95
+ program.addCommand(doctorCommand);
96
+ program.addCommand(agentCommand);
97
+ // Infrastructure commands (hidden from --help, still fully functional)
98
+ program.addCommand(projectCommand, { hidden: true });
99
+ program.addCommand(timelineCommand, { hidden: true });
100
+ program.addCommand(schemaCommand, { hidden: true });
101
+ program.addCommand(mediaCommand, { hidden: true });
102
+ program.addCommand(exportCommand, { hidden: true });
103
+ program.addCommand(batchCommand, { hidden: true });
104
+ program.addCommand(detectCommand, { hidden: true });
105
+ // Check if any arguments provided
106
+ if (process.argv.length <= 2) {
107
+ // No arguments - start Agent mode
108
+ if (process.env.VIBE_DEBUG === "1") {
109
+ console.log("[CLI] No args, starting Agent...");
110
+ }
111
+ startAgent().catch((err) => {
112
+ console.error("Failed to start Agent:", err);
113
+ process.exit(1);
114
+ });
115
+ }
116
+ else {
117
+ // Arguments provided - parse normally with global error handling
118
+ (async () => {
119
+ try {
120
+ await program.parseAsync();
121
+ }
122
+ catch (err) {
123
+ if (err instanceof ApiKeyError) {
124
+ exitWithError(err.toStructured());
125
+ }
126
+ // Re-throw non-ApiKeyError errors
127
+ throw err;
128
+ }
129
+ })();
130
+ }
131
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Load environment variables from .env files.
3
+ * Priority: CWD .env (project-scoped) > monorepo root .env (development)
4
+ * Later loads don't override earlier values, so CWD takes precedence.
5
+ */
6
+ export declare function loadEnv(): void;
7
+ /**
8
+ * Get API key from config, environment, or prompt
9
+ */
10
+ export declare function getApiKey(envVar: string, providerName: string, optionValue?: string): Promise<string | null>;
11
+ /**
12
+ * Error thrown when a required API key is missing (non-interactive mode)
13
+ */
14
+ export declare class ApiKeyError extends Error {
15
+ envVar: string;
16
+ providerName: string;
17
+ constructor(envVar: string, providerName: string);
18
+ toStructured(): {
19
+ success: false;
20
+ error: string;
21
+ code: string;
22
+ exitCode: number;
23
+ suggestion: string;
24
+ retryable: false;
25
+ };
26
+ }
27
+ /**
28
+ * Check if an API key is available without prompting or side effects.
29
+ */
30
+ export declare function hasApiKey(envVar: string): boolean;
31
+ /**
32
+ * Get API key or throw ApiKeyError if not found.
33
+ * Use this instead of getApiKey() + manual null check.
34
+ */
35
+ export declare function requireApiKey(envVar: string, providerName: string, cliOverride?: string): Promise<string>;
36
+ //# sourceMappingURL=api-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.d.ts","sourceRoot":"","sources":["../../src/utils/api-key.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAS9B;AAkED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2DxB;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;gBAEhB,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAUhD,YAAY,IAAI;QACd,OAAO,EAAE,KAAK,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,KAAK,CAAC;KAClB;CAUF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAMjB"}
@@ -0,0 +1,211 @@
1
+ import { createInterface } from "node:readline";
2
+ import { readFile, writeFile, access } from "node:fs/promises";
3
+ import { resolve } from "node:path";
4
+ import { config } from "dotenv";
5
+ import chalk from "chalk";
6
+ import { getApiKeyFromConfig } from "../config/index.js";
7
+ /**
8
+ * Load environment variables from .env files.
9
+ * Priority: CWD .env (project-scoped) > monorepo root .env (development)
10
+ * Later loads don't override earlier values, so CWD takes precedence.
11
+ */
12
+ export function loadEnv() {
13
+ // 1. Load from current working directory (project-scoped, highest priority)
14
+ config({ path: resolve(process.cwd(), ".env"), debug: false });
15
+ // 2. Load from monorepo root if in development (won't override existing vars)
16
+ const monorepoRoot = findMonorepoRoot();
17
+ if (monorepoRoot && monorepoRoot !== process.cwd()) {
18
+ config({ path: resolve(monorepoRoot, ".env"), debug: false });
19
+ }
20
+ }
21
+ // Find monorepo root for development environments
22
+ function findMonorepoRoot() {
23
+ let dir = process.cwd();
24
+ while (dir !== "/") {
25
+ try {
26
+ require.resolve(resolve(dir, "pnpm-workspace.yaml"));
27
+ return dir;
28
+ }
29
+ catch {
30
+ dir = resolve(dir, "..");
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+ /**
36
+ * Prompt user for input (hidden for API keys)
37
+ */
38
+ async function prompt(question, hidden = false) {
39
+ const rl = createInterface({
40
+ input: process.stdin,
41
+ output: process.stdout,
42
+ });
43
+ return new Promise((resolve) => {
44
+ // For hidden input, we need to handle it differently
45
+ if (hidden && process.stdin.isTTY) {
46
+ process.stdout.write(question);
47
+ let input = "";
48
+ process.stdin.setRawMode(true);
49
+ process.stdin.resume();
50
+ process.stdin.setEncoding("utf8");
51
+ const onData = (char) => {
52
+ if (char === "\n" || char === "\r" || char === "\u0004") {
53
+ process.stdin.setRawMode(false);
54
+ process.stdin.pause();
55
+ process.stdin.removeListener("data", onData);
56
+ process.stdout.write("\n");
57
+ rl.close();
58
+ resolve(input);
59
+ }
60
+ else if (char === "\u0003") {
61
+ // Ctrl+C
62
+ process.exit(1);
63
+ }
64
+ else if (char === "\u007F" || char === "\b") {
65
+ // Backspace
66
+ if (input.length > 0) {
67
+ input = input.slice(0, -1);
68
+ }
69
+ }
70
+ else {
71
+ input += char;
72
+ }
73
+ };
74
+ process.stdin.on("data", onData);
75
+ }
76
+ else {
77
+ rl.question(question, (answer) => {
78
+ rl.close();
79
+ resolve(answer);
80
+ });
81
+ }
82
+ });
83
+ }
84
+ /**
85
+ * Get API key from config, environment, or prompt
86
+ */
87
+ export async function getApiKey(envVar, providerName, optionValue) {
88
+ // 1. Check command line option
89
+ if (optionValue) {
90
+ return optionValue;
91
+ }
92
+ // 2. Check ~/.vibeframe/config.yaml
93
+ // Map env var to provider key
94
+ const providerKeyMap = {
95
+ ANTHROPIC_API_KEY: "anthropic",
96
+ OPENAI_API_KEY: "openai",
97
+ GOOGLE_API_KEY: "google",
98
+ ELEVENLABS_API_KEY: "elevenlabs",
99
+ RUNWAY_API_SECRET: "runway",
100
+ KLING_API_KEY: "kling",
101
+ IMGBB_API_KEY: "imgbb",
102
+ REPLICATE_API_TOKEN: "replicate",
103
+ };
104
+ const providerKey = providerKeyMap[envVar];
105
+ if (providerKey) {
106
+ const configKey = await getApiKeyFromConfig(providerKey);
107
+ if (configKey) {
108
+ return configKey;
109
+ }
110
+ }
111
+ // 3. Load .env and check environment
112
+ loadEnv();
113
+ const envValue = process.env[envVar];
114
+ if (envValue) {
115
+ return envValue;
116
+ }
117
+ // 4. Check if running in TTY (interactive terminal)
118
+ if (!process.stdin.isTTY) {
119
+ return null;
120
+ }
121
+ // 5. Prompt for API key
122
+ console.log();
123
+ console.log(chalk.yellow(`${providerName} API key not found.`));
124
+ console.log(chalk.dim(`Set ${envVar} in .env (current directory), run 'vibe setup', or enter below.`));
125
+ console.log();
126
+ const apiKey = await prompt(chalk.cyan(`Enter ${providerName} API key: `), true);
127
+ if (!apiKey || apiKey.trim() === "") {
128
+ return null;
129
+ }
130
+ // 6. Ask if user wants to save to .env
131
+ const save = await prompt(chalk.cyan("Save to .env for future use? (y/N): "));
132
+ if (save.toLowerCase() === "y" || save.toLowerCase() === "yes") {
133
+ await saveApiKeyToEnv(envVar, apiKey.trim());
134
+ console.log(chalk.green("API key saved to .env"));
135
+ }
136
+ return apiKey.trim();
137
+ }
138
+ /**
139
+ * Error thrown when a required API key is missing (non-interactive mode)
140
+ */
141
+ export class ApiKeyError extends Error {
142
+ envVar;
143
+ providerName;
144
+ constructor(envVar, providerName) {
145
+ super(`${providerName} API key required.\n` +
146
+ ` Set ${envVar} in .env, or run: vibe setup`);
147
+ this.name = "ApiKeyError";
148
+ this.envVar = envVar;
149
+ this.providerName = providerName;
150
+ }
151
+ toStructured() {
152
+ return {
153
+ success: false,
154
+ error: `${this.providerName} API key required.`,
155
+ code: "API_KEY_MISSING",
156
+ exitCode: 4,
157
+ suggestion: `Set ${this.envVar} in .env, or run: vibe setup`,
158
+ retryable: false,
159
+ };
160
+ }
161
+ }
162
+ /**
163
+ * Check if an API key is available without prompting or side effects.
164
+ */
165
+ export function hasApiKey(envVar) {
166
+ loadEnv();
167
+ if (process.env[envVar])
168
+ return true;
169
+ const key = getApiKeyFromConfig(envVar);
170
+ return !!key;
171
+ }
172
+ /**
173
+ * Get API key or throw ApiKeyError if not found.
174
+ * Use this instead of getApiKey() + manual null check.
175
+ */
176
+ export async function requireApiKey(envVar, providerName, cliOverride) {
177
+ const key = await getApiKey(envVar, providerName, cliOverride);
178
+ if (!key) {
179
+ throw new ApiKeyError(envVar, providerName);
180
+ }
181
+ return key;
182
+ }
183
+ /**
184
+ * Save API key to .env file
185
+ */
186
+ async function saveApiKeyToEnv(envVar, apiKey) {
187
+ const envPath = resolve(process.cwd(), ".env");
188
+ let content = "";
189
+ try {
190
+ await access(envPath);
191
+ content = await readFile(envPath, "utf-8");
192
+ }
193
+ catch {
194
+ // File doesn't exist, will create new
195
+ }
196
+ // Check if variable already exists
197
+ const regex = new RegExp(`^${envVar}=.*$`, "m");
198
+ if (regex.test(content)) {
199
+ // Replace existing
200
+ content = content.replace(regex, `${envVar}=${apiKey}`);
201
+ }
202
+ else {
203
+ // Append new
204
+ if (content && !content.endsWith("\n")) {
205
+ content += "\n";
206
+ }
207
+ content += `${envVar}=${apiKey}\n`;
208
+ }
209
+ await writeFile(envPath, content, "utf-8");
210
+ }
211
+ //# sourceMappingURL=api-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.js","sourceRoot":"","sources":["../../src/utils/api-key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api-key.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.test.d.ts","sourceRoot":"","sources":["../../src/utils/api-key.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
2
+ import { loadEnv, getApiKey } from "./api-key.js";
3
+ describe("api-key utilities", () => {
4
+ const originalEnv = process.env;
5
+ beforeEach(() => {
6
+ vi.resetModules();
7
+ process.env = { ...originalEnv };
8
+ });
9
+ afterEach(() => {
10
+ process.env = originalEnv;
11
+ });
12
+ describe("loadEnv", () => {
13
+ it("does not throw when .env file is missing", () => {
14
+ expect(() => loadEnv()).not.toThrow();
15
+ });
16
+ });
17
+ describe("getApiKey", () => {
18
+ it("returns option value if provided", async () => {
19
+ const result = await getApiKey("TEST_KEY", "Test", "my-api-key");
20
+ expect(result).toBe("my-api-key");
21
+ });
22
+ it("returns env value if option not provided", async () => {
23
+ process.env.TEST_KEY = "env-api-key";
24
+ const result = await getApiKey("TEST_KEY", "Test");
25
+ expect(result).toBe("env-api-key");
26
+ });
27
+ it("returns null when no key available and not TTY", async () => {
28
+ // In test environment, stdin is not TTY, so it should return null
29
+ delete process.env.TEST_KEY;
30
+ const result = await getApiKey("TEST_KEY", "Test");
31
+ expect(result).toBeNull();
32
+ });
33
+ });
34
+ });
35
+ //# sourceMappingURL=api-key.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.test.js","sourceRoot":"","sources":["../../src/utils/api-key.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAElD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAEhC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,GAAG,GAAG,WAAW,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;YACjE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,kEAAkE;YAClE,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Get the duration of an audio file using ffprobe
3
+ * @param filePath - Path to the audio file
4
+ * @returns Duration in seconds
5
+ */
6
+ export declare function getAudioDuration(filePath: string): Promise<number>;
7
+ /**
8
+ * Get the duration of a video file using ffprobe
9
+ * @param filePath - Path to the video file
10
+ * @returns Duration in seconds
11
+ */
12
+ export declare function getVideoDuration(filePath: string): Promise<number>;
13
+ /**
14
+ * Extend a video naturally to match target duration using progressive techniques.
15
+ * Uses slowdown, frame interpolation, and freeze frames based on extension ratio.
16
+ *
17
+ * @param videoPath - Path to the source video
18
+ * @param targetDuration - Target duration in seconds
19
+ * @param outputPath - Path for the extended video output
20
+ * @returns Promise that resolves when extension is complete
21
+ */
22
+ export declare function extendVideoNaturally(videoPath: string, targetDuration: number, outputPath: string): Promise<void>;
23
+ //# sourceMappingURL=audio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../src/utils/audio.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxE;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxE;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAuCf"}
@@ -0,0 +1,79 @@
1
+ import { execSafe, ffprobeDuration } from "./exec-safe.js";
2
+ /**
3
+ * Get the duration of an audio file using ffprobe
4
+ * @param filePath - Path to the audio file
5
+ * @returns Duration in seconds
6
+ */
7
+ export async function getAudioDuration(filePath) {
8
+ try {
9
+ return await ffprobeDuration(filePath);
10
+ }
11
+ catch (error) {
12
+ const message = error instanceof Error ? error.message : String(error);
13
+ throw new Error(`Failed to get audio duration: ${message}`);
14
+ }
15
+ }
16
+ /**
17
+ * Get the duration of a video file using ffprobe
18
+ * @param filePath - Path to the video file
19
+ * @returns Duration in seconds
20
+ */
21
+ export async function getVideoDuration(filePath) {
22
+ try {
23
+ return await ffprobeDuration(filePath);
24
+ }
25
+ catch (error) {
26
+ const message = error instanceof Error ? error.message : String(error);
27
+ throw new Error(`Failed to get video duration: ${message}`);
28
+ }
29
+ }
30
+ /**
31
+ * Extend a video naturally to match target duration using progressive techniques.
32
+ * Uses slowdown, frame interpolation, and freeze frames based on extension ratio.
33
+ *
34
+ * @param videoPath - Path to the source video
35
+ * @param targetDuration - Target duration in seconds
36
+ * @param outputPath - Path for the extended video output
37
+ * @returns Promise that resolves when extension is complete
38
+ */
39
+ export async function extendVideoNaturally(videoPath, targetDuration, outputPath) {
40
+ const videoDuration = await getVideoDuration(videoPath);
41
+ const ratio = targetDuration / videoDuration;
42
+ if (ratio <= 1.0) {
43
+ // No extension needed, just copy
44
+ const { copyFile } = await import("node:fs/promises");
45
+ await copyFile(videoPath, outputPath);
46
+ return;
47
+ }
48
+ if (ratio <= 1.15) {
49
+ // 0-15% extension: Simple slowdown using setpts
50
+ // setpts factor = 1/ratio to slow down the video
51
+ const slowFactor = (1 / ratio).toFixed(4);
52
+ await execSafe("ffmpeg", ["-y", "-i", videoPath, "-filter:v", `setpts=${slowFactor}*PTS`, "-an", outputPath]);
53
+ }
54
+ else if (ratio <= 1.4) {
55
+ // 15-40% extension: Frame interpolation + slowdown
56
+ // minterpolate creates smooth slow-motion effect
57
+ const slowFactor = (1 / ratio).toFixed(4);
58
+ await execSafe("ffmpeg", ["-y", "-i", videoPath, "-filter:v", `minterpolate=fps=60:mi_mode=mci,setpts=${slowFactor}*PTS`, "-an", outputPath]);
59
+ }
60
+ else {
61
+ // 40%+ extension: Slowdown to 0.7x speed + freeze last frame for remainder
62
+ // First, slow down to get ~43% extension
63
+ const slowRatio = 0.7;
64
+ const slowedDuration = videoDuration / slowRatio;
65
+ const freezeDuration = targetDuration - slowedDuration;
66
+ if (freezeDuration <= 0) {
67
+ // Can achieve target with slowdown alone
68
+ const slowFactor = (1 / ratio).toFixed(4);
69
+ await execSafe("ffmpeg", ["-y", "-i", videoPath, "-filter:v", `minterpolate=fps=60:mi_mode=mci,setpts=${slowFactor}*PTS`, "-an", outputPath]);
70
+ }
71
+ else {
72
+ // Need slowdown + freeze frame
73
+ // Use tpad to extend the last frame
74
+ const slowFactor = (1 / slowRatio).toFixed(4); // ~1.43 for 0.7x speed
75
+ await execSafe("ffmpeg", ["-y", "-i", videoPath, "-filter:v", `setpts=${slowFactor}*PTS,tpad=stop_mode=clone:stop_duration=${freezeDuration.toFixed(2)}`, "-an", outputPath]);
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=audio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../../src/utils/audio.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /** Safe async exec — no shell, args as array */
2
+ export declare function execSafe(cmd: string, args: string[], options?: {
3
+ timeout?: number;
4
+ maxBuffer?: number;
5
+ }): Promise<{
6
+ stdout: string;
7
+ stderr: string;
8
+ }>;
9
+ /** Safe sync exec — no shell, args as array */
10
+ export declare function execSafeSync(cmd: string, args: string[], options?: {
11
+ stdio?: "pipe" | "ignore";
12
+ }): string;
13
+ /** Shorthand: ffprobe duration query */
14
+ export declare function ffprobeDuration(filePath: string): Promise<number>;
15
+ /** Shorthand: ffprobe video dimensions */
16
+ export declare function ffprobeVideoSize(filePath: string): Promise<{
17
+ width: number;
18
+ height: number;
19
+ }>;
20
+ /** Shorthand: check if a command exists */
21
+ export declare function commandExists(cmd: string): boolean;
22
+ //# sourceMappingURL=exec-safe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-safe.d.ts","sourceRoot":"","sources":["../../src/utils/exec-safe.ts"],"names":[],"mappings":"AAKA,gDAAgD;AAChD,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAK7C;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,GACtC,MAAM,CAKR;AAED,wCAAwC;AACxC,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAavE;AAED,0CAA0C;AAC1C,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB5C;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOlD"}
@@ -0,0 +1,62 @@
1
+ import { execFile, execFileSync } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const execFileAsync = promisify(execFile);
4
+ /** Safe async exec — no shell, args as array */
5
+ export async function execSafe(cmd, args, options) {
6
+ return execFileAsync(cmd, args, {
7
+ timeout: options?.timeout,
8
+ maxBuffer: options?.maxBuffer ?? 50 * 1024 * 1024,
9
+ });
10
+ }
11
+ /** Safe sync exec — no shell, args as array */
12
+ export function execSafeSync(cmd, args, options) {
13
+ return execFileSync(cmd, args, {
14
+ encoding: "utf-8",
15
+ stdio: options?.stdio ?? "pipe",
16
+ });
17
+ }
18
+ /** Shorthand: ffprobe duration query */
19
+ export async function ffprobeDuration(filePath) {
20
+ const { stdout } = await execSafe("ffprobe", [
21
+ "-v",
22
+ "error",
23
+ "-show_entries",
24
+ "format=duration",
25
+ "-of",
26
+ "default=noprint_wrappers=1:nokey=1",
27
+ filePath,
28
+ ]);
29
+ const duration = parseFloat(stdout.trim());
30
+ if (isNaN(duration))
31
+ throw new Error(`Invalid duration: ${stdout}`);
32
+ return duration;
33
+ }
34
+ /** Shorthand: ffprobe video dimensions */
35
+ export async function ffprobeVideoSize(filePath) {
36
+ const { stdout } = await execSafe("ffprobe", [
37
+ "-v",
38
+ "error",
39
+ "-select_streams",
40
+ "v:0",
41
+ "-show_entries",
42
+ "stream=width,height",
43
+ "-of",
44
+ "csv=p=0:s=x",
45
+ filePath,
46
+ ]);
47
+ const [w, h] = stdout.trim().split("x").map(Number);
48
+ if (isNaN(w) || isNaN(h))
49
+ throw new Error(`Invalid dimensions: ${stdout.trim()}`);
50
+ return { width: w, height: h };
51
+ }
52
+ /** Shorthand: check if a command exists */
53
+ export function commandExists(cmd) {
54
+ try {
55
+ execFileSync("which", [cmd], { stdio: "ignore" });
56
+ return true;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
62
+ //# sourceMappingURL=exec-safe.js.map