Skip to content
ffmpeg-karaoke-animated-text logo

FFmpeg Karaoke & Animated Text (2025)

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...

SKILL.md

Full skill instructions

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 (/).


Quick Reference

EffectCommand
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 ASSUse ASS format with \k timing tags
Moving text-vf "drawtext=text='Move':x='w-mod(t*100,w+tw)'"

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
  • Countdown timers

FFmpeg Karaoke & Animated Text (2025)

Complete guide to karaoke subtitles, kinetic typography, scrolling credits, and advanced text animation with FFmpeg.

Karaoke Subtitles (ASS/​SSA Format)

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}are

Karaoke Timing Tags

TagEffectExample
\kFill from left{\k100}Word = 1 second fill
\kf or \KSmooth fill (fade){\kf100}Word
\koOutline highlight{\ko100}Word

Duration is in centiseconds (100 = 1 second).


CRITICAL: ASS Time Unit Reference

ASS uses TWO DIFFERENT time unit systems - this is a common source of bugs!

Karaoke Tags = CENTISECONDS (1/​100 second)

TagUnitExampleDuration
\kcentiseconds{\k50}0.5 seconds
\kfcentiseconds{\kf100}1.0 second
\kocentiseconds{\ko25}0.25 seconds

Conversion: seconds × 100 = centiseconds

Animation Tags = MILLISECONDS (1/​1000 second)

TagUnitExampleDuration
\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 (with decimals)

ExpressionUnitExample
tsecondst=2.5 means 2.5 seconds
enable='between(t,0,3)'seconds0-3 seconds
alpha='min(1,t/​2)'secondsfade over 2 seconds

Quick Conversion Table

SecondsCentiseconds (karaoke)Milliseconds (animation)
0.1s10100
0.25s25250
0.5s50500
1.0s1001000
2.0s2002000

Common Mistake Example

; 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!

Advanced Karaoke Timing Parameters (2026 Research)

Optimal Karaoke Timing by Song Tempo

BPM RangeSyllable DurationTag ValueNotes
60-80 (Slow ballad)600-800ms\kf60-80Long, emotional
80-100 (Moderate)400-600ms\kf40-60Standard pop
100-120 (Upbeat)300-500ms\kf30-50Most common
120-140 (Fast)250-400ms\kf25-40Energetic
140+ (Rapid)200-300ms\kf20-30Rap, EDM

Karaoke Tag Selection Guide

Based on syllable/​word duration and desired effect:

\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}foreeeever

Recommended: 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}glow

Multi-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 midpoint

Color progression formula:

Start: &H0000FFFF (Yellow)
Mid:   &H0000A5FF (Orange) - 50% through karaoke fill
End:   &H000000FF (Red)

Per-Character Karaoke (Fine-Grained Control)

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:

  • Slow-motion word reveal
  • Dramatic emphasis
  • Non-linear character highlighting (e.g., every other letter)

Advanced Text Animation Formulas (FFmpeg Drawtext)

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 center

Parameter 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

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:

  • 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 effect
Vertical 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 second

Countdown 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 change
Split-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 boundaries

Optimal Animation Timing by Content Type

Music Video Karaoke

GenreSyllable TimingAnimation StyleColor Scheme
Ballad100-200 centiseconds\kf smooth fillWhite → Soft Blue
Pop40-80 centiseconds\kf with bounceWhite → Bright Pink
Rap15-40 centiseconds\k instantWhite → Red
Rock50-100 centiseconds\k with shakeWhite → Orange
EDM30-60 centiseconds\ko outlineNeon 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 24fps

Scrolling 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 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

Sources

Enhanced with research from:


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.mp4

Advanced 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}down

ASS 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&)}Green

ASS Animation Tags Reference

TagEffect
\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, \fscyScale X/​Y percentage
\frx, \fry, \frzRotate on axis
\pos(x,y)Position text
\an1-9Alignment (numpad positions)

Scrolling 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/​second

credits.txt Format

DIRECTED BY
John Smith

PRODUCED BY
Jane Doe

STARRING
Actor One
Actor Two
Actor Three

MUSIC BY
Composer Name

SPECIAL THANKS
Everyone

Scrolling 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.mp4

Horizontal 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/​second

Looping 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:[email protected]:boxborderw=10" \
  news_ticker.mp4

Typewriter 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.mp4

Typewriter 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.mp4

Text Fade Effects

Fade In

# 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

# 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

Fade In and Out

# 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

Moving Text

Bouncing 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

Circular Motion

# 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

Enter from Side

# 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

Kinetic Typography

Word Pop Effect

# 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

Shake Effect

# 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

Rotation Animation

# 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

Lower Thirds

Basic Lower Third

# 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

Animated Lower Third

# 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

Countdown Timer

Simple Countdown

# 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

Countdown with Animation

# 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

Stopwatch/​Timer

# 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

Dynamic Text from Variables

Frame Number Display

# Show frame number
ffmpeg -i input.mp4 \
  -vf "drawtext=text='Frame\\: %{frame_num}':\
       fontsize=24:fontcolor=white:\
       x=10:y=10" \
  frame_numbers.mp4

Timecode Display

# 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

File Metadata Display

# Show filename
ffmpeg -i input.mp4 \
  -vf "drawtext=text='%{metadata\\:title}':\
       fontsize=24:fontcolor=white:\
       x=10:y=h-40" \
  metadata.mp4

Multi-Line Text

Centered Multi-Line

# 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

Text File Input

# 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 Reference

Useful Time Expressions

ExpressionResult
tCurrent time in seconds
t*100Speed 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

VariableMeaning
wVideo width
hVideo height
twText width
thText height
nFrame number
frame_numSame 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)'

This guide covers FFmpeg karaoke and animated text. For basic subtitles see ffmpeg-captions-subtitles, for shapes see ffmpeg-shapes-graphics.

More Design skills

brandkit logo
Design

brandkit

Premium brand-kit image generation for high-end identity systems, logo concepts, and visual-world presentations.

92.7K 345.8K
View

Premium website design-to-code skill that generates visual references first, then builds faithful frontend implementations.

92.7K 341.7K
View

Premium frontend image direction for landing pages and marketing sites, generating one distinct horizontal image per section.

92.7K 337.8K
View

Premium mobile app screen concepts and flows with clean hierarchy, strong imagery, and distinctive art direction.

92.7K 331.8K
View

Emil Kowalski's philosophy on UI polish, component design, and the invisible details that make software feel good.

43.5K 323.4K
View

Frontend design and iteration for production-grade interfaces, from concept to ship.

76.8K 313.3K
View

Reverse-engineer design tokens from public websites into starter token files for your project.

232 129.9K
View
Animate logo
Design

Animate

Builds an animation from scratch by making the decisions in the order that determines whether it feels right.

43.5K 117.9K
View

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.

179.7K 114.2K
View

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.

179.7K 100.1K
View

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.

179.7K 89.5K
View

Design AI tools

Maze Guru logo
Images

Maze Guru

Chat-to-edit AI studio for product photos, portraits, branding, and video.

Freemium
View
R
Design

RoomGPT

Generate your dream room in seconds.

Paid
View

Redesign your interior in seconds using AI

Paid
View
Reroom logo
Design

Reroom

Transform rooms with AI-generated designs.

Freemium
View
Jife logo
Design

Jife

Transform Your Space with AI-Powered Japanese Interior Designs by Jife

Paid
View
Visily logo
Design

Visily

AI-powered wireframes for non-designers.

Free
View

Revolutionize Property Viewing with AI-Generated Floor Plans and Virtual Tours

Paid
View
Archsynth logo
Design

Archsynth

Transform sketches into stunning architectural renders with AI.

Paid
View