
Ffmpeg Karaoke Animated Text
- 57 installs
- 50 repo stars
- Updated June 18, 2026
- josiahsiegel/claude-plugin-marketplace
Helps with ai & agent building tasks.
About
ffmpeg-karaoke-animated-text is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- ffmpeg-karaoke-animated-text
- AI & Agent Building
- AI-coding skill
Ffmpeg Karaoke Animated Text by the numbers
- 57 all-time installs (skills.sh)
- +6 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #6,590 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill ffmpeg-karaoke-animated-textAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 57 |
|---|---|
| repo stars | ★ 50 |
| Last updated | June 18, 2026 |
| Repository | josiahsiegel/claude-plugin-marketplace ↗ |
What it does
Helps with ai & agent building tasks.
Files
CRITICAL GUIDELINES
Windows File Path Requirements
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
---
FFmpeg Karaoke & Animated Text
Use this skill for karaoke subtitles, kinetic typography, scrolling credits, animated lower thirds, typewriter text, timers, and dynamic text overlays. Keep answers practical: identify whether ASS or drawtext is the right tool, provide a copy-paste-ready command or ASS snippet, and call out timing units.
Quick Reference
| Effect | Pattern |
|---|---|
| Karaoke ASS | Use ASS format with \k, \kf, or \ko timing tags |
| Burn karaoke | ffmpeg -i input.mp4 -vf "ass=karaoke.ass" -c:v libx264 -crf 18 -c:a copy output.mp4 |
| Scrolling credits | -vf "drawtext=textfile=credits.txt:y=h-80*t" |
| Typewriter | Stagger drawtext layers with enable='gte(t,...)' |
| Fade in text | -vf "drawtext=text='Title':alpha='min(1,t/2)'" |
| Bouncing text | -vf "drawtext=text='Bounce':y='h/2+50*sin(t*5)'" |
| Moving text | -vf "drawtext=text='Move':x='w-mod(t*100,w+tw)'" |
| Rotation | Use ASS (\frz, \frx, \fry); drawtext does not rotate text natively |
When to Use This Skill
Use for animated text and karaoke:
- Music video lyrics with karaoke highlighting
- Movie-style scrolling credits
- Animated titles and lower thirds
- Typewriter text reveal
- Kinetic typography and word pops
- Countdown timers, stopwatches, frame counters, timecode overlays
- Multi-line text and textfile-driven overlays
Tool Choice: ASS vs drawtext
| Need | Best Tool | Why |
|---|---|---|
| Word/syllable karaoke highlighting | ASS | Native \k, \kf, \ko support |
| Styled subtitles with outline/glow/rotation | ASS | Rich subtitle styling and transform tags |
| Simple overlay text | drawtext | Fast, direct FFmpeg filter |
| Timecode, frame numbers, metadata text | drawtext | Built-in variable expansion |
| Scrolling credits/news tickers | drawtext | Straightforward position expressions |
| Per-word kinetic captions | ASS or multiple drawtext layers | ASS is easier for rotation/scale; drawtext is direct for formula motion |
---
CRITICAL: ASS Time Unit Reference
ASS uses TWO DIFFERENT time unit systems. This is a common source of bugs. Karaoke tags use centiseconds; ASS animation tags use milliseconds; FFmpeg drawtext expressions use seconds.
Karaoke Tags = CENTISECONDS (1/100 second)
| Tag | Unit | Example | Duration |
|---|---|---|---|
\k | centiseconds | {\k50} | 0.5 seconds |
\kf | centiseconds | {\kf100} | 1.0 second |
\ko | centiseconds | {\ko25} | 0.25 seconds |
Conversion: seconds * 100 = centiseconds.
Animation Tags = MILLISECONDS (1/1000 second)
| Tag | Unit | Example | Duration |
|---|---|---|---|
\t(t1,t2,...) | milliseconds | \t(0,500,...) | 0-500ms animation |
\fad(in,out) | milliseconds | \fad(200,300) | 200ms in, 300ms out |
\move(x1,y1,x2,y2,t1,t2) | milliseconds | \move(0,0,100,100,0,1000) | 1 second move |
Conversion: seconds * 1000 = milliseconds.
FFmpeg drawtext = SECONDS
| Expression | Unit | Example |
|---|---|---|
t | seconds | t=2.5 means 2.5 seconds |
enable='between(t,0,3)' | seconds | visible from 0-3 seconds |
alpha='min(1,t/2)' | seconds | fade over 2 seconds |
Common Mistake
; WRONG - mixing units:
Dialogue: 0,0:00:00.00,0:00:02.00,Style,,0,0,0,,{\k100\t(0,100,...)}Word
; {\k100} = 1 second, but \t(0,100,...) = 0.1 seconds
; CORRECT - matched duration:
Dialogue: 0,0:00:00.00,0:00:02.00,Style,,0,0,0,,{\k100\t(0,1000,...)}WordFor the full timing-unit reference, use ffmpeg-animation-timing-reference.
---
Karaoke Core Pattern
[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Karaoke,Arial,72,&H00FFFFFF,&H000000FF,&H00000000,&H80000000,1,0,0,0,100,100,0,0,1,3,2,2,10,10,50,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:01.00,0:00:05.00,Karaoke,,0,0,0,,{\k50}Twinkle {\k50}twinkle {\k50}little {\k50}starBurn into video:
ffmpeg -i input.mp4 \
-vf "ass=karaoke.ass" \
-c:v libx264 -crf 18 -c:a copy \
output_karaoke.mp4For advanced styles, neon/gradient karaoke, per-character timing, and animated karaoke transforms, see references/karaoke-ass-patterns.md.
drawtext Core Patterns
# Fade in title over 2 seconds
ffmpeg -i input.mp4 \
-vf "drawtext=text='Title':fontsize=100:fontcolor=white:x=(w-tw)/2:y=(h-th)/2:alpha='min(1,t/2)'" \
output.mp4
# Vertical bounce
ffmpeg -i input.mp4 \
-vf "drawtext=text='BOUNCE':fontsize=80:fontcolor=yellow:x=(w-tw)/2:y='(h-th)/2+50*sin(t*5)'" \
bounce.mp4
# Scroll credits upward at 80px/sec
ffmpeg -i input.mp4 \
-vf "drawtext=textfile=credits.txt:fontsize=48:fontcolor=white:x=(w-tw)/2:y=h-80*t" \
-c:v libx264 -crf 18 output.mp4For spring/elastic/wobble formulas, typewriter effects, lower thirds, countdowns, stopwatches, metadata overlays, and multi-line text, see references/drawtext-animation-recipes.md.
Workflow
1. Choose ASS or drawtext using the tool-choice table. 2. Verify timing units before writing tags or expressions. 3. Probe input when needed (ffprobe) to confirm duration, frame rate, and resolution. 4. Set output encoding explicitly when burning text (-c:v libx264 -crf 18, audio copy only when compatible). 5. Use short test renders (-ss, -t) before rendering a full music video or credit roll. 6. Check readability: karaoke should track words within ~30ms; captions need enough display time; scrolling credits should move slowly enough to read.
Reference Map
references/karaoke-ass-patterns.md- ASS karaoke basics,\k/\kf/\ko, BPM timing, tag selection, neon/gradient styles, per-character karaoke, ASS color format, animated karaoke effects.references/drawtext-animation-recipes.md- Spring bounce, elastic overshoot, easing approximations, wobble/wiggle, pulse, wipes, typewriter, fades, moving text, kinetic typography, lower thirds, countdowns, stopwatches, dynamic variables, multi-line text.references/scrolling-credits-and-expressions.md- Music/education/credits timing, vertical credits, horizontal tickers, ASS rotation workaround,drawtextvariables and expression cookbook.
Related Skills
ffmpeg-animation-timing-reference- Timing units, caption durations, easing, sync tolerancesffmpeg-captions-subtitles- Subtitle fundamentals, extraction, burn-in, stylingffmpeg-kinetic-captions- Word-level pop/bounce/grow caption effectsviral-video-animated-captions- Social-video caption templatesffmpeg-shapes-graphics- Boxes, backgrounds, graphic overlaysffmpeg-transitions-effects- xfade and video transitions
Drawtext Animation Recipes
Advanced FFmpeg drawtext formulas and complete commands for animated text, kinetic typography, timers, and dynamic overlays.
Spring Physics Implementation
Create natural bounce effects with exponential decay:
# Vertical spring bounce (decaying oscillation)
# Formula: y_offset = amplitude * e^(-decay*t) * sin(frequency*t)
-vf "drawtext=text='BOUNCE':fontsize=80:fontcolor=white:\
x=(w-tw)/2:\
y='(h-th)/2-30*exp(-t*2.5)*sin(t*15)'"
# Breakdown:
# -30*exp(-t*2.5) = amplitude decays from 30px to 0
# sin(t*15) = oscillates at 15 rad/s (≈2.4 Hz)
# Combines: bounces 2-3 times over ~1 second, settling at centerParameter tuning:
- Decay rate (2.5): Higher = faster settling (3-4 for quick, 1-2 for slow)
- Frequency (15): Higher = more bounces (10-12 slow, 15-20 fast)
- Amplitude (30): Bounce height in pixels
Elastic Overshoot Effect
# Elastic scale effect (rubber band)
# Overshoots target size multiple times before settling
-vf "drawtext=text='ELASTIC':fontsize='72*(1+0.4*exp(-t*3)*sin(t*20))':\
fontcolor=yellow:x=(w-tw)/2:y=(h-th)/2"
# Scale oscillates: 72px → 101px → 65px → 80px → 70px → 72px (settled)
# Mathematical basis: e^(-3t) * sin(20t) creates damped oscillationElastic parameters:
- Base fontsize: 72 (target)
- Overshoot: 0.4 (40% maximum deviation) → 72 * 1.4 = 101px peak
- Decay: 3 (settles in ~1.5 seconds)
- Frequency: 20 (multiple small bounces)
Bezier Curve Approximation (Ease-In-Out)
FFmpeg doesn't support bezier directly, but we can approximate with piecewise functions:
# Ease-out approximation (fast start, slow end)
# Cubic bezier (0, 0, 0.2, 1) approximation
-vf "drawtext=text='EASE OUT':\
alpha='if(lt(t,0.5),1-exp(-t*6),1)':\
fontsize=80:fontcolor=white:x=(w-tw)/2:y=(h-th)/2:\
enable='lt(t,1)'"
# Ease-in approximation (slow start, fast end)
# Cubic bezier (0.8, 0, 1, 1) approximation
-vf "drawtext=text='EASE IN':\
alpha='if(lt(t,0.5),exp(-(1-t)*6),0)':\
fontsize=80:fontcolor=white:x=(w-tw)/2:y=(h-th)/2:\
enable='between(t,1,2)'"
# Ease-in-out (S-curve) using sigmoid approximation
-vf "drawtext=text='SMOOTH':\
alpha='1/(1+exp(-10*(t-0.5)))':\
fontsize=80:fontcolor=white:x=(w-tw)/2:y=(h-th)/2:\
enable='lt(t,1)'"Mathematical reasoning:
- Exponential ease:
1 - e^(-kt)creates natural deceleration - Sigmoid curve:
1/(1+e^(-k(t-0.5)))creates smooth S-curve (ease-in-out) - k parameter: Controls transition sharpness (6-10 for subtle, 15-20 for pronounced)
Wobble/Wiggle Effects
Create organic, unpredictable motion:
# Dual-frequency wobble (complex motion)
# Combines two sine waves at different frequencies for organic feel
-vf "drawtext=text='WOBBLE':fontsize=80:fontcolor=white:\
x='(w-tw)/2+8*sin(t*7)+4*sin(t*17)':\
y='(h-th)/2+6*cos(t*7)+3*cos(t*13)'"
# Breakdown:
# Primary wobble: 8*sin(t*7) = 8px amplitude, 7 rad/s (1.1 Hz)
# Secondary wobble: 4*sin(t*17) = 4px amplitude, 17 rad/s (2.7 Hz)
# Result: Complex, organic motion pattern
# Drunk/unstable effect (low frequency, large amplitude)
-vf "drawtext=text='UNSTABLE':fontsize=80:fontcolor=white:\
x='(w-tw)/2+20*sin(t*2.5)+10*sin(t*6.3)':\
y='(h-th)/2+15*cos(t*3.1)+8*cos(t*7.2)'"Wobble design principles:
- Use two frequencies (primary + secondary) for natural randomness
- Prime number ratios (e.g., 7 and 17) prevent pattern repetition
- Amplitude ratio 2:1 (primary twice the secondary) for balanced motion
Pulse with Variable Intensity
Create heartbeat or alarm-style pulsing:
# Heartbeat pulse (two quick beats, pause)
# Pattern: THUMP-thump ... pause ... THUMP-thump
-vf "drawtext=text='♥ HEARTBEAT ♥':\
fontsize='80+25*max(0,sin(t*15)*exp(-mod(t,1.2)*10))':\
fontcolor=red:x=(w-tw)/2:y=(h-th)/2"
# Breakdown:
# sin(t*15) = rapid oscillation
# exp(-mod(t,1.2)*10) = decay envelope every 1.2 seconds
# max(0, ...) = only positive pulses
# Result: Pulse decays quickly, resets every 1.2s
# Alarm pulse (constant urgent rhythm)
-vf "drawtext=text='ALERT':\
fontsize='80+20*abs(sin(t*8))':\
fontcolor=yellow:x=(w-tw)/2:y=(h-th)/2"
# abs(sin(t*8)) creates continuous pulsing at 8 rad/s (1.3 Hz)Text Reveal Animations (Wipe Effects)
Horizontal Wipe (Left to Right)
# Clip text progressively from left
# Uses drawbox mask to reveal text over time
-filter_complex "\
[0:v]drawtext=text='REVEALED':fontsize=100:fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2[txt];\
[txt]drawbox=x=0:y=0:w='min(w,t*500)':h=h:c=black@0:t=fill:replace=1[v]" \
-map "[v]"
# Breakdown:
# w='min(w,t*500)' = width grows at 500 pixels/second
# Creates left-to-right reveal effectVertical Wipe (Bottom to Top)
# Text rises from bottom
-vf "drawtext=text='RISING':fontsize=100:fontcolor=white:\
x=(w-tw)/2:\
y='if(lt(t,1),h-t*h,0)'"
# y position: starts at h (bottom), moves to 0 (top) over 1 secondCountdown Timer Variations
Animated Countdown with Anticipation
# Countdown that pulses on each second change
-vf "drawtext=text='%{eif\:10-floor(t)\:d}':\
fontsize='200+50*abs(sin(floor(t)*50))*exp(-(t-floor(t))*8)':\
fontcolor=white:x=(w-tw)/2:y=(h-th)/2"
# Breakdown:
# %{eif\:10-floor(t)\:d} = countdown number (10, 9, 8, ...)
# abs(sin(floor(t)*50)) = trigger pulse on integer seconds
# exp(-(t-floor(t))*8) = decay within each second
# Result: Number "pops" at each second changeSplit-Flap Display (Mechanical)
# Simulates old-school flip counter with vertical offset
-vf "drawtext=text='%{eif\:10-floor(t)\:d}':\
fontsize=200:fontcolor=white:\
x=(w-tw)/2:\
y='(h-th)/2-(t-floor(t))*100*step(t-floor(t))'"
# y offset creates "flipping" motion at second boundariesTypewriter Effect
Character-by-Character Reveal
# Typewriter effect using enable
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=10" \
-vf "\
drawtext=text='H':x=100:y=500:fontsize=72:fontcolor=white:enable='gte(t,0.0)',\
drawtext=text='e':x=150:y=500:fontsize=72:fontcolor=white:enable='gte(t,0.1)',\
drawtext=text='l':x=200:y=500:fontsize=72:fontcolor=white:enable='gte(t,0.2)',\
drawtext=text='l':x=250:y=500:fontsize=72:fontcolor=white:enable='gte(t,0.3)',\
drawtext=text='o':x=300:y=500:fontsize=72:fontcolor=white:enable='gte(t,0.4)'" \
typewriter.mp4Typewriter with Cursor
# Blinking cursor during typing
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=5" \
-vf "\
drawtext=text='Hello':fontsize=72:fontcolor=white:x=100:y=500:\
enable='gte(t,0)':alpha='min(1,(t-0)/0.5)',\
drawtext=text='|':fontsize=72:fontcolor=white:\
x='100+72*min(5,floor(t/0.1))':y=500:\
alpha='lt(mod(t,0.5),0.25)'" \
typewriter_cursor.mp4Text Fade Effects
# Simple fade in
ffmpeg -i input.mp4 \
-vf "drawtext=text='Title':fontsize=100:fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2:\
alpha='if(lt(t,2),t/2,1)'" \
fade_in.mp4
# Fade out (assuming 10 second video)
ffmpeg -i input.mp4 \
-vf "drawtext=text='Goodbye':fontsize=100:fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2:\
alpha='if(gt(t,8),1-(t-8)/2,1)'" \
fade_out.mp4
# Title card with fade in/out
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=6" \
-vf "drawtext=text='Chapter One':fontsize=120:fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2:\
alpha='if(lt(t,1),t,if(gt(t,5),1-(t-5),1))'" \
title_card.mp4Moving Text
# Vertical bounce
ffmpeg -i input.mp4 \
-vf "drawtext=text='BOUNCE':fontsize=80:fontcolor=yellow:\
x=(w-tw)/2:\
y='(h-th)/2+50*sin(t*5)'" \
bounce.mp4
# Horizontal bounce
ffmpeg -i input.mp4 \
-vf "drawtext=text='PING PONG':fontsize=60:fontcolor=cyan:\
x='(w-tw)/2+200*sin(t*3)':\
y=(h-th)/2" \
horizontal_bounce.mp4
# Text moving in circle
ffmpeg -i input.mp4 \
-vf "drawtext=text='ORBIT':fontsize=60:fontcolor=white:\
x='(w/2)+200*cos(t*2)-tw/2':\
y='(h/2)+200*sin(t*2)-th/2'" \
orbit.mp4
# Slide in from right
ffmpeg -i input.mp4 \
-vf "drawtext=text='SLIDE IN':fontsize=80:fontcolor=white:\
x='if(lt(t,1),w-tw*(t),w-tw)':\
y=(h-th)/2" \
slide_in.mp4
# Slide in from left
ffmpeg -i input.mp4 \
-vf "drawtext=text='FROM LEFT':fontsize=80:fontcolor=white:\
x='if(lt(t,1),-tw+tw*t,0)':\
y=(h-th)/2" \
slide_left.mp4Kinetic Typography
# Words appearing with scale
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=8" \
-vf "\
drawtext=text='THIS':fontsize='72*(1+0.3*exp(-3*(t-1)))':fontcolor=white:\
x=(w-tw)/2:y=h/2-100:enable='gte(t,1)',\
drawtext=text='IS':fontsize='72*(1+0.3*exp(-3*(t-2)))':fontcolor=white:\
x=(w-tw)/2:y=h/2:enable='gte(t,2)',\
drawtext=text='KINETIC':fontsize='72*(1+0.3*exp(-3*(t-3)))':fontcolor=red:\
x=(w-tw)/2:y=h/2+100:enable='gte(t,3)'" \
kinetic_pop.mp4
# Shaking text (impact effect)
ffmpeg -i input.mp4 \
-vf "drawtext=text='IMPACT':fontsize=120:fontcolor=white:\
x='(w-tw)/2+10*sin(t*50)*exp(-t*2)':\
y='(h-th)/2+10*cos(t*50)*exp(-t*2)'" \
shake.mp4Lower Thirds
# Name and title lower third
ffmpeg -i input.mp4 \
-vf "\
drawbox=x=50:y=h-150:w=500:h=100:c=blue@0.7:t=fill,\
drawtext=text='Name':fontsize=36:fontcolor=white:\
x=70:y=h-140,\
drawtext=text='Title':fontsize=24:fontcolor=white@0.8:\
x=70:y=h-100" \
lower_third.mp4
# Slide-in lower third
ffmpeg -i input.mp4 \
-vf "\
drawbox=x='if(lt(t,0.5),-500+1000*t,50)':\
y=h-150:w=500:h=100:c=blue@0.7:t=fill:\
enable='between(t,0,8)',\
drawtext=text='Name':fontsize=36:fontcolor=white:\
x='if(lt(t,0.5),-430+1000*t,70)':y=h-140:\
alpha='min(1,(t-0.3)/0.3)':\
enable='between(t,0.3,8)',\
drawtext=text='Title':fontsize=24:fontcolor=white:\
x='if(lt(t,0.5),-430+1000*t,70)':y=h-100:\
alpha='min(1,(t-0.5)/0.3)':\
enable='between(t,0.5,8)'" \
animated_lower_third.mp4Countdown, Stopwatch, and Dynamic Text
# 10 second countdown
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=10" \
-vf "drawtext=text='%{eif\:10-t\:d}':fontsize=200:fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2" \
countdown.mp4
# Pulsing countdown
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=10" \
-vf "drawtext=text='%{eif\:10-t\:d}':\
fontsize='200+30*sin(t*10)*exp(-mod(t,1)*3)':\
fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2" \
pulsing_countdown.mp4
# Count up timer (MM:SS)
ffmpeg -f lavfi -i "color=c=black:s=1920x1080:d=120" \
-vf "drawtext=text='%{eif\:floor(t/60)\:d\:2}\:%{eif\:mod(t,60)\:d\:2}':\
fontsize=100:fontcolor=green:\
x=(w-tw)/2:y=(h-th)/2" \
stopwatch.mp4
# Show frame number
ffmpeg -i input.mp4 \
-vf "drawtext=text='Frame\: %{frame_num}':\
fontsize=24:fontcolor=white:\
x=10:y=10" \
frame_numbers.mp4
# Show timecode
ffmpeg -i input.mp4 \
-vf "drawtext=text='%{pts\:hms}':\
fontsize=24:fontcolor=white:\
x=10:y=10" \
timecode.mp4
# With milliseconds
ffmpeg -i input.mp4 \
-vf "drawtext=text='%{pts}':\
fontsize=24:fontcolor=white:\
x=10:y=10" \
timecode_ms.mp4
# Show title metadata
ffmpeg -i input.mp4 \
-vf "drawtext=text='%{metadata\:title}':\
fontsize=24:fontcolor=white:\
x=10:y=h-40" \
metadata.mp4Multi-Line Text
# Multi-line centered text
ffmpeg -i input.mp4 \
-vf "drawtext=text='Line One
Line Two
Line Three':\
fontsize=48:fontcolor=white:\
x=(w-tw)/2:y=(h-th)/2:\
line_spacing=20" \
multiline.mp4
# Use text file for long text
ffmpeg -i input.mp4 \
-vf "drawtext=textfile=message.txt:\
fontsize=36:fontcolor=white:\
x=50:y=50:\
line_spacing=10" \
from_file.mp4Karaoke ASS Patterns
Detailed ASS/SSA karaoke subtitle recipes, timing tags, styling patterns, and burn-in commands.
ASS Karaoke Basics
ASS (Advanced SubStation Alpha) supports karaoke timing with \k tags.
[Script Info]
Title: Karaoke Example
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Karaoke,Arial,72,&H00FFFFFF,&H000000FF,&H00000000,&H80000000,1,0,0,0,100,100,0,0,1,3,2,2,10,10,50,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:01.00,0:00:05.00,Karaoke,,0,0,0,,{\k50}Twinkle {\k50}twinkle {\k50}little {\k50}star
Dialogue: 0,0:00:05.00,0:00:09.00,Karaoke,,0,0,0,,{\k50}How {\k50}I {\k50}wonder {\k50}what {\k50}you {\k50}areKaraoke Timing Tags
| Tag | Effect | Example |
|---|---|---|
\k | Fill from left | {\k100}Word = 1 second fill |
\kf or \K | Smooth fill (fade) | {\kf100}Word |
\ko | Outline highlight | {\ko100}Word |
Duration is in centiseconds (100 = 1 second).
Advanced Karaoke Timing Parameters
Optimal Karaoke Timing by Song Tempo
| BPM Range | Syllable Duration | Tag Value | Notes |
|---|---|---|---|
| 60-80 (Slow ballad) | 600-800ms | \kf60-80 | Long, emotional |
| 80-100 (Moderate) | 400-600ms | \kf40-60 | Standard pop |
| 100-120 (Upbeat) | 300-500ms | \kf30-50 | Most common |
| 120-140 (Fast) | 250-400ms | \kf25-40 | Energetic |
| 140+ (Rapid) | 200-300ms | \kf20-30 | Rap, EDM |
Karaoke Tag Selection Guide
\k (Instant Fill) - Best For
- Very short syllables: <120 centiseconds (1.2s)
- Rap/hip-hop: Fast lyric delivery
- Staccato rhythm: Percussive, sharp delivery
; Rap example (fast succession):
{\k25}Yo {\k20}this {\k15}is {\k30}rapid {\k25}fire {\k35}flow\kf (Progressive Fill) - Best For
- Long syllables: >120 centiseconds (1.2s)
- Ballads: Drawn-out emotional delivery
- Smooth transitions: Clean visual sweep
; Ballad example (sustained notes):
{\kf150}Loooooove {\kf120}yoooou {\kf180}foreeeeverRecommended: Use \kf for any syllable >100 centiseconds for smoothest visual effect.
\ko (Outline Reveal) - Best For
- High contrast: Text that needs to "pop"
- Neon/glow styles: Outline-heavy fonts
- Special emphasis: Chorus, key phrases
; Neon karaoke style:
[V4+ Styles]
Style: NeonKaraoke,Arial,80,&H00000000,&H0000FF00,&H0000FF00,&H00000000,1,0,0,0,100,100,0,0,3,6,0,2,10,10,50,1
[Events]
Dialogue: 0,0:00:01.00,0:00:05.00,NeonKaraoke,,0,0,0,,{\ko50}Electric {\ko60}neon {\ko40}glowMulti-Color Karaoke Transitions
Create dynamic color changes during karaoke fill:
; Gradient karaoke: Yellow → Orange → Red
[V4+ Styles]
Style: GradientKaraoke,Impact,80,&H0000FFFF,&H000000FF,&H00000000,&H00000000,1,0,0,0,100,100,0,0,1,5,0,2,10,10,50,1
; Primary^ Secondary^
; Yellow(start) Red(filled)
; Add intermediate color transition with \t tags:
[Events]
Dialogue: 0,0:00:01.00,0:00:05.00,GradientKaraoke,,0,0,0,,{\kf80\t(0,400,\2c&H0000A5FF&)}Word1 {\kf100\t(0,500,\2c&H0000A5FF&)}Word2
; ↑ Orange midpointColor progression formula:
Start: &H0000FFFF (Yellow)
Mid: &H0000A5FF (Orange) - 50% through karaoke fill
End: &H000000FF (Red)Per-Character Karaoke
For very precise timing (character-by-character):
; Each character gets individual timing (manual, tedious)
{\k10}H{\k8}e{\k12}l{\k10}l{\k15}o {\k20}w{\k18}o{\k15}r{\k12}l{\k10}d
; Best practice: Use tools like Aegisub Karaoke Timer
; Manual character timing only for special effectsUse character-level karaoke for:
- Slow-motion word reveal
- Dramatic emphasis
- Non-linear character highlighting (e.g., every other letter)
Apply Karaoke ASS to Video
# Burn karaoke subtitles into video
ffmpeg -i input.mp4 \
-vf "ass=karaoke.ass" \
-c:v libx264 -crf 18 -c:a copy \
output_karaoke.mp4
# With specific fonts directory
ffmpeg -i input.mp4 \
-vf "ass=karaoke.ass:fontsdir=/path/to/fonts" \
output.mp4Advanced ASS Karaoke Styles
[V4+ Styles]
; Gradient karaoke (yellow to red)
Style: KaraokeGradient,Impact,80,&H0000FFFF,&H000000FF,&H00000000,&H80000000,1,0,0,0,100,100,0,0,1,4,2,2,10,10,60,1
; Glow effect karaoke
Style: KaraokeGlow,Arial Black,72,&H00FFFFFF,&H00FF00FF,&H00FF00FF,&H00000000,1,0,0,0,100,100,0,0,4,0,20,2,10,10,50,1
; Outline only (neon style)
Style: KaraokeNeon,Arial,80,&H00000000,&H0000FF00,&H0000FF00,&H00000000,1,0,0,0,100,100,0,0,3,4,0,2,10,10,50,1
[Events]
; Word-by-word with effects
Dialogue: 0,0:00:01.00,0:00:05.00,KaraokeGradient,,0,0,0,,{\k50\fad(200,0)}Never {\k50}gonna {\k50}give {\k50}you {\k50}up
; With positioning
Dialogue: 0,0:00:05.00,0:00:09.00,KaraokeGlow,,0,0,0,,{\pos(960,900)\k50}Never {\k50}gonna {\k50}let {\k50}you {\k50}downASS Color Format
ASS uses &HAABBGGRR format (Alpha, Blue, Green, Red):
&H00FFFFFF= White (fully opaque)&H000000FF= Red&H0000FF00= Green&H00FF0000= Blue&H80000000= 50% transparent black
Karaoke with Animation Effects
[Events]
; Bounce effect per word
Dialogue: 0,0:00:01.00,0:00:05.00,Karaoke,,0,0,0,,{\k50\t(0,500,\fry360)}Word1 {\k50\t(0,500,\fry360)}Word2
; Scale pop on highlight
Dialogue: 0,0:00:01.00,0:00:05.00,Karaoke,,0,0,0,,{\k50\t(0,100,\fscx120\fscy120)\t(100,200,\fscx100\fscy100)}Pop
; Color transition
Dialogue: 0,0:00:01.00,0:00:05.00,Karaoke,,0,0,0,,{\k100\t(0,1000,\c&H0000FF&)}Red {\k100\t(0,1000,\c&H00FF00&)}GreenASS Animation Tags Reference
| Tag | Effect |
|---|---|
\t(t1,t2,tags) | Animate tags from t1 to t2 |
\move(x1,y1,x2,y2) | Move text from point to point |
\fad(fadein,fadeout) | Fade in/out (milliseconds) |
\fscx, \fscy | Scale X/Y percentage |
\frx, \fry, \frz | Rotate on axis |
\pos(x,y) | Position text |
\an1-9 | Alignment (numpad positions) |
Scrolling Credits and Drawtext Expressions
Recipes for vertical credits, horizontal tickers, genre/content timing, and drawtext expression reference.
Optimal Animation Timing by Content Type
Music Video Karaoke
| Genre | Syllable Timing | Animation Style | Color Scheme |
|---|---|---|---|
| Ballad | 100-200 centiseconds | \kf smooth fill | White → Soft Blue |
| Pop | 40-80 centiseconds | \kf with bounce | White → Bright Pink |
| Rap | 15-40 centiseconds | \k instant | White → Red |
| Rock | 50-100 centiseconds | \k with shake | White → Orange |
| EDM | 30-60 centiseconds | \ko outline | Neon colors |
Educational Content
# Slow, clear typewriter for learning
# 80ms per character = comfortable reading pace
-vf "drawtext=textfile=lesson.txt:\
fontsize=48:fontcolor=white:\
x=50:y=100:\
enable='gte(n,eif(n/24,80))'"
# Each character appears every 80/24 ≈ 3.3 frames at 24fpsScrolling Credits Optimization
# Professional credits scroll
# Speed: 60-80 pixels/second for comfortable reading
-vf "drawtext=textfile=credits.txt:\
fontsize=42:fontcolor=white:\
x=(w-tw)/2:\
y='h-60*t':\
line_spacing=25"
# Calculation:
# 60 px/s at 42px font = ~1.4 lines/second
# For 50 lines: 50/1.4 = ~36 seconds total durationCredits readability formula:
scroll_speed = font_size * 1.2 to 1.5 (pixels/second)
total_duration = (line_count * line_height) / scroll_speed
Example:
font_size = 42px
line_height = 42 + 25 (spacing) = 67px
scroll_speed = 42 * 1.4 = 59 px/s
50 lines = 50 * 67 = 3350 pixels
duration = 3350 / 59 = 56.8 secondsScrolling Credits
Vertical Scroll (Bottom to Top)
# Basic scrolling credits
ffmpeg -i input.mp4 \
-vf "drawtext=textfile=credits.txt:\
fontfile=/path/to/font.ttf:\
fontsize=48:\
fontcolor=white:\
x=(w-tw)/2:\
y=h-80*t" \
-c:v libx264 -crf 18 output.mp4
# y=h-80*t: Start at bottom (h), move up at 80 pixels/secondcredits.txt Format
DIRECTED BY
Name
PRODUCED BY
Name
STARRING
Actor One
Actor Two
Actor Three
MUSIC BY
Composer Name
SPECIAL THANKS
EveryoneScrolling Credits with Sections
# Multi-speed credits (slower for names)
ffmpeg -i input.mp4 \
-vf "drawtext=textfile=credits.txt:\
fontsize=48:\
fontcolor=white:\
x=(w-tw)/2:\
y='h-60*t':\
line_spacing=20" \
output.mp4Horizontal Scrolling (News Ticker)
# Right to left scroll
ffmpeg -i input.mp4 \
-vf "drawtext=text='BREAKING NEWS... This is a scrolling ticker message':\
fontsize=36:\
fontcolor=white:\
y=h-50:\
x='w-mod(t*150,w+tw)'" \
ticker.mp4
# x='w-mod(t*150,w+tw)': Continuous scroll at 150 pixels/secondLooping Horizontal Scroll
# Seamless looping ticker
ffmpeg -i input.mp4 \
-vf "drawtext=text=' LIVE NEWS BREAKING STORY UPDATES ':\
fontsize=40:\
fontcolor=yellow:\
y=h-60:\
x='w-mod(t*200\,w+tw)':\
box=1:boxcolor=red@0.8:boxborderw=10" \
news_ticker.mp4Rotation Animation via ASS
drawtext doesn't support rotation natively. Use ASS subtitles for rotation:
# Create spinning.ass
cat << 'EOF' > spinning.ass
[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
[V4+ Styles]
Style: Spin,Arial,72,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,0,5,0,0,0,1
[Events]
Dialogue: 0,0:00:00.00,0:00:05.00,Spin,,0,0,0,,{\an5\pos(960,540)\t(0,5000,\frz1080)}SPINNING
EOF
ffmpeg -i input.mp4 -vf "ass=spinning.ass" output.mp4Expression Reference
Useful Time Expressions
| Expression | Result |
|---|---|
t | Current time in seconds |
t*100 | Speed factor |
mod(t,5) | Loop every 5 seconds |
sin(t*3) | Oscillate 3 times/second |
exp(-t) | Exponential decay |
if(lt(t,2),expr1,expr2) | Conditional |
min(a,b) / max(a,b) | Min/max |
floor(t) / ceil(t) | Round down/up |
Useful Variables
| Variable | Meaning |
|---|---|
w | Video width |
h | Video height |
tw | Text width |
th | Text height |
n | Frame number |
frame_num | Same as n |
Common Patterns
# Appear after 2 seconds
enable='gte(t,2)'
# Visible between 2-5 seconds
enable='between(t,2,5)'
# Fade in over 1 second
alpha='min(1,t)'
# Center horizontally
x='(w-tw)/2'
# Center vertically
y='(h-th)/2'
# Loop position
x='mod(t*100,w)'
# Smooth oscillation
y='h/2+50*sin(t*3)'
# Decay animation
fontsize='100+50*exp(-t*2)'Sources
Enhanced with research from: