varg.ai-sdk 0.1.1 → 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 (246) 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 +43 -10
  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} +58 -68
  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 -169
  206. package/action/edit/SKILL.md +0 -235
  207. package/action/edit/index.ts +0 -437
  208. package/action/image/SKILL.md +0 -140
  209. package/action/image/index.ts +0 -105
  210. package/action/sync/SKILL.md +0 -136
  211. package/action/sync/index.ts +0 -145
  212. package/action/transcribe/SKILL.md +0 -179
  213. package/action/video/SKILL.md +0 -116
  214. package/action/video/index.ts +0 -125
  215. package/action/voice/SKILL.md +0 -125
  216. package/action/voice/index.ts +0 -136
  217. package/cli/commands/find.ts +0 -58
  218. package/cli/commands/help.ts +0 -70
  219. package/cli/commands/list.ts +0 -49
  220. package/cli/commands/run.ts +0 -237
  221. package/cli/commands/which.ts +0 -66
  222. package/cli/discover.ts +0 -66
  223. package/cli/index.ts +0 -33
  224. package/cli/runner.ts +0 -65
  225. package/cli/types.ts +0 -49
  226. package/cli/ui.ts +0 -185
  227. package/index.ts +0 -75
  228. package/lib/README.md +0 -144
  229. package/lib/ai-sdk/fal.ts +0 -106
  230. package/lib/ai-sdk/replicate.ts +0 -107
  231. package/lib/elevenlabs.ts +0 -382
  232. package/lib/fal.ts +0 -467
  233. package/lib/ffmpeg.ts +0 -467
  234. package/lib/fireworks.ts +0 -235
  235. package/lib/groq.ts +0 -246
  236. package/lib/higgsfield.ts +0 -176
  237. package/lib/remotion/SKILL.md +0 -823
  238. package/lib/remotion/cli.ts +0 -115
  239. package/lib/remotion/functions.ts +0 -283
  240. package/lib/remotion/index.ts +0 -19
  241. package/lib/remotion/templates.ts +0 -73
  242. package/lib/replicate.ts +0 -304
  243. package/output.txt +0 -1
  244. package/test-import.ts +0 -7
  245. package/test-services.ts +0 -97
  246. package/utilities/s3.ts +0 -147
package/lib/fal.ts DELETED
@@ -1,467 +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
- export async function imageToImage(args: FalImageToImageArgs) {
174
- const modelId = "fal-ai/nano-banana-pro/edit";
175
-
176
- console.log(`[fal] starting image-to-image: ${modelId}`);
177
- console.log(`[fal] prompt: ${args.prompt}`);
178
- console.log(`[fal] source image: ${args.imageUrl}`);
179
-
180
- // upload local file if needed
181
- const imageUrl = await ensureImageUrl(args.imageUrl);
182
-
183
- try {
184
- const result = await fal.subscribe(modelId, {
185
- input: {
186
- prompt: args.prompt,
187
- image_urls: [imageUrl],
188
- aspect_ratio: args.aspectRatio || "auto",
189
- resolution: "2K",
190
- },
191
- logs: true,
192
- onQueueUpdate: (update: {
193
- status: string;
194
- logs?: Array<{ message: string }>;
195
- }) => {
196
- if (update.status === "IN_PROGRESS") {
197
- console.log(
198
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
199
- );
200
- }
201
- },
202
- });
203
-
204
- console.log("[fal] completed!");
205
- return result;
206
- } catch (error) {
207
- console.error("[fal] error:", error);
208
- throw error;
209
- }
210
- }
211
-
212
- interface FalWan25Args {
213
- prompt: string;
214
- imageUrl: string; // can be url or local file path
215
- audioUrl: string; // can be url or local file path
216
- resolution?: "480p" | "720p" | "1080p";
217
- duration?: "5" | "10";
218
- negativePrompt?: string;
219
- enablePromptExpansion?: boolean;
220
- enableSafetyChecker?: boolean;
221
- }
222
-
223
- /**
224
- * helper to upload audio file to fal storage if needed
225
- */
226
- async function ensureAudioUrl(audioPathOrUrl: string): Promise<string> {
227
- // if it's already a url, return it
228
- if (
229
- audioPathOrUrl.startsWith("http://") ||
230
- audioPathOrUrl.startsWith("https://")
231
- ) {
232
- return audioPathOrUrl;
233
- }
234
-
235
- // check if local file exists
236
- if (!existsSync(audioPathOrUrl)) {
237
- throw new Error(`local audio file not found: ${audioPathOrUrl}`);
238
- }
239
-
240
- console.log(`[fal] uploading local audio: ${audioPathOrUrl}`);
241
-
242
- // read file and upload to fal
243
- const file = await Bun.file(audioPathOrUrl).arrayBuffer();
244
-
245
- const uploadedUrl = await fal.storage.upload(
246
- new Blob([file], { type: "audio/mpeg" }),
247
- );
248
-
249
- console.log(`[fal] uploaded audio to: ${uploadedUrl}`);
250
- return uploadedUrl;
251
- }
252
-
253
- export async function wan25(args: FalWan25Args) {
254
- const modelId = "fal-ai/wan-25-preview/image-to-video";
255
-
256
- console.log(`[fal] starting wan-25: ${modelId}`);
257
- console.log(`[fal] prompt: ${args.prompt}`);
258
- console.log(`[fal] image: ${args.imageUrl}`);
259
- console.log(`[fal] audio: ${args.audioUrl}`);
260
-
261
- // upload local files if needed
262
- const imageUrl = await ensureImageUrl(args.imageUrl);
263
- const audioUrl = await ensureAudioUrl(args.audioUrl);
264
-
265
- try {
266
- const result = await fal.subscribe(modelId, {
267
- input: {
268
- prompt: args.prompt,
269
- image_url: imageUrl,
270
- audio_url: audioUrl,
271
- resolution: args.resolution || "480p",
272
- duration: args.duration || "5",
273
- negative_prompt:
274
- args.negativePrompt ||
275
- "low resolution, error, worst quality, low quality, defects",
276
- enable_prompt_expansion: args.enablePromptExpansion ?? true,
277
- },
278
- logs: true,
279
- onQueueUpdate: (update: {
280
- status: string;
281
- logs?: Array<{ message: string }>;
282
- }) => {
283
- if (update.status === "IN_PROGRESS") {
284
- console.log(
285
- `[fal] ${update.logs?.map((l) => l.message).join(" ") || "processing..."}`,
286
- );
287
- }
288
- },
289
- });
290
-
291
- console.log("[fal] completed!");
292
- return result;
293
- } catch (error) {
294
- console.error("[fal] error:", error);
295
- if (error && typeof error === "object" && "body" in error) {
296
- console.error(
297
- "[fal] validation details:",
298
- JSON.stringify(error.body, null, 2),
299
- );
300
- }
301
- throw error;
302
- }
303
- }
304
-
305
- // cli runner
306
- if (import.meta.main) {
307
- const [command, ...args] = process.argv.slice(2);
308
-
309
- switch (command) {
310
- case "image_to_video": {
311
- if (!args[0] || !args[1]) {
312
- console.log(`
313
- usage: bun run lib/fal.ts image_to_video <prompt> <image_path_or_url> [duration]
314
-
315
- examples:
316
- bun run lib/fal.ts image_to_video "person talking" "https://image.url" 5
317
- bun run lib/fal.ts image_to_video "ocean waves" "./media/beach.jpg" 10
318
- `);
319
- process.exit(1);
320
- }
321
- const duration = args[2];
322
- if (duration && duration !== "5" && duration !== "10") {
323
- console.error("duration must be 5 or 10");
324
- process.exit(1);
325
- }
326
- const i2vResult = await imageToVideo({
327
- prompt: args[0],
328
- imageUrl: args[1],
329
- duration: duration === "10" ? 10 : 5,
330
- });
331
- console.log(JSON.stringify(i2vResult, null, 2));
332
- break;
333
- }
334
-
335
- case "text_to_video": {
336
- if (!args[0]) {
337
- console.log(`
338
- usage:
339
- bun run lib/fal.ts text_to_video <prompt> [duration]
340
-
341
- examples:
342
- bun run lib/fal.ts text_to_video "ocean waves crashing" 5
343
- `);
344
- process.exit(1);
345
- }
346
- const duration = args[1];
347
- if (duration && duration !== "5" && duration !== "10") {
348
- console.error("duration must be 5 or 10");
349
- process.exit(1);
350
- }
351
- const t2vResult = await textToVideo({
352
- prompt: args[0],
353
- duration: duration === "10" ? 10 : 5,
354
- });
355
- console.log(JSON.stringify(t2vResult, null, 2));
356
- break;
357
- }
358
-
359
- case "image_to_image": {
360
- if (!args[0] || !args[1]) {
361
- console.log(`
362
- usage: bun run lib/fal.ts image_to_image <prompt> <image_path_or_url> [aspect_ratio]
363
-
364
- examples:
365
- bun run lib/fal.ts image_to_image "woman at busy conference hall" media/friend/katia.jpg
366
- bun run lib/fal.ts image_to_image "person in underground station" https://image.url 9:16
367
-
368
- parameters:
369
- 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)
370
-
371
- note: now uses nano banana pro for better quality and aspect ratio preservation
372
- `);
373
- process.exit(1);
374
- }
375
- const aspectRatio = args[2] || "auto";
376
- const i2iResult = await imageToImage({
377
- prompt: args[0],
378
- imageUrl: args[1],
379
- aspectRatio,
380
- });
381
- console.log(JSON.stringify(i2iResult, null, 2));
382
- break;
383
- }
384
-
385
- case "generate_image": {
386
- if (!args[0]) {
387
- console.log(`
388
- usage:
389
- bun run lib/fal.ts generate_image <prompt> [model] [imageSize]
390
-
391
- examples:
392
- bun run lib/fal.ts generate_image "mountain landscape" "fal-ai/flux-pro/v1.1"
393
-
394
- available image sizes:
395
- - square_hd, square, portrait_4_3, portrait_16_9
396
- - landscape_4_3, landscape_16_9
397
- `);
398
- process.exit(1);
399
- }
400
- const imgResult = await generateImage({
401
- prompt: args[0],
402
- model: args[1],
403
- imageSize: args[2],
404
- });
405
- console.log(JSON.stringify(imgResult, null, 2));
406
- break;
407
- }
408
-
409
- case "wan": {
410
- if (!args[0] || !args[1] || !args[2]) {
411
- console.log(`
412
- usage: bun run lib/fal.ts wan <image_path_or_url> <audio_path_or_url> <prompt> [duration] [resolution]
413
-
414
- examples:
415
- bun run lib/fal.ts wan media/friend/aleks/option2.jpg media/friend/aleks/voice.mp3 "selfie POV video, handheld camera" 5 480p
416
- bun run lib/fal.ts wan https://image.url https://audio.url "talking video" 10 720p
417
-
418
- parameters:
419
- duration: 5 or 10 (default: 5)
420
- resolution: 480p, 720p, or 1080p (default: 480p)
421
- `);
422
- process.exit(1);
423
- }
424
- const wanDuration = args[3];
425
- if (wanDuration && wanDuration !== "5" && wanDuration !== "10") {
426
- console.error("duration must be 5 or 10");
427
- process.exit(1);
428
- }
429
- const wanResolution = args[4];
430
- if (
431
- wanResolution &&
432
- wanResolution !== "480p" &&
433
- wanResolution !== "720p" &&
434
- wanResolution !== "1080p"
435
- ) {
436
- console.error("resolution must be 480p, 720p, or 1080p");
437
- process.exit(1);
438
- }
439
- const wanResult = await wan25({
440
- imageUrl: args[0],
441
- audioUrl: args[1],
442
- prompt: args[2],
443
- duration: (wanDuration as "5" | "10") || "5",
444
- resolution:
445
- (wanResolution as "480p" | "720p" | "1080p" | undefined) || "480p",
446
- });
447
- console.log(JSON.stringify(wanResult, null, 2));
448
- break;
449
- }
450
-
451
- default:
452
- console.log(`
453
- usage:
454
- # video generation (supports local files and urls)
455
- bun run lib/fal.ts image_to_video <prompt> <image_path_or_url> [duration]
456
- bun run lib/fal.ts text_to_video <prompt> [duration]
457
- bun run lib/fal.ts wan <image_path_or_url> <audio_path_or_url> <prompt> [duration] [resolution]
458
-
459
- # image generation (fal client with all features)
460
- bun run lib/fal.ts generate_image <prompt> [model] [imageSize]
461
- bun run lib/fal.ts image_to_image <prompt> <image_path_or_url> [strength]
462
-
463
- note: for simpler image generation, use lib/ai-sdk/fal.ts instead
464
- `);
465
- process.exit(1);
466
- }
467
- }