@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
@@ -0,0 +1,229 @@
1
+ ---
2
+ name: music-generation
3
+ description: generate full songs and instrumentals using sonauto v2 via fal.ai. create music in any style with customizable tags, lyrics, tempo, and output formats. use when user needs background music, theme songs, soundtracks, or custom audio tracks.
4
+ allowed-tools: Read, Bash
5
+ ---
6
+
7
+ # music generation
8
+
9
+ generate complete songs with vocals or instrumental tracks using sonauto v2 text-to-music model.
10
+
11
+ ## features
12
+
13
+ - **text-to-music** - describe the song you want in natural language
14
+ - **style tags** - specify exact genres and musical styles
15
+ - **custom lyrics** - provide lyrics or generate instrumentals
16
+ - **tempo control** - set bpm or auto-detect from style
17
+ - **multiple formats** - output as mp3, wav, flac, ogg, or m4a
18
+ - **multi-song generation** - generate up to 2 variations at once
19
+ - **reproducible** - use seed parameter to regenerate same song
20
+
21
+ ## usage
22
+
23
+ ### generate from prompt
24
+ ```bash
25
+ bun run service/music generate <prompt> [format] [numSongs] [upload]
26
+ ```
27
+
28
+ **parameters:**
29
+ - `prompt` (required): natural language description of the song
30
+ - `format` (optional): mp3 (default), wav, flac, ogg, m4a
31
+ - `numSongs` (optional): 1 (default) or 2
32
+ - `upload` (optional): "true" to upload to s3
33
+
34
+ **examples:**
35
+ ```bash
36
+ # simple generation
37
+ bun run service/music generate "A pop song about turtles flying"
38
+
39
+ # generate 2 versions as mp3
40
+ bun run service/music generate "upbeat electronic dance music" mp3 2
41
+
42
+ # generate and upload to s3
43
+ bun run service/music generate "sad acoustic ballad" mp3 1 true
44
+ ```
45
+
46
+ ### generate from style tags
47
+ ```bash
48
+ bun run service/music tags <tag1> <tag2> ... [format] [upload]
49
+ ```
50
+
51
+ **examples:**
52
+ ```bash
53
+ # rock song
54
+ bun run service/music tags "rock" "energetic" "electric guitar"
55
+
56
+ # ambient track
57
+ bun run service/music tags "ambient" "calm" "ethereal" wav
58
+
59
+ # upload to s3
60
+ bun run service/music tags "jazz" "smooth" "piano" mp3 true
61
+ ```
62
+
63
+ explore all available tags at: https://sonauto.ai/tag-explorer
64
+
65
+ ### generate instrumental
66
+ ```bash
67
+ bun run service/music instrumental <tag1> <tag2> ... [format] [upload]
68
+ ```
69
+
70
+ **examples:**
71
+ ```bash
72
+ # piano instrumental
73
+ bun run service/music instrumental "piano" "calm" "ambient"
74
+
75
+ # electronic instrumental
76
+ bun run service/music instrumental "electronic" "upbeat" "synth" wav true
77
+ ```
78
+
79
+ ## as library
80
+
81
+ ```typescript
82
+ import { generateMusic } from "./service/music"
83
+
84
+ // generate from prompt
85
+ const result = await generateMusic({
86
+ prompt: "A pop song about summer",
87
+ format: "mp3",
88
+ upload: true,
89
+ outputPath: "media/summer-song.mp3"
90
+ })
91
+
92
+ // generate from tags with custom lyrics
93
+ const customSong = await generateMusic({
94
+ tags: ["rock", "energetic", "guitar"],
95
+ lyrics: "Verse 1\nI'm walking down the street\nFeeling the beat\n\nChorus\nThis is my song",
96
+ format: "mp3",
97
+ bpm: 120,
98
+ promptStrength: 2.5,
99
+ outputPath: "media/custom-rock.mp3"
100
+ })
101
+
102
+ // generate instrumental
103
+ const instrumental = await generateMusic({
104
+ tags: ["ambient", "calm", "piano"],
105
+ lyrics: "", // empty for instrumental
106
+ format: "wav",
107
+ outputPath: "media/ambient-instrumental.wav"
108
+ })
109
+
110
+ console.log(result.seed) // save seed to regenerate exact song
111
+ console.log(result.audio[0].url)
112
+ console.log(result.uploadUrls)
113
+ ```
114
+
115
+ ## output
116
+
117
+ returns `MusicResult`:
118
+ ```typescript
119
+ {
120
+ seed: number, // seed used (save for reproducibility)
121
+ tags?: string[], // style tags used
122
+ lyrics?: string, // lyrics used (if any)
123
+ audio: Array<{
124
+ url: string, // download url
125
+ fileName: string, // original filename
126
+ contentType: string, // audio/mp3, audio/wav, etc
127
+ fileSize: number // size in bytes
128
+ }>,
129
+ uploadUrls?: string[] // s3 urls if upload requested
130
+ }
131
+ ```
132
+
133
+ saves audio file(s) to `media/music-{timestamp}.{format}`
134
+
135
+ ## advanced options
136
+
137
+ ```typescript
138
+ interface GenerateMusicOptions {
139
+ prompt?: string; // text description
140
+ tags?: string[]; // style tags
141
+ lyrics?: string; // custom lyrics (empty string = instrumental)
142
+ seed?: number; // for reproducibility
143
+ promptStrength?: number; // 1.4-3.1, default 2 (higher = more prompt adherence)
144
+ balanceStrength?: number; // 0-1, default 0.7 (higher = more natural vocals)
145
+ numSongs?: 1 | 2; // generate variations (2 costs 1.5x)
146
+ format?: string; // output format
147
+ bitRate?: 128 | 192 | 256 | 320; // for mp3/m4a only
148
+ bpm?: number | "auto"; // beats per minute
149
+ upload?: boolean; // upload to s3
150
+ outputPath?: string; // local save path
151
+ }
152
+ ```
153
+
154
+ ## when to use
155
+
156
+ use this skill when:
157
+ - creating background music for videos
158
+ - generating theme songs or intros
159
+ - producing soundtracks for content
160
+ - testing different musical styles quickly
161
+ - need instrumental tracks for voiceovers
162
+ - creating audio for social media content
163
+ - prototyping music ideas
164
+
165
+ ## tips
166
+
167
+ **for better results:**
168
+ - be specific with style descriptions
169
+ - combine multiple style tags for unique sounds
170
+ - use "auto" bpm to let the model choose appropriate tempo
171
+ - generating 2 songs gives you variations to choose from
172
+ - save the seed if you want to recreate the exact same song
173
+ - use instrumental mode (empty lyrics) for background music
174
+
175
+ **prompt strength:**
176
+ - `1.4-2.0` - more natural, flowing music
177
+ - `2.0-2.5` - balanced (recommended)
178
+ - `2.5-3.1` - strict adherence to prompt (may sound less natural)
179
+
180
+ **balance strength:**
181
+ - `0.5-0.6` - sharper instrumentals, less clear vocals
182
+ - `0.7` - balanced (recommended)
183
+ - `0.8-1.0` - more natural vocals
184
+
185
+ **format selection:**
186
+ - `mp3` - best for web/social media (small size, good quality)
187
+ - `wav` - uncompressed, best for further editing
188
+ - `flac` - lossless compression
189
+ - `ogg` - open format, good compression
190
+ - `m4a` - apple devices, good compression
191
+
192
+ ## integration with other services
193
+
194
+ perfect companion for:
195
+ - **video service** - add background music to generated videos
196
+ - **edit service** - combine music with video content
197
+ - **voice service** - create instrumentals for voiceovers
198
+ - **captions service** - sync music with captioned videos
199
+
200
+ ## environment variables
201
+
202
+ required:
203
+ - `FAL_API_KEY` - for music generation
204
+
205
+ optional (for s3 upload):
206
+ - `CLOUDFLARE_R2_API_URL`
207
+ - `CLOUDFLARE_ACCESS_KEY_ID`
208
+ - `CLOUDFLARE_ACCESS_SECRET`
209
+ - `CLOUDFLARE_R2_BUCKET`
210
+
211
+ ## generation time
212
+
213
+ expect 30-120 seconds depending on song complexity and duration. generating 2 songs takes longer but costs only 1.5x.
214
+
215
+ ## cost
216
+
217
+ - 1 song: 1x credit
218
+ - 2 songs: 1.5x credit
219
+
220
+ ## reproducibility
221
+
222
+ to regenerate the exact same song:
223
+ 1. use the same `tags` and `lyrics` (not `prompt`)
224
+ 2. use the same `seed` from the previous result
225
+ 3. keep all other parameters identical
226
+ 4. keep `numSongs` the same
227
+
228
+ note: using `prompt` instead of `tags` + `lyrics` will not guarantee reproducibility even with the same seed.
229
+
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * music service - high-level music generation using sonauto via fal.ai
5
+ * supports text-to-music with customizable styles, lyrics, and parameters
6
+ */
7
+
8
+ import { textToMusic } from "../../lib/fal";
9
+ import { uploadFromUrl } from "../../utilities/s3";
10
+ import { writeFile } from "node:fs/promises";
11
+
12
+ // types
13
+ export interface GenerateMusicOptions {
14
+ prompt?: string;
15
+ tags?: string[];
16
+ lyrics?: string;
17
+ seed?: number;
18
+ promptStrength?: number;
19
+ balanceStrength?: number;
20
+ numSongs?: 1 | 2;
21
+ format?: "flac" | "mp3" | "wav" | "ogg" | "m4a";
22
+ bitRate?: 128 | 192 | 256 | 320;
23
+ bpm?: number | "auto";
24
+ upload?: boolean;
25
+ outputPath?: string;
26
+ }
27
+
28
+ export interface MusicResult {
29
+ seed: number;
30
+ tags?: string[];
31
+ lyrics?: string;
32
+ audio: Array<{
33
+ url: string;
34
+ fileName: string;
35
+ contentType: string;
36
+ fileSize: number;
37
+ }>;
38
+ uploadUrls?: string[];
39
+ }
40
+
41
+ // core functions
42
+ export async function generateMusic(
43
+ options: GenerateMusicOptions,
44
+ ): Promise<MusicResult> {
45
+ const {
46
+ prompt,
47
+ tags,
48
+ lyrics,
49
+ seed,
50
+ promptStrength = 2,
51
+ balanceStrength = 0.7,
52
+ numSongs = 1,
53
+ format = "mp3",
54
+ bitRate,
55
+ bpm = "auto",
56
+ upload = false,
57
+ outputPath,
58
+ } = options;
59
+
60
+ if (!prompt && !tags) {
61
+ throw new Error("either prompt or tags is required");
62
+ }
63
+
64
+ console.log(`[music] generating ${numSongs} song(s)...`);
65
+ if (prompt) console.log(`[music] prompt: ${prompt}`);
66
+ if (tags) console.log(`[music] tags: ${tags.join(", ")}`);
67
+ if (lyrics) console.log(`[music] lyrics: ${lyrics.substring(0, 50)}...`);
68
+
69
+ const result = await textToMusic({
70
+ prompt,
71
+ tags,
72
+ lyricsPrompt: lyrics,
73
+ seed,
74
+ promptStrength,
75
+ balanceStrength,
76
+ numSongs,
77
+ outputFormat: format,
78
+ outputBitRate: bitRate,
79
+ bpm,
80
+ });
81
+
82
+ const musicResult: MusicResult = {
83
+ seed: result.data.seed,
84
+ tags: result.data.tags,
85
+ lyrics: result.data.lyrics,
86
+ audio: Array.isArray(result.data.audio)
87
+ ? result.data.audio.map((a: any) => ({
88
+ url: a.url,
89
+ fileName: a.file_name,
90
+ contentType: a.content_type,
91
+ fileSize: a.file_size,
92
+ }))
93
+ : [
94
+ {
95
+ url: result.data.audio.url,
96
+ fileName: result.data.audio.file_name,
97
+ contentType: result.data.audio.content_type,
98
+ fileSize: result.data.audio.file_size,
99
+ },
100
+ ],
101
+ };
102
+
103
+ // save files locally if requested
104
+ if (outputPath) {
105
+ for (let i = 0; i < musicResult.audio.length; i++) {
106
+ const audio = musicResult.audio[i];
107
+ const ext = format || "wav";
108
+ const filePath =
109
+ musicResult.audio.length === 1
110
+ ? outputPath
111
+ : outputPath.replace(/\.[^.]+$/, `-${i + 1}.${ext}`);
112
+
113
+ // download the audio
114
+ const response = await fetch(audio.url);
115
+ const buffer = await response.arrayBuffer();
116
+ await writeFile(filePath, Buffer.from(buffer));
117
+ console.log(`[music] saved to ${filePath}`);
118
+ }
119
+ }
120
+
121
+ // upload to s3 if requested
122
+ if (upload) {
123
+ const uploadUrls: string[] = [];
124
+ for (let i = 0; i < musicResult.audio.length; i++) {
125
+ const audio = musicResult.audio[i];
126
+ const objectKey = `music/${Date.now()}-${i + 1}.${format || "wav"}`;
127
+ const uploadUrl = await uploadFromUrl(audio.url, objectKey);
128
+ uploadUrls.push(uploadUrl);
129
+ console.log(`[music] uploaded to ${uploadUrl}`);
130
+ }
131
+ musicResult.uploadUrls = uploadUrls;
132
+ }
133
+
134
+ return musicResult;
135
+ }
136
+
137
+ // cli
138
+ async function cli() {
139
+ const args = process.argv.slice(2);
140
+ const command = args[0];
141
+
142
+ if (!command || command === "help") {
143
+ console.log(`
144
+ usage:
145
+ bun run service/music <command> [args]
146
+
147
+ commands:
148
+ generate <prompt> [format] [numSongs] [upload] generate music from prompt
149
+ tags <tags...> [format] [upload] generate music from tags
150
+ instrumental <tags...> [format] [upload] generate instrumental track
151
+ help show this help
152
+
153
+ examples:
154
+ bun run service/music generate "A pop song about turtles flying"
155
+ bun run service/music generate "upbeat electronic" mp3 2 true
156
+ bun run service/music tags "rock" "energetic" "guitar" mp3
157
+ bun run service/music instrumental "ambient" "calm" "piano" wav true
158
+
159
+ formats:
160
+ mp3 (default), wav, flac, ogg, m4a
161
+
162
+ environment:
163
+ FAL_API_KEY - required for music generation
164
+ CLOUDFLARE_* - required for upload
165
+ `);
166
+ process.exit(0);
167
+ }
168
+
169
+ try {
170
+ switch (command) {
171
+ case "generate": {
172
+ const prompt = args[1];
173
+ const format = (args[2] || "mp3") as "flac" | "mp3" | "wav" | "ogg" | "m4a";
174
+ const numSongs = (parseInt(args[3]) || 1) as 1 | 2;
175
+ const upload = args[4] === "true";
176
+
177
+ if (!prompt) {
178
+ throw new Error("prompt is required");
179
+ }
180
+
181
+ const outputPath = `media/music-${Date.now()}.${format}`;
182
+
183
+ const result = await generateMusic({
184
+ prompt,
185
+ format,
186
+ numSongs,
187
+ upload,
188
+ outputPath,
189
+ });
190
+
191
+ console.log(`[music] result:`, {
192
+ seed: result.seed,
193
+ tags: result.tags,
194
+ audioCount: result.audio.length,
195
+ outputPath,
196
+ uploadUrls: result.uploadUrls,
197
+ });
198
+ break;
199
+ }
200
+
201
+ case "tags": {
202
+ // collect all tag arguments until we hit format/upload
203
+ const tags: string[] = [];
204
+ let format: "flac" | "mp3" | "wav" | "ogg" | "m4a" = "mp3";
205
+ let upload = false;
206
+
207
+ for (let i = 1; i < args.length; i++) {
208
+ const arg = args[i];
209
+ if (["mp3", "wav", "flac", "ogg", "m4a"].includes(arg)) {
210
+ format = arg as "flac" | "mp3" | "wav" | "ogg" | "m4a";
211
+ } else if (arg === "true") {
212
+ upload = true;
213
+ } else {
214
+ tags.push(arg);
215
+ }
216
+ }
217
+
218
+ if (tags.length === 0) {
219
+ throw new Error("at least one tag is required");
220
+ }
221
+
222
+ const outputPath = `media/music-${Date.now()}.${format}`;
223
+
224
+ const result = await generateMusic({
225
+ tags,
226
+ format,
227
+ upload,
228
+ outputPath,
229
+ });
230
+
231
+ console.log(`[music] result:`, {
232
+ seed: result.seed,
233
+ tags: result.tags,
234
+ audioCount: result.audio.length,
235
+ outputPath,
236
+ uploadUrls: result.uploadUrls,
237
+ });
238
+ break;
239
+ }
240
+
241
+ case "instrumental": {
242
+ // same as tags but with empty lyrics
243
+ const tags: string[] = [];
244
+ let format: "flac" | "mp3" | "wav" | "ogg" | "m4a" = "mp3";
245
+ let upload = false;
246
+
247
+ for (let i = 1; i < args.length; i++) {
248
+ const arg = args[i];
249
+ if (["mp3", "wav", "flac", "ogg", "m4a"].includes(arg)) {
250
+ format = arg as "flac" | "mp3" | "wav" | "ogg" | "m4a";
251
+ } else if (arg === "true") {
252
+ upload = true;
253
+ } else {
254
+ tags.push(arg);
255
+ }
256
+ }
257
+
258
+ if (tags.length === 0) {
259
+ throw new Error("at least one tag is required");
260
+ }
261
+
262
+ const outputPath = `media/music-${Date.now()}.${format}`;
263
+
264
+ const result = await generateMusic({
265
+ tags,
266
+ lyrics: "", // empty string for instrumental
267
+ format,
268
+ upload,
269
+ outputPath,
270
+ });
271
+
272
+ console.log(`[music] result:`, {
273
+ seed: result.seed,
274
+ tags: result.tags,
275
+ audioCount: result.audio.length,
276
+ outputPath,
277
+ uploadUrls: result.uploadUrls,
278
+ });
279
+ break;
280
+ }
281
+
282
+ default:
283
+ console.error(`unknown command: ${command}`);
284
+ console.log(`run 'bun run service/music help' for usage`);
285
+ process.exit(1);
286
+ }
287
+ } catch (error) {
288
+ console.error(`[music] error:`, error);
289
+ process.exit(1);
290
+ }
291
+ }
292
+
293
+ if (import.meta.main) {
294
+ cli();
295
+ }
296
+
package/test-import.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { generateImage, imageToVideo, uploadFromUrl } from "./index";
2
+
3
+ console.log("✓ imports successful");
4
+ console.log("available functions:");
5
+ console.log("- generateImage:", typeof generateImage);
6
+ console.log("- imageToVideo:", typeof imageToVideo);
7
+ console.log("- uploadFromUrl:", typeof uploadFromUrl);
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * test script for all sdk services
5
+ * saves all media files to media/ directory
6
+ */
7
+
8
+ import { generateImage as generateFalImage } from "./lib/ai-sdk/fal";
9
+ import { generateImage as generateReplicateImage } from "./lib/ai-sdk/replicate";
10
+ import { textToSpeech } from "./lib/elevenlabs";
11
+ import { runImage } from "./lib/replicate";
12
+
13
+ async function testFalImage() {
14
+ console.log("\n=== testing fal image generation ===");
15
+
16
+ const result = await generateFalImage({
17
+ prompt: "a cozy coffee shop interior with warm lighting",
18
+ model: "fal-ai/flux/dev",
19
+ aspectRatio: "16:9",
20
+ });
21
+
22
+ if (result.image.uint8Array) {
23
+ const filename = "media/fal-coffee-shop.png";
24
+ await Bun.write(filename, result.image.uint8Array);
25
+ console.log(`✓ saved to ${filename}`);
26
+ }
27
+ }
28
+
29
+ async function testReplicateImage() {
30
+ console.log("\n=== testing replicate image generation ===");
31
+
32
+ const result = await generateReplicateImage({
33
+ prompt: "a mystical forest with glowing mushrooms",
34
+ model: "black-forest-labs/flux-dev",
35
+ aspectRatio: "1:1",
36
+ });
37
+
38
+ if (result.image.uint8Array) {
39
+ const filename = "media/replicate-forest.png";
40
+ await Bun.write(filename, result.image.uint8Array);
41
+ console.log(`✓ saved to ${filename}`);
42
+ }
43
+ }
44
+
45
+ async function testReplicateClient() {
46
+ console.log("\n=== testing replicate client (flux) ===");
47
+
48
+ try {
49
+ const output = await runImage({
50
+ model: "black-forest-labs/flux-schnell",
51
+ input: { prompt: "a serene zen garden with cherry blossoms" },
52
+ });
53
+
54
+ // output is array of FileOutput objects
55
+ if (Array.isArray(output) && output[0]) {
56
+ const imageUrl = output[0].toString();
57
+ console.log(`✓ generated image: ${imageUrl}`);
58
+
59
+ // download and save
60
+ const response = await fetch(imageUrl);
61
+ const buffer = await response.arrayBuffer();
62
+ const filename = "media/replicate-zen-garden.png";
63
+ await Bun.write(filename, buffer);
64
+ console.log(`✓ saved to ${filename}`);
65
+ }
66
+ } catch (error) {
67
+ console.error("✗ replicate client error:", error);
68
+ }
69
+ }
70
+
71
+ async function testElevenlabs() {
72
+ console.log("\n=== testing elevenlabs tts ===");
73
+
74
+ try {
75
+ await textToSpeech({
76
+ text: "welcome to varg ai sdk, your complete video production toolkit",
77
+ voiceId: "21m00Tcm4TlvDq8ikWAM",
78
+ outputPath: "media/welcome.mp3",
79
+ });
80
+ console.log("✓ saved to media/welcome.mp3");
81
+ } catch (error) {
82
+ console.error("✗ elevenlabs error:", error);
83
+ }
84
+ }
85
+
86
+ async function main() {
87
+ console.log("🚀 testing varg.ai sdk services...\n");
88
+
89
+ await testFalImage();
90
+ await testReplicateImage();
91
+ await testReplicateClient();
92
+ await testElevenlabs();
93
+
94
+ console.log("\n✨ all tests complete! check media/ directory");
95
+ }
96
+
97
+ main().catch(console.error);
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Environment setup & latest features
4
+ "lib": ["ESNext"],
5
+ "target": "ESNext",
6
+ "module": "Preserve",
7
+ "moduleDetection": "force",
8
+ "jsx": "react-jsx",
9
+ "allowJs": true,
10
+
11
+ // Bundler mode
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "noEmit": true,
16
+
17
+ // Best practices
18
+ "strict": true,
19
+ "skipLibCheck": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noUncheckedIndexedAccess": true,
22
+ "noImplicitOverride": true,
23
+
24
+ // Some stricter flags (disabled by default)
25
+ "noUnusedLocals": false,
26
+ "noUnusedParameters": false,
27
+ "noPropertyAccessFromIndexSignature": false
28
+ }
29
+ }