gpt-taste
gpt taste
ffmpeg-karaoke-animated-text
Complete karaoke subtitle system and advanced animated text effects. PROACTIVELY activate for: (1) Karaoke-style highlighted lyrics, (2) ASS/SSA advanced subtitle styling, (3) Scrolling credits (horizontal/vertical), (4) Typewriter text animation, (5) Bouncing/moving text, (6) Text fade in/out ef...
Full skill instructions
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 (/).
| Effect | Command |
|---|---|
| Scrolling credits | -vf "drawtext=textfile=credits.txt:y=h-80*t" |
| Typewriter | -vf "drawtext=text='Hello':enable='gte(t,n*0.1)'" |
| 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)'" |
| Karaoke ASS | Use ASS format with \k timing tags |
| Moving text | -vf "drawtext=text='Move':x='w-mod(t*100,w+tw)'" |
Use for animated text and karaoke:
Complete guide to karaoke subtitles, kinetic typography, scrolling credits, and advanced text animation with FFmpeg.
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}are
| 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).
ASS uses TWO DIFFERENT time unit systems - this is a common source of bugs!
| 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
| 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
| Expression | Unit | Example |
|---|---|---|
t | seconds | t=2.5 means 2.5 seconds |
enable='between(t,0,3)' | seconds | 0-3 seconds |
alpha='min(1,t/2)' | seconds | fade over 2 seconds |
| Seconds | Centiseconds (karaoke) | Milliseconds (animation) |
|---|---|---|
| 0.1s | 10 | 100 |
| 0.25s | 25 | 250 |
| 0.5s | 50 | 500 |
| 1.0s | 100 | 1000 |
| 2.0s | 200 | 2000 |
; 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 (centiseconds)
; \t(0,100,...) = 0-100ms = 0.1 seconds (milliseconds) - NOT THE SAME!
; CORRECT - consistent timing
Dialogue: 0,0:00:00.00,0:00:02.00,Style,,0,0,0,,{\k100\t(0,1000,...)}Word
; {\k100} = 1 second
; \t(0,1000,...) = 1 second - NOW THEY MATCH!
| 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 |
Based on syllable/word duration and desired effect:
\k (Instant Fill) - Best For:; Rap example (fast succession):
{\k25}Yo {\k20}this {\k15}is {\k30}rapid {\k25}fire {\k35}flow
\kf (Progressive Fill) - Best For:; Ballad example (sustained notes):
{\kf150}Loooooove {\kf120}yoooou {\kf180}foreeeever
Recommended: Use \kf for any syllable >100 centiseconds for smoothest visual effect.
\ko (Outline Reveal) - Best For:; 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}glow
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 midpoint
Color progression formula:
Start: &H0000FFFF (Yellow)
Mid: &H0000A5FF (Orange) - 50% through karaoke fill
End: &H000000FF (Red)
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 effects
When to use character-level karaoke:
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 center
Parameter tuning:
Simulate elastic material with multiple overshoots:
# 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 oscillation
Elastic parameters:
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:
1 - e^(-kt) creates natural deceleration1/(1+e^(-k(t-0.5))) creates smooth S-curve (ease-in-out)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:
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)
# 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 effect
# 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 second
# 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 change
# 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 boundaries
| 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 |
# 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 24fps
# 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 duration
Credits 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 seconds
Enhanced with research from:
# 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.mp4
[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}down
ASS uses &HAABBGGRR format (Alpha, Blue, Green, Red):
&H00FFFFFF = White (fully opaque)&H000000FF = Red&H0000FF00 = Green&H00FF0000 = Blue&H80000000 = 50% transparent black[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&)}Green
| 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) |
# 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/second
DIRECTED BY
John Smith
PRODUCED BY
Jane Doe
STARRING
Actor One
Actor Two
Actor Three
MUSIC BY
Composer Name
SPECIAL THANKS
Everyone
# 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.mp4
# 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/second
# 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:[email protected]:boxborderw=10" \
news_ticker.mp4
# 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.mp4
# 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.mp4
# 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
# Explanation: alpha goes from 0 to 1 over 2 seconds
# 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.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
# 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.mp4
# 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.mp4
# Spinning text (requires recent FFmpeg)
# Note: 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.mp4
# Name and title lower third
ffmpeg -i input.mp4 \
-vf "\
drawbox=x=50:y=h-150:w=500:h=100:[email protected]:t=fill,\
drawtext=text='John Smith':fontsize=36:fontcolor=white:\
x=70:y=h-140,\
drawtext=text='CEO, Company Inc.':fontsize=24:[email protected]:\
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:[email protected]:t=fill:\
enable='between(t,0,8)',\
drawtext=text='John Smith':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='CEO, Company Inc.':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.mp4
# 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 filename
ffmpeg -i input.mp4 \
-vf "drawtext=text='%{metadata\\:title}':\
fontsize=24:fontcolor=white:\
x=10:y=h-40" \
metadata.mp4
# Multi-line centered text
ffmpeg -i input.mp4 \
-vf "drawtext=text='Line One\nLine Two\nLine 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.mp4
| 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 |
| Variable | Meaning |
|---|---|
w | Video width |
h | Video height |
tw | Text width |
th | Text height |
n | Frame number |
frame_num | Same as n |
# 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)'
This guide covers FFmpeg karaoke and animated text. For basic subtitles see ffmpeg-captions-subtitles, for shapes see ffmpeg-shapes-graphics.
gpt taste
Premium brand-kit image generation for high-end identity systems, logo concepts, and visual-world presentations.
Premium website design-to-code skill that generates visual references first, then builds faithful frontend implementations.
Premium frontend image direction for landing pages and marketing sites, generating one distinct horizontal image per section.
Premium mobile app screen concepts and flows with clean hierarchy, strong imagery, and distinctive art direction.
Emil Kowalski's philosophy on UI polish, component design, and the invisible details that make software feel good.
Frontend design and iteration for production-grade interfaces, from concept to ship.
Reverse-engineer design tokens from public websites into starter token files for your project.
Builds an animation from scratch by making the decisions in the order that determines whether it feels right.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.
Chat-to-edit AI studio for product photos, portraits, branding, and video.
Generate your dream room in seconds.
Redesign your interior in seconds using AI
Transform rooms with AI-generated designs.
Transform Your Space with AI-Powered Japanese Interior Designs by Jife
AI-powered wireframes for non-designers.
Revolutionize Property Viewing with AI-Generated Floor Plans and Virtual Tours
Transform sketches into stunning architectural renders with AI.