@vargai/sdk 0.1.1 → 0.2.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/.github/workflows/ci.yml +23 -0
- package/.husky/README.md +102 -0
- package/.husky/commit-msg +9 -0
- package/.husky/pre-commit +12 -0
- package/.husky/pre-push +9 -0
- package/.size-limit.json +8 -0
- package/.test-hooks.ts +5 -0
- package/CONTRIBUTING.md +150 -0
- package/LICENSE.md +53 -0
- package/README.md +7 -0
- package/action/captions/index.ts +202 -12
- package/action/captions/tiktok.ts +538 -0
- package/action/cut/index.ts +119 -0
- package/action/fade/index.ts +116 -0
- package/action/merge/index.ts +177 -0
- package/action/remove/index.ts +184 -0
- package/action/split/index.ts +133 -0
- package/action/transition/index.ts +154 -0
- package/action/trim/index.ts +117 -0
- package/bun.lock +299 -8
- package/cli/commands/upload.ts +215 -0
- package/cli/index.ts +3 -1
- package/commitlint.config.js +22 -0
- package/index.ts +12 -0
- package/lib/ass.ts +547 -0
- package/lib/fal.ts +75 -1
- package/lib/ffmpeg.ts +400 -0
- package/lib/higgsfield/example.ts +22 -29
- package/lib/higgsfield/index.ts +3 -2
- package/lib/higgsfield/soul.ts +0 -5
- package/lib/remotion/SKILL.md +240 -21
- package/lib/remotion/cli.ts +34 -0
- package/package.json +20 -3
- package/pipeline/cookbooks/scripts/animate-frames-parallel.ts +83 -0
- package/pipeline/cookbooks/scripts/combine-scenes.sh +53 -0
- package/pipeline/cookbooks/scripts/generate-frames-parallel.ts +98 -0
- package/pipeline/cookbooks/scripts/still-to-video.sh +37 -0
- package/pipeline/cookbooks/text-to-tiktok.md +669 -0
- package/scripts/.gitkeep +0 -0
- package/service/music/index.ts +29 -14
- package/tsconfig.json +1 -1
- package/utilities/s3.ts +2 -2
- package/HIGGSFIELD_REWRITE_SUMMARY.md +0 -300
- package/TEST_RESULTS.md +0 -122
- package/output.txt +0 -1
- package/scripts/produce-menopause-campaign.sh +0 -202
- package/test-import.ts +0 -7
- package/test-services.ts +0 -97
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Automated production script for 15 Menopause Diet campaign videos
|
|
3
|
-
# Prerequisites:
|
|
4
|
-
# - All character images generated (✅ done)
|
|
5
|
-
# - Voiceover generated (✅ done)
|
|
6
|
-
# - Screencast video file at media/funnel-screencast.mp4
|
|
7
|
-
# - Background music at media/background-music.mp3 (optional)
|
|
8
|
-
# - FAL API credentials configured
|
|
9
|
-
|
|
10
|
-
set -e # Exit on error
|
|
11
|
-
|
|
12
|
-
echo "🎬 Starting Menopause Campaign Video Production"
|
|
13
|
-
echo "==============================================="
|
|
14
|
-
|
|
15
|
-
# Load asset data
|
|
16
|
-
ASSETS_FILE="media/menopause-campaign-assets.json"
|
|
17
|
-
VOICE_URL="http://s3.varg.ai/varg/voice/1763782542061-rachel.mp3"
|
|
18
|
-
VOICE_LOCAL="media/voice-1763782540364.mp3"
|
|
19
|
-
|
|
20
|
-
# Create output directories
|
|
21
|
-
mkdir -p media/campaign/{animated,synced,captioned,hooks,final}
|
|
22
|
-
|
|
23
|
-
echo ""
|
|
24
|
-
echo "📋 Step 0: Generate SRT from voiceover"
|
|
25
|
-
echo "--------------------------------------"
|
|
26
|
-
if [ ! -f "media/voice-1763782540364.srt" ]; then
|
|
27
|
-
bun run service/transcribe/index.ts \
|
|
28
|
-
"$VOICE_LOCAL" \
|
|
29
|
-
fireworks \
|
|
30
|
-
media/voice-1763782540364.srt
|
|
31
|
-
echo "✅ SRT file generated"
|
|
32
|
-
else
|
|
33
|
-
echo "⏭️ SRT file already exists"
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
echo ""
|
|
37
|
-
echo "🎨 Step 1: Animate all 15 character images"
|
|
38
|
-
echo "-------------------------------------------"
|
|
39
|
-
for i in {0..14}; do
|
|
40
|
-
IMAGE_URL=$(jq -r ".characters[$i].imageUrl" "$ASSETS_FILE")
|
|
41
|
-
PROFESSION=$(jq -r ".characters[$i].profession" "$ASSETS_FILE" | tr ' ' '-')
|
|
42
|
-
OUTPUT_NUM=$((i+1))
|
|
43
|
-
|
|
44
|
-
echo "Animating $PROFESSION ($OUTPUT_NUM/15)..."
|
|
45
|
-
|
|
46
|
-
# Run animation
|
|
47
|
-
bun run service/video/index.ts from_image \
|
|
48
|
-
"person talking naturally to camera, professional demeanor" \
|
|
49
|
-
"$IMAGE_URL" \
|
|
50
|
-
5 \
|
|
51
|
-
true \
|
|
52
|
-
> "media/campaign/animated/result-$OUTPUT_NUM.json"
|
|
53
|
-
|
|
54
|
-
# Extract video URL from result
|
|
55
|
-
VIDEO_URL=$(jq -r '.uploaded' "media/campaign/animated/result-$OUTPUT_NUM.json")
|
|
56
|
-
echo "$VIDEO_URL" >> media/campaign/animated/video-urls.txt
|
|
57
|
-
|
|
58
|
-
echo "✅ Animated: $PROFESSION"
|
|
59
|
-
done
|
|
60
|
-
|
|
61
|
-
echo ""
|
|
62
|
-
echo "🎤 Step 2: Lipsync videos with voiceover"
|
|
63
|
-
echo "-----------------------------------------"
|
|
64
|
-
line_num=1
|
|
65
|
-
while IFS= read -r video_url; do
|
|
66
|
-
echo "Lipsyncing video $line_num/15..."
|
|
67
|
-
|
|
68
|
-
bun run service/sync/index.ts wav2lip \
|
|
69
|
-
"$video_url" \
|
|
70
|
-
"$VOICE_URL" \
|
|
71
|
-
> "media/campaign/synced/result-$line_num.json"
|
|
72
|
-
|
|
73
|
-
# Download the synced video
|
|
74
|
-
SYNCED_URL=$(jq -r '.videoUrl' "media/campaign/synced/result-$line_num.json")
|
|
75
|
-
curl -o "media/campaign/synced/video-$line_num.mp4" "$SYNCED_URL"
|
|
76
|
-
|
|
77
|
-
echo "✅ Lipsynced video $line_num"
|
|
78
|
-
((line_num++))
|
|
79
|
-
done < media/campaign/animated/video-urls.txt
|
|
80
|
-
|
|
81
|
-
echo ""
|
|
82
|
-
echo "📝 Step 3: Add dynamic captions"
|
|
83
|
-
echo "--------------------------------"
|
|
84
|
-
for i in {1..15}; do
|
|
85
|
-
echo "Adding captions to video $i/15..."
|
|
86
|
-
|
|
87
|
-
bun run service/captions/index.ts \
|
|
88
|
-
"media/campaign/synced/video-$i.mp4" \
|
|
89
|
-
"media/campaign/captioned/video-$i.mp4" \
|
|
90
|
-
--srt media/voice-1763782540364.srt \
|
|
91
|
-
--font "Arial Black" \
|
|
92
|
-
--size 32 \
|
|
93
|
-
--color "&HFFFFFF"
|
|
94
|
-
|
|
95
|
-
echo "✅ Captioned video $i"
|
|
96
|
-
done
|
|
97
|
-
|
|
98
|
-
echo ""
|
|
99
|
-
echo "🏷️ Step 4: Add subtitle and disclaimer overlays"
|
|
100
|
-
echo "------------------------------------------------"
|
|
101
|
-
for i in {1..15}; do
|
|
102
|
-
echo "Adding overlays to video $i/15..."
|
|
103
|
-
|
|
104
|
-
# Add title "My Menopause weight loss" at top
|
|
105
|
-
# Add subtitle "Scientifically designed for women 40+" near bottom
|
|
106
|
-
# Add disclaimer at bottom
|
|
107
|
-
ffmpeg -i "media/campaign/captioned/video-$i.mp4" \
|
|
108
|
-
-vf "[in]drawtext=fontfile=/System/Library/Fonts/Supplemental/Arial.ttf:text='My Menopause weight loss':fontcolor=white:fontsize=42:x=(w-text_w)/2:y=60:box=1:boxcolor=black@0.7:boxborderw=10:borderw=2:bordercolor=white,\
|
|
109
|
-
drawtext=fontfile=/System/Library/Fonts/Supplemental/Arial.ttf:text='Scientifically designed for women 40+':fontcolor=white:fontsize=16:x=(w-text_w)/2:y=h-100:alpha=0.9,\
|
|
110
|
-
drawtext=fontfile=/System/Library/Fonts/Supplemental/Arial.ttf:text='Results may vary. Always consult your doctor before starting any diet program':fontcolor=white:fontsize=12:x=(w-text_w)/2:y=h-60:alpha=0.8[out]" \
|
|
111
|
-
-codec:a copy \
|
|
112
|
-
-y \
|
|
113
|
-
"media/campaign/hooks/hook-$i.mp4"
|
|
114
|
-
|
|
115
|
-
echo "✅ Added overlays to video $i"
|
|
116
|
-
done
|
|
117
|
-
|
|
118
|
-
echo ""
|
|
119
|
-
echo "🎞️ Step 5: Prepare screencast with music"
|
|
120
|
-
echo "-----------------------------------------"
|
|
121
|
-
if [ ! -f "media/funnel-screencast.mp4" ]; then
|
|
122
|
-
echo "❌ ERROR: media/funnel-screencast.mp4 not found!"
|
|
123
|
-
echo " Please provide the menopause funnel screencast."
|
|
124
|
-
exit 1
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
if [ -f "media/background-music.mp3" ]; then
|
|
128
|
-
echo "Adding music to screencast..."
|
|
129
|
-
ffmpeg -i media/funnel-screencast.mp4 \
|
|
130
|
-
-i media/background-music.mp3 \
|
|
131
|
-
-c:v copy \
|
|
132
|
-
-map 0:v:0 \
|
|
133
|
-
-map 1:a:0 \
|
|
134
|
-
-shortest \
|
|
135
|
-
-y \
|
|
136
|
-
media/campaign/funnel-with-music.mp4
|
|
137
|
-
echo "✅ Music added to screencast"
|
|
138
|
-
else
|
|
139
|
-
echo "⚠️ No background music found, using screencast as-is"
|
|
140
|
-
cp media/funnel-screencast.mp4 media/campaign/funnel-with-music.mp4
|
|
141
|
-
fi
|
|
142
|
-
|
|
143
|
-
echo ""
|
|
144
|
-
echo "🔗 Step 6: Merge hooks with screencast"
|
|
145
|
-
echo "---------------------------------------"
|
|
146
|
-
for i in {1..15}; do
|
|
147
|
-
echo "Merging video $i/15..."
|
|
148
|
-
|
|
149
|
-
# Create concat file
|
|
150
|
-
echo "file '../../hooks/hook-$i.mp4'" > "media/campaign/concat-$i.txt"
|
|
151
|
-
echo "file '../funnel-with-music.mp4'" >> "media/campaign/concat-$i.txt"
|
|
152
|
-
|
|
153
|
-
# Merge
|
|
154
|
-
ffmpeg -f concat -safe 0 -i "media/campaign/concat-$i.txt" \
|
|
155
|
-
-c copy \
|
|
156
|
-
-y \
|
|
157
|
-
"media/campaign/merged-$i.mp4"
|
|
158
|
-
|
|
159
|
-
echo "✅ Merged video $i"
|
|
160
|
-
done
|
|
161
|
-
|
|
162
|
-
echo ""
|
|
163
|
-
echo "📱 Step 7: Optimize for social media (TikTok vertical)"
|
|
164
|
-
echo "-------------------------------------------------------"
|
|
165
|
-
for i in {0..14}; do
|
|
166
|
-
VIDEO_NUM=$((i+1))
|
|
167
|
-
PROFESSION=$(jq -r ".characters[$i].profession" "$ASSETS_FILE" | tr ' ' '-')
|
|
168
|
-
|
|
169
|
-
echo "Optimizing $PROFESSION ($VIDEO_NUM/15)..."
|
|
170
|
-
|
|
171
|
-
bun run service/edit/index.ts social \
|
|
172
|
-
"media/campaign/merged-$VIDEO_NUM.mp4" \
|
|
173
|
-
"media/campaign/final/$PROFESSION-tiktok.mp4" \
|
|
174
|
-
tiktok
|
|
175
|
-
|
|
176
|
-
echo "✅ Final video: $PROFESSION"
|
|
177
|
-
done
|
|
178
|
-
|
|
179
|
-
echo ""
|
|
180
|
-
echo "✨ PRODUCTION COMPLETE!"
|
|
181
|
-
echo "======================"
|
|
182
|
-
echo ""
|
|
183
|
-
echo "📊 Summary:"
|
|
184
|
-
echo " • 15 character images ✅"
|
|
185
|
-
echo " • 1 voiceover audio ✅"
|
|
186
|
-
echo " • 15 animated videos ✅"
|
|
187
|
-
echo " • 15 lipsynced videos ✅"
|
|
188
|
-
echo " • 15 captioned videos ✅"
|
|
189
|
-
echo " • 15 final videos with overlays ✅"
|
|
190
|
-
echo ""
|
|
191
|
-
echo "📁 Final videos location: media/campaign/final/"
|
|
192
|
-
echo ""
|
|
193
|
-
echo "🎯 Next steps:"
|
|
194
|
-
echo " 1. Review all 15 videos"
|
|
195
|
-
echo " 2. Test on target platforms"
|
|
196
|
-
echo " 3. Upload to ad platform"
|
|
197
|
-
echo " 4. Start A/B testing!"
|
|
198
|
-
echo ""
|
|
199
|
-
|
|
200
|
-
# List all final files
|
|
201
|
-
echo "📋 Final video files:"
|
|
202
|
-
ls -lh media/campaign/final/
|
package/test-import.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
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);
|
package/test-services.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
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);
|