From 1627ad3920affabfd1f1f86adbcc1f0c7fb9bf30 Mon Sep 17 00:00:00 2001 From: Michailbul Date: Fri, 23 Jan 2026 02:13:18 +0300 Subject: [PATCH 1/5] docs(agent): add confirmation-first execution guidance --- README.md | 10 +++++++++- docs/react.md | 8 ++++++++ docs/sdk.md | 10 ++++++++++ skills/varg-video-generation/SKILL.md | 19 +++++++++++++++++-- src/init.ts | 23 ++++++++++++++--------- 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 675fcaaf..830a310d 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,15 @@ run it: bun run hello.tsx ``` +## agent usage (confirmation before costs) + +when using the agent in this repo: + +- ask for confirmation before any command that triggers paid api calls +- create tsx when needed, then run: `bun run src/cli/index.ts render -o output/.mp4` +- use `bun run src/cli/index.ts preview ` for zero-cost checks +- use single-step actions with: `bun run src/cli/index.ts run ...` + ## installation ```bash @@ -534,4 +543,3 @@ see [CONTRIBUTING.md](CONTRIBUTING.md) for development setup. Apache-2.0 — see [LICENSE.md](LICENSE.md) - diff --git a/docs/react.md b/docs/react.md index 96dcc2a0..2817f003 100644 --- a/docs/react.md +++ b/docs/react.md @@ -22,6 +22,14 @@ await render( ); ``` +## agent execution (confirmation before costs) + +when using the agent in this repo: + +- ask for confirmation before any command that triggers paid api calls +- create tsx when needed, then run `bun run src/cli/index.ts render -o output/.mp4` +- use `bun run src/cli/index.ts preview ` for zero-cost checks + ## core concepts ### everything is cached diff --git a/docs/sdk.md b/docs/sdk.md index 2b3de16b..82f6d571 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -39,6 +39,16 @@ const { video } = await generateVideo({ }); ``` +## agent execution (confirmation before costs) + +when using the agent in this repo: + +- ask for confirmation before any command that triggers paid api calls +- prefer cli execution for outputs: + - `bun run src/cli/index.ts run ...` + - `bun run src/cli/index.ts render -o output/.mp4` + - `bun run src/cli/index.ts preview ` for zero-cost checks + --- ## core concepts diff --git a/skills/varg-video-generation/SKILL.md b/skills/varg-video-generation/SKILL.md index 80c23ca0..d5e1afff 100644 --- a/skills/varg-video-generation/SKILL.md +++ b/skills/varg-video-generation/SKILL.md @@ -1,6 +1,6 @@ --- name: varg-video-generation -description: Generate AI videos using varg SDK React engine. Use when creating videos, animations, talking characters, slideshows, or social media content. Always run onboarding first to check API keys. +description: This skill should be used when the user asks to "create a video", "generate a video", "render a tsx", "make a slideshow", "create a talking character", or "animate an image" using the varg React engine. license: MIT metadata: author: vargHQ @@ -13,6 +13,14 @@ allowed-tools: Bash(bun:*) Bash(cat:*) Read Write Edit Generate AI videos using declarative JSX syntax with automatic caching and parallel generation. +## Execution policy (must follow) + +- Ask for confirmation before running any command that triggers paid API calls. +- Proceed without extra confirmation only when the user explicitly asks to run/render/generate now. +- Prefer CLI execution after creating TSX; do not leave TSX files unrun. +- Prefer `preview` for zero-cost checks before paid renders. +- Write outputs to `output/` and do not commit new outputs. + ## Quick Setup Run the setup script to initialize a project: @@ -21,7 +29,7 @@ Run the setup script to initialize a project: bun scripts/setup.ts ``` -Or manually check API keys: +Or check API keys directly: ```bash cat .env 2>/dev/null | grep -E "^(FAL_API_KEY|ELEVENLABS_API_KEY)=" || echo "No API keys found" @@ -142,6 +150,13 @@ See [references/templates.md](references/templates.md) for more templates. ## Running Videos ```bash +# preferred: render via CLI after creating TSX +bun run src/cli/index.ts render your-video.tsx -o output/your-video.mp4 + +# optional: fast, zero-cost preview +bun run src/cli/index.ts preview your-video.tsx + +# direct execution (acceptable but less consistent) bun run your-video.tsx ``` diff --git a/src/init.ts b/src/init.ts index 3de40678..026f2efd 100644 --- a/src/init.ts +++ b/src/init.ts @@ -238,11 +238,12 @@ const character = Image({ prompt: "blue robot" }); `; // Example video file -const EXAMPLE_VIDEO = `/** +const EXAMPLE_VIDEO = `/** @jsxImportSource vargai */ +/** * Example: Simple animated video * Run: bun run examples/my-first-video.tsx */ -import { render, Render, Clip, Image, Animate } from "vargai/react"; +import { render, Render, Clip, Image, Video } from "vargai/react"; import { fal } from "vargai/ai"; async function main() { @@ -251,13 +252,17 @@ async function main() { await render( - From 611f6c009ad1a00c5212d518a0ddc3f72878a87b Mon Sep 17 00:00:00 2001 From: Michailbul Date: Fri, 23 Jan 2026 02:07:09 +0300 Subject: [PATCH 2/5] chore(gitignore): ignore cache and output --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8cfcecdc..86b509f5 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ lib output *.mp4 + +.cache/ +output/ From 89f76e271a4039481760ee3296cbd1cc3208cd29 Mon Sep 17 00:00:00 2001 From: Michailbul Date: Fri, 23 Jan 2026 02:05:49 +0300 Subject: [PATCH 3/5] feat(init): install pipeline cookbook skill --- SKILLS.md | 172 +---- skills/vargai-pipeline-cookbooks/SKILL.md | 29 + .../references/remotion-video.md | 585 +++++++++++++++ .../references/round-video-character.md | 337 +++++++++ .../references/talking-character-pipeline.md | 285 ++++++++ .../references/talking-character.md | 59 ++ .../references/text-to-tiktok.md | 669 ++++++++++++++++++ .../references/trendwatching.md | 156 ++++ .../scripts/animate-frames-parallel.ts | 84 +++ .../scripts/combine-scenes.sh | 53 ++ .../scripts/generate-frames-parallel.ts | 99 +++ .../scripts/still-to-video.sh | 37 + src/init.ts | 272 +++---- 13 files changed, 2491 insertions(+), 346 deletions(-) create mode 100644 skills/vargai-pipeline-cookbooks/SKILL.md create mode 100644 skills/vargai-pipeline-cookbooks/references/remotion-video.md create mode 100644 skills/vargai-pipeline-cookbooks/references/round-video-character.md create mode 100644 skills/vargai-pipeline-cookbooks/references/talking-character-pipeline.md create mode 100644 skills/vargai-pipeline-cookbooks/references/talking-character.md create mode 100644 skills/vargai-pipeline-cookbooks/references/text-to-tiktok.md create mode 100644 skills/vargai-pipeline-cookbooks/references/trendwatching.md create mode 100644 skills/vargai-pipeline-cookbooks/scripts/animate-frames-parallel.ts create mode 100755 skills/vargai-pipeline-cookbooks/scripts/combine-scenes.sh create mode 100644 skills/vargai-pipeline-cookbooks/scripts/generate-frames-parallel.ts create mode 100755 skills/vargai-pipeline-cookbooks/scripts/still-to-video.sh diff --git a/SKILLS.md b/SKILLS.md index 223dee56..33eb6bdd 100644 --- a/SKILLS.md +++ b/SKILLS.md @@ -1,173 +1,39 @@ # agent skills -this sdk includes claude code agent skills for each service. each skill is co-located with its service code. +this repo exposes a small set of claude code skills plus a cli. use skills for guidance and run the cli to produce outputs. ## available skills -### service skills +1. **varg-video-generation** (`skills/varg-video-generation/`) + - generate videos with the react engine + - agent should create tsx if needed, then run a render after confirmation + - cli: `bun run src/cli/index.ts render [-o output.mp4]` + - preview: `bun run src/cli/index.ts preview ` -located in `service//SKILL.md`: +2. **vargai-pipeline-cookbooks** (`skills/vargai-pipeline-cookbooks/`) + - end-to-end workflows (talking character, text-to-tiktok, round selfie, trendwatching, remotion) + - source cookbooks in `pipeline/cookbooks/` -1. **image-generation** (`service/image/`) - - generate ai images using fal (flux models) or higgsfield soul characters - - cli: `bun run service/image fal|soul [options]` +## agent execution policy (important) -2. **video-generation** (`service/video/`) - - generate videos from images (local or url) or text prompts using fal.ai - - supports local image files - automatically uploads to fal storage - - cli: `bun run service/video from_image|from_text ` +- ask for confirmation before running any command that triggers paid api calls +- if the user explicitly says "run/render/generate now," proceed without extra confirmation +- prefer cli execution over leaving tsx files unrun +- write outputs to `output/` and do not commit new outputs -3. **voice-synthesis** (`service/voice/`) - - generate realistic text-to-speech audio using elevenlabs - - cli: `bun run service/voice generate|elevenlabs [options]` +## cli actions (non-skill) -3b. **music-generation** (`lib/elevenlabs.ts`) - - generate music from text prompts using elevenlabs - - generate sound effects from descriptions - - cli: `bun run lib/elevenlabs.ts music|sfx [options]` - -4. **video-lipsync** (`service/sync/`) - - sync video with audio using wav2lip or simple overlay - - cli: `bun run service/sync sync|wav2lip|overlay ` - -5. **video-captions** (`service/captions/`) - - add auto-generated or custom subtitles to videos - - cli: `bun run service/captions [options]` - -6. **video-editing** (`service/edit/`) - - edit videos with ffmpeg (resize, trim, concat, social media prep) - - cli: `bun run service/edit social|montage|trim|resize|merge_audio ` - -7. **audio-transcription** (`service/transcribe/`) - - transcribe audio to text or subtitles using groq/fireworks - - cli: `bun run service/transcribe [outputPath]` - -### library skills - -8. **apify-scraping** (`lib/apify.ts`) - - run apify actors for web scraping (tiktok, google maps, social media, etc.) - - cli: `bun run lib/apify.ts run [input_json]` - - example: `bun run lib/apify.ts run clockworks/tiktok-scraper '{"hashtags":["viral"],"resultsPerPage":10}'` - -### utility skills - -9. **telegram-send** (external: `/Users/aleks/Github/Badaboom1995/rumble-b2c`) - - send videos to telegram users/channels as round videos - - automatically converts to 512x512 square format for telegram - - cli: `cd /Users/aleks/Github/Badaboom1995/rumble-b2c && bun run scripts/telegram-send-video.ts <@username>` - - example: `cd /Users/aleks/Github/Badaboom1995/rumble-b2c && bun run scripts/telegram-send-video.ts /path/to/video.mp4 @caffeinum` - -### pipeline skills - -located in `pipeline/cookbooks/SKILL.md`: - -10. **talking-character-pipeline** (`pipeline/cookbooks/`) - - complete workflow to create talking character videos - - combines: character generation → voiceover → animation → lipsync → captions → social prep - -11. **round-video-character** (`pipeline/cookbooks/round-video-character.md`) - - create realistic round selfie videos for telegram using nano banana pro + wan 2.5 - - workflow: generate selfie first frame (person in setting) → voiceover → wan 2.5 video - - uses: `bun run lib/fal.ts`, `bun run lib/replicate.ts`, `bun run lib/elevenlabs.ts` - - input: text script + profile photo - - output: extreme close-up selfie video with authentic camera shake, lighting, and audio - -12. **trendwatching** (`pipeline/cookbooks/trendwatching.md`) - - discover viral tiktok content for any topic/hashtag - - uses apify tiktok scraper to find trending videos - - get engagement metrics: plays, likes, shares, comments - - cli: `bun run lib/apify.ts run clockworks/tiktok-scraper '{"hashtags":["topic"],"resultsPerPage":10}'` - -## structure - -each skill follows this pattern: - -``` -service// -├── index.ts # service implementation -└── SKILL.md # claude code agent skill -``` - -## how skills work - -skills are **model-invoked** - claude autonomously decides when to use them based on your request and the skill's description. - -**example:** -- you say: "create a talking character video" -- claude reads `talking-character-pipeline` skill -- claude executes the workflow using the pipeline steps - -## using skills - -### in claude code - -skills are automatically discovered when you're in the sdk directory: - -``` -user: create an image of a sunset -claude: [uses image-generation skill] - bun run service/image fal "beautiful sunset over mountains" -``` - -### manually - -you can also run services directly: +use `varg run` for single-step actions: ```bash -# generate image -bun run service/image fal "sunset over mountains" true - -# generate video from that image -bun run service/video from_image "camera pan" https://image-url.jpg 5 true - -# add voice -bun run service/voice elevenlabs "this is a beautiful sunset" rachel true - -# sync with video -bun run service/sync wav2lip https://video-url.mp4 https://audio-url.mp3 +bun run src/cli/index.ts run image|video|voice|music|transcribe|captions|sync|upload|edit --help ``` -## skill features - -each skill includes: - -- **name**: unique skill identifier -- **description**: when claude should use this skill -- **allowed-tools**: restricted to Read, Bash for safety -- **usage examples**: cli and programmatic examples -- **when to use**: specific use cases -- **tips**: best practices -- **environment variables**: required api keys - -## benefits - -- **discoverability**: claude knows all available services -- **context**: skills provide usage examples and best practices -- **safety**: `allowed-tools` limits to read-only and bash execution -- **documentation**: skills serve as living documentation - -## skill reference - -| skill | service | primary use case | -|-------|---------|------------------| -| image-generation | image | create ai images, character headshots | -| video-generation | video | animate images, generate video clips | -| voice-synthesis | voice | text-to-speech, voiceovers | -| music-generation | elevenlabs | generate music, create sound effects | -| video-lipsync | sync | sync audio with video, talking characters | -| video-captions | captions | add subtitles, accessibility | -| video-editing | edit | resize, trim, social media optimization | -| audio-transcription | transcribe | speech-to-text, subtitle generation | -| apify-scraping | lib/apify | web scraping via apify actors (tiktok, etc.) | -| telegram-send | external | send videos to telegram as round videos | -| talking-character-pipeline | pipeline | end-to-end talking character videos | -| round-video-character | pipeline | telegram round selfie videos with wan 2.5 | -| trendwatching | pipeline | discover viral tiktok content by hashtag | - ## see also - [README.md](README.md) - sdk overview and installation -- [STRUCTURE.md](STRUCTURE.md) - detailed module organization +- [docs/react.md](docs/react.md) - jsx rendering +- [docs/sdk.md](docs/sdk.md) - ai sdk usage - [pipeline/cookbooks/talking-character.md](pipeline/cookbooks/talking-character.md) - talking character workflow - [pipeline/cookbooks/round-video-character.md](pipeline/cookbooks/round-video-character.md) - telegram round selfie video cookbook - [pipeline/cookbooks/trendwatching.md](pipeline/cookbooks/trendwatching.md) - discover viral tiktok content diff --git a/skills/vargai-pipeline-cookbooks/SKILL.md b/skills/vargai-pipeline-cookbooks/SKILL.md new file mode 100644 index 00000000..0ab265cc --- /dev/null +++ b/skills/vargai-pipeline-cookbooks/SKILL.md @@ -0,0 +1,29 @@ +--- +name: vargai-pipeline-cookbooks +description: This skill should be used when the user asks to "create a talking character pipeline", "make a text-to-tiktok video", "build a round selfie video for Telegram", "do trendwatching with Apify", or "create a Remotion video pipeline". +version: 0.1.0 +allowed-tools: Read, Bash +--- + +# pipeline cookbooks + +Provide complete, multi-step workflows for common varg pipelines. Select the closest cookbook and follow its steps end-to-end. + +## select a cookbook + +- **Talking character (full workflow)**: `references/talking-character-pipeline.md` +- **Talking character (short form)**: `references/talking-character.md` +- **Text-to-TikTok**: `references/text-to-tiktok.md` +- **Round video character (Telegram selfie)**: `references/round-video-character.md` +- **Trendwatching (Apify + TikTok)**: `references/trendwatching.md` +- **Remotion editing pipeline**: `references/remotion-video.md` + +## scripts + +Use helper scripts from `scripts/` when the cookbook calls for them. Avoid editing scripts unless requested. + +## notes + +- Assume Bun and the varg SDK are available. +- Many steps require API keys (`FAL_API_KEY`, `ELEVENLABS_API_KEY`, `REPLICATE_API_TOKEN`, `GROQ_API_KEY`). +- Prefer the full talking-character pipeline when quality matters; use the short form for quick tests. diff --git a/skills/vargai-pipeline-cookbooks/references/remotion-video.md b/skills/vargai-pipeline-cookbooks/references/remotion-video.md new file mode 100644 index 00000000..c4520d9f --- /dev/null +++ b/skills/vargai-pipeline-cookbooks/references/remotion-video.md @@ -0,0 +1,585 @@ +# remotion video creation pipeline + +## overview +create programmatic videos using react components with remotion + +## what remotion can do + +### video editing & effects +- **trim & cut**: extract specific frame ranges from videos +- **zoom & pan**: smooth ken burns effects, dynamic camera movements +- **speed control**: slow motion, time-lapse, variable playback speed +- **filters**: apply CSS filters (brightness, contrast, blur, grayscale) +- **transitions**: crossfades, wipes, custom transitions between clips + +### combining content +- **concatenate videos**: join multiple videos sequentially +- **multi-track**: side-by-side, grid layouts, picture-in-picture +- **audio mixing**: combine background music, voiceover, sound effects +- **volume control**: fade in/out, dynamic volume adjustment +- **layering**: overlay graphics, text, images on video + +### beautiful subtitles +- **word-by-word captions**: sync text with audio timing +- **custom styling**: fonts, colors, backgrounds, borders +- **animations**: fade in/out, slide up, bounce effects +- **positioning**: center, bottom, top, custom placement +- **karaoke mode**: highlight current word +- **rich formatting**: bold, italic, emoji, multi-line + +### thumbnail generation +- **specific frame render**: capture any frame as still image using renderStill +- **custom thumbnails**: create compositions with overlaid text/graphics +- **multiple previews**: render several frames at different timestamps +- **branded thumbnails**: add logos, titles, watermarks to frame captures + +### advanced capabilities +- **motion graphics**: animated text, shapes, data visualizations +- **responsive layouts**: adapt to different aspect ratios +- **programmatic content**: generate videos from data/templates +- **frame-perfect timing**: precise control down to single frame +- **react ecosystem**: use any react library (charts, animations, etc) + +## when to use +- need precise control over video composition +- want to add dynamic captions/subtitles +- combining multiple videos with effects +- creating videos from templates +- need frame-perfect synchronization +- editing videos programmatically +- generating thumbnails and previews +- creating social media content at scale + +## prerequisites +```bash +bun install remotion @remotion/cli +``` + +## pipeline steps + +### step 1: analyze source media +probe all input videos to get metadata + +```bash +bun run lib/ffmpeg.ts probe media/video1.mp4 +bun run lib/ffmpeg.ts probe media/video2.mp4 +``` + +**capture:** +- duration (seconds) +- fps (frames per second) +- resolution (width x height) +- codec + +**calculate:** +- total frames = duration * fps +- end frame for concatenation + +### step 2: setup composition +```bash +bun run lib/remotion/index.ts create MyVideo +``` + +**output:** +- compositionPath: lib/remotion/compositions/MyVideo.tsx +- rootPath: lib/remotion/compositions/MyVideo.root.tsx +- compositionsDir: lib/remotion/compositions/ + +### step 3: create composition component +edit generated file `lib/remotion/compositions/MyVideo.tsx` + +**media files:** +- copy media to `lib/remotion/public/` directory +- use `staticFile("filename.ext")` to reference files +- never use absolute paths in compositions + +```bash +mkdir -p lib/remotion/public +cp media/video.mp4 media/audio.mp3 lib/remotion/public/ +``` + +if using subtitles, copy SRT and read: +```bash +cp media/subtitles.srt lib/remotion/public/ +``` + +```typescript +import { staticFile } from "remotion"; +const srtContent = await Bun.file(staticFile("subtitles.srt")).text(); +``` + +**basic structure:** +```typescript +import { AbsoluteFill, OffthreadVideo, useCurrentFrame, useVideoConfig, staticFile } from "remotion"; + +export const MyComposition: React.FC = () => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + + const video = staticFile("video1.mp4"); + + return ( + + + + ); +}; +``` + +**for captions:** +```typescript +// parse SRT at top of file +const subtitles = parseSRT(`1 +00:00:00,231 --> 00:00:00,491 +Hello + +2 +00:00:00,491 --> 00:00:00,651 +World +`); + +// in component +const currentTime = frame / fps; +const currentSubtitle = subtitles.find( + sub => currentTime >= sub.startTime && currentTime <= sub.endTime +); + +{currentSubtitle && ( +
+ {currentSubtitle.text} +
+)} +``` + +**for concatenation:** +```typescript +const video1 = staticFile("video1.mp4"); +const video2 = staticFile("video2.mp4"); + +const video1EndFrame = 1430; // calculated from probe +const video2StartFrame = video1EndFrame; + +{frame < video1EndFrame ? ( + +) : ( + +)} +``` + +### step 4: register composition +edit generated file `lib/remotion/compositions/MyVideo.root.tsx` + +```typescript +import React from "react"; +import { Composition, registerRoot } from "remotion"; +import { MyComposition } from "./MyVideo"; + +const fps = 30; +const durationInFrames = 1582; // total frames +const width = 1920; +const height = 1080; + +registerRoot(() => { + return ( + <> + + + ); +}); +``` + +**calculate durationInFrames:** +- single video: `duration * fps` +- concatenated: `video1Frames + video2Frames` +- use fps from probe results + +### step 5: verify compositions +```bash +bun run lib/remotion/index.ts compositions lib/remotion/compositions/MyVideo.root.tsx +``` + +**check output:** +- composition id matches +- dimensions are correct +- fps is correct +- durationInFrames is correct + +### step 6: render video +```bash +bun run lib/remotion/index.ts render lib/remotion/compositions/MyVideo.root.tsx MyVideo media/output.mp4 +``` + +**rendering process:** +1. bundles project with webpack +2. launches chrome headless +3. renders each frame +4. encodes with ffmpeg (h264 codec) +5. saves to output.mp4 + +**monitor:** +- progress percentage +- frames rendered +- frames encoded + +### step 7: verify output +```bash +bun run lib/ffmpeg.ts probe media/output.mp4 +``` + +check: +- duration matches expected +- fps is correct +- resolution is correct + +## common workflows + +### workflow 1: video + captions +``` +1. probe video → get duration, fps +2. setup composition +3. create composition with Video + captions +4. parse SRT file into subtitle array +5. sync captions with useCurrentFrame() +6. register composition in root +7. render +``` + +### workflow 2: concatenate videos +``` +1. probe all videos → get durations, fps +2. calculate frame boundaries +3. setup composition +4. create composition with frame-based switching +5. use absolute paths to media files +6. handle fps conversions if needed +7. register composition with total duration +8. render +``` + +### workflow 3: video with overlay graphics +``` +1. probe video +2. setup composition +3. copy video + images to lib/remotion/public/ +4. create composition with layers using staticFile() +5. use interpolate() for animations +6. position overlays with AbsoluteFill +7. register composition with registerRoot() +8. render +``` + +### workflow 4: render custom thumbnail +``` +1. setup composition +2. copy video to lib/remotion/public/ +3. create thumbnail composition with OffthreadVideo + overlays +4. use staticFile() for video path +5. add text, logos, graphics on top +6. register composition with registerRoot() +7. render specific frame as png/jpg using renderStill +``` + +### workflow 5: zoom & pan effect +``` +1. probe video or image +2. setup composition +3. copy media to lib/remotion/public/ +4. create composition with transform animations +5. use staticFile() for media paths +6. use interpolate() for scale and translate +7. set easing for smooth motion +8. register composition with registerRoot() +9. render +``` + +### workflow 6: multi-track audio/video +``` +1. probe all media files +2. setup composition +3. copy videos + audio files to lib/remotion/public/ +4. create composition with multiple OffthreadVideo/Audio components +5. use staticFile() for all media paths +6. adjust volume levels with interpolate() +7. sync timing using frame calculations +8. register composition with registerRoot() +9. render +``` + +## calculation formulas + +### frames to seconds +```typescript +const seconds = frames / fps; +``` + +### seconds to frames +```typescript +const frames = Math.floor(seconds * fps); +``` + +### fps conversion +```typescript +// video is 24fps, composition is 30fps +const adjustedFrame = Math.floor(frame * (24 / 30)); +``` + +### srt time to seconds +```typescript +function parseTime(time: string) { + const [hours, minutes, rest] = time.split(":"); + const [seconds, ms] = rest.split(","); + return ( + parseInt(hours) * 3600 + + parseInt(minutes) * 60 + + parseInt(seconds) + + parseInt(ms) / 1000 + ); +} +``` + +## tips & tricks + +### caption styling +```typescript +// word-by-word bold captions +{ + fontFamily: "Inter", + fontSize: 48, + fontWeight: "bold", + color: "white", + textAlign: "center", + backgroundColor: "rgba(0, 0, 0, 0.7)", + padding: "20px 40px", + borderRadius: 12, + textTransform: "uppercase", + letterSpacing: 2, +} +``` + +### smooth transitions +```typescript +import { interpolate } from "remotion"; + +const opacity = interpolate( + frame, + [0, 30, 60], + [0, 1, 0], + { extrapolateRight: "clamp" } +); +``` + +### loading fonts +```typescript +import { loadFont } from "@remotion/google-fonts/Inter"; +const { fontFamily } = loadFont(); +``` + +### responsive layouts +```typescript +const { width, height } = useVideoConfig(); +const scale = Math.min(width / 1920, height / 1080); +``` + +## troubleshooting + +### issue: video not loading +**solution:** +- copy media files to `lib/remotion/public/` +- use `staticFile("filename.ext")` not absolute paths +- verify file exists in public directory +- check file permissions + +### issue: captions out of sync +**solution:** +- verify SRT timestamps +- check fps matches video fps +- log currentTime to debug: `console.log(frame / fps)` + +### issue: wrong video duration +**solution:** +- probe video to get exact duration +- calculate frames correctly: `duration * fps` +- round to nearest frame + +### issue: concatenation glitch +**solution:** +- calculate exact end frame of first video +- adjust `startFrom` for fps differences +- use `Math.floor()` for frame calculations + +### issue: render fails +**solution:** +- verify all media files exist in `lib/remotion/public/` +- check composition is registered with `registerRoot()` +- ensure durationInFrames is sufficient +- verify all media paths use `staticFile()` +- check console for webpack errors + +## performance optimization + +### use OffthreadVideo +for better performance when concatenating: +```typescript + +``` + +### limit font requests +```typescript +loadFont({ + weights: ["400", "700"], // only needed weights + subsets: ["latin"], // only needed subsets +}); +``` + +### optimize media files +```bash +# compress video before using +bun run lib/ffmpeg.ts convert input.mp4 output.mp4 +``` + +## example workflows + +### example 1: video with captions and concatenation +```bash +# 1. probe videos +bun run lib/ffmpeg.ts probe media/fitness-demo.mp4 +# output: 360x640 @ 30fps, 47.67s + +bun run lib/ffmpeg.ts probe media/kangaroo-scene.mp4 +# output: 1920x1080 @ 24fps, 5.04s + +# 2. setup composition +bun run lib/remotion/index.ts create Demo + +# 3. create composition files +# edit lib/remotion/compositions/Demo.tsx +# edit lib/remotion/compositions/Demo.root.tsx + +# 4. verify +bun run lib/remotion/index.ts compositions lib/remotion/compositions/Demo.root.tsx +# Demo: 360x640 @ 30fps (1582 frames) + +# 5. render +bun run lib/remotion/index.ts render lib/remotion/compositions/Demo.root.tsx Demo media/output.mp4 +# [remotion] progress: 100.0% | rendered: 1582 | encoded: 1582 +# [remotion] saved to media/output.mp4 + +# 6. verify output +bun run lib/ffmpeg.ts probe media/output.mp4 +# 360x640 @ 30fps, 52.73s +``` + +### example 2: custom thumbnail with overlay +```bash +# 1. setup composition +bun run lib/remotion/index.ts create Thumbnail + +# 2. copy media +cp media/video.mp4 lib/remotion/public/ + +# 3. edit thumbnail composition lib/remotion/compositions/Thumbnail.tsx +# import { AbsoluteFill, OffthreadVideo, staticFile } from "remotion"; +# export const Thumbnail = () => { +# const video = staticFile("video.mp4"); +# return ( +# +# +#
+# MY VIDEO TITLE +#
+#
+# ); +# }; + +# 4. edit root with registerRoot() lib/remotion/compositions/Thumbnail.root.tsx + +# 5. render frame 90 (3 seconds in @ 30fps) +bun run lib/remotion/index.ts still lib/remotion/compositions/Thumbnail.root.tsx Thumbnail 90 media/thumbnail.png +# [remotion] saved to media/thumbnail.png +``` + +### example 3: zoom effect with audio +```bash +# 1. setup composition +bun run lib/remotion/index.ts create Zoom + +# 2. copy media +cp media/image.jpg media/music.mp3 lib/remotion/public/ + +# 3. edit composition lib/remotion/compositions/Zoom.tsx +# import { Img, Audio, staticFile, interpolate, useCurrentFrame } from "remotion"; +# const frame = useCurrentFrame(); +# const image = staticFile("image.jpg"); +# const audio = staticFile("music.mp3"); +# const scale = interpolate(frame, [0, 150], [1, 1.5]); +#
+# +#
+#