vargai 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +7 -0
- package/.env.example +27 -0
- package/.github/workflows/ci.yml +23 -0
- package/.husky/README.md +102 -0
- package/.husky/commit-msg +6 -0
- package/.husky/pre-commit +9 -0
- package/.husky/pre-push +6 -0
- package/.size-limit.json +8 -0
- package/.test-hooks.ts +5 -0
- package/CLAUDE.md +125 -0
- package/CONTRIBUTING.md +150 -0
- package/LICENSE.md +53 -0
- package/README.md +78 -0
- package/SKILLS.md +173 -0
- package/STRUCTURE.md +92 -0
- package/biome.json +34 -0
- package/bun.lock +1254 -0
- package/commitlint.config.js +22 -0
- package/docs/plan.md +66 -0
- package/docs/todo.md +14 -0
- package/docs/varg-sdk.md +812 -0
- package/ffmpeg/CLAUDE.md +68 -0
- package/package.json +69 -0
- package/pipeline/cookbooks/SKILL.md +285 -0
- package/pipeline/cookbooks/remotion-video.md +585 -0
- package/pipeline/cookbooks/round-video-character.md +337 -0
- package/pipeline/cookbooks/scripts/animate-frames-parallel.ts +84 -0
- package/pipeline/cookbooks/scripts/combine-scenes.sh +53 -0
- package/pipeline/cookbooks/scripts/generate-frames-parallel.ts +99 -0
- package/pipeline/cookbooks/scripts/still-to-video.sh +37 -0
- package/pipeline/cookbooks/talking-character.md +59 -0
- package/pipeline/cookbooks/text-to-tiktok.md +669 -0
- package/pipeline/cookbooks/trendwatching.md +156 -0
- package/plan.md +281 -0
- package/scripts/.gitkeep +0 -0
- package/src/ai-sdk/cache.ts +142 -0
- package/src/ai-sdk/examples/cached-generation.ts +53 -0
- package/src/ai-sdk/examples/duet-scene-4.ts +53 -0
- package/src/ai-sdk/examples/duet-scene-5-audio.ts +32 -0
- package/src/ai-sdk/examples/duet-video.ts +56 -0
- package/src/ai-sdk/examples/editly-composition.ts +63 -0
- package/src/ai-sdk/examples/editly-test.ts +57 -0
- package/src/ai-sdk/examples/editly-video-test.ts +52 -0
- package/src/ai-sdk/examples/fal-lipsync.ts +43 -0
- package/src/ai-sdk/examples/higgsfield-image.ts +61 -0
- package/src/ai-sdk/examples/music-generation.ts +19 -0
- package/src/ai-sdk/examples/openai-sora.ts +34 -0
- package/src/ai-sdk/examples/replicate-bg-removal.ts +52 -0
- package/src/ai-sdk/examples/simpsons-scene.ts +61 -0
- package/src/ai-sdk/examples/talking-lion.ts +55 -0
- package/src/ai-sdk/examples/video-generation.ts +39 -0
- package/src/ai-sdk/examples/workflow-animated-girl.ts +104 -0
- package/src/ai-sdk/examples/workflow-before-after.ts +114 -0
- package/src/ai-sdk/examples/workflow-character-grid.ts +112 -0
- package/src/ai-sdk/examples/workflow-slideshow.ts +161 -0
- package/src/ai-sdk/file-cache.ts +112 -0
- package/src/ai-sdk/file.ts +238 -0
- package/src/ai-sdk/generate-element.ts +92 -0
- package/src/ai-sdk/generate-music.ts +46 -0
- package/src/ai-sdk/generate-video.ts +165 -0
- package/src/ai-sdk/index.ts +72 -0
- package/src/ai-sdk/music-model.ts +110 -0
- package/src/ai-sdk/providers/editly/editly.test.ts +1108 -0
- package/src/ai-sdk/providers/editly/ffmpeg.ts +60 -0
- package/src/ai-sdk/providers/editly/index.ts +817 -0
- package/src/ai-sdk/providers/editly/layers.ts +772 -0
- package/src/ai-sdk/providers/editly/plan.md +144 -0
- package/src/ai-sdk/providers/editly/types.ts +328 -0
- package/src/ai-sdk/providers/elevenlabs-provider.ts +255 -0
- package/src/ai-sdk/providers/fal-provider.ts +512 -0
- package/src/ai-sdk/providers/higgsfield.ts +379 -0
- package/src/ai-sdk/providers/openai.ts +251 -0
- package/src/ai-sdk/providers/replicate.ts +16 -0
- package/src/ai-sdk/video-model.ts +185 -0
- package/src/cli/commands/find.tsx +137 -0
- package/src/cli/commands/help.tsx +85 -0
- package/src/cli/commands/index.ts +9 -0
- package/src/cli/commands/list.tsx +238 -0
- package/src/cli/commands/run.tsx +511 -0
- package/src/cli/commands/which.tsx +253 -0
- package/src/cli/index.ts +112 -0
- package/src/cli/quiet.ts +44 -0
- package/src/cli/types.ts +32 -0
- package/src/cli/ui/components/Badge.tsx +29 -0
- package/src/cli/ui/components/DataTable.tsx +51 -0
- package/src/cli/ui/components/Header.tsx +23 -0
- package/src/cli/ui/components/HelpBlock.tsx +44 -0
- package/src/cli/ui/components/KeyValue.tsx +33 -0
- package/src/cli/ui/components/OptionRow.tsx +81 -0
- package/src/cli/ui/components/Separator.tsx +23 -0
- package/src/cli/ui/components/StatusBox.tsx +108 -0
- package/src/cli/ui/components/VargBox.tsx +51 -0
- package/src/cli/ui/components/VargProgress.tsx +36 -0
- package/src/cli/ui/components/VargSpinner.tsx +34 -0
- package/src/cli/ui/components/VargText.tsx +56 -0
- package/src/cli/ui/components/index.ts +19 -0
- package/src/cli/ui/index.ts +12 -0
- package/src/cli/ui/render.ts +35 -0
- package/src/cli/ui/theme.ts +63 -0
- package/src/cli/utils.ts +78 -0
- package/src/core/executor/executor.ts +201 -0
- package/src/core/executor/index.ts +13 -0
- package/src/core/executor/job.ts +214 -0
- package/src/core/executor/pipeline.ts +222 -0
- package/src/core/index.ts +11 -0
- package/src/core/registry/index.ts +9 -0
- package/src/core/registry/loader.ts +149 -0
- package/src/core/registry/registry.ts +221 -0
- package/src/core/registry/resolver.ts +206 -0
- package/src/core/schema/helpers.ts +134 -0
- package/src/core/schema/index.ts +8 -0
- package/src/core/schema/shared.ts +102 -0
- package/src/core/schema/types.ts +279 -0
- package/src/core/schema/validator.ts +92 -0
- package/src/definitions/actions/captions.ts +261 -0
- package/src/definitions/actions/edit.ts +298 -0
- package/src/definitions/actions/image.ts +125 -0
- package/src/definitions/actions/index.ts +114 -0
- package/src/definitions/actions/music.ts +205 -0
- package/src/definitions/actions/sync.ts +128 -0
- package/src/definitions/actions/transcribe.ts +200 -0
- package/src/definitions/actions/upload.ts +111 -0
- package/src/definitions/actions/video.ts +163 -0
- package/src/definitions/actions/voice.ts +119 -0
- package/src/definitions/index.ts +23 -0
- package/src/definitions/models/elevenlabs.ts +50 -0
- package/src/definitions/models/flux.ts +56 -0
- package/src/definitions/models/index.ts +36 -0
- package/src/definitions/models/kling.ts +56 -0
- package/src/definitions/models/llama.ts +54 -0
- package/src/definitions/models/nano-banana-pro.ts +102 -0
- package/src/definitions/models/sonauto.ts +68 -0
- package/src/definitions/models/soul.ts +65 -0
- package/src/definitions/models/wan.ts +54 -0
- package/src/definitions/models/whisper.ts +44 -0
- package/src/definitions/skills/index.ts +12 -0
- package/src/definitions/skills/talking-character.ts +87 -0
- package/src/definitions/skills/text-to-tiktok.ts +97 -0
- package/src/index.ts +118 -0
- package/src/providers/apify.ts +269 -0
- package/src/providers/base.ts +264 -0
- package/src/providers/elevenlabs.ts +217 -0
- package/src/providers/fal.ts +392 -0
- package/src/providers/ffmpeg.ts +544 -0
- package/src/providers/fireworks.ts +193 -0
- package/src/providers/groq.ts +149 -0
- package/src/providers/higgsfield.ts +145 -0
- package/src/providers/index.ts +143 -0
- package/src/providers/replicate.ts +147 -0
- package/src/providers/storage.ts +206 -0
- package/src/tests/all.test.ts +509 -0
- package/src/tests/index.ts +33 -0
- package/src/tests/unit.test.ts +403 -0
- package/tsconfig.json +45 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { File, fal, generateVideo } from "../index";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("=== taisa closeup with audio - scene 5 ===\n");
|
|
5
|
+
|
|
6
|
+
const imageData = await File.fromPath(
|
|
7
|
+
"output/duet-frame-4.png",
|
|
8
|
+
).arrayBuffer();
|
|
9
|
+
const audioData = await File.fromPath(
|
|
10
|
+
"output/audio-1m09s-5s.mp3",
|
|
11
|
+
).arrayBuffer();
|
|
12
|
+
|
|
13
|
+
console.log("generating 5s video with wan-2.5-preview (audio-driven)...");
|
|
14
|
+
const { video } = await generateVideo({
|
|
15
|
+
model: fal.videoModel("wan-2.5-preview"),
|
|
16
|
+
prompt: {
|
|
17
|
+
images: [imageData],
|
|
18
|
+
audio: audioData,
|
|
19
|
+
text: "static camera, fixed closeup shot of woman singing passionately, no camera movement, no zoom, lips synced to audio, subtle head movements, natural breathing, blinking, emotional expressions, concert atmosphere with stage lighting",
|
|
20
|
+
},
|
|
21
|
+
duration: 5,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await Bun.write("output/duet-scene-5-audio.mp4", video.uint8Array);
|
|
25
|
+
console.log(
|
|
26
|
+
`video saved: output/duet-scene-5-audio.mp4 (${video.uint8Array.byteLength} bytes)`,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
console.log("\ndone!");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { generateImage } from "ai";
|
|
2
|
+
import { File, fal, generateVideo } from "../index";
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
console.log("=== taisa & irina duet - scene 3 ===\n");
|
|
6
|
+
|
|
7
|
+
console.log("loading reference images...");
|
|
8
|
+
const referenceImages = [
|
|
9
|
+
File.fromPath("media/taisa/taisa.jpg"),
|
|
10
|
+
File.fromPath("media/taisa/irina.jpg"),
|
|
11
|
+
File.fromPath("media/taisa/irina-scene.png"),
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const imageContents = await Promise.all(
|
|
15
|
+
referenceImages.map((f) => f.arrayBuffer()),
|
|
16
|
+
);
|
|
17
|
+
console.log("loaded.\n");
|
|
18
|
+
|
|
19
|
+
console.log("generating first frame with nano-banana-pro/edit...");
|
|
20
|
+
const { image } = await generateImage({
|
|
21
|
+
model: fal.imageModel("nano-banana-pro"),
|
|
22
|
+
prompt: {
|
|
23
|
+
images: imageContents,
|
|
24
|
+
text: "Wide shot of two different women singing duet on grand concert stage, dark-haired brunette Taisa on left and blonde Irina on right, both facing camera, dramatic purple blue stage lighting, audience visible, glamorous dresses, professional concert hall",
|
|
25
|
+
},
|
|
26
|
+
aspectRatio: "16:9",
|
|
27
|
+
n: 1,
|
|
28
|
+
providerOptions: {
|
|
29
|
+
fal: { resolution: "1K" },
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await Bun.write("output/duet-frame-3.png", image.uint8Array);
|
|
34
|
+
console.log(
|
|
35
|
+
`frame saved: output/duet-frame-3.png (${image.uint8Array.byteLength} bytes)\n`,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
console.log("animating 10s with kling-v2.5...");
|
|
39
|
+
const { video } = await generateVideo({
|
|
40
|
+
model: fal.videoModel("kling-v2.5"),
|
|
41
|
+
prompt: {
|
|
42
|
+
images: [image.uint8Array],
|
|
43
|
+
text: "two women singing together on stage, subtle head movements, lips moving as singing, natural breathing, blinking, emotional expressions, concert atmosphere with stage lighting",
|
|
44
|
+
},
|
|
45
|
+
duration: 10,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await Bun.write("output/duet-scene-3.mp4", video.uint8Array);
|
|
49
|
+
console.log(
|
|
50
|
+
`video saved: output/duet-scene-3.mp4 (${video.uint8Array.byteLength} bytes)`,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
console.log("\ndone!");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editly Video Composition
|
|
3
|
+
* Requires: ffmpeg installed system-wide
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { generateImage } from "ai";
|
|
7
|
+
import { editly, File, fal, generateVideo } from "../index";
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log("generating product image...");
|
|
11
|
+
const { image } = await generateImage({
|
|
12
|
+
model: fal.imageModel("flux-schnell"),
|
|
13
|
+
prompt: "product shot of headphones on white background",
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
console.log("animating image to video...");
|
|
17
|
+
const { video } = await generateVideo({
|
|
18
|
+
model: fal.videoModel("kling-v2.5"),
|
|
19
|
+
prompt: {
|
|
20
|
+
images: [image.uint8Array],
|
|
21
|
+
text: "headphones slowly rotating, product showcase",
|
|
22
|
+
},
|
|
23
|
+
duration: 5,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const videoPath = await File.toTemp(video);
|
|
27
|
+
const imagePath = await File.toTemp(image);
|
|
28
|
+
|
|
29
|
+
console.log("composing final video with editly...");
|
|
30
|
+
await editly({
|
|
31
|
+
outPath: "output/editly-composed.mp4",
|
|
32
|
+
width: 1080,
|
|
33
|
+
height: 1920,
|
|
34
|
+
fps: 30,
|
|
35
|
+
clips: [
|
|
36
|
+
{
|
|
37
|
+
duration: 5,
|
|
38
|
+
layers: [
|
|
39
|
+
{
|
|
40
|
+
type: "video",
|
|
41
|
+
path: videoPath,
|
|
42
|
+
resizeMode: "contain-blur",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
duration: 3,
|
|
48
|
+
transition: { name: "fade", duration: 0.5 },
|
|
49
|
+
layers: [
|
|
50
|
+
{
|
|
51
|
+
type: "image",
|
|
52
|
+
path: imagePath,
|
|
53
|
+
zoomDirection: "in",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log("done! output saved to output/editly-composed.mp4");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { editly } from "../providers/editly";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("Testing editly implementation...\n");
|
|
5
|
+
|
|
6
|
+
await editly({
|
|
7
|
+
outPath: "output/editly-test.mp4",
|
|
8
|
+
width: 640,
|
|
9
|
+
height: 480,
|
|
10
|
+
fps: 30,
|
|
11
|
+
verbose: true,
|
|
12
|
+
clips: [
|
|
13
|
+
{
|
|
14
|
+
duration: 3,
|
|
15
|
+
layers: [
|
|
16
|
+
{ type: "fill-color", color: "#1a1a2e" },
|
|
17
|
+
{
|
|
18
|
+
type: "title",
|
|
19
|
+
text: "Hello Editly!",
|
|
20
|
+
textColor: "#ffffff",
|
|
21
|
+
position: "center",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
duration: 3,
|
|
27
|
+
layers: [
|
|
28
|
+
{ type: "fill-color", color: "#16213e" },
|
|
29
|
+
{
|
|
30
|
+
type: "title",
|
|
31
|
+
text: "Second Slide",
|
|
32
|
+
textColor: "#e94560",
|
|
33
|
+
position: "center",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
transition: { name: "fade", duration: 0.5 },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
duration: 3,
|
|
40
|
+
layers: [
|
|
41
|
+
{ type: "fill-color", color: "#0f3460" },
|
|
42
|
+
{
|
|
43
|
+
type: "title",
|
|
44
|
+
text: "The End",
|
|
45
|
+
textColor: "#ffffff",
|
|
46
|
+
position: "center",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
transition: { name: "fade", duration: 0.5 },
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.log("\nDone!");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { editly } from "../providers/editly";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("test 1: merge two videos with fade transition\n");
|
|
5
|
+
|
|
6
|
+
await editly({
|
|
7
|
+
outPath: "output/editly-merge-test.mp4",
|
|
8
|
+
width: 1280,
|
|
9
|
+
height: 720,
|
|
10
|
+
fps: 30,
|
|
11
|
+
verbose: true,
|
|
12
|
+
clips: [
|
|
13
|
+
{
|
|
14
|
+
layers: [{ type: "video", path: "output/sora-landscape.mp4" }],
|
|
15
|
+
transition: { name: "fade", duration: 0.5 },
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
layers: [{ type: "video", path: "output/simpsons-scene.mp4" }],
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
console.log("\ntest 2: picture-in-picture (pip)\n");
|
|
24
|
+
|
|
25
|
+
await editly({
|
|
26
|
+
outPath: "output/editly-pip-test.mp4",
|
|
27
|
+
width: 1280,
|
|
28
|
+
height: 720,
|
|
29
|
+
fps: 30,
|
|
30
|
+
verbose: true,
|
|
31
|
+
clips: [
|
|
32
|
+
{
|
|
33
|
+
duration: 5,
|
|
34
|
+
layers: [
|
|
35
|
+
{ type: "video", path: "output/sora-landscape.mp4" },
|
|
36
|
+
{
|
|
37
|
+
type: "video",
|
|
38
|
+
path: "output/simpsons-scene.mp4",
|
|
39
|
+
width: 0.3,
|
|
40
|
+
height: 0.3,
|
|
41
|
+
left: 0.68,
|
|
42
|
+
top: 0.02,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log("\ndone!");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fal Lipsync
|
|
3
|
+
* Required env: FAL_API_KEY
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { File, fal, generateVideo } from "../index";
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const videoPath = "media/talking-aleks-animated.mp4";
|
|
10
|
+
const audioPath = "media/talking-aleks-voice.mp3";
|
|
11
|
+
|
|
12
|
+
console.log("loading media files...");
|
|
13
|
+
const videoFile = File.fromPath(videoPath);
|
|
14
|
+
const audioFile = File.fromPath(audioPath);
|
|
15
|
+
|
|
16
|
+
console.log("lipsyncing with sync-v2...");
|
|
17
|
+
const { video } = await generateVideo({
|
|
18
|
+
model: fal.videoModel("sync-v2"),
|
|
19
|
+
prompt: {
|
|
20
|
+
video: await videoFile.data(),
|
|
21
|
+
audio: await audioFile.data(),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.log(`lipsynced video: ${video.uint8Array.byteLength} bytes`);
|
|
26
|
+
await Bun.write("output/lipsynced-v2.mp4", video.uint8Array);
|
|
27
|
+
|
|
28
|
+
console.log("\nlipsyncing with sync-v2-pro...");
|
|
29
|
+
const { video: proVideo } = await generateVideo({
|
|
30
|
+
model: fal.videoModel("sync-v2-pro"),
|
|
31
|
+
prompt: {
|
|
32
|
+
video: await videoFile.data(),
|
|
33
|
+
audio: await audioFile.data(),
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log(`pro lipsynced video: ${proVideo.uint8Array.byteLength} bytes`);
|
|
38
|
+
await Bun.write("output/lipsynced-pro.mp4", proVideo.uint8Array);
|
|
39
|
+
|
|
40
|
+
console.log("\ndone!");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Higgsfield Soul Image Generation
|
|
3
|
+
* Required env: HIGGSFIELD_API_KEY, HIGGSFIELD_SECRET
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { generateImage } from "ai";
|
|
7
|
+
import { createHiggsfield, higgsfield } from "../index";
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log("generating with default settings...");
|
|
11
|
+
const { images } = await generateImage({
|
|
12
|
+
model: higgsfield.imageModel("soul"),
|
|
13
|
+
prompt:
|
|
14
|
+
"a photorealistic portrait of a wise elderly man with deep blue eyes",
|
|
15
|
+
aspectRatio: "1:1",
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
console.log(`image generated: ${images[0]!.uint8Array.byteLength} bytes`);
|
|
19
|
+
await Bun.write("output/higgsfield-default.png", images[0]!.uint8Array);
|
|
20
|
+
|
|
21
|
+
console.log("\ngenerating with model settings...");
|
|
22
|
+
const { images: styledImages } = await generateImage({
|
|
23
|
+
model: higgsfield.imageModel("soul", {
|
|
24
|
+
quality: "1080p",
|
|
25
|
+
}),
|
|
26
|
+
prompt:
|
|
27
|
+
"a cyberpunk street scene at night, neon lights reflecting on wet pavement",
|
|
28
|
+
aspectRatio: "16:9",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
console.log(`styled image: ${styledImages[0]!.uint8Array.byteLength} bytes`);
|
|
32
|
+
await Bun.write(
|
|
33
|
+
"output/higgsfield-cinematic.png",
|
|
34
|
+
styledImages[0]!.uint8Array,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
console.log("\ngenerating with provider defaults...");
|
|
38
|
+
const customHiggsfield = createHiggsfield({
|
|
39
|
+
defaultModelSettings: {
|
|
40
|
+
enhancePrompt: true,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const { images: enhancedImages } = await generateImage({
|
|
45
|
+
model: customHiggsfield.imageModel("soul"),
|
|
46
|
+
prompt: "a serene japanese garden with cherry blossoms",
|
|
47
|
+
aspectRatio: "4:3",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(
|
|
51
|
+
`enhanced image: ${enhancedImages[0]!.uint8Array.byteLength} bytes`,
|
|
52
|
+
);
|
|
53
|
+
await Bun.write(
|
|
54
|
+
"output/higgsfield-enhanced.png",
|
|
55
|
+
enhancedImages[0]!.uint8Array,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
console.log("\ndone!");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { elevenlabs, generateMusic } from "../index";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log("generating rap beat...");
|
|
5
|
+
|
|
6
|
+
const { audio } = await generateMusic({
|
|
7
|
+
model: elevenlabs.musicModel(),
|
|
8
|
+
prompt:
|
|
9
|
+
"hard hitting trap beat, 808 bass, hi-hats, dark and aggressive vibe, 140 bpm",
|
|
10
|
+
duration: 30,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
console.log(`audio: ${audio.uint8Array.byteLength} bytes`);
|
|
14
|
+
|
|
15
|
+
await Bun.write("output/rap-beat.mp3", audio.uint8Array);
|
|
16
|
+
console.log("saved to output/rap-beat.mp3");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Sora Video Generation
|
|
3
|
+
* Required env: OPENAI_API_KEY
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { generateVideo, openai } from "../index";
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
console.log("generating 16:9 video with sora...");
|
|
10
|
+
const { video } = await generateVideo({
|
|
11
|
+
model: openai.videoModel("sora-2"),
|
|
12
|
+
prompt: "a cat walking on a sunny beach, waves gently lapping at the shore",
|
|
13
|
+
duration: 4,
|
|
14
|
+
aspectRatio: "16:9",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log(`video generated: ${video.uint8Array.byteLength} bytes`);
|
|
18
|
+
await Bun.write("output/sora-landscape.mp4", video.uint8Array);
|
|
19
|
+
|
|
20
|
+
console.log("\ngenerating 9:16 vertical video...");
|
|
21
|
+
const { video: verticalVideo } = await generateVideo({
|
|
22
|
+
model: openai.videoModel("sora-2"),
|
|
23
|
+
prompt: "a rocket launching into space, dramatic smoke and flames",
|
|
24
|
+
duration: 4,
|
|
25
|
+
aspectRatio: "9:16",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
console.log(`vertical video: ${verticalVideo.uint8Array.byteLength} bytes`);
|
|
29
|
+
await Bun.write("output/sora-vertical.mp4", verticalVideo.uint8Array);
|
|
30
|
+
|
|
31
|
+
console.log("\ndone!");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replicate Background Removal
|
|
3
|
+
* Required env: REPLICATE_API_TOKEN
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { generateImage } from "ai";
|
|
7
|
+
import { File, fal, replicate } from "../index";
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log("generating source image...");
|
|
11
|
+
const { images: sourceImages } = await generateImage({
|
|
12
|
+
model: fal.imageModel("flux-schnell"),
|
|
13
|
+
prompt: "a red sports car on a city street, urban background",
|
|
14
|
+
n: 1,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log(`source image: ${sourceImages[0]!.uint8Array.byteLength} bytes`);
|
|
18
|
+
await Bun.write("output/bg-removal-source.png", sourceImages[0]!.uint8Array);
|
|
19
|
+
|
|
20
|
+
const sourceFile = File.from(sourceImages[0]!);
|
|
21
|
+
|
|
22
|
+
console.log("\nremoving background...");
|
|
23
|
+
const { images: processedImages } = await generateImage({
|
|
24
|
+
model: replicate.image("851-labs/background-remover"),
|
|
25
|
+
prompt: {
|
|
26
|
+
images: [await sourceFile.data()],
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
console.log(
|
|
31
|
+
`processed image: ${processedImages[0]!.uint8Array.byteLength} bytes`,
|
|
32
|
+
);
|
|
33
|
+
await Bun.write(
|
|
34
|
+
"output/bg-removal-result.png",
|
|
35
|
+
processedImages[0]!.uint8Array,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
console.log("\nusing alternative model...");
|
|
39
|
+
const { images: altImages } = await generateImage({
|
|
40
|
+
model: replicate.image("lucataco/remove-bg"),
|
|
41
|
+
prompt: {
|
|
42
|
+
images: [await sourceFile.data()],
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(`alt result: ${altImages[0]!.uint8Array.byteLength} bytes`);
|
|
47
|
+
await Bun.write("output/bg-removal-alt.png", altImages[0]!.uint8Array);
|
|
48
|
+
|
|
49
|
+
console.log("\ndone!");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { generateImage } from "ai";
|
|
2
|
+
import { File, fal, generateElement, generateVideo, scene } from "../index";
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
console.log("generating ralph...");
|
|
6
|
+
|
|
7
|
+
const ralphShot = await File.fromPath("media/ralph.jpg").arrayBuffer();
|
|
8
|
+
|
|
9
|
+
const { element: ralph } = await generateElement({
|
|
10
|
+
model: fal.imageModel("nano-banana-pro/edit"),
|
|
11
|
+
type: "character",
|
|
12
|
+
prompt: {
|
|
13
|
+
text: "ralph wiggum from the simpsons, yellow skin, blue shorts, red shirt, simple cartoon style",
|
|
14
|
+
images: [ralphShot],
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
console.log(`ralph: ${ralph.images.length} images`);
|
|
18
|
+
|
|
19
|
+
await Promise.all(
|
|
20
|
+
ralph.images.map((img, i) => Bun.write(`output/ralph-${i}.png`, img)),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
console.log("generating blackboard...");
|
|
24
|
+
const { element: blackboard } = await generateElement({
|
|
25
|
+
model: fal.imageModel("nano-banana-pro"),
|
|
26
|
+
type: "item",
|
|
27
|
+
prompt:
|
|
28
|
+
"green chalkboard from simpsons intro that says 'I will not run claude code in a loop', white chalk text",
|
|
29
|
+
});
|
|
30
|
+
console.log(`blackboard: ${blackboard.images.length} images`);
|
|
31
|
+
|
|
32
|
+
await Promise.all(
|
|
33
|
+
blackboard.images.map((img, i) =>
|
|
34
|
+
Bun.write(`output/blackboard-${i}.png`, img),
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const { image: firstFrame } = await generateImage({
|
|
39
|
+
model: fal.imageModel("nano-banana-pro/edit"),
|
|
40
|
+
prompt: scene`${ralph} writes on the ${blackboard}`,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await Bun.write("output/first-frame.png", firstFrame.uint8Array);
|
|
44
|
+
|
|
45
|
+
console.log("generating video...");
|
|
46
|
+
const { video } = await generateVideo({
|
|
47
|
+
model: fal.videoModel("wan-2.5"),
|
|
48
|
+
prompt: {
|
|
49
|
+
text: `${ralph.text} writes on the ${blackboard.text}`,
|
|
50
|
+
images: [firstFrame.base64],
|
|
51
|
+
},
|
|
52
|
+
duration: 5,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log(`video: ${video.uint8Array.byteLength} bytes`);
|
|
56
|
+
await Bun.write("output/simpsons-scene.mp4", video.uint8Array);
|
|
57
|
+
|
|
58
|
+
console.log("\ndone!");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateImage,
|
|
3
|
+
experimental_generateSpeech as generateSpeech,
|
|
4
|
+
} from "ai";
|
|
5
|
+
import { elevenlabs, File, fal, generateVideo } from "../index";
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
const script = `Hey there! I'm Leo the Lion, and I'm here to tell you about the Varg SDK.
|
|
9
|
+
It's an incredible tool that lets you generate videos, images, and speech using AI.
|
|
10
|
+
You can create talking characters like me, animate images into videos, and even add captions automatically.
|
|
11
|
+
The SDK integrates seamlessly with the Vercel AI SDK, so you can use familiar patterns.
|
|
12
|
+
Whether you're building social content or creative apps, Varg has got you covered. Roar!`;
|
|
13
|
+
|
|
14
|
+
console.log("generating lion image and voice in parallel...");
|
|
15
|
+
const [imageResult, speechResult] = await Promise.all([
|
|
16
|
+
generateImage({
|
|
17
|
+
model: fal.imageModel("flux-schnell"),
|
|
18
|
+
prompt:
|
|
19
|
+
"majestic lion portrait, photorealistic, facing camera, warm lighting, savanna background, friendly expression",
|
|
20
|
+
n: 1,
|
|
21
|
+
}),
|
|
22
|
+
generateSpeech({
|
|
23
|
+
model: elevenlabs.speechModel("turbo"),
|
|
24
|
+
text: script,
|
|
25
|
+
voice: "adam",
|
|
26
|
+
}),
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const image = File.from(imageResult.images[0]!);
|
|
30
|
+
const audio = File.from(speechResult.audio);
|
|
31
|
+
|
|
32
|
+
console.log(`image: ${(await image.data()).byteLength} bytes`);
|
|
33
|
+
console.log(`audio: ${(await audio.data()).byteLength} bytes`);
|
|
34
|
+
|
|
35
|
+
await Bun.write("output/lion-image.png", await image.data());
|
|
36
|
+
await Bun.write("output/lion-voice.mp3", await audio.data());
|
|
37
|
+
|
|
38
|
+
console.log("\nanimating lion (5 seconds)...");
|
|
39
|
+
const { video } = await generateVideo({
|
|
40
|
+
model: fal.videoModel("wan-2.5"),
|
|
41
|
+
prompt: {
|
|
42
|
+
text: "lion talking and moving its mouth naturally, subtle head movements, breathing, blinking",
|
|
43
|
+
images: [await image.data()],
|
|
44
|
+
},
|
|
45
|
+
duration: 5,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const output = File.from(video);
|
|
49
|
+
console.log(`video: ${(await output.data()).byteLength} bytes`);
|
|
50
|
+
await Bun.write("output/talking-lion.mp4", await output.data());
|
|
51
|
+
|
|
52
|
+
console.log("\ndone! files saved to output/");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { generateImage } from "ai";
|
|
2
|
+
import { File, fal, generateVideo } from "../index";
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
console.log("generating video from text...");
|
|
6
|
+
const { video } = await generateVideo({
|
|
7
|
+
model: fal.videoModel("wan-2.5"),
|
|
8
|
+
prompt: "a serene mountain lake at sunset, gentle ripples on the water",
|
|
9
|
+
duration: 5,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
console.log(`video generated: ${video.uint8Array.byteLength} bytes`);
|
|
13
|
+
await Bun.write("output/text-to-video.mp4", video.uint8Array);
|
|
14
|
+
|
|
15
|
+
console.log("\ngenerating image first...");
|
|
16
|
+
const { images } = await generateImage({
|
|
17
|
+
model: fal.imageModel("flux-schnell"),
|
|
18
|
+
prompt: "a cute robot waving, 3d render, studio lighting",
|
|
19
|
+
n: 1,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
console.log("animating image to video...");
|
|
23
|
+
const image = File.from(images[0]!);
|
|
24
|
+
const { video: animatedVideo } = await generateVideo({
|
|
25
|
+
model: fal.videoModel("wan-2.5"),
|
|
26
|
+
prompt: {
|
|
27
|
+
text: "robot waves cheerfully, smooth animation",
|
|
28
|
+
images: [await image.data()],
|
|
29
|
+
},
|
|
30
|
+
duration: 5,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(`animated video: ${animatedVideo.uint8Array.byteLength} bytes`);
|
|
34
|
+
await Bun.write("output/image-to-video.mp4", animatedVideo.uint8Array);
|
|
35
|
+
|
|
36
|
+
console.log("\ndone!");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
main().catch(console.error);
|