varg.ai-sdk 0.1.0 → 0.4.0-alpha.1

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 (236) hide show
  1. package/.claude/settings.local.json +1 -1
  2. package/.env.example +3 -0
  3. package/.github/workflows/ci.yml +23 -0
  4. package/.husky/README.md +102 -0
  5. package/.husky/commit-msg +6 -0
  6. package/.husky/pre-commit +9 -0
  7. package/.husky/pre-push +6 -0
  8. package/.size-limit.json +8 -0
  9. package/.test-hooks.ts +5 -0
  10. package/CLAUDE.md +10 -3
  11. package/CONTRIBUTING.md +150 -0
  12. package/LICENSE.md +53 -0
  13. package/README.md +56 -209
  14. package/SKILLS.md +26 -10
  15. package/biome.json +7 -1
  16. package/bun.lock +1286 -0
  17. package/commitlint.config.js +22 -0
  18. package/docs/index.html +1130 -0
  19. package/docs/prompting.md +326 -0
  20. package/docs/react.md +834 -0
  21. package/docs/sdk.md +812 -0
  22. package/ffmpeg/CLAUDE.md +68 -0
  23. package/package.json +48 -8
  24. package/pipeline/cookbooks/scripts/animate-frames-parallel.ts +84 -0
  25. package/pipeline/cookbooks/scripts/combine-scenes.sh +53 -0
  26. package/pipeline/cookbooks/scripts/generate-frames-parallel.ts +99 -0
  27. package/pipeline/cookbooks/scripts/still-to-video.sh +37 -0
  28. package/pipeline/cookbooks/text-to-tiktok.md +669 -0
  29. package/pipeline/cookbooks/trendwatching.md +156 -0
  30. package/plan.md +281 -0
  31. package/scripts/.gitkeep +0 -0
  32. package/src/ai-sdk/cache.ts +142 -0
  33. package/src/ai-sdk/examples/cached-generation.ts +53 -0
  34. package/src/ai-sdk/examples/duet-scene-4.ts +53 -0
  35. package/src/ai-sdk/examples/duet-scene-5-audio.ts +32 -0
  36. package/src/ai-sdk/examples/duet-video.ts +56 -0
  37. package/src/ai-sdk/examples/editly-composition.ts +63 -0
  38. package/src/ai-sdk/examples/editly-test.ts +57 -0
  39. package/src/ai-sdk/examples/editly-video-test.ts +52 -0
  40. package/src/ai-sdk/examples/fal-lipsync.ts +43 -0
  41. package/src/ai-sdk/examples/higgsfield-image.ts +61 -0
  42. package/src/ai-sdk/examples/music-generation.ts +19 -0
  43. package/src/ai-sdk/examples/openai-sora.ts +34 -0
  44. package/src/ai-sdk/examples/replicate-bg-removal.ts +52 -0
  45. package/src/ai-sdk/examples/simpsons-scene.ts +61 -0
  46. package/src/ai-sdk/examples/talking-lion.ts +55 -0
  47. package/src/ai-sdk/examples/video-generation.ts +39 -0
  48. package/src/ai-sdk/examples/workflow-animated-girl.ts +104 -0
  49. package/src/ai-sdk/examples/workflow-before-after.ts +114 -0
  50. package/src/ai-sdk/examples/workflow-character-grid.ts +112 -0
  51. package/src/ai-sdk/examples/workflow-slideshow.ts +161 -0
  52. package/src/ai-sdk/file-cache.ts +112 -0
  53. package/src/ai-sdk/file.ts +238 -0
  54. package/src/ai-sdk/generate-element.ts +92 -0
  55. package/src/ai-sdk/generate-music.ts +46 -0
  56. package/src/ai-sdk/generate-video.ts +165 -0
  57. package/src/ai-sdk/index.ts +72 -0
  58. package/src/ai-sdk/music-model.ts +110 -0
  59. package/src/ai-sdk/providers/editly/editly.test.ts +1108 -0
  60. package/src/ai-sdk/providers/editly/ffmpeg.ts +60 -0
  61. package/src/ai-sdk/providers/editly/index.ts +817 -0
  62. package/src/ai-sdk/providers/editly/layers.ts +776 -0
  63. package/src/ai-sdk/providers/editly/plan.md +144 -0
  64. package/src/ai-sdk/providers/editly/types.ts +328 -0
  65. package/src/ai-sdk/providers/elevenlabs-provider.ts +255 -0
  66. package/src/ai-sdk/providers/fal-provider.ts +512 -0
  67. package/src/ai-sdk/providers/higgsfield.ts +379 -0
  68. package/src/ai-sdk/providers/openai.ts +251 -0
  69. package/src/ai-sdk/providers/replicate.ts +16 -0
  70. package/src/ai-sdk/video-model.ts +185 -0
  71. package/src/cli/commands/find.tsx +137 -0
  72. package/src/cli/commands/help.tsx +85 -0
  73. package/src/cli/commands/index.ts +6 -0
  74. package/src/cli/commands/list.tsx +238 -0
  75. package/src/cli/commands/render.tsx +71 -0
  76. package/src/cli/commands/run.tsx +511 -0
  77. package/src/cli/commands/which.tsx +253 -0
  78. package/src/cli/index.ts +114 -0
  79. package/src/cli/quiet.ts +44 -0
  80. package/src/cli/types.ts +32 -0
  81. package/src/cli/ui/components/Badge.tsx +29 -0
  82. package/src/cli/ui/components/DataTable.tsx +51 -0
  83. package/src/cli/ui/components/Header.tsx +23 -0
  84. package/src/cli/ui/components/HelpBlock.tsx +44 -0
  85. package/src/cli/ui/components/KeyValue.tsx +33 -0
  86. package/src/cli/ui/components/OptionRow.tsx +81 -0
  87. package/src/cli/ui/components/Separator.tsx +23 -0
  88. package/src/cli/ui/components/StatusBox.tsx +108 -0
  89. package/src/cli/ui/components/VargBox.tsx +51 -0
  90. package/src/cli/ui/components/VargProgress.tsx +36 -0
  91. package/src/cli/ui/components/VargSpinner.tsx +34 -0
  92. package/src/cli/ui/components/VargText.tsx +56 -0
  93. package/src/cli/ui/components/index.ts +19 -0
  94. package/src/cli/ui/index.ts +12 -0
  95. package/src/cli/ui/render.ts +35 -0
  96. package/src/cli/ui/theme.ts +63 -0
  97. package/src/cli/utils.ts +78 -0
  98. package/src/core/executor/executor.ts +201 -0
  99. package/src/core/executor/index.ts +13 -0
  100. package/src/core/executor/job.ts +214 -0
  101. package/src/core/executor/pipeline.ts +222 -0
  102. package/src/core/index.ts +11 -0
  103. package/src/core/registry/index.ts +9 -0
  104. package/src/core/registry/loader.ts +149 -0
  105. package/src/core/registry/registry.ts +221 -0
  106. package/src/core/registry/resolver.ts +206 -0
  107. package/src/core/schema/helpers.ts +134 -0
  108. package/src/core/schema/index.ts +8 -0
  109. package/src/core/schema/shared.ts +102 -0
  110. package/src/core/schema/types.ts +279 -0
  111. package/src/core/schema/validator.ts +92 -0
  112. package/src/definitions/actions/captions.ts +261 -0
  113. package/src/definitions/actions/edit.ts +298 -0
  114. package/src/definitions/actions/image.ts +125 -0
  115. package/src/definitions/actions/index.ts +114 -0
  116. package/src/definitions/actions/music.ts +205 -0
  117. package/src/definitions/actions/sync.ts +128 -0
  118. package/{action/transcribe/index.ts → src/definitions/actions/transcribe.ts} +63 -90
  119. package/src/definitions/actions/upload.ts +111 -0
  120. package/src/definitions/actions/video.ts +163 -0
  121. package/src/definitions/actions/voice.ts +119 -0
  122. package/src/definitions/index.ts +23 -0
  123. package/src/definitions/models/elevenlabs.ts +50 -0
  124. package/src/definitions/models/flux.ts +56 -0
  125. package/src/definitions/models/index.ts +36 -0
  126. package/src/definitions/models/kling.ts +56 -0
  127. package/src/definitions/models/llama.ts +54 -0
  128. package/src/definitions/models/nano-banana-pro.ts +102 -0
  129. package/src/definitions/models/sonauto.ts +68 -0
  130. package/src/definitions/models/soul.ts +65 -0
  131. package/src/definitions/models/wan.ts +54 -0
  132. package/src/definitions/models/whisper.ts +44 -0
  133. package/src/definitions/skills/index.ts +12 -0
  134. package/src/definitions/skills/talking-character.ts +87 -0
  135. package/src/definitions/skills/text-to-tiktok.ts +97 -0
  136. package/src/index.ts +118 -0
  137. package/src/providers/apify.ts +269 -0
  138. package/src/providers/base.ts +264 -0
  139. package/src/providers/elevenlabs.ts +217 -0
  140. package/src/providers/fal.ts +392 -0
  141. package/src/providers/ffmpeg.ts +544 -0
  142. package/src/providers/fireworks.ts +193 -0
  143. package/src/providers/groq.ts +149 -0
  144. package/src/providers/higgsfield.ts +145 -0
  145. package/src/providers/index.ts +143 -0
  146. package/src/providers/replicate.ts +147 -0
  147. package/src/providers/storage.ts +206 -0
  148. package/src/react/cli.ts +52 -0
  149. package/src/react/elements.ts +146 -0
  150. package/src/react/examples/branching.tsx +66 -0
  151. package/src/react/examples/captions-demo.tsx +37 -0
  152. package/src/react/examples/character-video.tsx +84 -0
  153. package/src/react/examples/grid.tsx +53 -0
  154. package/src/react/examples/layouts-demo.tsx +57 -0
  155. package/src/react/examples/madi.tsx +60 -0
  156. package/src/react/examples/music-test.tsx +35 -0
  157. package/src/react/examples/onlyfans-1m/workflow.tsx +88 -0
  158. package/src/react/examples/orange-portrait.tsx +41 -0
  159. package/src/react/examples/split-element-demo.tsx +60 -0
  160. package/src/react/examples/split-layout-demo.tsx +60 -0
  161. package/src/react/examples/split.tsx +41 -0
  162. package/src/react/examples/video-grid.tsx +46 -0
  163. package/src/react/index.ts +43 -0
  164. package/src/react/layouts/grid.tsx +28 -0
  165. package/src/react/layouts/index.ts +2 -0
  166. package/src/react/layouts/split.tsx +20 -0
  167. package/src/react/react.test.ts +309 -0
  168. package/src/react/render.ts +21 -0
  169. package/src/react/renderers/animate.ts +59 -0
  170. package/src/react/renderers/captions.ts +297 -0
  171. package/src/react/renderers/clip.ts +248 -0
  172. package/src/react/renderers/context.ts +17 -0
  173. package/src/react/renderers/image.ts +109 -0
  174. package/src/react/renderers/index.ts +22 -0
  175. package/src/react/renderers/music.ts +60 -0
  176. package/src/react/renderers/packshot.ts +84 -0
  177. package/src/react/renderers/progress.ts +173 -0
  178. package/src/react/renderers/render.ts +243 -0
  179. package/src/react/renderers/slider.ts +69 -0
  180. package/src/react/renderers/speech.ts +53 -0
  181. package/src/react/renderers/split.ts +91 -0
  182. package/src/react/renderers/subtitle.ts +16 -0
  183. package/src/react/renderers/swipe.ts +75 -0
  184. package/src/react/renderers/title.ts +17 -0
  185. package/src/react/renderers/utils.ts +124 -0
  186. package/src/react/renderers/video.ts +127 -0
  187. package/src/react/runtime/jsx-dev-runtime.ts +43 -0
  188. package/src/react/runtime/jsx-runtime.ts +35 -0
  189. package/src/react/types.ts +232 -0
  190. package/src/studio/index.ts +26 -0
  191. package/src/studio/scanner.ts +102 -0
  192. package/src/studio/server.ts +554 -0
  193. package/src/studio/stages.ts +251 -0
  194. package/src/studio/step-renderer.ts +279 -0
  195. package/src/studio/types.ts +60 -0
  196. package/src/studio/ui/cache.html +303 -0
  197. package/src/studio/ui/index.html +1820 -0
  198. package/src/tests/all.test.ts +509 -0
  199. package/src/tests/index.ts +33 -0
  200. package/src/tests/unit.test.ts +403 -0
  201. package/tsconfig.cli.json +8 -0
  202. package/tsconfig.json +21 -3
  203. package/TEST_RESULTS.md +0 -122
  204. package/action/captions/SKILL.md +0 -170
  205. package/action/captions/index.ts +0 -227
  206. package/action/edit/SKILL.md +0 -235
  207. package/action/edit/index.ts +0 -493
  208. package/action/image/SKILL.md +0 -140
  209. package/action/image/index.ts +0 -112
  210. package/action/sync/SKILL.md +0 -136
  211. package/action/sync/index.ts +0 -187
  212. package/action/transcribe/SKILL.md +0 -179
  213. package/action/video/SKILL.md +0 -116
  214. package/action/video/index.ts +0 -135
  215. package/action/voice/SKILL.md +0 -125
  216. package/action/voice/index.ts +0 -201
  217. package/index.ts +0 -38
  218. package/lib/README.md +0 -144
  219. package/lib/ai-sdk/fal.ts +0 -106
  220. package/lib/ai-sdk/replicate.ts +0 -107
  221. package/lib/elevenlabs.ts +0 -382
  222. package/lib/fal.ts +0 -478
  223. package/lib/ffmpeg.ts +0 -467
  224. package/lib/fireworks.ts +0 -235
  225. package/lib/groq.ts +0 -246
  226. package/lib/higgsfield.ts +0 -176
  227. package/lib/remotion/SKILL.md +0 -823
  228. package/lib/remotion/cli.ts +0 -115
  229. package/lib/remotion/functions.ts +0 -283
  230. package/lib/remotion/index.ts +0 -19
  231. package/lib/remotion/templates.ts +0 -73
  232. package/lib/replicate.ts +0 -304
  233. package/output.txt +0 -1
  234. package/test-import.ts +0 -7
  235. package/test-services.ts +0 -97
  236. package/utilities/s3.ts +0 -147
package/lib/fal.ts DELETED
@@ -1,478 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- /**
4
- * fal.ai wrapper using @fal-ai/client directly
5
- * for video generation and advanced features
6
- *
7
- * usage: bun run lib/fal.ts <command> <args>
8
- */
9
-
10
- import { existsSync } from "node:fs";
11
- import { fal } from "@fal-ai/client";
12
-
13
- interface FalImageToVideoArgs {
14
- prompt: string;
15
- imageUrl: string; // can be url or local file path
16
- modelVersion?: string;
17
- duration?: 5 | 10;
18
- }
19
-
20
- /**
21
- * upload local file to fal storage if needed
22
- * returns the url (either original or uploaded)
23
- */
24
- async function ensureImageUrl(imagePathOrUrl: string): Promise<string> {
25
- // if it's already a url, return it
26
- if (
27
- imagePathOrUrl.startsWith("http://") ||
28
- imagePathOrUrl.startsWith("https://")
29
- ) {
30
- return imagePathOrUrl;
31
- }
32
-
33
- // check if local file exists
34
- if (!existsSync(imagePathOrUrl)) {
35
- throw new Error(`local file not found: ${imagePathOrUrl}`);
36
- }
37
-
38
- console.log(`[fal] uploading local file: ${imagePathOrUrl}`);
39
-
40
- // read file and upload to fal
41
- const file = await Bun.file(imagePathOrUrl).arrayBuffer();
42
-
43
- const uploadedUrl = await fal.storage.upload(
44
- new Blob([file], { type: "image/jpeg" }),
45
- );
46
-
47
- console.log(`[fal] uploaded to: ${uploadedUrl}`);
48
- return uploadedUrl;
49
- }
50
-
51
- interface FalTextToVideoArgs {
52
- prompt: string;
53
- modelVersion?: string;
54
- duration?: 5 | 10;
55
- }
56
-
57
- export async function imageToVideo(args: FalImageToVideoArgs) {
58
- const modelId = `fal-ai/kling-video/${args.modelVersion || "v2.5-turbo/pro"}/image-to-video`;
59
-
60
- console.log(`[fal] starting image-to-video: ${modelId}`);
61
- console.log(`[fal] prompt: ${args.prompt}`);
62
- console.log(`[fal] image: ${args.imageUrl}`);
63
-
64
- // upload local file if needed
65
- const imageUrl = await ensureImageUrl(args.imageUrl);
66
-
67
- try {
68
- const result = await fal.subscribe(modelId, {
69
- input: {
70
- prompt: args.prompt,
71
- image_url: imageUrl,
72
- duration: args.duration || 5,
73
- },
74
- logs: true,
75
- onQueueUpdate: (update: {
76
- status: string;
77
- logs?: Array<{ message: string }>;
78
- }) => {
79
- if (update.status === "IN_PROGRESS") {
80
- console.log(
81
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
82
- );
83
- }
84
- },
85
- });
86
-
87
- console.log("[fal] completed!");
88
- return result;
89
- } catch (error) {
90
- console.error("[fal] error:", error);
91
- throw error;
92
- }
93
- }
94
-
95
- export async function textToVideo(args: FalTextToVideoArgs) {
96
- const modelId = `fal-ai/kling-video/${args.modelVersion || "v2.5-turbo/pro"}/text-to-video`;
97
-
98
- console.log(`[fal] starting text-to-video: ${modelId}`);
99
- console.log(`[fal] prompt: ${args.prompt}`);
100
-
101
- try {
102
- const result = await fal.subscribe(modelId, {
103
- input: {
104
- prompt: args.prompt,
105
- duration: args.duration || 5,
106
- },
107
- logs: true,
108
- onQueueUpdate: (update: {
109
- status: string;
110
- logs?: Array<{ message: string }>;
111
- }) => {
112
- if (update.status === "IN_PROGRESS") {
113
- console.log(
114
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
115
- );
116
- }
117
- },
118
- });
119
-
120
- console.log("[fal] completed!");
121
- return result;
122
- } catch (error) {
123
- console.error("[fal] error:", error);
124
- throw error;
125
- }
126
- }
127
-
128
- export async function generateImage(args: {
129
- prompt: string;
130
- model?: string;
131
- imageSize?: string;
132
- }) {
133
- const modelId = args.model || "fal-ai/flux-pro/v1.1";
134
-
135
- console.log(`[fal] generating image with ${modelId}`);
136
- console.log(`[fal] prompt: ${args.prompt}`);
137
-
138
- try {
139
- const result = await fal.subscribe(modelId, {
140
- input: {
141
- prompt: args.prompt,
142
- image_size: args.imageSize || "landscape_4_3",
143
- },
144
- logs: true,
145
- onQueueUpdate: (update: {
146
- status: string;
147
- logs?: Array<{ message: string }>;
148
- }) => {
149
- if (update.status === "IN_PROGRESS") {
150
- console.log(
151
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
152
- );
153
- }
154
- },
155
- });
156
-
157
- console.log("[fal] completed!");
158
- return result;
159
- } catch (error) {
160
- console.error("[fal] error:", error);
161
- throw error;
162
- }
163
- }
164
-
165
- interface FalImageToImageArgs {
166
- prompt: string;
167
- imageUrl: string; // can be url or local file path
168
- strength?: number;
169
- numInferenceSteps?: number;
170
- aspectRatio?: string; // auto, 21:9, 16:9, 3:2, 4:3, 5:4, 1:1, 4:5, 3:4, 2:3, 9:16
171
- }
172
-
173
- interface FalWan25Args {
174
- prompt: string;
175
- imageUrl: string; // can be url or local file path
176
- audioUrl: string; // can be url or local file path
177
- resolution?: "480p" | "720p" | "1080p";
178
- duration?: "5" | "10";
179
- negativePrompt?: string;
180
- enablePromptExpansion?: boolean;
181
- enableSafetyChecker?: boolean;
182
- }
183
-
184
- export async function imageToImage(args: FalImageToImageArgs) {
185
- const modelId = "fal-ai/nano-banana-pro/edit";
186
-
187
- console.log(`[fal] starting image-to-image: ${modelId}`);
188
- console.log(`[fal] prompt: ${args.prompt}`);
189
- console.log(`[fal] source image: ${args.imageUrl}`);
190
-
191
- // upload local file if needed
192
- const imageUrl = await ensureImageUrl(args.imageUrl);
193
-
194
- try {
195
- const result = await fal.subscribe(modelId, {
196
- input: {
197
- prompt: args.prompt,
198
- image_urls: [imageUrl],
199
- aspect_ratio: args.aspectRatio || "auto",
200
- resolution: "2K",
201
- },
202
- logs: true,
203
- onQueueUpdate: (update: {
204
- status: string;
205
- logs?: Array<{ message: string }>;
206
- }) => {
207
- if (update.status === "IN_PROGRESS") {
208
- console.log(
209
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
210
- );
211
- }
212
- },
213
- });
214
-
215
- console.log("[fal] completed!");
216
- return result;
217
- } catch (error) {
218
- console.error("[fal] error:", error);
219
- throw error;
220
- }
221
- }
222
-
223
- interface FalWan25Args {
224
- prompt: string;
225
- imageUrl: string; // can be url or local file path
226
- audioUrl: string; // can be url or local file path
227
- resolution?: "480p" | "720p" | "1080p";
228
- duration?: "5" | "10";
229
- negativePrompt?: string;
230
- enablePromptExpansion?: boolean;
231
- enableSafetyChecker?: boolean;
232
- }
233
-
234
- /**
235
- * helper to upload audio file to fal storage if needed
236
- */
237
- async function ensureAudioUrl(audioPathOrUrl: string): Promise<string> {
238
- // if it's already a url, return it
239
- if (
240
- audioPathOrUrl.startsWith("http://") ||
241
- audioPathOrUrl.startsWith("https://")
242
- ) {
243
- return audioPathOrUrl;
244
- }
245
-
246
- // check if local file exists
247
- if (!existsSync(audioPathOrUrl)) {
248
- throw new Error(`local audio file not found: ${audioPathOrUrl}`);
249
- }
250
-
251
- console.log(`[fal] uploading local audio: ${audioPathOrUrl}`);
252
-
253
- // read file and upload to fal
254
- const file = await Bun.file(audioPathOrUrl).arrayBuffer();
255
-
256
- const uploadedUrl = await fal.storage.upload(
257
- new Blob([file], { type: "audio/mpeg" }),
258
- );
259
-
260
- console.log(`[fal] uploaded audio to: ${uploadedUrl}`);
261
- return uploadedUrl;
262
- }
263
-
264
- export async function wan25(args: FalWan25Args) {
265
- const modelId = "fal-ai/wan-25-preview/image-to-video";
266
-
267
- console.log(`[fal] starting wan-25: ${modelId}`);
268
- console.log(`[fal] prompt: ${args.prompt}`);
269
- console.log(`[fal] image: ${args.imageUrl}`);
270
- console.log(`[fal] audio: ${args.audioUrl}`);
271
-
272
- // upload local files if needed
273
- const imageUrl = await ensureImageUrl(args.imageUrl);
274
- const audioUrl = await ensureAudioUrl(args.audioUrl);
275
-
276
- try {
277
- const result = await fal.subscribe(modelId, {
278
- input: {
279
- prompt: args.prompt,
280
- image_url: imageUrl,
281
- audio_url: audioUrl,
282
- resolution: args.resolution || "480p",
283
- duration: args.duration || "5",
284
- negative_prompt:
285
- args.negativePrompt ||
286
- "low resolution, error, worst quality, low quality, defects",
287
- enable_prompt_expansion: args.enablePromptExpansion ?? true,
288
- },
289
- logs: true,
290
- onQueueUpdate: (update: {
291
- status: string;
292
- logs?: Array<{ message: string }>;
293
- }) => {
294
- if (update.status === "IN_PROGRESS") {
295
- console.log(
296
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
297
- );
298
- }
299
- },
300
- });
301
-
302
- console.log("[fal] completed!");
303
- return result;
304
- } catch (error) {
305
- console.error("[fal] error:", error);
306
- if (error && typeof error === "object" && "body" in error) {
307
- console.error(
308
- "[fal] validation details:",
309
- JSON.stringify(error.body, null, 2),
310
- );
311
- }
312
- throw error;
313
- }
314
- }
315
-
316
- // cli runner
317
- if (import.meta.main) {
318
- const [command, ...args] = process.argv.slice(2);
319
-
320
- switch (command) {
321
- case "image_to_video": {
322
- if (!args[0] || !args[1]) {
323
- console.log(`
324
- usage: bun run lib/fal.ts image_to_video <prompt> <image_path_or_url> [duration]
325
-
326
- examples:
327
- bun run lib/fal.ts image_to_video "person talking" "https://image.url" 5
328
- bun run lib/fal.ts image_to_video "ocean waves" "./media/beach.jpg" 10
329
- `);
330
- process.exit(1);
331
- }
332
- const duration = args[2];
333
- if (duration && duration !== "5" && duration !== "10") {
334
- console.error("duration must be 5 or 10");
335
- process.exit(1);
336
- }
337
- const i2vResult = await imageToVideo({
338
- prompt: args[0],
339
- imageUrl: args[1],
340
- duration: duration === "10" ? 10 : 5,
341
- });
342
- console.log(JSON.stringify(i2vResult, null, 2));
343
- break;
344
- }
345
-
346
- case "text_to_video": {
347
- if (!args[0]) {
348
- console.log(`
349
- usage:
350
- bun run lib/fal.ts text_to_video <prompt> [duration]
351
-
352
- examples:
353
- bun run lib/fal.ts text_to_video "ocean waves crashing" 5
354
- `);
355
- process.exit(1);
356
- }
357
- const duration = args[1];
358
- if (duration && duration !== "5" && duration !== "10") {
359
- console.error("duration must be 5 or 10");
360
- process.exit(1);
361
- }
362
- const t2vResult = await textToVideo({
363
- prompt: args[0],
364
- duration: duration === "10" ? 10 : 5,
365
- });
366
- console.log(JSON.stringify(t2vResult, null, 2));
367
- break;
368
- }
369
-
370
- case "image_to_image": {
371
- if (!args[0] || !args[1]) {
372
- console.log(`
373
- usage: bun run lib/fal.ts image_to_image <prompt> <image_path_or_url> [aspect_ratio]
374
-
375
- examples:
376
- bun run lib/fal.ts image_to_image "woman at busy conference hall" media/friend/katia.jpg
377
- bun run lib/fal.ts image_to_image "person in underground station" https://image.url 9:16
378
-
379
- parameters:
380
- aspect_ratio: auto (preserves input), 21:9, 16:9, 3:2, 4:3, 5:4, 1:1, 4:5, 3:4, 2:3, 9:16 (default: auto)
381
-
382
- note: now uses nano banana pro for better quality and aspect ratio preservation
383
- `);
384
- process.exit(1);
385
- }
386
- const aspectRatio = args[2] || "auto";
387
- const i2iResult = await imageToImage({
388
- prompt: args[0],
389
- imageUrl: args[1],
390
- aspectRatio,
391
- });
392
- console.log(JSON.stringify(i2iResult, null, 2));
393
- break;
394
- }
395
-
396
- case "generate_image": {
397
- if (!args[0]) {
398
- console.log(`
399
- usage:
400
- bun run lib/fal.ts generate_image <prompt> [model] [imageSize]
401
-
402
- examples:
403
- bun run lib/fal.ts generate_image "mountain landscape" "fal-ai/flux-pro/v1.1"
404
-
405
- available image sizes:
406
- - square_hd, square, portrait_4_3, portrait_16_9
407
- - landscape_4_3, landscape_16_9
408
- `);
409
- process.exit(1);
410
- }
411
- const imgResult = await generateImage({
412
- prompt: args[0],
413
- model: args[1],
414
- imageSize: args[2],
415
- });
416
- console.log(JSON.stringify(imgResult, null, 2));
417
- break;
418
- }
419
-
420
- case "wan": {
421
- if (!args[0] || !args[1] || !args[2]) {
422
- console.log(`
423
- usage: bun run lib/fal.ts wan <image_path_or_url> <audio_path_or_url> <prompt> [duration] [resolution]
424
-
425
- examples:
426
- bun run lib/fal.ts wan media/friend/aleks/option2.jpg media/friend/aleks/voice.mp3 "selfie POV video, handheld camera" 5 480p
427
- bun run lib/fal.ts wan https://image.url https://audio.url "talking video" 10 720p
428
-
429
- parameters:
430
- duration: 5 or 10 (default: 5)
431
- resolution: 480p, 720p, or 1080p (default: 480p)
432
- `);
433
- process.exit(1);
434
- }
435
- const wanDuration = args[3];
436
- if (wanDuration && wanDuration !== "5" && wanDuration !== "10") {
437
- console.error("duration must be 5 or 10");
438
- process.exit(1);
439
- }
440
- const wanResolution = args[4];
441
- if (
442
- wanResolution &&
443
- wanResolution !== "480p" &&
444
- wanResolution !== "720p" &&
445
- wanResolution !== "1080p"
446
- ) {
447
- console.error("resolution must be 480p, 720p, or 1080p");
448
- process.exit(1);
449
- }
450
- const wanResult = await wan25({
451
- imageUrl: args[0],
452
- audioUrl: args[1],
453
- prompt: args[2],
454
- duration: (wanDuration as "5" | "10") || "5",
455
- resolution:
456
- (wanResolution as "480p" | "720p" | "1080p" | undefined) || "480p",
457
- });
458
- console.log(JSON.stringify(wanResult, null, 2));
459
- break;
460
- }
461
-
462
- default:
463
- console.log(`
464
- usage:
465
- # video generation (supports local files and urls)
466
- bun run lib/fal.ts image_to_video <prompt> <image_path_or_url> [duration]
467
- bun run lib/fal.ts text_to_video <prompt> [duration]
468
- bun run lib/fal.ts wan <image_path_or_url> <audio_path_or_url> <prompt> [duration] [resolution]
469
-
470
- # image generation (fal client with all features)
471
- bun run lib/fal.ts generate_image <prompt> [model] [imageSize]
472
- bun run lib/fal.ts image_to_image <prompt> <image_path_or_url> [strength]
473
-
474
- note: for simpler image generation, use lib/ai-sdk/fal.ts instead
475
- `);
476
- process.exit(1);
477
- }
478
- }