@vargai/sdk 0.1.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 (67) hide show
  1. package/.env.example +24 -0
  2. package/CLAUDE.md +118 -0
  3. package/HIGGSFIELD_REWRITE_SUMMARY.md +300 -0
  4. package/README.md +231 -0
  5. package/SKILLS.md +157 -0
  6. package/STRUCTURE.md +92 -0
  7. package/TEST_RESULTS.md +122 -0
  8. package/action/captions/SKILL.md +170 -0
  9. package/action/captions/index.ts +169 -0
  10. package/action/edit/SKILL.md +235 -0
  11. package/action/edit/index.ts +437 -0
  12. package/action/image/SKILL.md +140 -0
  13. package/action/image/index.ts +105 -0
  14. package/action/sync/SKILL.md +136 -0
  15. package/action/sync/index.ts +145 -0
  16. package/action/transcribe/SKILL.md +179 -0
  17. package/action/transcribe/index.ts +210 -0
  18. package/action/video/SKILL.md +116 -0
  19. package/action/video/index.ts +125 -0
  20. package/action/voice/SKILL.md +125 -0
  21. package/action/voice/index.ts +136 -0
  22. package/biome.json +33 -0
  23. package/bun.lock +842 -0
  24. package/cli/commands/find.ts +58 -0
  25. package/cli/commands/help.ts +70 -0
  26. package/cli/commands/list.ts +49 -0
  27. package/cli/commands/run.ts +237 -0
  28. package/cli/commands/which.ts +66 -0
  29. package/cli/discover.ts +66 -0
  30. package/cli/index.ts +33 -0
  31. package/cli/runner.ts +65 -0
  32. package/cli/types.ts +49 -0
  33. package/cli/ui.ts +185 -0
  34. package/index.ts +75 -0
  35. package/lib/README.md +144 -0
  36. package/lib/ai-sdk/fal.ts +106 -0
  37. package/lib/ai-sdk/replicate.ts +107 -0
  38. package/lib/elevenlabs.ts +382 -0
  39. package/lib/fal.ts +467 -0
  40. package/lib/ffmpeg.ts +467 -0
  41. package/lib/fireworks.ts +235 -0
  42. package/lib/groq.ts +246 -0
  43. package/lib/higgsfield/MIGRATION.md +308 -0
  44. package/lib/higgsfield/README.md +273 -0
  45. package/lib/higgsfield/example.ts +228 -0
  46. package/lib/higgsfield/index.ts +241 -0
  47. package/lib/higgsfield/soul.ts +262 -0
  48. package/lib/higgsfield.ts +176 -0
  49. package/lib/remotion/SKILL.md +823 -0
  50. package/lib/remotion/cli.ts +115 -0
  51. package/lib/remotion/functions.ts +283 -0
  52. package/lib/remotion/index.ts +19 -0
  53. package/lib/remotion/templates.ts +73 -0
  54. package/lib/replicate.ts +304 -0
  55. package/output.txt +1 -0
  56. package/package.json +42 -0
  57. package/pipeline/cookbooks/SKILL.md +285 -0
  58. package/pipeline/cookbooks/remotion-video.md +585 -0
  59. package/pipeline/cookbooks/round-video-character.md +337 -0
  60. package/pipeline/cookbooks/talking-character.md +59 -0
  61. package/scripts/produce-menopause-campaign.sh +202 -0
  62. package/service/music/SKILL.md +229 -0
  63. package/service/music/index.ts +296 -0
  64. package/test-import.ts +7 -0
  65. package/test-services.ts +97 -0
  66. package/tsconfig.json +29 -0
  67. package/utilities/s3.ts +147 -0
package/cli/ui.ts ADDED
@@ -0,0 +1,185 @@
1
+ /**
2
+ * terminal ui helpers for varg cli
3
+ * beautiful boxes and formatting
4
+ */
5
+
6
+ const COLORS = {
7
+ reset: "\x1b[0m",
8
+ bold: "\x1b[1m",
9
+ dim: "\x1b[2m",
10
+ green: "\x1b[32m",
11
+ yellow: "\x1b[33m",
12
+ blue: "\x1b[34m",
13
+ magenta: "\x1b[35m",
14
+ cyan: "\x1b[36m",
15
+ red: "\x1b[31m",
16
+ gray: "\x1b[90m",
17
+ };
18
+
19
+ export const c = {
20
+ reset: (s: string) => `${COLORS.reset}${s}${COLORS.reset}`,
21
+ bold: (s: string) => `${COLORS.bold}${s}${COLORS.reset}`,
22
+ dim: (s: string) => `${COLORS.dim}${s}${COLORS.reset}`,
23
+ green: (s: string) => `${COLORS.green}${s}${COLORS.reset}`,
24
+ yellow: (s: string) => `${COLORS.yellow}${s}${COLORS.reset}`,
25
+ blue: (s: string) => `${COLORS.blue}${s}${COLORS.reset}`,
26
+ magenta: (s: string) => `${COLORS.magenta}${s}${COLORS.reset}`,
27
+ cyan: (s: string) => `${COLORS.cyan}${s}${COLORS.reset}`,
28
+ red: (s: string) => `${COLORS.red}${s}${COLORS.reset}`,
29
+ gray: (s: string) => `${COLORS.gray}${s}${COLORS.reset}`,
30
+ };
31
+
32
+ // strip ansi codes for length calculation
33
+ // biome-ignore lint/complexity/useRegexLiterals: literal triggers noControlCharactersInRegex
34
+ const ANSI_REGEX = new RegExp("\x1b\\[[0-9;]*m", "g");
35
+ function stripAnsi(s: string): string {
36
+ return s.replace(ANSI_REGEX, "");
37
+ }
38
+
39
+ // box drawing characters
40
+ const BOX = {
41
+ topLeft: "┌",
42
+ topRight: "┐",
43
+ bottomLeft: "└",
44
+ bottomRight: "┘",
45
+ horizontal: "─",
46
+ vertical: "│",
47
+ line: "─",
48
+ };
49
+
50
+ export const WIDTH = 71;
51
+
52
+ export function box(title: string, content: string[]): string {
53
+ const lines: string[] = [];
54
+
55
+ // top border with title
56
+ const titlePart = title ? `${BOX.line} ${title} ` : "";
57
+ const remainingWidth = WIDTH - 2 - stripAnsi(titlePart).length;
58
+ lines.push(
59
+ `${BOX.topLeft}${titlePart}${BOX.horizontal.repeat(remainingWidth)}${BOX.topRight}`,
60
+ );
61
+
62
+ // content lines
63
+ for (const line of content) {
64
+ const stripped = stripAnsi(line);
65
+ const padding = WIDTH - 2 - stripped.length;
66
+ if (padding >= 0) {
67
+ lines.push(`${BOX.vertical}${line}${" ".repeat(padding)}${BOX.vertical}`);
68
+ } else {
69
+ // truncate if too long
70
+ lines.push(
71
+ `${BOX.vertical}${line.slice(0, WIDTH - 5)}...${BOX.vertical}`,
72
+ );
73
+ }
74
+ }
75
+
76
+ // bottom border
77
+ lines.push(
78
+ `${BOX.bottomLeft}${BOX.horizontal.repeat(WIDTH - 2)}${BOX.bottomRight}`,
79
+ );
80
+
81
+ return lines.join("\n");
82
+ }
83
+
84
+ export function separator(): string {
85
+ return ` ${c.dim(BOX.horizontal.repeat(WIDTH - 4))}`;
86
+ }
87
+
88
+ export function header(text: string): string {
89
+ return c.bold(c.dim(` ${text}`));
90
+ }
91
+
92
+ export function row(label: string, value: string, indent = 2): string {
93
+ const spaces = " ".repeat(indent);
94
+ const labelWidth = 14;
95
+ const paddedLabel = label.padEnd(labelWidth);
96
+ return `${spaces}${c.dim(paddedLabel)}${value}`;
97
+ }
98
+
99
+ export function success(message: string): string {
100
+ return ` ${c.green("✓")} ${message}`;
101
+ }
102
+
103
+ export function error(message: string): string {
104
+ return ` ${c.red("✗")} ${message}`;
105
+ }
106
+
107
+ export function spinner(message: string): string {
108
+ return ` ${c.cyan("◐")} ${message}`;
109
+ }
110
+
111
+ export function formatDuration(ms: number): string {
112
+ if (ms < 1000) return `${ms}ms`;
113
+ const s = Math.round(ms / 1000);
114
+ return `${s}s`;
115
+ }
116
+
117
+ export function formatCost(dollars: number): string {
118
+ return `$${dollars.toFixed(3)}`;
119
+ }
120
+
121
+ // table formatting for list command
122
+ export interface TableRow {
123
+ name: string;
124
+ description: string;
125
+ providers?: string;
126
+ }
127
+
128
+ export function table(rows: TableRow[], nameWidth = 16): string[] {
129
+ const lines: string[] = [];
130
+
131
+ for (const row of rows) {
132
+ const name = row.name.padEnd(nameWidth);
133
+ const desc = row.description;
134
+ const providers = row.providers ? c.dim(row.providers) : "";
135
+
136
+ if (providers) {
137
+ lines.push(` ${c.cyan(name)}${desc.padEnd(30)}${providers}`);
138
+ } else {
139
+ lines.push(` ${c.cyan(name)}${desc}`);
140
+ }
141
+ }
142
+
143
+ return lines;
144
+ }
145
+
146
+ // progress output for running commands
147
+ export function runningBox(
148
+ name: string,
149
+ params: Record<string, string>,
150
+ status: "running" | "done" | "error",
151
+ result?: { output?: string; cost?: number; error?: string; time?: number },
152
+ ): string {
153
+ const content: string[] = [""];
154
+
155
+ // params
156
+ for (const [key, value] of Object.entries(params)) {
157
+ const displayValue =
158
+ value.length > 40 ? `"${value.slice(0, 37)}..."` : `"${value}"`;
159
+ content.push(row(key, displayValue));
160
+ }
161
+
162
+ content.push("");
163
+
164
+ // status
165
+ if (status === "running") {
166
+ content.push(spinner("generating..."));
167
+ } else if (status === "done" && result) {
168
+ content.push(success(`done in ${formatDuration(result.time || 0)}`));
169
+ content.push("");
170
+ if (result.output) {
171
+ content.push(row("output", result.output));
172
+ }
173
+ if (result.cost) {
174
+ content.push(row("cost", formatCost(result.cost)));
175
+ }
176
+ } else if (status === "error" && result?.error) {
177
+ content.push(error("failed"));
178
+ content.push("");
179
+ content.push(row("error", result.error));
180
+ }
181
+
182
+ content.push("");
183
+
184
+ return box(name, content);
185
+ }
package/index.ts ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * varg.ai sdk
3
+ * video generation and editing tools
4
+ */
5
+
6
+ // re-export external clients
7
+ export { fal } from "@ai-sdk/fal";
8
+ export { replicate } from "@ai-sdk/replicate";
9
+ export { fal as falClient } from "@fal-ai/client";
10
+ export { HiggsfieldClient } from "@higgsfield/client";
11
+ // action exports (excluding meta to avoid conflicts)
12
+ export {
13
+ type AddCaptionsOptions,
14
+ addCaptions,
15
+ type SubtitleStyle,
16
+ } from "./action/captions";
17
+ export {
18
+ type CreateMontageOptions,
19
+ createMontage,
20
+ type EditPipelineOptions,
21
+ type EditPipelineStep,
22
+ editPipeline,
23
+ mergeWithAudio,
24
+ type PrepareForSocialOptions,
25
+ prepareForSocial,
26
+ quickResize,
27
+ quickTrim,
28
+ } from "./action/edit";
29
+ export {
30
+ generateWithFal,
31
+ generateWithSoul,
32
+ type ImageGenerationResult,
33
+ } from "./action/image";
34
+ export {
35
+ type LipsyncOptions,
36
+ lipsync,
37
+ lipsyncOverlay,
38
+ lipsyncWav2Lip,
39
+ type Wav2LipOptions,
40
+ } from "./action/sync";
41
+ export {
42
+ type TranscribeOptions,
43
+ type TranscribeResult,
44
+ transcribe,
45
+ } from "./action/transcribe";
46
+ export {
47
+ generateVideoFromImage,
48
+ generateVideoFromText,
49
+ type VideoGenerationResult,
50
+ } from "./action/video";
51
+ export {
52
+ type GenerateVoiceOptions,
53
+ generateVoice,
54
+ type VoiceResult,
55
+ } from "./action/voice";
56
+ // lib exports - ai-sdk/fal (provider)
57
+ export * as aiSdkFal from "./lib/ai-sdk/fal";
58
+ // lib exports - ai-sdk/replicate (provider)
59
+ export * as aiSdkReplicate from "./lib/ai-sdk/replicate";
60
+ // lib exports - elevenlabs
61
+ export * from "./lib/elevenlabs";
62
+ // lib exports - fal (client)
63
+ export * from "./lib/fal";
64
+ // lib exports - ffmpeg
65
+ export * from "./lib/ffmpeg";
66
+ // lib exports - fireworks
67
+ export * from "./lib/fireworks";
68
+ // lib exports - groq
69
+ export * from "./lib/groq";
70
+ // lib exports - higgsfield
71
+ export * from "./lib/higgsfield";
72
+ // lib exports - replicate
73
+ export * from "./lib/replicate";
74
+ // utilities exports
75
+ export * from "./utilities/s3";
package/lib/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # lib/ modules
2
+
3
+ ## two fal implementations
4
+
5
+ ### lib/ai-sdk/fal.ts - ai-sdk provider (recommended for images)
6
+
7
+ uses `@ai-sdk/fal` with the vercel ai sdk's `experimental_generateImage`
8
+
9
+ **benefits:**
10
+ - clean, typed api via vercel ai sdk
11
+ - automatic image format handling (uint8array)
12
+ - consistent interface with other ai providers
13
+ - built-in aspect ratio support
14
+ - better for standard image generation
15
+
16
+ **example:**
17
+ ```bash
18
+ bun run lib/ai-sdk/fal.ts generate_image "cyberpunk city" "fal-ai/flux/dev" "16:9"
19
+ ```
20
+
21
+ **code:**
22
+ ```typescript
23
+ import { fal } from "@ai-sdk/fal"
24
+ import { experimental_generateImage as generateImage } from "ai"
25
+
26
+ const { image, providerMetadata } = await generateImage({
27
+ model: fal.image("fal-ai/flux/dev"),
28
+ prompt: "beautiful sunset",
29
+ aspectRatio: "16:9",
30
+ })
31
+ ```
32
+
33
+ ### lib/fal.ts - fal client direct (for video & advanced features)
34
+
35
+ uses `@fal-ai/client` directly with the raw fal api
36
+
37
+ **benefits:**
38
+ - access to all fal features (video, advanced params)
39
+ - streaming/queue updates
40
+ - full control over api parameters
41
+ - required for video generation (no ai-sdk support yet)
42
+ - **supports local images** - automatically uploads local files to fal storage
43
+
44
+ **examples:**
45
+ ```bash
46
+ # image generation
47
+ bun run lib/fal.ts generate_image "aurora borealis" "fal-ai/flux-pro/v1.1"
48
+
49
+ # video from url
50
+ bun run lib/fal.ts image_to_video "person talking" "https://image.url" 5
51
+
52
+ # video from local file (auto-uploads)
53
+ bun run lib/fal.ts image_to_video "ocean waves" "./media/beach.jpg" 10
54
+ ```
55
+
56
+ **code:**
57
+ ```typescript
58
+ import { imageToVideo } from "./lib/fal"
59
+
60
+ // works with both urls and local files
61
+ const result = await imageToVideo({
62
+ prompt: "person talking",
63
+ imageUrl: "./local/image.jpg", // or "https://..."
64
+ duration: 5,
65
+ })
66
+
67
+ // local files are automatically uploaded to fal storage
68
+ ```
69
+
70
+ ## when to use which?
71
+
72
+ | use case | approach |
73
+ |----------|----------|
74
+ | standard image generation | ai-sdk provider ✓ |
75
+ | video generation | fal client direct ✓ |
76
+ | advanced fal features | fal client direct ✓ |
77
+ | multi-provider app | ai-sdk provider ✓ |
78
+ | custom queue handling | fal client direct ✓ |
79
+
80
+ ## higgsfield.ts
81
+
82
+ uses `@higgsfield/client` for soul character generation
83
+
84
+ **features:**
85
+ - generate soul images with custom styles
86
+ - create and manage character references
87
+ - list available soul styles
88
+ - poll for job completion
89
+
90
+ **example:**
91
+ ```bash
92
+ HF_API_KEY=xxx HF_API_SECRET=xxx bun run lib/higgsfield.ts generate_soul "professional headshot"
93
+ ```
94
+
95
+ ## elevenlabs.ts
96
+
97
+ uses `@elevenlabs/elevenlabs-js` for voice, music, and sound effects generation
98
+
99
+ **features:**
100
+ - text-to-speech with multiple voices
101
+ - music generation from text prompts
102
+ - sound effects generation
103
+ - voice management
104
+
105
+ **examples:**
106
+ ```bash
107
+ # text-to-speech
108
+ bun run lib/elevenlabs.ts tts "hello world" rachel output.mp3
109
+
110
+ # music generation
111
+ bun run lib/elevenlabs.ts music "upbeat electronic dance music" 30000 music.mp3
112
+
113
+ # sound effects
114
+ bun run lib/elevenlabs.ts sfx "ocean waves crashing" 5 waves.mp3
115
+
116
+ # list voices
117
+ bun run lib/elevenlabs.ts voices
118
+ ```
119
+
120
+ **code:**
121
+ ```typescript
122
+ import { textToSpeech, generateMusic, generateSoundEffect } from "./lib/elevenlabs"
123
+
124
+ // voice
125
+ const audio = await textToSpeech({
126
+ text: "hello world",
127
+ voiceId: "rachel",
128
+ outputPath: "output.mp3"
129
+ })
130
+
131
+ // music
132
+ const music = await generateMusic({
133
+ prompt: "epic orchestral music",
134
+ musicLengthMs: 60000,
135
+ outputPath: "music.mp3"
136
+ })
137
+
138
+ // sound effects
139
+ const sfx = await generateSoundEffect({
140
+ text: "thunder and rain",
141
+ durationSeconds: 10,
142
+ outputPath: "sfx.mp3"
143
+ })
144
+ ```
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * fal.ai wrapper using @ai-sdk/fal provider
4
+ * recommended for standard image generation with vercel ai sdk
5
+ *
6
+ * usage: bun run lib/ai-sdk/fal.ts <command> <args>
7
+ */
8
+
9
+ import { fal } from "@ai-sdk/fal";
10
+ import { experimental_generateImage as generateImageAI } from "ai";
11
+
12
+ export async function generateImage(args: {
13
+ prompt: string;
14
+ model?: string;
15
+ aspectRatio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4";
16
+ }) {
17
+ const modelId = args.model || "fal-ai/flux/dev";
18
+
19
+ console.log(`[ai-sdk/fal] generating image with ${modelId}`);
20
+ console.log(`[ai-sdk/fal] prompt: ${args.prompt}`);
21
+ if (args.aspectRatio) {
22
+ console.log(`[ai-sdk/fal] aspect ratio: ${args.aspectRatio}`);
23
+ }
24
+
25
+ try {
26
+ const { image, providerMetadata } = await generateImageAI({
27
+ model: fal.image(modelId),
28
+ prompt: args.prompt,
29
+ aspectRatio: args.aspectRatio,
30
+ });
31
+
32
+ console.log("[ai-sdk/fal] completed!");
33
+
34
+ // return in consistent format
35
+ return {
36
+ image: {
37
+ url: image.base64 ? `data:image/png;base64,${image.base64}` : undefined,
38
+ uint8Array: image.uint8Array,
39
+ },
40
+ metadata: providerMetadata?.fal,
41
+ };
42
+ } catch (error) {
43
+ console.error("[ai-sdk/fal] error:", error);
44
+ throw error;
45
+ }
46
+ }
47
+
48
+ // cli runner
49
+ if (import.meta.main) {
50
+ const [command, ...args] = process.argv.slice(2);
51
+
52
+ switch (command) {
53
+ case "generate_image": {
54
+ if (!args[0]) {
55
+ console.log(`
56
+ usage:
57
+ bun run lib/ai-sdk/fal.ts generate_image <prompt> [model] [aspectRatio]
58
+
59
+ examples:
60
+ bun run lib/ai-sdk/fal.ts generate_image "sunset over ocean" "fal-ai/flux/dev" "16:9"
61
+ bun run lib/ai-sdk/fal.ts generate_image "portrait photo" "fal-ai/flux-pro/v1.1" "9:16"
62
+
63
+ available models:
64
+ - fal-ai/flux/dev (default, fast)
65
+ - fal-ai/flux-pro/v1.1 (high quality)
66
+ - fal-ai/flux/schnell (very fast)
67
+ - fal-ai/ideogram/character (character consistency)
68
+ `);
69
+ process.exit(1);
70
+ }
71
+
72
+ const result = await generateImage({
73
+ prompt: args[0],
74
+ model: args[1],
75
+ aspectRatio: args[2] as
76
+ | "1:1"
77
+ | "16:9"
78
+ | "9:16"
79
+ | "4:3"
80
+ | "3:4"
81
+ | undefined,
82
+ });
83
+
84
+ // save image to file
85
+ if (result.image.uint8Array) {
86
+ const filename = `/tmp/fal-ai-sdk-${Date.now()}.png`;
87
+ await Bun.write(filename, result.image.uint8Array);
88
+ console.log(`\nimage saved to: ${filename}`);
89
+
90
+ // open image
91
+ await Bun.spawn(["open", filename]);
92
+ }
93
+
94
+ console.log("\nmetadata:");
95
+ console.log(JSON.stringify(result.metadata, null, 2));
96
+ break;
97
+ }
98
+
99
+ default:
100
+ console.log(`
101
+ usage:
102
+ bun run lib/ai-sdk/fal.ts generate_image <prompt> [model] [aspectRatio]
103
+ `);
104
+ process.exit(1);
105
+ }
106
+ }
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * replicate wrapper using @ai-sdk/replicate provider
4
+ * recommended for standard image generation with vercel ai sdk
5
+ *
6
+ * usage: bun run lib/ai-sdk/replicate.ts <command> <args>
7
+ */
8
+
9
+ import { replicate } from "@ai-sdk/replicate";
10
+ import { experimental_generateImage as generateImageAI } from "ai";
11
+
12
+ export async function generateImage(args: {
13
+ prompt: string;
14
+ model?: string;
15
+ aspectRatio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4";
16
+ }) {
17
+ const modelId = args.model || "black-forest-labs/flux-dev";
18
+
19
+ console.log(`[ai-sdk/replicate] generating image with ${modelId}`);
20
+ console.log(`[ai-sdk/replicate] prompt: ${args.prompt}`);
21
+ if (args.aspectRatio) {
22
+ console.log(`[ai-sdk/replicate] aspect ratio: ${args.aspectRatio}`);
23
+ }
24
+
25
+ try {
26
+ const { image, providerMetadata } = await generateImageAI({
27
+ model: replicate.image(modelId),
28
+ prompt: args.prompt,
29
+ aspectRatio: args.aspectRatio,
30
+ });
31
+
32
+ console.log("[ai-sdk/replicate] completed!");
33
+
34
+ // return in consistent format
35
+ return {
36
+ image: {
37
+ url: image.base64 ? `data:image/png;base64,${image.base64}` : undefined,
38
+ uint8Array: image.uint8Array,
39
+ },
40
+ metadata: providerMetadata?.replicate,
41
+ };
42
+ } catch (error) {
43
+ console.error("[ai-sdk/replicate] error:", error);
44
+ throw error;
45
+ }
46
+ }
47
+
48
+ // cli runner
49
+ if (import.meta.main) {
50
+ const [command, ...args] = process.argv.slice(2);
51
+
52
+ switch (command) {
53
+ case "generate_image": {
54
+ if (!args[0]) {
55
+ console.log(`
56
+ usage:
57
+ bun run lib/ai-sdk/replicate.ts generate_image <prompt> [model] [aspectRatio]
58
+
59
+ examples:
60
+ bun run lib/ai-sdk/replicate.ts generate_image "sunset over ocean" "black-forest-labs/flux-dev" "16:9"
61
+ bun run lib/ai-sdk/replicate.ts generate_image "portrait photo" "black-forest-labs/flux-1.1-pro" "9:16"
62
+ bun run lib/ai-sdk/replicate.ts generate_image "cyberpunk city" "black-forest-labs/flux-schnell" "1:1"
63
+
64
+ available models:
65
+ - black-forest-labs/flux-dev (default, fast)
66
+ - black-forest-labs/flux-1.1-pro (high quality)
67
+ - black-forest-labs/flux-schnell (very fast)
68
+ - stability-ai/sdxl (stable diffusion xl)
69
+ `);
70
+ process.exit(1);
71
+ }
72
+
73
+ const result = await generateImage({
74
+ prompt: args[0],
75
+ model: args[1],
76
+ aspectRatio: args[2] as
77
+ | "1:1"
78
+ | "16:9"
79
+ | "9:16"
80
+ | "4:3"
81
+ | "3:4"
82
+ | undefined,
83
+ });
84
+
85
+ // save image to file
86
+ if (result.image.uint8Array) {
87
+ const filename = `/tmp/replicate-ai-sdk-${Date.now()}.png`;
88
+ await Bun.write(filename, result.image.uint8Array);
89
+ console.log(`\nimage saved to: ${filename}`);
90
+
91
+ // open image
92
+ await Bun.spawn(["open", filename]);
93
+ }
94
+
95
+ console.log("\nmetadata:");
96
+ console.log(JSON.stringify(result.metadata, null, 2));
97
+ break;
98
+ }
99
+
100
+ default:
101
+ console.log(`
102
+ usage:
103
+ bun run lib/ai-sdk/replicate.ts generate_image <prompt> [model] [aspectRatio]
104
+ `);
105
+ process.exit(1);
106
+ }
107
+ }