Communitygithub.com

vertical-reels-video-studio-pro

Full production recipe for narrated vertical (9:16) educational/explainer Reels for Instagram, Threads and TikTok with Remotion + ElevenLabs: brand config, fact-checked draft with hook options, voiceover with pronunciation map, word-timed kinetic motion, optional lip-synced presenter, Reels-safe export, mandatory QA, 4 cover options and platform captions. Use for any narrated edu or explainer Reel once the basic skill is not enough.

What is vertical-reels-video-studio-pro?

vertical-reels-video-studio-pro is a Claude Code agent skill that full production recipe for narrated vertical (9:16) educational/explainer Reels for Instagram, Threads and TikTok with Remotion + ElevenLabs: brand config, fact-checked draft with hook options, voiceover with pronunciation map, word-timed kinetic motion, optional lip-synced presenter, Reels-safe export, mandatory QA, 4 cover options and platform captions. Use for any narrated edu or explainer Reel once the basic skill is not enough.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ahmadaryanto/vertical-reels-video-studio/tree/HEAD/skills/vertical-reels-video-studio-pro

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Vertical Reels Video Studio (pro)

End-to-end: (first run: ask for the user's handles/watermark/CTA/voice) → topic → research → draft → approval → voiceover → timing → Remotion scenes → render → Reels export → QA → covers + captions → deliver. This is the fuller version of vertical-reels-video-studio (basic). The brand config lives in brand.config.json (read by src/brand.ts and passed to compositions as the brand prop).

0a. First run: ask the user for THEIR settings (never use defaults)

Before the first video, if brand.config.json is missing, has "configured": false, or still contains @yourhandle, ask the user (one question at a time) and save the answers in brand.config.json:

  1. Social handles: Instagram, Threads, TikTok, X (whichever they use).
  2. Watermark text (exactly as it should appear, e.g. @yourhandle or @ig / @x) and position (bottom-center, bottom-left, top-left, top-right).
  3. CTA text and the handle it mentions.
  4. Voice: their ElevenLabs voice id + model + language, or "I'll record my own voice". The API key is requested only as the ELEVENLABS_API_KEY secret.
  5. Language and tone; how the voice should say their name/handle.

Then set "configured": true. Never invent a handle, never reuse someone else's (including the author of this kit), and never render a watermark that still says @yourhandle.

0b. Brand config (brand.config.json, filled from the user's answers)

KeyPlaceholderNotes
Handles{{IG_HANDLE}}, {{THREADS_HANDLE}}, {{TIKTOK_HANDLE}}, {{X_HANDLE}}handles.*, the user's own
Watermark{{WATERMARK}} + positionwatermark.text / watermark.position, exact text the user gave; never hard-code in scenes
Language / tone{{LANGUAGE}}, {{TONE}}e.g. casual Indonesian gua/lu, sparse emoji
Spoken name{{SPOKEN_NAME}}How the voice says your handle (e.g. "Jane Doe" for @janedoe_). Captions still show the real handle
Disclaimer{{DISCLAIMER}}For finance topics, e.g. "Education, not financial advice"
Voice{{VOICE_ID}}, {{TTS_MODEL}}, {{LANGUAGE_CODE}}voice.*, the user's choice (or their own recording)
API keyenv ELEVENLABS_API_KEYNever print, log or commit it
CTA{{CTA}}, {{CTA_HANDLE}}cta.text / cta.handle, asked from the user (e.g. "Follow {{CTA_HANDLE}} for more", "Comment TUTORIAL")
Hard rules{{HARD_RULES}}Brands never to mock, names to blur, words never to say
Render device{{RENDER_DEVICE}}GPU machine or CPU. Always report which one was actually used

1. Research and draft (no audio, no render)

  1. Fact-check every claim with primary sources: official docs/PRs, the author's own post, registries, dated screenshots. Exec posts count as official statements. Label estimates (ESTIMATE · not official) and allegations (ALLEGED). Drop what you cannot verify instead of softening it.
  2. One story per video, everyday words, slow pace. Hard product names go on screen, not in the voiceover.
  3. Offer 2–4 hook options (H1, H2, …): a why/how question or a bold contrast. Let the user pick.
  4. Timed table: time | on-screen | VO. Target 45–65 s, hard max 90 s (aim ≤ 88 s so a revision still fits).
  5. Write factcheck.md (claim → source → status) and sources.md.
  6. Send the draft and wait for approval. "Don't render" from the user is final until they say go.

2. Voiceover (ElevenLabs)

  • Two scripts: script-display.txt (what captions show) and script-tts.txt (spelled for the voice). Keep a display↔TTS map.
  • Pronunciation (see docs/VOICEOVER.md): A.I. with dots so it sounds English; tickers letter by letter in non-English VO (ETH → E, T, H); numbers as words; English terms in plain English spelling (no hyphen respellings); a comma after a final /t/ before a vowel; brand names respelled only when tests prove it helps.
  • Post-process atempo 1.05 (1.1 for fast content). Loudness −14 LUFS integrated, ≤ −1 dBTP.
  • No duplicate lines. If a line repeats the hook or an earlier beat, cut or reword it.
  • Check the character quota first. Re-voice only failing lines (pass previous_text for continuity).

3. Timing

  • Word timestamps from the TTS alignment (divide by the tempo factor) or faster-whisper → timing.json {duration, phrases:[{s,e,words:[{w,s,e}]}], scenes:[{id,start}]} (scripts/build-timing.py).
  • Merge respelled tokens back to display words (A.I.→AI, E, T, H→ETH) or captions start late.
  • Scenes key off spoken words: wt(scene, word) → frame where that word starts.

4. Motion style (Remotion, 1080x1920, 30 fps)

Look: base #0A1016, cream #EFE6D2, amber #FFB000, red #E2553F, green #7BD88F. Fonts via @remotion/google-fonts: Big Shoulders 800 (headlines), Plus Jakarta Sans (body/captions), JetBrains Mono (chips/code). Layout: important content y 200–1500. Footer cluster: karaoke captions ~y 1310–1353, watermark (if the user chose bottom) ~y 1427–1446, progress ~y 1474, all left of x 960 (Reels draws its buttons on the right). No empty frames: the hook is readable at frame 0; the opening and the ending are as full as the middle (a hero image, the presenter, a chip), never a lone line on a blank background.

Easing helpers (src/motion/ease.ts):

const clamp01=(x:number)=>Math.max(0,Math.min(1,x));
const P=(t:number,a:number,b:number)=>clamp01((t-a)/(b-a));
const eOut=(x:number)=>1-Math.pow(1-x,3);
const eIn=(x:number)=>x*x*x;
const backOut=(x:number,s=1.70158)=>1+(s+1)*Math.pow(x-1,3)+s*Math.pow(x-1,2);
const sec=(f:number,at:number)=>(f-at)/30;
const ap=(f:number,at:number,d=0.3)=>eOut(P(sec(f,at),0,d));
const pop=(f:number,at:number)=>Math.max(0,backOut(P(sec(f,at),0,0.35),2.2));
const punch=(f:number,at:number)=>{const t=sec(f,at);if(t<0)return 1;return 1+0.12*eOut(P(t,0,0.2))-0.06*eOut(P(t,0.2,2.5));};
const shake=(f:number,at:number)=>{const t=sec(f,at);return t<0||t>0.4?0:14*Math.exp(-t*10)*Math.sin(t*70);};

Moves: kinetic type (word lands on its VO time, scale(0.6+0.4*pop), ±4° settling over 0.25 s, stressed words bigger + amber/red), zoom punch on key images, circle-mask reveal, zoom-through transitions (scale 1→4.2 over ~9 frames, next scene 1.3→1), rotated stamps and mono chips, red highlight boxes on screenshots, step counter, karaoke captions (current word amber + 1.08×), CTA pop with shake, whoosh/pop SFX under the VO. About one beat every 1.5–3 s.

Video clips: wrap every <OffthreadVideo> in a <Sequence from={at}> and set startFrom relative to it; otherwise the clip clamps to its last frame and looks frozen. Loop short clips for long beats. Clips start on the first usable frame.

Audio transitions: when an opening uses live audio (a song, a clip) before the narration, fade it to silence and leave ~0.3–0.5 s (a flash/whoosh transition) before the first VO word so it is never masked.

Optional presenter (mascot) with lip sync

  • One consistent character identity across every video. Separate layers: body (closed mouth painted out), arm on a shoulder pivot under the coat edge, a static shoulder cap, mouth sprites closed/half/open/wide/round.
  • Drive the mouth from the VO wav, not a loop: scripts/build-mouth-track.py → per-frame states (closed in silence and end hold, 2-frame minimum hold). Clamp the arm to the rig's range; a whole-image bob alone is not enough.
  • Mount the presenter only while on screen; covers use the static closed-mouth body.

5. Render

  • Prefer a GPU machine if you have one (Remotion --hardware-acceleration, a config without encodingBufferSize/encodingMaxRate, which break required NVENC); fall back to CPU only if allowed. Always say which device rendered.
  • Raw render: yuv420p + bt709 in remotion.config.ts, then the Reels pass.

6. Reels-safe export (scripts/reels-export.sh, details in docs/REELS_SAFE_EXPORT.md)

1080x1920 SAR 1, H.264 High level 4.1, yuv420p TV range, BT.709 tags, CFR 30, GOP 60 closed, 10 Mbps (min 8, max 12), two-pass loudnorm −14 LUFS / −1.5 dBTP, AAC 192k 48 kHz stereo, +faststart, < 90 s. Also a small preview < 40 MB (scripts/make-preview.sh).

7. QA (mandatory, before delivery)

  • Whisper the final MP4 (scripts/whisper-check.py): wrong pronunciations, stutters, stray sounds, duplicate lines, first word of every scene audible.
  • Contact sheet at every scene boundary (scripts/contact-sheet.sh): glitches, overlaps, cut-off text, safe zone, frozen clips, empty opening/ending, watermark present, matching brand.config.json and spelled exactly.
  • scripts/qa-check.sh: codec/profile/level, pix_fmt, range, colour tags, CFR, AAC 48k, moov before mdat, duration < 90 s, −14 LUFS.
  • Fix and re-render. Keep the previous version when you revise.

8. Always deliver with the video

  1. Captions for IG (hook, body, CTA, light hashtags), Threads (shorter, no hashtags), TikTok, plus an .srt.
  2. Four covers A–D: 1080x1920 + 1080x1350 grid, key text inside the centre 1080x1080; one hook, one main photo, max 2–3 number cards; contact sheet + let the user pick.
  3. Source credits and the fact-check file.
  4. A line in videos-log.md: title, files, duration, loudness, device, sources, status "not posted".

Rules

  • Never post, DM, upload or buy. Deliver files.
  • No fabricated facts, stars, prices or results. Credit open-source authors on screen.
  • Real photos, logos and clips only; no AI-generated faces of real people. Mark mock-ups illustration.
  • Use media you have rights to; tell the user when music or clips are copyrighted (mute/claim risk).
  • No secrets in files. Ask any question last, in its own message.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Related Skills