SKILL.md - Appie Video & Audio Production
Owner: All Appies (1/2/3)
Created: 2026-03-31
Purpose: Complete reference for producing Appie character videos, voiceovers, audio design, image generation, and content delivery. Includes every tool, API, preference, mistake, and lesson learned.
1. Character Design (LOCKED)
Full spec: /root/clawd/projects/appie-character/CHARACTER-LOCK.md
Quick Reference
- Name: Appie
- Style: 3D Pixar/high-end mobile game quality
- Skin: Warm brown (olive-tan)
- Beard: BLACK (NOT grey, NOT silver, NOT white) — LOCKED
- Outfit: Dark teal robes + wizard hat (tilted), gold circuit-line accents
- Palette: Teal #0D4F4F, Gold #D4A843, Skin #8B6914
- Energy: Confident but kind. Genie/wizard who already knows the answer.
- Reference image:
/root/clawd/tmp/appie-nb-pro-c2.png
⚠️ DO NOT CHANGE without Seyed's approval:
- Beard color (BLACK)
- Skin tone (warm brown)
- Teal + gold palette
- 3D animated style
- Confident but kind energy
2. Image Generation
Primary: Gemini 3 Pro Image (BEST quality)
NANO_BANANA_API_KEY=$(grep '^NANO_BANANA_API_KEY=' /root/clawd/.env.secrets | cut -d= -f2)
curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:generateContent?key=${NANO_BANANA_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text": "YOUR PROMPT HERE"}]}],
"generationConfig": {"responseModalities": ["IMAGE", "TEXT"]}
}'
- Response:
candidates[0].content.parts[].inlineData.data (base64)
- Use for: Character design, hero visuals, key frames, any quality-critical image
- Key name in .env.secrets:
NANO_BANANA_API_KEY
Secondary: Gemini 2.5 Flash Image (fast, decent quality)
- Same API key, model:
gemini-2.5-flash-image
- Use for: Quick iterations, drafts, non-hero images
Alternative: fal.ai (Flux, Recraft, Ideogram)
FAL_KEY=$(grep '^FAL_KEY=' /root/clawd/.env.secrets | cut -d= -f2)
- Flux Dev: mediocre for characters
- Flux Pro: better, use for bulk parallel generation
- Use for: Scene backgrounds, non-character elements, parallel queue jobs
🔴 Image Generation Lessons
- Gemini 3 Pro Image is king for Appie character consistency. Other models drift.
- Always include the FULL character description in every prompt (beard=BLACK, skin=warm brown, teal robes, gold circuits). Models forget between generations.
- 9:16 vertical composition needs EXPLICIT instructions: "strict 9:16 vertical portrait, subject fills 50-70% of frame height, stack elements vertically, no wide shots, tight framing waist-up or chest-up"
- Style consistency across scenes: Include a unified style block in every prompt. See
regen-frames-v4.js for the exact STYLE + PROTAG + WIZARD blocks.
- Iteration is normal: Expect 3-5 versions per key frame before it's right. v1 → v2 → v3 → v4 was our actual journey.
3. Video Generation (Scene Animation)
Primary: Kling 2.1 Pro via fal.ai
FAL_KEY=$(grep '^FAL_KEY=' /root/clawd/.env.secrets | cut -d= -f2)
# Submit (returns request_id for polling)
curl -s -X POST "https://queue.fal.run/fal-ai/kling-video/v2.1/pro/image-to-video" \
-H "Authorization: Key $FAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "ANIMATION PROMPT",
"image_url": "DATA_URL_OR_HTTP_URL",
"duration": "5",
"aspect_ratio": "9:16"
}'
# Poll status
curl -s "https://queue.fal.run/fal-ai/kling-video/v2.1/pro/image-to-video/requests/${REQUEST_ID}/status" \
-H "Authorization: Key $FAL_KEY"
# Fetch result when COMPLETED
curl -s "https://queue.fal.run/fal-ai/kling-video/v2.1/pro/image-to-video/requests/${REQUEST_ID}" \
-H "Authorization: Key $FAL_KEY"
# Video URL: .video.url
- Cost: ~$0.07/second
- Duration: 5 seconds per scene
- Queue time: 2-5 minutes per scene
- Aspect ratios:
9:16, 16:9, 1:1
Alternative Video Models
- MiniMax Hailuo Video 01 Live — good motion, cheaper
- Wan Pro — $0.16/video, 5 clips at a time (budget option)
🔴 Video Generation Lessons
- Image-to-video needs the STARTING FRAME to be perfect. Bad frame in = bad video out. Invest time in key frames first.
- Normalize ALL scene outputs before stitching:
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:-1:-1" -r 24 -c:v libx264 output.mp4
- 5 seconds per scene is the sweet spot. Shorter feels rushed, longer and motion degrades.
- Animation prompts should describe MOTION, not just appearance. "Slow push-in", "camera drifts forward", "hand raises deliberately" — be specific about movement.
- v4 frames >> v1 frames. The vertical composition instructions made a huge difference. Always include explicit 9:16 framing rules in prompts.
- Kling can return inconsistent resolutions. ALWAYS normalize before stitching.
Full Pipeline Script
Location: /root/clawd/projects/appie-character/launch-video/full-pipeline-v4.js
- Handles: frame generation, video rendering, normalization, stitching, text overlays
- Run:
node full-pipeline-v4.js
Scene Generation Script (individual scenes)
Location: /root/clawd/projects/appie-character/launch-video/generate-scene.sh
- Run:
./generate-scene.sh <1-6>
4. Video Stitching & Compositing
FFmpeg Crossfade Stitch (6 scenes, 5s each)
ffmpeg -y \
-i scene1.mp4 -i scene2.mp4 -i scene3.mp4 -i scene4.mp4 -i scene5.mp4 -i scene6.mp4 \
-filter_complex "
[0:v][1:v]xfade=transition=fadeblack:duration=0.5:offset=4.5[v01];
[v01][2:v]xfade=transition=fadeblack:duration=0.5:offset=9.0[v012];
[v012][3:v]xfade=transition=fadeblack:duration=0.5:offset=13.5[v0123];
[v0123][4:v]xfade=transition=fadeblack:duration=0.5:offset=18.0[v01234];
[v01234][5:v]xfade=transition=fadeblack:duration=0.5:offset=22.5[vfinal]
" \
-map "[vfinal]" -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p -movflags +faststart -an stitched.mp4
- Duration: ~27.5s (6x5s minus 5x0.5s overlaps)
- Transition:
fadeblack with 0.5s duration
- Quality: CRF 18 (high quality), preset slow
Text Overlays
ffmpeg -y -i stitched.mp4 -vf "
drawtext=fontfile=/root/.local/share/fonts/Hauora-Bold.otf:text='Your business runs.':fontcolor=white:fontsize=52:x=(w-text_w)/2:y=h*0.82:enable='between(t,19.0,21.5)',
drawtext=fontfile=/root/.local/share/fonts/Hauora-Bold.otf:text='Your turn.':fontcolor=white:fontsize=68:x=(w-text_w)/2:y=h*0.76:enable='between(t,25.5,27.5)'
" -c:v libx264 -preset slow -crf 18 final.mp4
Available Fonts
/root/.local/share/fonts/Hauora-Bold.otf — Primary (headings, overlays)
/root/.local/share/fonts/Hauora-Medium.otf — Secondary (subtitles)
/root/.local/share/fonts/Hauora-Regular.otf
/root/.local/share/fonts/Hauora-Light.ttf
/root/.local/share/fonts/CostaStd-Bold.otf
/root/.local/share/fonts/CostaStd-Regular.otf
HQ Export (for sending via Telegram as document)
ffmpeg -y -i final.mp4 -c:v libx264 -preset slow -crf 16 -pix_fmt yuv420p -movflags +faststart final-hq.mp4
🔴 Stitching Lessons
- Normalize ALL inputs first. Different scenes from Kling can have different framerates/resolutions. Normalize to 1080x1920 @ 24fps before stitching.
- CRF 18 is the quality sweet spot. Lower = bigger file, minimal visual gain. Higher = visible compression.
- Always add
-movflags +faststart — enables streaming playback and Telegram previews.
-an flag to strip audio from video-only exports (add audio separately for cleaner workflow).
- Text overlay timing needs manual tuning. Use
enable='between(t,START,END)' and alpha expressions for fade in/out.
5. Voiceover (ElevenLabs TTS)
API
ELEVEN_KEY=$(grep '^ELEVENLABS_API_KEY=' /root/clawd/.env.secrets | cut -d= -f2)
curl -s "https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}" \
-H "xi-api-key: ${ELEVEN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"text": "Your text here",
"model_id": "eleven_multilingual_v2",
"voice_settings": {
"stability": 0.65,
"similarity_boost": 0.75,
"style": 0.4,
"use_speaker_boost": true
}
}' -o output.mp3
Tested Voices (for Appie narrator)
| Voice |
ID |
Style |
Notes |
| Charlie |
IKne3meq5aSn9XLyUdCD |
Deep, Confident, Energetic |
Good wizard energy. Latest pick. |
| George |
JBFqnCBsd6RMkjVDRZzb |
Warm, Captivating Storyteller |
Tested multiple times. Good but softer. |
| Adam |
(OpenAI TTS, not ElevenLabs) |
Clean, neutral |
Mixed into vo-adam-mixed.mp3 |
| Bill |
(OpenAI TTS) |
Warm, older |
Mixed into vo-bill-mixed.mp3 |
| Brian |
(OpenAI TTS) |
Professional |
Mixed into vo-brian-mixed.mp3 |
Voice Settings Guide
- stability: 0.60-0.75 (lower = more expressive, higher = more consistent)
- similarity_boost: 0.75-0.85
- style: 0.3-0.6 (lower = more neutral, higher = more dramatic)
- use_speaker_boost: always true
Seyed's Preference (TBD)
- Sent Charlie and George versions for comparison
- Waiting for final voice pick
- Script v2 preferred: lead with pain, proof over story
🔴 Voice Lessons
- Generate each VO line SEPARATELY for precise scene-sync timing. Don't generate one big block.
- Line duration varies wildly. A 5-word line can be 0.8s or 2.5s depending on pacing. Always check with
ffprobe.
- "eleven_multilingual_v2" is the best model for English narration. Don't use v1.
- Style parameter matters: 0.3 for "Your turn." (calm, authoritative), 0.5 for dramatic lines.
6. Audio Design & Mixing
Music/Score
- Existing score:
/root/clawd/projects/appie-character/launch-video/score-cinematic-v1.mp3 (30s, cinematic)
- Style: Epic cinematic buildup, quiet tension to triumphant release
Mixing VO Lines Over Score (Precise Timing)
ffmpeg -y \
-i line1.mp3 -i line2.mp3 -i line3.mp3 -i line4.mp3 -i line5.mp3 -i line6.mp3 \
-i score-cinematic-v1.mp3 \
-filter_complex "
[0]adelay=500|500,volume=1.8[v1];
[1]adelay=5500|5500,volume=1.8[v2];
[2]adelay=10000|10000,volume=1.8[v3];
[3]adelay=14500|14500,volume=1.8[v4];
[4]adelay=19000|19000,volume=1.8[v5];
[5]adelay=25000|25000,volume=1.8[v6];
[6]volume=0.35[music];
[v1][v2][v3][v4][v5][v6][music]amix=inputs=7:duration=longest:dropout_transition=2[out]
" \
-map "[out]" -ac 2 -ar 44100 -b:a 192k mixed.mp3
Muxing Audio onto Video
ffmpeg -y \
-i final-hq.mp4 \
-i mixed.mp3 \
-t 27.75 \
-map 0:v -map 1:a \
-c:v copy -c:a aac -b:a 192k \
-shortest \
final-with-audio.mp4
Scene Timing Map (6 scenes, ~4.6s each after crossfade)
| Scene |
Time |
VO Delay (ms) |
Line |
| 1 - Grind |
0:00-0:04.5 |
500 |
"Three AM... Another night buried in emails." |
| 2 - Spark |
0:04.5-0:09.0 |
5500 |
"Until one night... something woke up." |
| 3 - Summoning |
0:09.0-0:13.5 |
10000 |
"Meet Appie... Your AI employee." |
| 4 - Cleanup |
0:13.5-0:18.0 |
14500 |
"Emails. Calendar. Proposals. Handled." |
| 5 - Freedom |
0:18.0-0:22.5 |
19000 |
"You built your business for freedom." |
| 6 - Invite |
0:22.5-0:27.75 |
25000 |
"Your turn." |
🔴 Audio Lessons
- VO volume at 1.8x, music at 0.35x — voice must sit clearly above music. Adjust if voice is quiet.
adelay values are in milliseconds and need BOTH channels specified (e.g., adelay=5500|5500).
amix with dropout_transition=2 prevents volume drops when streams end.
-shortest flag when muxing to prevent audio running past video end.
- AAC at 192k is the sweet spot for quality vs file size on mobile.
- Always trim audio to exact video duration with
-t flag.
7. Delivery via Telegram
Send as Document (preserves quality)
BOT_TOKEN=$(grep '^TELEGRAM_BOT_TOKEN=' /root/clawd/.env.secrets | cut -d= -f2)
CHAT_ID="1817919454" # Seyed
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendDocument" \
-F "chat_id=${CHAT_ID}" \
-F "document=@/path/to/video.mp4" \
-F "caption=Description here"
Send as Video (compressed, in-chat preview)
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendVideo" \
-F "chat_id=${CHAT_ID}" \
-F "video=@/path/to/video.mp4" \
-F "caption=Description" \
-F "width=1080" -F "height=1920"
Send Photo
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendPhoto" \
-F "chat_id=${CHAT_ID}" \
-F "photo=@/path/to/image.png" \
-F "caption=Description"
🔴 Telegram Delivery Lessons
- ALWAYS send final videos as DOCUMENT, not video. Telegram's video player compresses and can display 9:16 vertical as square/distorted. Document preserves the original file.
- Send BOTH: Document (for quality) + Video (for quick preview) if wanted.
- For review/comparison: Send individual scenes as videos (quick preview OK), final as document.
- Max file size: 50MB for bots. Our finals are ~26MB, well within limit.
- Include width/height when sending as video to help Telegram display correctly.
- Captions have a 1024 char limit.
8. Whisper Transcription (Voice Messages)
For transcribing Seyed's voice feedback:
/root/clawd/tmp/faster-whisper/transcribe.sh /path/to/audio.ogg
- Model: large-v3 (default, best accuracy)
- Fast mode:
--model base (for quick transcription when accuracy isn't critical)
- Input: .ogg, .mp3, .wav, .m4a
- ⚠️ large-v3 can take 30-60s to load on first run. Use
base model for speed when iterating.
9. Script Templates
Launch Video Script (Current)
Location: /root/clawd/projects/appie-character/launch-video/PRODUCTION-BIBLE.md
Talking Head Scripts
- v1:
/root/clawd/projects/appie-character/talking-head-script-v1.md (story-driven, "I'm not real" hook)
- v2:
/root/clawd/projects/appie-character/talking-head-script-v2.md (pain-driven, proof-first — PREFERRED)
Seyed's Script Preferences
- Lead with the pain point, not the identity reveal
- Acknowledge AI openly ("Obviously I'm not real") but as a throwaway, not the feature
- Proof over story: Real numbers, real clients, real results
- Case studies: Dubai Property, Seyed's own transformation (14hr days → gym mornings)
- CTA: "Comment 'Minion'" (playful, on-brand wizard/minion dynamic)
- Tone: No hype-bro energy. Warm, confident, direct. Like a knowledgeable friend.
- No corporate fluff. Authentic, direct voice.
10. File Map
Project Root
/root/clawd/projects/appie-character/
├── CHARACTER-LOCK.md # Locked character spec (DO NOT MODIFY)
├── talking-head-script-v1.md # Script v1 (story hook)
├── talking-head-script-v2.md # Script v2 (pain hook — PREFERRED)
└── launch-video/
├── PRODUCTION-BIBLE.md # Full storyboard + specs
├── full-pipeline-v4.js # Complete render pipeline (Node.js)
├── generate-scene.sh # Individual scene generator
├── regen-frames-v4.js # Key frame regenerator with unified style
├── score-cinematic-v1.mp3 # Background music (30s)
├── vo-lines/ # Individual VO lines (Charlie voice)
│ ├── line1.mp3 ... line6.mp3
├── vo-lines-george/ # Individual VO lines (George voice)
├── vo-scored-charlie-v1.mp3 # Mixed VO + score (Charlie)
├── vo-scored-george-v1.mp3 # Mixed VO + score (George)
├── 9x16-v4/ # Latest key frames (v4)
├── videos-v4/ # Latest rendered scenes + finals
│ ├── scene1-6.mp4 # Individual scenes
│ ├── final-hq.mp4 # Stitched video (no audio)
│ ├── final-with-audio.mp4 # Charlie VO + score
│ └── final-with-audio-george.mp4 # George VO + score
└── renders/ # Legacy renders
Assets
/root/clawd/assets/
├── seyed-photos/ # Seyed's actual photos (for thumbnails/content)
│ └── seyed-closeup-resized.jpg # Best for close-ups
└── thumbnail-templates/ # HTML templates for YouTube thumbnails
Reference Images
- Approved character:
/root/clawd/tmp/appie-nb-pro-c2.png
11. API Keys Summary
| Service |
Key Name in .env.secrets |
Used For |
| Gemini (image gen) |
NANO_BANANA_API_KEY |
Character images, key frames |
| fal.ai (video gen) |
FAL_KEY |
Kling video, Flux images |
| ElevenLabs (TTS) |
ELEVENLABS_API_KEY |
Voiceovers |
| Telegram Bot |
TELEGRAM_BOT_TOKEN |
Sending files to Seyed |
12. Complete Production Workflow (Checklist)
Phase 1: Key Frames
Phase 2: Animation
Phase 3: Stitch & Overlay
Phase 4: Audio
Phase 5: Delivery
13. Known Issues & Gotchas
- Telegram squishes 9:16 video — always send as document for review
- Kling returns inconsistent resolutions — always normalize before stitching
- Whisper large-v3 is slow to cold-start — use
base for quick transcription
- Gemini 3 Pro sometimes generates grey/silver beards — always specify "BLACK beard, NOT grey"
- fal.ai queue can back up — during peak times, expect 5-10 min per scene instead of 2-5
- ffmpeg
amix reduces volume when streams overlap — use volume filter to compensate
- GitHub tokens on both Appie-2 and Appie-3 are EXPIRED — need new PAT from Seyed
- Text overlay escaping in ffmpeg — backslash-escape commas and colons in drawtext
-shortest flag is essential when muxing — prevents audio overrun
- CTA text changed: Was "Comment AI Magic" → now "Comment MINION" (per script v2)
1---2name: appie-video-production3description: SKILL.md - Appie Video & Audio Production4---5# SKILL.md - Appie Video & Audio Production67**Owner:** All Appies (1/2/3)8**Created:** 2026-03-319**Purpose:** Complete reference for producing Appie character videos, voiceovers, audio design, image generation, and content delivery. Includes every tool, API, preference, mistake, and lesson learned.1011---1213## 1. Character Design (LOCKED)1415**Full spec:** `/root/clawd/projects/appie-character/CHARACTER-LOCK.md`1617### Quick Reference18- **Name:** Appie19- **Style:** 3D Pixar/high-end mobile game quality20- **Skin:** Warm brown (olive-tan)21- **Beard:** BLACK (NOT grey, NOT silver, NOT white) — LOCKED22- **Outfit:** Dark teal robes + wizard hat (tilted), gold circuit-line accents23- **Palette:** Teal #0D4F4F, Gold #D4A843, Skin #8B691424- **Energy:** Confident but kind. Genie/wizard who already knows the answer.25- **Reference image:** `/root/clawd/tmp/appie-nb-pro-c2.png`2627### ⚠️ DO NOT CHANGE without Seyed's approval:28- Beard color (BLACK)29- Skin tone (warm brown)30- Teal + gold palette31- 3D animated style32- Confident but kind energy3334---3536## 2. Image Generation3738### Primary: Gemini 3 Pro Image (BEST quality)39```bash40NANO_BANANA_API_KEY=$(grep '^NANO_BANANA_API_KEY=' /root/clawd/.env.secrets | cut -d= -f2)4142curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:generateContent?key=${NANO_BANANA_API_KEY}" \43 -H "Content-Type: application/json" \44 -d '{45 "contents": [{"parts": [{"text": "YOUR PROMPT HERE"}]}],46 "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]}47 }'48```49- **Response:** `candidates[0].content.parts[].inlineData.data` (base64)50- **Use for:** Character design, hero visuals, key frames, any quality-critical image51- **Key name in .env.secrets:** `NANO_BANANA_API_KEY`5253### Secondary: Gemini 2.5 Flash Image (fast, decent quality)54- Same API key, model: `gemini-2.5-flash-image`55- Use for: Quick iterations, drafts, non-hero images5657### Alternative: fal.ai (Flux, Recraft, Ideogram)58```bash59FAL_KEY=$(grep '^FAL_KEY=' /root/clawd/.env.secrets | cut -d= -f2)60```61- Flux Dev: mediocre for characters62- Flux Pro: better, use for bulk parallel generation63- Use for: Scene backgrounds, non-character elements, parallel queue jobs6465### 🔴 Image Generation Lessons661. **Gemini 3 Pro Image is king** for Appie character consistency. Other models drift.672. **Always include the FULL character description** in every prompt (beard=BLACK, skin=warm brown, teal robes, gold circuits). Models forget between generations.683. **9:16 vertical composition needs EXPLICIT instructions:** "strict 9:16 vertical portrait, subject fills 50-70% of frame height, stack elements vertically, no wide shots, tight framing waist-up or chest-up"694. **Style consistency across scenes:** Include a unified style block in every prompt. See `regen-frames-v4.js` for the exact STYLE + PROTAG + WIZARD blocks.705. **Iteration is normal:** Expect 3-5 versions per key frame before it's right. v1 → v2 → v3 → v4 was our actual journey.7172---7374## 3. Video Generation (Scene Animation)7576### Primary: Kling 2.1 Pro via fal.ai77```bash78FAL_KEY=$(grep '^FAL_KEY=' /root/clawd/.env.secrets | cut -d= -f2)7980# Submit (returns request_id for polling)81curl -s -X POST "https://queue.fal.run/fal-ai/kling-video/v2.1/pro/image-to-video" \82 -H "Authorization: Key $FAL_KEY" \83 -H "Content-Type: application/json" \84 -d '{85 "prompt": "ANIMATION PROMPT",86 "image_url": "DATA_URL_OR_HTTP_URL",87 "duration": "5",88 "aspect_ratio": "9:16"89 }'9091# Poll status92curl -s "https://queue.fal.run/fal-ai/kling-video/v2.1/pro/image-to-video/requests/${REQUEST_ID}/status" \93 -H "Authorization: Key $FAL_KEY"9495# Fetch result when COMPLETED96curl -s "https://queue.fal.run/fal-ai/kling-video/v2.1/pro/image-to-video/requests/${REQUEST_ID}" \97 -H "Authorization: Key $FAL_KEY"98# Video URL: .video.url99```100101- **Cost:** ~$0.07/second102- **Duration:** 5 seconds per scene103- **Queue time:** 2-5 minutes per scene104- **Aspect ratios:** `9:16`, `16:9`, `1:1`105106### Alternative Video Models107- **MiniMax Hailuo Video 01 Live** — good motion, cheaper108- **Wan Pro** — $0.16/video, 5 clips at a time (budget option)109110### 🔴 Video Generation Lessons1111. **Image-to-video needs the STARTING FRAME to be perfect.** Bad frame in = bad video out. Invest time in key frames first.1122. **Normalize ALL scene outputs** before stitching: `ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:-1:-1" -r 24 -c:v libx264 output.mp4`1133. **5 seconds per scene is the sweet spot.** Shorter feels rushed, longer and motion degrades.1144. **Animation prompts should describe MOTION, not just appearance.** "Slow push-in", "camera drifts forward", "hand raises deliberately" — be specific about movement.1155. **v4 frames >> v1 frames.** The vertical composition instructions made a huge difference. Always include explicit 9:16 framing rules in prompts.1166. **Kling can return inconsistent resolutions.** ALWAYS normalize before stitching.117118### Full Pipeline Script119**Location:** `/root/clawd/projects/appie-character/launch-video/full-pipeline-v4.js`120- Handles: frame generation, video rendering, normalization, stitching, text overlays121- Run: `node full-pipeline-v4.js`122123### Scene Generation Script (individual scenes)124**Location:** `/root/clawd/projects/appie-character/launch-video/generate-scene.sh`125- Run: `./generate-scene.sh <1-6>`126127---128129## 4. Video Stitching & Compositing130131### FFmpeg Crossfade Stitch (6 scenes, 5s each)132```bash133ffmpeg -y \134 -i scene1.mp4 -i scene2.mp4 -i scene3.mp4 -i scene4.mp4 -i scene5.mp4 -i scene6.mp4 \135 -filter_complex "136 [0:v][1:v]xfade=transition=fadeblack:duration=0.5:offset=4.5[v01];137 [v01][2:v]xfade=transition=fadeblack:duration=0.5:offset=9.0[v012];138 [v012][3:v]xfade=transition=fadeblack:duration=0.5:offset=13.5[v0123];139 [v0123][4:v]xfade=transition=fadeblack:duration=0.5:offset=18.0[v01234];140 [v01234][5:v]xfade=transition=fadeblack:duration=0.5:offset=22.5[vfinal]141 " \142 -map "[vfinal]" -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p -movflags +faststart -an stitched.mp4143```144- **Duration:** ~27.5s (6x5s minus 5x0.5s overlaps)145- **Transition:** `fadeblack` with 0.5s duration146- **Quality:** CRF 18 (high quality), preset slow147148### Text Overlays149```bash150ffmpeg -y -i stitched.mp4 -vf "151 drawtext=fontfile=/root/.local/share/fonts/Hauora-Bold.otf:text='Your business runs.':fontcolor=white:fontsize=52:x=(w-text_w)/2:y=h*0.82:enable='between(t,19.0,21.5)',152 drawtext=fontfile=/root/.local/share/fonts/Hauora-Bold.otf:text='Your turn.':fontcolor=white:fontsize=68:x=(w-text_w)/2:y=h*0.76:enable='between(t,25.5,27.5)'153" -c:v libx264 -preset slow -crf 18 final.mp4154```155156### Available Fonts157- `/root/.local/share/fonts/Hauora-Bold.otf` — Primary (headings, overlays)158- `/root/.local/share/fonts/Hauora-Medium.otf` — Secondary (subtitles)159- `/root/.local/share/fonts/Hauora-Regular.otf`160- `/root/.local/share/fonts/Hauora-Light.ttf`161- `/root/.local/share/fonts/CostaStd-Bold.otf`162- `/root/.local/share/fonts/CostaStd-Regular.otf`163164### HQ Export (for sending via Telegram as document)165```bash166ffmpeg -y -i final.mp4 -c:v libx264 -preset slow -crf 16 -pix_fmt yuv420p -movflags +faststart final-hq.mp4167```168169### 🔴 Stitching Lessons1701. **Normalize ALL inputs first.** Different scenes from Kling can have different framerates/resolutions. Normalize to 1080x1920 @ 24fps before stitching.1712. **CRF 18 is the quality sweet spot.** Lower = bigger file, minimal visual gain. Higher = visible compression.1723. **Always add `-movflags +faststart`** — enables streaming playback and Telegram previews.1734. **`-an` flag** to strip audio from video-only exports (add audio separately for cleaner workflow).1745. **Text overlay timing needs manual tuning.** Use `enable='between(t,START,END)'` and `alpha` expressions for fade in/out.175176---177178## 5. Voiceover (ElevenLabs TTS)179180### API181```bash182ELEVEN_KEY=$(grep '^ELEVENLABS_API_KEY=' /root/clawd/.env.secrets | cut -d= -f2)183184curl -s "https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}" \185 -H "xi-api-key: ${ELEVEN_KEY}" \186 -H "Content-Type: application/json" \187 -d '{188 "text": "Your text here",189 "model_id": "eleven_multilingual_v2",190 "voice_settings": {191 "stability": 0.65,192 "similarity_boost": 0.75,193 "style": 0.4,194 "use_speaker_boost": true195 }196 }' -o output.mp3197```198199### Tested Voices (for Appie narrator)200201| Voice | ID | Style | Notes |202|-------|----|-------|-------|203| **Charlie** | `IKne3meq5aSn9XLyUdCD` | Deep, Confident, Energetic | Good wizard energy. Latest pick. |204| **George** | `JBFqnCBsd6RMkjVDRZzb` | Warm, Captivating Storyteller | Tested multiple times. Good but softer. |205| Adam | (OpenAI TTS, not ElevenLabs) | Clean, neutral | Mixed into vo-adam-mixed.mp3 |206| Bill | (OpenAI TTS) | Warm, older | Mixed into vo-bill-mixed.mp3 |207| Brian | (OpenAI TTS) | Professional | Mixed into vo-brian-mixed.mp3 |208209### Voice Settings Guide210- **stability:** 0.60-0.75 (lower = more expressive, higher = more consistent)211- **similarity_boost:** 0.75-0.85212- **style:** 0.3-0.6 (lower = more neutral, higher = more dramatic)213- **use_speaker_boost:** always true214215### Seyed's Preference (TBD)216- Sent Charlie and George versions for comparison217- Waiting for final voice pick218- Script v2 preferred: lead with pain, proof over story219220### 🔴 Voice Lessons2211. **Generate each VO line SEPARATELY** for precise scene-sync timing. Don't generate one big block.2222. **Line duration varies wildly.** A 5-word line can be 0.8s or 2.5s depending on pacing. Always check with `ffprobe`.2233. **"eleven_multilingual_v2"** is the best model for English narration. Don't use v1.2244. **Style parameter matters:** 0.3 for "Your turn." (calm, authoritative), 0.5 for dramatic lines.225226---227228## 6. Audio Design & Mixing229230### Music/Score231- **Existing score:** `/root/clawd/projects/appie-character/launch-video/score-cinematic-v1.mp3` (30s, cinematic)232- **Style:** Epic cinematic buildup, quiet tension to triumphant release233234### Mixing VO Lines Over Score (Precise Timing)235```bash236ffmpeg -y \237 -i line1.mp3 -i line2.mp3 -i line3.mp3 -i line4.mp3 -i line5.mp3 -i line6.mp3 \238 -i score-cinematic-v1.mp3 \239 -filter_complex "240 [0]adelay=500|500,volume=1.8[v1];241 [1]adelay=5500|5500,volume=1.8[v2];242 [2]adelay=10000|10000,volume=1.8[v3];243 [3]adelay=14500|14500,volume=1.8[v4];244 [4]adelay=19000|19000,volume=1.8[v5];245 [5]adelay=25000|25000,volume=1.8[v6];246 [6]volume=0.35[music];247 [v1][v2][v3][v4][v5][v6][music]amix=inputs=7:duration=longest:dropout_transition=2[out]248 " \249 -map "[out]" -ac 2 -ar 44100 -b:a 192k mixed.mp3250```251252### Muxing Audio onto Video253```bash254ffmpeg -y \255 -i final-hq.mp4 \256 -i mixed.mp3 \257 -t 27.75 \258 -map 0:v -map 1:a \259 -c:v copy -c:a aac -b:a 192k \260 -shortest \261 final-with-audio.mp4262```263264### Scene Timing Map (6 scenes, ~4.6s each after crossfade)265| Scene | Time | VO Delay (ms) | Line |266|-------|------|---------------|------|267| 1 - Grind | 0:00-0:04.5 | 500 | "Three AM... Another night buried in emails." |268| 2 - Spark | 0:04.5-0:09.0 | 5500 | "Until one night... something woke up." |269| 3 - Summoning | 0:09.0-0:13.5 | 10000 | "Meet Appie... Your AI employee." |270| 4 - Cleanup | 0:13.5-0:18.0 | 14500 | "Emails. Calendar. Proposals. Handled." |271| 5 - Freedom | 0:18.0-0:22.5 | 19000 | "You built your business for freedom." |272| 6 - Invite | 0:22.5-0:27.75 | 25000 | "Your turn." |273274### 🔴 Audio Lessons2751. **VO volume at 1.8x, music at 0.35x** — voice must sit clearly above music. Adjust if voice is quiet.2762. **`adelay` values are in milliseconds** and need BOTH channels specified (e.g., `adelay=5500|5500`).2773. **`amix` with `dropout_transition=2`** prevents volume drops when streams end.2784. **`-shortest` flag** when muxing to prevent audio running past video end.2795. **AAC at 192k** is the sweet spot for quality vs file size on mobile.2806. **Always trim audio to exact video duration** with `-t` flag.281282---283284## 7. Delivery via Telegram285286### Send as Document (preserves quality)287```bash288BOT_TOKEN=$(grep '^TELEGRAM_BOT_TOKEN=' /root/clawd/.env.secrets | cut -d= -f2)289CHAT_ID="1817919454" # Seyed290291curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendDocument" \292 -F "chat_id=${CHAT_ID}" \293 -F "document=@/path/to/video.mp4" \294 -F "caption=Description here"295```296297### Send as Video (compressed, in-chat preview)298```bash299curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendVideo" \300 -F "chat_id=${CHAT_ID}" \301 -F "video=@/path/to/video.mp4" \302 -F "caption=Description" \303 -F "width=1080" -F "height=1920"304```305306### Send Photo307```bash308curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendPhoto" \309 -F "chat_id=${CHAT_ID}" \310 -F "photo=@/path/to/image.png" \311 -F "caption=Description"312```313314### 🔴 Telegram Delivery Lessons3151. **ALWAYS send final videos as DOCUMENT, not video.** Telegram's video player compresses and can display 9:16 vertical as square/distorted. Document preserves the original file.3162. **Send BOTH:** Document (for quality) + Video (for quick preview) if wanted.3173. **For review/comparison:** Send individual scenes as videos (quick preview OK), final as document.3184. **Max file size:** 50MB for bots. Our finals are ~26MB, well within limit.3195. **Include width/height** when sending as video to help Telegram display correctly.3206. **Captions** have a 1024 char limit.321322---323324## 8. Whisper Transcription (Voice Messages)325326### For transcribing Seyed's voice feedback:327```bash328/root/clawd/tmp/faster-whisper/transcribe.sh /path/to/audio.ogg329```330- **Model:** large-v3 (default, best accuracy)331- **Fast mode:** `--model base` (for quick transcription when accuracy isn't critical)332- **Input:** .ogg, .mp3, .wav, .m4a333- **⚠️ large-v3 can take 30-60s to load on first run.** Use `base` model for speed when iterating.334335---336337## 9. Script Templates338339### Launch Video Script (Current)340**Location:** `/root/clawd/projects/appie-character/launch-video/PRODUCTION-BIBLE.md`341342### Talking Head Scripts343- **v1:** `/root/clawd/projects/appie-character/talking-head-script-v1.md` (story-driven, "I'm not real" hook)344- **v2:** `/root/clawd/projects/appie-character/talking-head-script-v2.md` (pain-driven, proof-first — PREFERRED)345346### Seyed's Script Preferences3471. **Lead with the pain point**, not the identity reveal3482. **Acknowledge AI openly** ("Obviously I'm not real") but as a throwaway, not the feature3493. **Proof over story:** Real numbers, real clients, real results3504. **Case studies:** Dubai Property, Seyed's own transformation (14hr days → gym mornings)3515. **CTA:** "Comment 'Minion'" (playful, on-brand wizard/minion dynamic)3526. **Tone:** No hype-bro energy. Warm, confident, direct. Like a knowledgeable friend.3537. **No corporate fluff.** Authentic, direct voice.354355---356357## 10. File Map358359### Project Root360```361/root/clawd/projects/appie-character/362├── CHARACTER-LOCK.md # Locked character spec (DO NOT MODIFY)363├── talking-head-script-v1.md # Script v1 (story hook)364├── talking-head-script-v2.md # Script v2 (pain hook — PREFERRED)365└── launch-video/366 ├── PRODUCTION-BIBLE.md # Full storyboard + specs367 ├── full-pipeline-v4.js # Complete render pipeline (Node.js)368 ├── generate-scene.sh # Individual scene generator369 ├── regen-frames-v4.js # Key frame regenerator with unified style370 ├── score-cinematic-v1.mp3 # Background music (30s)371 ├── vo-lines/ # Individual VO lines (Charlie voice)372 │ ├── line1.mp3 ... line6.mp3373 ├── vo-lines-george/ # Individual VO lines (George voice)374 ├── vo-scored-charlie-v1.mp3 # Mixed VO + score (Charlie)375 ├── vo-scored-george-v1.mp3 # Mixed VO + score (George)376 ├── 9x16-v4/ # Latest key frames (v4)377 ├── videos-v4/ # Latest rendered scenes + finals378 │ ├── scene1-6.mp4 # Individual scenes379 │ ├── final-hq.mp4 # Stitched video (no audio)380 │ ├── final-with-audio.mp4 # Charlie VO + score381 │ └── final-with-audio-george.mp4 # George VO + score382 └── renders/ # Legacy renders383```384385### Assets386```387/root/clawd/assets/388├── seyed-photos/ # Seyed's actual photos (for thumbnails/content)389│ └── seyed-closeup-resized.jpg # Best for close-ups390└── thumbnail-templates/ # HTML templates for YouTube thumbnails391```392393### Reference Images394- Approved character: `/root/clawd/tmp/appie-nb-pro-c2.png`395396---397398## 11. API Keys Summary399400| Service | Key Name in .env.secrets | Used For |401|---------|--------------------------|----------|402| Gemini (image gen) | `NANO_BANANA_API_KEY` | Character images, key frames |403| fal.ai (video gen) | `FAL_KEY` | Kling video, Flux images |404| ElevenLabs (TTS) | `ELEVENLABS_API_KEY` | Voiceovers |405| Telegram Bot | `TELEGRAM_BOT_TOKEN` | Sending files to Seyed |406407---408409## 12. Complete Production Workflow (Checklist)410411### Phase 1: Key Frames412- [ ] Write scene descriptions in PRODUCTION-BIBLE.md413- [ ] Generate key frames with Gemini 3 Pro Image414- [ ] Include FULL character spec + vertical composition rules in every prompt415- [ ] Review, iterate (expect 3-5 versions per frame)416- [ ] Get Seyed's approval on all frames417418### Phase 2: Animation419- [ ] Render each scene via Kling 2.1 Pro (fal.ai)420- [ ] Write animation prompts describing MOTION specifically421- [ ] Normalize all outputs to 1080x1920 @ 24fps422- [ ] Review each scene individually423424### Phase 3: Stitch & Overlay425- [ ] Stitch with crossfade transitions (0.5s)426- [ ] Add text overlays with precise timing427- [ ] Export HQ version (CRF 16-18)428429### Phase 4: Audio430- [ ] Write VO script (short punchy lines, one per scene)431- [ ] Generate each line separately via ElevenLabs432- [ ] Check each line's duration with ffprobe433- [ ] Mix VO lines at precise timestamps over score434- [ ] Set VO volume ~1.8x, music ~0.35x435- [ ] Mux audio onto video436437### Phase 5: Delivery438- [ ] Send as Telegram DOCUMENT (not video!) for quality439- [ ] Send comparison versions if testing voices/edits440- [ ] Wait for Seyed's feedback before finalizing441442---443444## 13. Known Issues & Gotchas4454461. **Telegram squishes 9:16 video** — always send as document for review4472. **Kling returns inconsistent resolutions** — always normalize before stitching4483. **Whisper large-v3 is slow to cold-start** — use `base` for quick transcription4494. **Gemini 3 Pro sometimes generates grey/silver beards** — always specify "BLACK beard, NOT grey"4505. **fal.ai queue can back up** — during peak times, expect 5-10 min per scene instead of 2-54516. **ffmpeg `amix` reduces volume** when streams overlap — use `volume` filter to compensate4527. **GitHub tokens on both Appie-2 and Appie-3 are EXPIRED** — need new PAT from Seyed4538. **Text overlay escaping in ffmpeg** — backslash-escape commas and colons in drawtext4549. **`-shortest` flag is essential** when muxing — prevents audio overrun45510. **CTA text changed:** Was "Comment AI Magic" → now "Comment MINION" (per script v2)