@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
@@ -0,0 +1,329 @@
1
+ /**
2
+ * @module ai-narrate
3
+ *
4
+ * Auto-narration pipeline and provider listing.
5
+ *
6
+ * CLI commands: narrate, providers
7
+ *
8
+ * Execute function:
9
+ * autoNarrate - Analyze video -> generate script -> TTS voiceover
10
+ *
11
+ * Extracted from ai.ts as part of modularisation.
12
+ * ai.ts calls registerNarrateCommands(aiCommand).
13
+ *
14
+ * @dependencies Gemini (video analysis), Claude/OpenAI (script generation),
15
+ * ElevenLabs (TTS), FFmpeg (duration probe)
16
+ */
17
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
18
+ import { resolve, dirname, basename } from "node:path";
19
+ import { existsSync } from "node:fs";
20
+ import chalk from "chalk";
21
+ import ora from "ora";
22
+ import { providerRegistry, whisperProvider, geminiProvider, openaiProvider, claudeProvider, elevenLabsProvider, openaiImageProvider, runwayProvider, klingProvider, replicateProvider, GeminiProvider, OpenAIProvider, ClaudeProvider, ElevenLabsProvider, } from "@vibeframe/ai-providers";
23
+ import { Project } from "../engine/index.js";
24
+ import { getApiKey } from "../utils/api-key.js";
25
+ import { ffprobeDuration } from "../utils/exec-safe.js";
26
+ import { getAudioDuration } from "../utils/audio.js";
27
+ import { formatTime } from "./ai-helpers.js";
28
+ /**
29
+ * Generate narration for a video that doesn't have one.
30
+ *
31
+ * Pipeline:
32
+ * 1. Analyze video with Gemini Video Understanding
33
+ * 2. Generate narration script with Claude (fallback to OpenAI on 529)
34
+ * 3. Convert to speech with ElevenLabs TTS
35
+ *
36
+ * Saves both the audio file and script text to the output directory.
37
+ *
38
+ * @param options - Auto-narrate configuration
39
+ * @returns Result with audio path, script text, and timed segments
40
+ */
41
+ export async function autoNarrate(options) {
42
+ const { videoPath, duration, outputDir, voice = "rachel", style = "informative", language = "en", scriptProvider = "claude", } = options;
43
+ // Validate API keys
44
+ const geminiApiKey = await getApiKey("GOOGLE_API_KEY", "Google");
45
+ if (!geminiApiKey) {
46
+ return { success: false, error: "GOOGLE_API_KEY required for video analysis. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
47
+ }
48
+ let claudeApiKey = null;
49
+ let openaiScriptApiKey = null;
50
+ if (scriptProvider === "openai") {
51
+ openaiScriptApiKey = await getApiKey("OPENAI_API_KEY", "OpenAI");
52
+ if (!openaiScriptApiKey) {
53
+ return { success: false, error: "OPENAI_API_KEY required for script generation. Run 'vibe setup' or set OPENAI_API_KEY in .env" };
54
+ }
55
+ }
56
+ else {
57
+ claudeApiKey = await getApiKey("ANTHROPIC_API_KEY", "Anthropic");
58
+ if (!claudeApiKey) {
59
+ return { success: false, error: "ANTHROPIC_API_KEY required for script generation. Run 'vibe setup' or set ANTHROPIC_API_KEY in .env" };
60
+ }
61
+ }
62
+ const elevenlabsApiKey = await getApiKey("ELEVENLABS_API_KEY", "ElevenLabs");
63
+ if (!elevenlabsApiKey) {
64
+ return { success: false, error: "ELEVENLABS_API_KEY required for TTS. Run 'vibe setup' or set ELEVENLABS_API_KEY in .env" };
65
+ }
66
+ try {
67
+ // Step 1: Analyze video with Gemini
68
+ const gemini = new GeminiProvider();
69
+ await gemini.initialize({ apiKey: geminiApiKey });
70
+ const videoBuffer = await readFile(videoPath);
71
+ const analysisPrompt = `Analyze this video in detail for narration purposes. Describe:
72
+ 1. What is happening visually (actions, movements, subjects)
73
+ 2. The setting and environment
74
+ 3. Any text or graphics visible
75
+ 4. The mood and tone of the content
76
+ 5. Key moments and their approximate timestamps
77
+
78
+ Provide a detailed description that could be used to write a voiceover narration.
79
+ Focus on what viewers need to know to understand and appreciate the video.`;
80
+ const analysisResult = await gemini.analyzeVideo(videoBuffer, analysisPrompt, {
81
+ fps: 0.5, // Lower FPS for cost optimization
82
+ lowResolution: duration > 60, // Use low res for longer videos
83
+ });
84
+ if (!analysisResult.success || !analysisResult.response) {
85
+ return { success: false, error: `Video analysis failed: ${analysisResult.error}` };
86
+ }
87
+ // Step 2: Generate narration script with Claude or OpenAI
88
+ let scriptResult;
89
+ if (scriptProvider === "openai") {
90
+ const gpt = new OpenAIProvider();
91
+ await gpt.initialize({ apiKey: openaiScriptApiKey });
92
+ scriptResult = await gpt.generateNarrationScript(analysisResult.response, duration, style, language);
93
+ }
94
+ else {
95
+ const claude = new ClaudeProvider();
96
+ await claude.initialize({ apiKey: claudeApiKey });
97
+ scriptResult = await claude.generateNarrationScript(analysisResult.response, duration, style, language);
98
+ // Auto-fallback to OpenAI on Claude overload (529)
99
+ if (!scriptResult.success && scriptResult.error?.includes("529")) {
100
+ const fallbackKey = await getApiKey("OPENAI_API_KEY", "OpenAI");
101
+ if (fallbackKey) {
102
+ console.error("⚠️ Claude overloaded, falling back to OpenAI...");
103
+ const gpt = new OpenAIProvider();
104
+ await gpt.initialize({ apiKey: fallbackKey });
105
+ scriptResult = await gpt.generateNarrationScript(analysisResult.response, duration, style, language);
106
+ }
107
+ }
108
+ }
109
+ if (!scriptResult.success || !scriptResult.script) {
110
+ return { success: false, error: `Script generation failed: ${scriptResult.error}` };
111
+ }
112
+ // Step 3: Convert to speech with ElevenLabs
113
+ const elevenlabs = new ElevenLabsProvider();
114
+ await elevenlabs.initialize({ apiKey: elevenlabsApiKey });
115
+ const ttsResult = await elevenlabs.textToSpeech(scriptResult.script, {
116
+ voiceId: voice,
117
+ });
118
+ if (!ttsResult.success || !ttsResult.audioBuffer) {
119
+ return { success: false, error: `TTS generation failed: ${ttsResult.error}` };
120
+ }
121
+ // Ensure output directory exists
122
+ if (!existsSync(outputDir)) {
123
+ await mkdir(outputDir, { recursive: true });
124
+ }
125
+ // Save audio file
126
+ const audioPath = resolve(outputDir, "auto-narration.mp3");
127
+ await writeFile(audioPath, ttsResult.audioBuffer);
128
+ // Save script for reference
129
+ const scriptPath = resolve(outputDir, "narration-script.txt");
130
+ await writeFile(scriptPath, scriptResult.script, "utf-8");
131
+ return {
132
+ success: true,
133
+ audioPath,
134
+ script: scriptResult.script,
135
+ segments: scriptResult.segments,
136
+ };
137
+ }
138
+ catch (error) {
139
+ return {
140
+ success: false,
141
+ error: error instanceof Error ? error.message : "Unknown error in autoNarrate",
142
+ };
143
+ }
144
+ }
145
+ // ==========================================
146
+ // CLI Command Registration
147
+ // ==========================================
148
+ export function registerNarrateCommands(ai) {
149
+ ai
150
+ .command("providers")
151
+ .description("List available AI providers")
152
+ .action(async () => {
153
+ // Register default providers
154
+ providerRegistry.register(whisperProvider);
155
+ providerRegistry.register(geminiProvider);
156
+ providerRegistry.register(openaiProvider);
157
+ providerRegistry.register(claudeProvider);
158
+ providerRegistry.register(elevenLabsProvider);
159
+ providerRegistry.register(openaiImageProvider);
160
+ providerRegistry.register(runwayProvider);
161
+ providerRegistry.register(klingProvider);
162
+ providerRegistry.register(replicateProvider);
163
+ console.log();
164
+ console.log(chalk.bold.cyan("Available AI Providers"));
165
+ console.log(chalk.dim("─".repeat(60)));
166
+ const providers = providerRegistry.getAll();
167
+ for (const provider of providers) {
168
+ const status = provider.isAvailable ? chalk.green("●") : chalk.red("○");
169
+ console.log();
170
+ console.log(`${status} ${chalk.bold(provider.name)} ${chalk.dim(`(${provider.id})`)}`);
171
+ console.log(` ${provider.description}`);
172
+ console.log(` ${chalk.dim("Capabilities:")} ${provider.capabilities.join(", ")}`);
173
+ }
174
+ console.log();
175
+ });
176
+ // Auto-Narrate command
177
+ ai
178
+ .command("narrate")
179
+ .description("Generate AI narration for a video file or project")
180
+ .argument("<input>", "Video file or project file (.vibe.json)")
181
+ .option("-o, --output <dir>", "Output directory for generated files", ".")
182
+ .option("-v, --voice <name>", "ElevenLabs voice name (rachel, adam, josh, etc.)", "rachel")
183
+ .option("-s, --style <style>", "Narration style: informative, energetic, calm, dramatic", "informative")
184
+ .option("-l, --language <lang>", "Language code (e.g., en, ko)", "en")
185
+ .option("-p, --provider <name>", "LLM for script generation: claude (default), openai", "claude")
186
+ .option("--add-to-project", "Add narration to project (only for .vibe.json input)")
187
+ .action(async (inputPath, options) => {
188
+ try {
189
+ const absPath = resolve(process.cwd(), inputPath);
190
+ if (!existsSync(absPath)) {
191
+ console.error(chalk.red(`File not found: ${absPath}`));
192
+ process.exit(1);
193
+ }
194
+ console.log();
195
+ console.log(chalk.bold.cyan("🎙️ Auto-Narrate Pipeline"));
196
+ console.log(chalk.dim("─".repeat(60)));
197
+ console.log();
198
+ const isProject = inputPath.endsWith(".vibe.json");
199
+ let videoPath;
200
+ let project = null;
201
+ let outputDir = resolve(process.cwd(), options.output);
202
+ if (isProject) {
203
+ // Load project to find video source
204
+ const content = await readFile(absPath, "utf-8");
205
+ const data = JSON.parse(content);
206
+ project = Project.fromJSON(data);
207
+ const sources = project.getSources();
208
+ const videoSource = sources.find((s) => s.type === "video");
209
+ if (!videoSource) {
210
+ console.error(chalk.red("No video source found in project"));
211
+ process.exit(1);
212
+ }
213
+ videoPath = resolve(dirname(absPath), videoSource.url);
214
+ if (!existsSync(videoPath)) {
215
+ console.error(chalk.red(`Video file not found: ${videoPath}`));
216
+ process.exit(1);
217
+ }
218
+ // Use project directory as output if not specified
219
+ if (options.output === ".") {
220
+ outputDir = dirname(absPath);
221
+ }
222
+ console.log(`📁 Project: ${chalk.bold(project.getMeta().name)}`);
223
+ }
224
+ else {
225
+ videoPath = absPath;
226
+ console.log(`🎬 Video: ${chalk.bold(basename(videoPath))}`);
227
+ }
228
+ // Get video duration
229
+ const durationSpinner = ora("📊 Analyzing video...").start();
230
+ let duration;
231
+ try {
232
+ duration = await ffprobeDuration(videoPath);
233
+ durationSpinner.succeed(chalk.green(`Duration: ${formatTime(duration)}`));
234
+ }
235
+ catch {
236
+ durationSpinner.fail(chalk.red("Failed to get video duration"));
237
+ process.exit(1);
238
+ }
239
+ // Validate style option
240
+ const validStyles = ["informative", "energetic", "calm", "dramatic"];
241
+ if (!validStyles.includes(options.style)) {
242
+ console.error(chalk.red(`Invalid style: ${options.style}`));
243
+ console.error(chalk.dim(`Valid styles: ${validStyles.join(", ")}`));
244
+ process.exit(1);
245
+ }
246
+ // Generate narration
247
+ const generateSpinner = ora("🤖 Generating narration...").start();
248
+ generateSpinner.text = "📹 Analyzing video with Gemini...";
249
+ const result = await autoNarrate({
250
+ videoPath,
251
+ duration,
252
+ outputDir,
253
+ voice: options.voice,
254
+ style: options.style,
255
+ language: options.language,
256
+ scriptProvider: options.provider,
257
+ });
258
+ if (!result.success) {
259
+ generateSpinner.fail(chalk.red(`Failed: ${result.error}`));
260
+ process.exit(1);
261
+ }
262
+ generateSpinner.succeed(chalk.green("Narration generated successfully"));
263
+ // Display result
264
+ console.log();
265
+ console.log(chalk.bold.cyan("Generated Files"));
266
+ console.log(chalk.dim("─".repeat(60)));
267
+ console.log(` 🎵 Audio: ${chalk.green(result.audioPath)}`);
268
+ console.log(` 📝 Script: ${chalk.green(resolve(outputDir, "narration-script.txt"))}`);
269
+ if (result.segments && result.segments.length > 0) {
270
+ console.log();
271
+ console.log(chalk.bold.cyan("Narration Segments"));
272
+ console.log(chalk.dim("─".repeat(60)));
273
+ for (const seg of result.segments.slice(0, 5)) {
274
+ console.log(` [${formatTime(seg.startTime)} - ${formatTime(seg.endTime)}] ${chalk.dim(seg.text.substring(0, 50))}${seg.text.length > 50 ? "..." : ""}`);
275
+ }
276
+ if (result.segments.length > 5) {
277
+ console.log(chalk.dim(` ... and ${result.segments.length - 5} more segments`));
278
+ }
279
+ }
280
+ // Add to project if requested
281
+ if (options.addToProject && project && isProject) {
282
+ const addSpinner = ora("Adding narration to project...").start();
283
+ // Get audio duration
284
+ let audioDuration;
285
+ try {
286
+ audioDuration = await getAudioDuration(result.audioPath);
287
+ }
288
+ catch {
289
+ audioDuration = duration; // Fallback to video duration
290
+ }
291
+ // Add audio source
292
+ const audioSource = project.addSource({
293
+ name: "Auto-generated narration",
294
+ url: basename(result.audioPath),
295
+ type: "audio",
296
+ duration: audioDuration,
297
+ });
298
+ // Add audio clip to audio track
299
+ const audioTrack = project.getTracks().find((t) => t.type === "audio");
300
+ if (audioTrack) {
301
+ project.addClip({
302
+ sourceId: audioSource.id,
303
+ trackId: audioTrack.id,
304
+ startTime: 0,
305
+ duration: Math.min(audioDuration, duration),
306
+ sourceStartOffset: 0,
307
+ sourceEndOffset: Math.min(audioDuration, duration),
308
+ });
309
+ }
310
+ // Save updated project
311
+ await writeFile(absPath, JSON.stringify(project.toJSON(), null, 2), "utf-8");
312
+ addSpinner.succeed(chalk.green("Narration added to project"));
313
+ }
314
+ console.log();
315
+ console.log(chalk.bold.green("✅ Auto-narrate complete!"));
316
+ if (!options.addToProject && isProject) {
317
+ console.log();
318
+ console.log(chalk.dim("Tip: Use --add-to-project to automatically add the narration to your project"));
319
+ }
320
+ console.log();
321
+ }
322
+ catch (error) {
323
+ console.error(chalk.red("Auto-narrate failed"));
324
+ console.error(error);
325
+ process.exit(1);
326
+ }
327
+ });
328
+ } // end registerNarrateCommands
329
+ //# sourceMappingURL=ai-narrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-narrate.js","sourceRoot":"","sources":["../../src/commands/ai-narrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @module ai-review
3
+ *
4
+ * AI-powered video quality review and auto-fix using Gemini.
5
+ *
6
+ * CLI command: review
7
+ *
8
+ * Execute function:
9
+ * executeReview - Analyze video quality across 5 categories and optionally auto-fix
10
+ *
11
+ * @dependencies Gemini (Google), FFmpeg (auto-fix filters)
12
+ */
13
+ import { Command } from "commander";
14
+ import type { VideoReviewFeedback } from "./ai-edit.js";
15
+ /** Options for {@link executeReview}. */
16
+ export interface ReviewOptions {
17
+ /** Path to the video file to review */
18
+ videoPath: string;
19
+ /** Optional storyboard JSON for context-aware review */
20
+ storyboardPath?: string;
21
+ /** Automatically apply fixable corrections via FFmpeg */
22
+ autoApply?: boolean;
23
+ /** Run a verification pass after applying fixes */
24
+ verify?: boolean;
25
+ /** Gemini model shorthand (default: "flash") */
26
+ model?: "flash" | "flash-2.5" | "pro";
27
+ /** Output path for the fixed video (auto-apply mode) */
28
+ outputPath?: string;
29
+ }
30
+ /** Result from {@link executeReview}. */
31
+ export interface ReviewResult {
32
+ /** Whether the review completed successfully */
33
+ success: boolean;
34
+ /** Structured review feedback with per-category scores */
35
+ feedback?: VideoReviewFeedback;
36
+ /** Descriptions of fixes that were auto-applied */
37
+ appliedFixes?: string[];
38
+ /** Post-fix verification quality score 1-10 */
39
+ verificationScore?: number;
40
+ /** Path to the reviewed/fixed output video */
41
+ outputPath?: string;
42
+ /** Error message on failure */
43
+ error?: string;
44
+ }
45
+ /**
46
+ * Review video quality using Gemini AI and optionally auto-fix issues.
47
+ *
48
+ * Analyzes 5 quality categories (pacing, color, text readability, audio-visual
49
+ * sync, composition) and returns scored feedback. When auto-apply is enabled,
50
+ * applies fixable corrections via FFmpeg filters.
51
+ *
52
+ * @param options - Review configuration
53
+ * @returns Result with structured feedback and optional fix details
54
+ */
55
+ export declare function executeReview(options: ReviewOptions): Promise<ReviewResult>;
56
+ export declare function registerReviewCommand(aiCommand: Command): void;
57
+ //# sourceMappingURL=ai-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-review.d.ts","sourceRoot":"","sources":["../../src/commands/ai-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;IACtC,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yCAAyC;AACzC,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAyBD;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAiIjF;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAwF9D"}
@@ -0,0 +1,251 @@
1
+ /**
2
+ * @module ai-review
3
+ *
4
+ * AI-powered video quality review and auto-fix using Gemini.
5
+ *
6
+ * CLI command: review
7
+ *
8
+ * Execute function:
9
+ * executeReview - Analyze video quality across 5 categories and optionally auto-fix
10
+ *
11
+ * @dependencies Gemini (Google), FFmpeg (auto-fix filters)
12
+ */
13
+ import { readFile, rename } from "node:fs/promises";
14
+ import { resolve } from "node:path";
15
+ import { existsSync } from "node:fs";
16
+ import chalk from "chalk";
17
+ import ora from "ora";
18
+ import { GeminiProvider } from "@vibeframe/ai-providers";
19
+ import { getApiKey, loadEnv } from "../utils/api-key.js";
20
+ import { execSafe } from "../utils/exec-safe.js";
21
+ function parseReviewFeedback(response) {
22
+ let cleaned = response.trim();
23
+ if (cleaned.startsWith("```json")) {
24
+ cleaned = cleaned.slice(7);
25
+ }
26
+ else if (cleaned.startsWith("```")) {
27
+ cleaned = cleaned.slice(3);
28
+ }
29
+ if (cleaned.endsWith("```")) {
30
+ cleaned = cleaned.slice(0, -3);
31
+ }
32
+ cleaned = cleaned.trim();
33
+ try {
34
+ const parsed = JSON.parse(cleaned);
35
+ if (typeof parsed.overallScore !== "number" || !parsed.categories) {
36
+ return null;
37
+ }
38
+ return parsed;
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ /**
45
+ * Review video quality using Gemini AI and optionally auto-fix issues.
46
+ *
47
+ * Analyzes 5 quality categories (pacing, color, text readability, audio-visual
48
+ * sync, composition) and returns scored feedback. When auto-apply is enabled,
49
+ * applies fixable corrections via FFmpeg filters.
50
+ *
51
+ * @param options - Review configuration
52
+ * @returns Result with structured feedback and optional fix details
53
+ */
54
+ export async function executeReview(options) {
55
+ const { videoPath, storyboardPath, autoApply = false, verify = false, model = "flash" } = options;
56
+ const absVideoPath = resolve(process.cwd(), videoPath);
57
+ if (!existsSync(absVideoPath)) {
58
+ return { success: false, error: `Video not found: ${absVideoPath}` };
59
+ }
60
+ const apiKey = process.env.GOOGLE_API_KEY || (await getApiKey("GOOGLE_API_KEY", "Google"));
61
+ if (!apiKey) {
62
+ return { success: false, error: "Google API key required for Gemini video review. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
63
+ }
64
+ let storyboardContext = "";
65
+ if (storyboardPath) {
66
+ const absStoryboardPath = resolve(process.cwd(), storyboardPath);
67
+ if (existsSync(absStoryboardPath)) {
68
+ const content = await readFile(absStoryboardPath, "utf-8");
69
+ storyboardContext = `\n\nOriginal storyboard for reference:\n${content}`;
70
+ }
71
+ }
72
+ const modelMap = {
73
+ flash: "gemini-3-flash-preview",
74
+ "flash-2.5": "gemini-2.5-flash",
75
+ pro: "gemini-2.5-pro",
76
+ };
77
+ const modelId = modelMap[model] || modelMap.flash;
78
+ const reviewPrompt = `You are a professional video editor reviewing this video for quality. Analyze the video and return a JSON review with the following structure. Return ONLY valid JSON, no extra text.
79
+
80
+ {
81
+ "overallScore": <number 1-10>,
82
+ "categories": {
83
+ "pacing": { "score": <1-10>, "issues": ["..."], "fixable": <boolean> },
84
+ "color": { "score": <1-10>, "issues": ["..."], "fixable": <boolean>, "suggestedFilter": "<ffmpeg filter or null>" },
85
+ "textReadability": { "score": <1-10>, "issues": ["..."], "fixable": <boolean>, "suggestions": ["..."] },
86
+ "audioVisualSync": { "score": <1-10>, "issues": ["..."], "fixable": <boolean> },
87
+ "composition": { "score": <1-10>, "issues": ["..."], "fixable": <boolean> }
88
+ },
89
+ "autoFixable": [
90
+ { "type": "color_grade"|"text_overlay_adjust"|"speed_adjust"|"crop", "description": "...", "ffmpegFilter": "..." }
91
+ ],
92
+ "recommendations": ["..."]
93
+ }
94
+
95
+ Score each category 1-10. For fixable issues, provide an FFmpeg filter in autoFixable. Be specific and practical.${storyboardContext}`;
96
+ const gemini = new GeminiProvider();
97
+ await gemini.initialize({ apiKey });
98
+ const videoData = await readFile(absVideoPath);
99
+ const analysisResult = await gemini.analyzeVideo(videoData, reviewPrompt, {
100
+ model: modelId,
101
+ });
102
+ if (!analysisResult.success || !analysisResult.response) {
103
+ return { success: false, error: analysisResult.error || "Gemini video analysis failed" };
104
+ }
105
+ const feedback = parseReviewFeedback(analysisResult.response);
106
+ if (!feedback) {
107
+ return {
108
+ success: false,
109
+ error: "Failed to parse review feedback from Gemini response",
110
+ };
111
+ }
112
+ const result = {
113
+ success: true,
114
+ feedback,
115
+ appliedFixes: [],
116
+ };
117
+ if (autoApply && feedback.autoFixable.length > 0) {
118
+ let currentInput = absVideoPath;
119
+ const outputBase = options.outputPath
120
+ ? resolve(process.cwd(), options.outputPath)
121
+ : absVideoPath.replace(/(\.[^.]+)$/, "-reviewed$1");
122
+ for (const fix of feedback.autoFixable) {
123
+ if (fix.type === "color_grade" && fix.ffmpegFilter) {
124
+ try {
125
+ const tempOutput = outputBase.replace(/(\.[^.]+)$/, `-fix-${result.appliedFixes.length}$1`);
126
+ await execSafe("ffmpeg", ["-i", currentInput, "-vf", fix.ffmpegFilter, "-c:a", "copy", tempOutput, "-y"], { timeout: 600000, maxBuffer: 50 * 1024 * 1024 });
127
+ currentInput = tempOutput;
128
+ result.appliedFixes.push(`${fix.type}: ${fix.description}`);
129
+ }
130
+ catch {
131
+ // Skip failed fix, continue with others
132
+ }
133
+ }
134
+ else if (fix.type === "text_overlay_adjust") {
135
+ result.appliedFixes.push(`${fix.type}: ${fix.description} (manual adjustment recommended)`);
136
+ }
137
+ }
138
+ if (currentInput !== absVideoPath) {
139
+ const finalOutput = outputBase;
140
+ try {
141
+ await rename(currentInput, finalOutput);
142
+ result.outputPath = finalOutput;
143
+ }
144
+ catch {
145
+ result.outputPath = currentInput;
146
+ }
147
+ }
148
+ }
149
+ if (verify && result.outputPath) {
150
+ const verifyVideoData = await readFile(result.outputPath);
151
+ const verifyResult = await gemini.analyzeVideo(verifyVideoData, "Rate this video overall quality on a scale of 1-10. Return ONLY a JSON object: {\"score\": <number>}", { model: modelId });
152
+ if (verifyResult.success && verifyResult.response) {
153
+ try {
154
+ let cleaned = verifyResult.response.trim();
155
+ if (cleaned.startsWith("```json"))
156
+ cleaned = cleaned.slice(7);
157
+ if (cleaned.startsWith("```"))
158
+ cleaned = cleaned.slice(3);
159
+ if (cleaned.endsWith("```"))
160
+ cleaned = cleaned.slice(0, -3);
161
+ const parsed = JSON.parse(cleaned.trim());
162
+ result.verificationScore = parsed.score;
163
+ }
164
+ catch {
165
+ // Verification parse failed, not critical
166
+ }
167
+ }
168
+ }
169
+ return result;
170
+ }
171
+ export function registerReviewCommand(aiCommand) {
172
+ aiCommand
173
+ .command("review")
174
+ .description("Review video quality using Gemini AI and optionally auto-fix issues")
175
+ .argument("<video>", "Video file path")
176
+ .option("-s, --storyboard <path>", "Storyboard JSON file for context")
177
+ .option("--auto-apply", "Automatically apply fixable corrections")
178
+ .option("--verify", "Run verification pass after applying fixes")
179
+ .option("-m, --model <model>", "Gemini model: flash (default), flash-2.5, pro", "flash")
180
+ .option("-o, --output <path>", "Output video file path (for auto-apply)")
181
+ .action(async (videoPath, options) => {
182
+ try {
183
+ loadEnv();
184
+ const spinner = ora("Reviewing video with Gemini...").start();
185
+ const result = await executeReview({
186
+ videoPath,
187
+ storyboardPath: options.storyboard,
188
+ autoApply: options.autoApply,
189
+ verify: options.verify,
190
+ model: options.model,
191
+ outputPath: options.output,
192
+ });
193
+ if (!result.success) {
194
+ spinner.fail(chalk.red(result.error || "Video review failed"));
195
+ process.exit(1);
196
+ }
197
+ spinner.succeed(chalk.green("Video review complete"));
198
+ console.log();
199
+ const fb = result.feedback;
200
+ console.log(chalk.bold.cyan("Video Review"));
201
+ console.log(chalk.dim("─".repeat(60)));
202
+ console.log(`Overall Score: ${chalk.bold(fb.overallScore >= 7 ? chalk.green(String(fb.overallScore)) : fb.overallScore >= 5 ? chalk.yellow(String(fb.overallScore)) : chalk.red(String(fb.overallScore)))}/10`);
203
+ console.log();
204
+ const categories = [
205
+ ["Pacing", fb.categories.pacing],
206
+ ["Color", fb.categories.color],
207
+ ["Text Readability", fb.categories.textReadability],
208
+ ["Audio-Visual Sync", fb.categories.audioVisualSync],
209
+ ["Composition", fb.categories.composition],
210
+ ];
211
+ for (const [name, cat] of categories) {
212
+ const scoreColor = cat.score >= 7 ? chalk.green : cat.score >= 5 ? chalk.yellow : chalk.red;
213
+ const fixable = cat.fixable ? chalk.dim(" [fixable]") : "";
214
+ console.log(` ${name.padEnd(20)} ${scoreColor(String(cat.score).padStart(2))}/10${fixable}`);
215
+ if (cat.issues.length > 0) {
216
+ for (const issue of cat.issues) {
217
+ console.log(chalk.dim(` - ${issue}`));
218
+ }
219
+ }
220
+ }
221
+ if (result.appliedFixes && result.appliedFixes.length > 0) {
222
+ console.log();
223
+ console.log(chalk.bold.green("Applied Fixes:"));
224
+ for (const fix of result.appliedFixes) {
225
+ console.log(chalk.green(` + ${fix}`));
226
+ }
227
+ if (result.outputPath) {
228
+ console.log(chalk.green(` Output: ${result.outputPath}`));
229
+ }
230
+ }
231
+ if (result.verificationScore !== undefined) {
232
+ console.log();
233
+ console.log(chalk.bold(`Verification Score: ${result.verificationScore}/10`));
234
+ }
235
+ if (fb.recommendations.length > 0) {
236
+ console.log();
237
+ console.log(chalk.bold("Recommendations:"));
238
+ for (const rec of fb.recommendations) {
239
+ console.log(chalk.dim(` * ${rec}`));
240
+ }
241
+ }
242
+ console.log();
243
+ }
244
+ catch (error) {
245
+ console.error(chalk.red("Video review failed"));
246
+ console.error(error);
247
+ process.exit(1);
248
+ }
249
+ });
250
+ }
251
+ //# sourceMappingURL=ai-review.js.map