A Remotion-based tool for generating ad videos for TravelAnimator. It composes hook videos with animated text overlays, app demo footage, outro sequences, and background music into ready-to-publish ads — with multilanguage support and batch rendering.
Each ad is a three-part video composition:
[ Hook Section ] --> [ Base Video Section ] --> [ Outro Section ]
hook video app demo video closing animation
+ text overlay (EN or SP version)
+ custom font
|----- background music with fade-in/fade-out loops across all sections -----|
- Hook Section — A short attention-grabbing video (3-10s) with a bold animated text overlay (e.g., "This app changed everything"). The text pops in with a scale + fade animation.
- Base Video Section — A longer app demo video showing TravelAnimator in action. Two variants available (
video1at ~30s,video2at ~43s), each with English and Spanish versions. - Outro Section — A ~3s branded closing animation.
- Background Music — Loops across all sections with a smooth 15-frame fade-in and 30-frame fade-out. 130+ royalty-free tracks available across 15 mood categories.
jishnu-marketing-ai/
├── src/
│ ├── index.ts # Entry point — registers Remotion root
│ ├── Root.tsx # Composition registry, auto-save, metadata calculation
│ ├── schemas/
│ │ └── ugc-ad-schema.ts # Zod schema — all customizable props
│ ├── config/
│ │ ├── fonts.ts # 12 Google Fonts + 1 custom font (ValicorePro)
│ │ ├── hooks.ts # Hook video catalog (from hooks-catalog.json)
│ │ ├── hook-texts.ts # EN + SP hook text arrays, language lookup
│ │ ├── music-tracks.ts # Music catalog (from music-catalog.json)
│ │ └── video-durations.ts # Hardcoded frame counts for base/outro videos
│ └── components/
│ ├── UGCAdComposition.tsx # Main composition — assembles all three sections
│ ├── HookSection.tsx # Hook video + animated text overlay
│ ├── BaseVideoSection.tsx # App demo video (handles two layout modes)
│ └── OutroSection.tsx # Closing animation
├── scripts/
│ ├── start-dev.js # Starts dashboard + Remotion Studio together
│ ├── dashboard.js # Web UI for render management (port 4000)
│ ├── render-all.js # Batch render all compositions (supports --lang)
│ ├── generate-hooks-catalog.js # Scans public/hooks/ → hooks-catalog.json
│ ├── generate-music-catalog.js # Scans music library → music-catalog.json
│ └── download-music.js # Downloads NCS tracks (optional)
├── public/
│ ├── hooks/ # Hook video files (.mp4) — auto-detected
│ ├── travelanimator/ # Base videos (EN + SP) and outro
│ ├── fonts/ # Custom font files (Valicore Pro.ttf)
│ ├── music/ # Downloaded NCS tracks
│ ├── travel_music_library/ # 130+ tracks across 15 categories
│ ├── hook-texts.json # 140 English hook texts
│ ├── hook-texts-sp.json # 140 Spanish hook texts
│ ├── hooks-catalog.json # Auto-generated hook metadata
│ └── music-catalog.json # Auto-generated music metadata
├── out/ # Rendered output videos
│ ├── en/ # English renders
│ └── sp/ # Spanish renders
├── package.json
├── tsconfig.json
└── remotion.config.ts
- Node.js (v18+)
- ffmpeg and ffprobe installed and available in PATH (required by Remotion for rendering and by the catalog generators for duration detection)
npm installThe hook and music catalogs are auto-generated from the files in public/. Run this once after cloning, or after adding/removing assets:
npm run scan-hooks # Generates public/hooks-catalog.json
node scripts/generate-music-catalog.js # Generates public/music-catalog.jsonThese are also auto-regenerated when you run npm run dev or npm run render:all.
npm run devThis starts two things:
- Remotion Studio at
http://localhost:3000— visual editor where you preview compositions, adjust props (language, hook, text, font, music, volumes), and render individual videos. - Dashboard at
http://localhost:4000— a simple web UI for batch rendering and monitoring.
The dashboard also watches public/hooks/ for changes. Drop a new .mp4 file in there and the hooks catalog auto-regenerates within 2 seconds.
| Prop | Type | Default | Description |
|---|---|---|---|
language |
"en" | "sp" |
"en" |
Language — controls base video and auto-translates hook text |
hookChoice |
enum | "hook1" |
Which hook video to use |
hookText |
enum (140 options) | First text | Text overlay on the hook (dropdown shows EN; auto-translated when SP) |
hookTextCustom |
string | "" |
Custom text override (takes priority over hookText) |
hookFontFamily |
enum (13 fonts) | "ValicorePro" |
Font for the hook text overlay |
hookFontSize |
20–160 | 68 |
Font size in pixels |
hookTextUppercase |
boolean | true |
Whether to uppercase the text |
baseVideoChoice |
"video1" | "video2" | "random" |
"random" |
Which app demo video to use |
musicTrack |
enum (130+ tracks) | First track | Background music selection |
musicVolume |
0–1 | 0.15 |
Background music volume |
hookVolume |
0–1 | 0 |
Hook video audio volume |
baseVideoVolume |
0–1 | 0 |
Base video audio volume |
outroVolume |
0–1 | 1 |
Outro video audio volume |
hookDurationSec |
-1–10 | -1 |
Hook duration override (-1 = use source video length) |
Props are auto-saved to localStorage and restored on reload.
Render all hook compositions at once:
npm run render:all # Renders English (default)
npm run render:all:en # Renders English explicitly
npm run render:all:sp # Renders SpanishOr use the dashboard at http://localhost:4000 — select a language from the dropdown and click "Render All Compositions".
Output structure:
out/
├── en/
│ ├── ugc-ad-hook1-en.mp4
│ ├── ugc-ad-hook2-en.mp4
│ └── ...
└── sp/
├── ugc-ad-hook1-sp.mp4
├── ugc-ad-hook2-sp.mp4
└── ...
Each render cycles through the language-specific hook texts, assigning one per hook video.
npm run render
# Renders: UGCAd-hook1 → out/ugc-ad.mp4
# Or render a specific composition:
npx remotion render src/index.ts UGCAd-hook3 out/my-ad.mp4The project supports English (en) and Spanish (sp). The language setting controls two things:
-
Base video — Selects the localized app demo:
en→usingapp-video1.mp4/usingapp-video2.mp4sp→usingapp-video1-sp.mp4/usingapp-video2-sp.mp4
-
Hook text — The dropdown always shows English texts. When language is set to
sp, the selected text is automatically mapped to its Spanish translation by index (the EN and SP text files have 1:1 matching translations). ThehookTextCustomfield can always be used to type any text in any language.
Hook videos and the outro are shared across languages.
- Create
public/hook-texts-{code}.jsonwith translated hook texts (same order as the English file). - Add localized base videos:
public/travelanimator/usingapp-video1-{code}.mp4andusingapp-video2-{code}.mp4. - Add
"{code}"toLANGUAGE_OPTIONSinsrc/schemas/ugc-ad-schema.ts. - Import the new text file in
src/config/hook-texts.tsand add it toHOOK_TEXTS_BY_LANG. - Add
"{code}"to theVALID_LANGSarray inscripts/render-all.js. - Add a
<option>to the language selector inscripts/dashboard.js.
Drop any .mp4 file into public/hooks/. If the dev server is running, the catalog regenerates automatically. Otherwise run:
npm run scan-hooksEach hook video gets its own Remotion composition (UGCAd-{filename}), appears in the Studio dropdown, and is included in batch renders.
The public/travel_music_library/ directory contains 130+ royalty-free tracks organized by mood:
| Category | Tracks | Vibe |
|---|---|---|
| background_atmospheric | 8 | Ambient, eerie |
| chill_loops | 8 | Relaxing, game-style |
| cinematic_atmospheric | 11 | Dark, sci-fi |
| cinematic_epic | 9 | Action, uplifting |
| cinematic_sfx | 9 | Sound effects, impacts |
| drums_stingers | 8 | Percussion, stabs |
| electronic_atmosphere | 9 | Synth, electronic |
| experimental | 8 | Abstract |
| loopable_pads | 9 | Pads, synth loops |
| nature_ambience | 9 | Nature, forest |
| nature_background | 8 | Location ambience |
| space_ambient | 9 | Space, cyberpunk |
| synth_ambient | 10 | Synthesizer pads |
| water_soundscape | 10 | Rain, ocean, streams |
| wind_nature | 6 | Wind, weather |
To add tracks, drop .mp3 files into any category folder and run:
node scripts/generate-music-catalog.jsAnton, Bangers, Bebas Neue, Black Han Sans, Luckiest Guy, Montserrat, Oswald, Pacifico, Permanent Marker, Poppins, Inter, Rubik Mono One, Valicore Pro (custom).
| Script | Description |
|---|---|
npm run dev |
Start Remotion Studio (3000) + Dashboard (4000) |
npm run render |
Render a single composition (UGCAd-hook1) |
npm run render:all |
Batch render all hooks (English by default) |
npm run render:all:en |
Batch render all hooks in English |
npm run render:all:sp |
Batch render all hooks in Spanish |
npm run build |
Bundle for production deployment |
npm run dashboard |
Start the render dashboard only |
npm run scan-hooks |
Regenerate hooks-catalog.json from public/hooks/ |
npm run download-music |
Download NCS tracks to public/music/ |
- Remotion 4.0 — Programmatic video creation with React
- React 19 — Component-based video composition
- TypeScript 5.9 — Type safety across the project
- Zod 4.3 — Schema validation for composition props
- FFprobe — Video duration detection for catalog generation