Claude Code Plugins

Community-maintained marketplace

Feedback

ffmpeg-animation-timing-reference

@JosiahSiegel/claude-plugin-marketplace
4
0

Definitive reference for FFmpeg and ASS/SSA animation timing units, optimal durations, and best practices. PROACTIVELY activate for: (1) Animation timing questions, (2) ASS subtitle timing, (3) Karaoke timing tags, (4) Caption duration calculation, (5) Transition duration selection, (6) Fade/zoom timing, (7) Frame rate considerations, (8) Platform-specific timing (TikTok/Shorts/Reels), (9) Readability formulas, (10) Audio-video sync tolerances. Provides: Complete time unit reference tables, optimal duration guidelines, psychology-based timing recommendations, caption readability formulas, and platform-specific timing profiles.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md


name: ffmpeg-animation-timing-reference description: Definitive reference for FFmpeg and ASS/SSA animation timing units, optimal durations, and best practices. PROACTIVELY activate for: (1) Animation timing questions, (2) ASS subtitle timing, (3) Karaoke timing tags, (4) Caption duration calculation, (5) Transition duration selection, (6) Fade/zoom timing, (7) Frame rate considerations, (8) Platform-specific timing (TikTok/Shorts/Reels), (9) Readability formulas, (10) Audio-video sync tolerances. Provides: Complete time unit reference tables, optimal duration guidelines, psychology-based timing recommendations, caption readability formulas, and platform-specific timing profiles.

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

Documentation Guidelines

NEVER create new documentation files unless explicitly requested by the user.


FFmpeg Animation Timing Reference (2025-2026)

Quick Reference Card

Context Unit Example
FFmpeg filters (fade, xfade, drawtext) Seconds duration=1.5
FFmpeg zoompan d= parameter Frames d=150 (150 frames)
FFmpeg time variable t Seconds enable='gte(t,2)'
ASS karaoke tags (\k, \kf, \ko) Centiseconds {\k100} = 1 second
ASS animation tags (\t, \fad, \move) Milliseconds \t(0,500,...) = 0.5s
ASS dialogue timestamps H:MM:SS.CC 0:00:05.50

CRITICAL: ASS Has TWO Different Time Units!

This is the most common source of confusion in subtitle animations.

ASS/SSA Time Unit Disambiguation

Tag Type Unit Conversion Example
Karaoke tags (\k, \kf, \ko, \K) Centiseconds (1/100s) × 100 {\k50} = 0.5 seconds
Animation tags (\t) Milliseconds (1/1000s) × 1000 \t(0,200,...) = 0.2 seconds
Fade tags (\fad) Milliseconds × 1000 \fad(300,0) = 0.3s fade in
Move tags (\move) Milliseconds × 1000 \move(x1,y1,x2,y2,0,500) = 0.5s
Dialogue timestamps H:MM:SS.CC Centiseconds 0:00:01.50 = 1.5 seconds

Example: Same Duration, Different Units

; Both animations last 0.5 seconds but use DIFFERENT UNITS:

; Karaoke: 50 CENTISECONDS = 0.5 seconds
{\k50}Word

; Animation: 500 MILLISECONDS = 0.5 seconds
{\t(0,500,\fscx120)}Word

Section 1: FFmpeg Time Units (All Filters)

Complete FFmpeg Time Unit Reference

Filter/Context Parameter Unit Example Notes
fade duration (d) Seconds fade=t=in:d=2 Floating point
fade start_time (st) Seconds fade=st=5:d=2 When fade begins
afade duration (d) Seconds afade=d=3 Audio fade
xfade duration Seconds duration=1.5 Transition length
xfade offset Seconds offset=4 When transition starts
acrossfade duration (d) Seconds acrossfade=d=1 Audio crossfade
drawtext t variable Seconds enable='gte(t,5)' Time since start
drawtext alpha 0-1 scale alpha='min(1,t/2)' Opacity over time
zoompan d Frames d=150 Duration in frames
zoompan t variable Seconds z='1+0.1*t' Time in expressions
fps fps Frames/second fps=30 Frame rate
trim start, end Seconds trim=start=2:end=10 Cut points
setpts PTS Timestamps setpts=PTS-STARTPTS Presentation timestamps

Frame Rate Conversion

Frame Rate 1 Frame Duration 30 Frames 60 Frames
24 fps 41.67 ms 1.25 s 2.5 s
25 fps 40 ms 1.2 s 2.4 s
30 fps 33.33 ms 1 s 2 s
50 fps 20 ms 0.6 s 1.2 s
60 fps 16.67 ms 0.5 s 1 s

Zoompan Duration Calculation

# zoompan d= parameter is in FRAMES, not seconds!

# For 2-second zoom at 30fps:
ffmpeg -i input.mp4 -vf "zoompan=z='1.2':d=60:s=1080x1920" output.mp4
# d=60 frames ÷ 30fps = 2 seconds

# For 2-second zoom at 60fps:
ffmpeg -i input.mp4 -vf "zoompan=z='1.2':d=120:s=1080x1920" output.mp4
# d=120 frames ÷ 60fps = 2 seconds

# Formula: frames = seconds × fps

Viral Video Timing Optimizations (2025-2026)

Based on the 1.3-second attention threshold research, hook animations must be fast and dramatic:

Effect Type FPS Effect Duration Frame Count d= Parameter
Hook zoom punch 60 0.4-0.5s 24-30 frames d=1 (use time conditional)
Hook flash 60 0.2-0.3s 12-18 frames d=1 (use time conditional)
Continuous zoom 30 Entire video N/A d=1 (recalc per frame)
Text animations 60 0.3-0.5s 18-30 frames d=1 (use time conditional)

Important: Always use d=1 for continuous per-frame processing. Limit effect duration using time conditionals like if(lt(t,0.5),effect,1) rather than setting d= to a frame count (which would freeze the video after that many frames).

Critical Rule: Hook animations MUST complete within 0.5 seconds to fit in the 1.3-second attention window with room for text/content.

Optimal Zoom Parameters by Platform

Platform Hook Zoom Hook Duration Continuous Zoom Recommended FPS
TikTok 1.5x (50%) 0.4-0.5s +0.2%/sec 60fps for hooks
YouTube Shorts 1.5x (50%) 0.5-0.6s +0.15%/sec 60fps throughout
Instagram Reels 1.4x (40%) 0.5-0.6s +0.18%/sec 60fps for hooks

Optimized Hook Effect Formulas

# 1.5x zoom punch over 0.5s at 60fps (RECOMMENDED):
# Always use d=1 for continuous processing; time conditional limits effect duration
fps=60,zoompan=z='if(lt(t,0.5),1.5-t,1)':d=1:s=1080x1920

# 8% zoom pulse at ~2Hz for 1.5s (sin(t*12) = 12 rad/s = 1.91 Hz):
fps=60,zoompan=z='if(lt(t,1.5),1+0.08*sin(t*12),1)':d=1:s=1080x1920

# Subtle continuous zoom for TikTok (0.2%/sec - minimum perceptible):
zoompan=z='1+0.002*t':d=1:s=1080x1920

# Subtle continuous zoom for YouTube Shorts (0.15%/sec - larger screens):
zoompan=z='1+0.0015*t':d=1:s=1080x1920

Section 2: ASS/SSA Subtitle Timing

Karaoke Tags (Centiseconds)

Tag Name Unit Effect
\k Karaoke Centiseconds Instant highlight (no fill)
\kf Karaoke Fill Centiseconds Progressive fill left-to-right
\ko Karaoke Outline Centiseconds Outline wipe effect
\K Karaoke (alt) Centiseconds Same as \k

Karaoke Timing Examples

; Each word highlights for the specified duration
; Values are in CENTISECONDS (100 = 1 second)

; 0.5 second per word:
{\k50}This {\k50}is {\k50}a {\k50}test

; Variable timing matching speech:
{\k30}The {\k25}quick {\k40}brown {\k35}fox

; Karaoke fill (progressive highlight):
{\kf100}Slowly {\kf150}highlighting {\kf80}each {\kf120}word

Conversion Table: Centiseconds

Centiseconds Seconds Common Use
10 0.1s Very fast syllable
25 0.25s Quick word
50 0.5s Normal word
100 1.0s Long word/pause
150 1.5s Extended emphasis
200 2.0s Dramatic pause

Animation Tags (Milliseconds)

Tag Format Unit Effect
\t \t(t1,t2,tags) Milliseconds Animate between t1 and t2
\fad \fad(in,out) Milliseconds Fade in/out duration
\move \move(x1,y1,x2,y2,t1,t2) Milliseconds Move from t1 to t2

Animation Timing Examples

; Animation over 300 milliseconds (0.3 seconds):
{\t(0,300,\fscx120\fscy120)}Pop effect

; Scale animation: 0-200ms scale up, 200-400ms scale down
{\fscx80\fscy80\t(0,200,\fscx110\fscy110)\t(200,400,\fscx100\fscy100)}Bounce

; Fade in over 500ms, no fade out:
{\fad(500,0)}Fade in text

; Move over 800ms:
{\move(0,1920,540,960,0,800)}Slide in from bottom

Conversion Table: Milliseconds

Milliseconds Seconds Common Use
50 0.05s Instant flash
100 0.1s Very fast animation
200 0.2s Quick pop/snap
300 0.3s Standard UI animation
500 0.5s Smooth transition
800 0.8s Noticeable movement
1000 1.0s Slow, deliberate
2000 2.0s Very slow, dramatic

Dialogue Timestamps (H:MM:SS.CC)

; Format: Hours:Minutes:Seconds.Centiseconds
; Dialogue line from 1.5s to 5.0s:
Dialogue: 0,0:00:01.50,0:00:05.00,Default,,0,0,0,,Your text here

; Examples:
0:00:00.00  = 0 seconds (start)
0:00:01.50  = 1.5 seconds
0:00:10.00  = 10 seconds
0:01:00.00  = 60 seconds (1 minute)
0:05:30.25  = 5 minutes, 30.25 seconds

Section 3: Optimal Animation Durations

Human Perception Thresholds

Timing Brain Response Application
<16ms Sub-perceptual Cannot perceive (below 60fps frame)
16-50ms Preattentive Flash effects, subliminal
50-100ms Motion detection Pattern interrupts, glitches
100-200ms Conscious recognition Quick animations, snappy UI
200-400ms Attention capture Standard animations
400-800ms Processing time Complex transitions
800ms-2s Contemplation Dramatic, emotional effects
>2s Extended focus Deliberate, artistic pacing

Recommended Durations by Effect Type

Text Animations

Effect Fast Standard Slow Notes
Word pop (scale) 100-150ms 150-250ms 250-400ms Material Design: 200ms
Fade in 200-300ms 300-500ms 500-800ms Smooth appearance
Fade out 150-250ms 200-400ms 400-600ms Slightly faster than fade in
Slide in 200-300ms 300-500ms 500-800ms Distance affects perception
Bounce 300-400ms 400-600ms 600-800ms Needs overshoot time
Typewriter 30-50ms/char 50-80ms/char 80-120ms/char Per character

Video Transitions (xfade)

Transition Fast Standard Slow Best For
Fade/Dissolve 0.3-0.5s 0.8-1.2s 1.5-2.5s Universal
Wipe 0.2-0.4s 0.5-0.8s 1.0-1.5s Directional energy
Slide 0.3-0.5s 0.6-1.0s 1.2-2.0s Dynamic movement
Circle/Iris 0.5-0.8s 1.0-1.5s 2.0-3.0s Dramatic reveal
Zoom 0.4-0.6s 0.8-1.2s 1.5-2.5s Impact, intensity
Pixelize 0.3-0.5s 0.5-0.8s 1.0-1.5s Glitch aesthetic

Hook Effects (First 1-3 Seconds)

Hook Type Effect Duration Total Hook Timing Pattern
Pattern Interrupt 50-150ms 0.5-1.5s Instant grab
Flash/Brightness 80-200ms 0.3-0.8s Quick pulse
Zoom Punch 200-400ms 1-2s Fast zoom-in, hold
Glitch 100-300ms 0.5-1.5s Multiple bursts
Text Slam 150-250ms 1-2s Quick appear, hold

Karaoke/Caption Animations

Content Duration Formula Example
Single word Word length × 50-100ms "Hello" = 250-500ms
Short phrase 1-2 seconds "Check this out"
Sentence Words ÷ 3 per second 9 words = 3 seconds
Reading captions See readability formula Based on WPM

Section 4: Caption Readability Formula

Reading Speed Standards

Audience Words Per Minute (WPM) Use Case
Slow readers 120-140 WPM Accessibility, elderly
Average 160-180 WPM Recommended default
Fast readers 200-220 WPM Experienced viewers
Skim reading 250-300 WPM Not recommended for video

Caption Duration Calculation

Formula

# Basic formula:
caption_duration = (word_count / words_per_minute) * 60

# With minimum duration (accessibility):
minimum_duration = 1.5  # seconds - WCAG recommendation
duration = max(minimum_duration, caption_duration)

# Conservative formula (recommended):
duration = max(1.5, (word_count / 160) * 60)

Quick Reference Table

Word Count @ 160 WPM @ 180 WPM Recommended
1-2 words 0.75s 0.67s 1.5s (minimum)
3 words 1.13s 1.0s 1.5s (minimum)
4 words 1.5s 1.33s 1.5s
5 words 1.88s 1.67s 1.9s
6 words 2.25s 2.0s 2.3s
8 words 3.0s 2.67s 3.0s
10 words 3.75s 3.33s 3.8s
15 words 5.63s 5.0s 5.6s

Python Implementation

def calculate_caption_duration(text: str, wpm: int = 160) -> float:
    """
    Calculate optimal caption display duration.

    Args:
        text: Caption text
        wpm: Words per minute (default 160 for comfortable reading)

    Returns:
        Duration in seconds
    """
    word_count = len(text.split())
    calculated = (word_count / wpm) * 60

    # WCAG minimum: 1.5 seconds for any caption
    minimum = 1.5

    # Add 0.5s buffer for cognitive processing
    buffer = 0.5

    return max(minimum, calculated + buffer)

# Examples:
print(calculate_caption_duration("Hello"))           # 1.5s (minimum)
print(calculate_caption_duration("This is a test")) # 2.0s
print(calculate_caption_duration("Check out this incredible transformation")) # 2.88s

Accessibility Guidelines (WCAG 2.2)

Guideline Requirement
Minimum duration 1.5 seconds for any caption
Maximum reading speed 200 WPM (3.3 words/second)
Character limit 42 characters per line (readability)
Lines per caption Maximum 2 lines
Persistence Caption visible for full duration

Section 5: Platform-Specific Timing

TikTok (Fast, Energetic)

Element Timing Notes
Cut/transition 0.5-1.5s between clips Fast pacing
Text animation 100-200ms Snappy, punchy
Hook window 1-1.5s Immediate grab
Caption duration 0.8-1.5s per phrase Short, readable
Zoom effects 200-400ms Quick, impactful
Optimal video length 15-30s (sweet spot) Completion rate focus

YouTube Shorts (Medium-Fast)

Element Timing Notes
Cut/transition 1-2s between clips Slightly slower than TikTok
Text animation 150-300ms Smooth but quick
Hook window 2-3s Slightly more time
Caption duration 1.2-2s per phrase More readable
Zoom effects 300-600ms Noticeable but smooth
Optimal video length 50-60s Algorithm favored

Instagram Reels (Aesthetic, Polished)

Element Timing Notes
Cut/transition 1.5-2.5s between clips More polished
Text animation 150-250ms Stylish timing
Hook window 2-3s Visual-first platform
Caption duration 1-1.8s per phrase Instagram style
Zoom effects 400-800ms Cinematic feel
Optimal video length 15-30s (trending) Engagement focused

Professional/Broadcast

Element Timing Notes
Cut/transition 2-4s between clips Deliberate pacing
Text animation 300-500ms Smooth, professional
Lower third entrance 400-600ms Broadcast standard
Caption duration 2-4s per phrase Full readability
Zoom effects 800-1500ms Subtle, cinematic
Typical segment 30-90s Standard TV timing

Section 6: Easing Functions and Natural Motion

Material Design Timing Standards

Animation Type Duration Easing Use Case
Small (icon, button) 100ms ease-out Micro-interactions
Medium (card, dialog) 200-300ms ease-in-out Standard UI
Large (page, panel) 300-500ms ease-out Major transitions
Complex (multi-element) 400-700ms ease-in-out Choreographed

FFmpeg Easing Expressions

Ease Out (Deceleration) - Elements Entering

# Ease out: fast start, slow finish
# Good for: Elements appearing, sliding in
-vf "drawtext=text='Hello':alpha='1-exp(-t*5)':fontsize=48:fontcolor=white:x=(w-tw)/2:y=(h-th)/2"

Ease In (Acceleration) - Elements Leaving

# Ease in: slow start, fast finish
# Good for: Elements disappearing, sliding out
-vf "drawtext=text='Goodbye':alpha='exp(-(5-t)*5)':fontsize=48:fontcolor=white:x=(w-tw)/2:y=(h-th)/2:enable='lt(t,5)'"

Bounce Effect

# Bounce: overshoot then settle
# Duration: 400-600ms recommended
-vf "drawtext=text='Bounce':y='h/2-50+50*exp(-t*3)*sin(t*15)':fontsize=48:fontcolor=white:x=(w-tw)/2"

Elastic Effect

# Elastic: spring-like oscillation
# Duration: 600-1000ms recommended
-vf "drawtext=text='Elastic':fontsize='48*(1+0.3*exp(-t*2)*sin(t*10))':fontcolor=white:x=(w-tw)/2:y=(h-th)/2"

Smooth Oscillation (Continuous)

# Pulse/float effect
# Period: 2-4 seconds per cycle
-vf "drawtext=text='Float':y='h/2+20*sin(t*2)':fontsize=48:fontcolor=white:x=(w-tw)/2"

Recommended Easing by Context

Context Function Duration
Element appearing 1-exp(-t*5) 200-400ms
Element disappearing exp(-t*5) 150-300ms
Emphasis/attention 1+0.2*sin(t*6) Continuous
Bounce entrance exp(-t*3)*sin(t*15) 400-600ms
Smooth transition Linear (no easing) Any

Section 10: Mathematical Animation Formula Reference

Complete Easing Function Formulas

Based on standard animation libraries (CSS, anime.js, React Spring) and adapted for FFmpeg.

Linear (No Easing)

f(t) = t

FFmpeg: alpha='t' or x='t*100'

Use for: Constant speed motion, mechanical effects

Quadratic Easing

Ease In (Acceleration):

f(t) = t²

FFmpeg: alpha='t*t'

Ease Out (Deceleration):

f(t) = 1 - (1-t)²

FFmpeg: alpha='1-(1-t)*(1-t)'

Ease In-Out:

f(t) = if(t < 0.5, 2*t², 1 - 2*(1-t)²)

FFmpeg: alpha='if(lt(t,0.5),2*t*t,1-2*(1-t)*(1-t))'

Cubic Easing

Ease In:

f(t) = t³

FFmpeg: alpha='t*t*t'

Ease Out:

f(t) = 1 - (1-t)³

FFmpeg: alpha='1-(1-t)*(1-t)*(1-t)'

Ease In-Out (Material Design Default):

f(t) = if(t < 0.5, 4*t³, 1 - 4*(1-t)³)

FFmpeg: alpha='if(lt(t,0.5),4*t*t*t,1-4*(1-t)*(1-t)*(1-t))'

Exponential Easing

Ease In:

f(t) = 2^(10*(t-1))

FFmpeg: alpha='exp(10*(t-1)*0.693)' (Note: 2^x = e^(x*ln(2)) where ln(2) ≈ 0.693)

Ease Out (Recommended for text appearing):

f(t) = 1 - 2^(-10*t)

FFmpeg: alpha='1-exp(-10*t*0.693)'

Sine Easing (Smooth, Gentle)

Ease In:

f(t) = 1 - cos(t*π/2)

FFmpeg: alpha='1-cos(t*1.571)' (Note: π/2 ≈ 1.571)

Ease Out:

f(t) = sin(t*π/2)

FFmpeg: alpha='sin(t*1.571)'

Ease In-Out:

f(t) = -(cos(π*t) - 1)/2

FFmpeg: alpha='-(cos(3.1416*t)-1)/2'

Circular Easing (Sharp Curve)

Ease In:

f(t) = 1 - sqrt(1 - t²)

FFmpeg: alpha='1-sqrt(1-t*t)'

Ease Out:

f(t) = sqrt(1 - (1-t)²)

FFmpeg: alpha='sqrt(1-(1-t)*(1-t))'

Elastic Easing (Overshoot with Oscillation)

Ease Out (Most Common):

f(t) = 2^(-10*t) * sin((t*10 - 0.75)*2π/3) + 1

FFmpeg approximation:

alpha='exp(-10*t*0.693)*sin((t*10-0.75)*2.094)+1'

(Note: 2π/3 ≈ 2.094)

Ease In:

f(t) = -2^(10*(t-1)) * sin((t*10 - 10.75)*2π/3)

FFmpeg:

alpha='-exp(10*(t-1)*0.693)*sin((t*10-10.75)*2.094)'

Bounce Easing (Multiple Bounces)

Ease Out (Complex, piecewise):

For FFmpeg, simplified bounce approximation:

# Single bounce (easier implementation):
alpha='if(lt(t,0.4),
         7.5625*t*t,
         if(lt(t,0.8),
            7.5625*(t-0.6)*(t-0.6)+0.75,
            7.5625*(t-0.9)*(t-0.9)+0.9375))'

Simplified damped oscillation bounce:

# More natural, continuous bounce:
alpha='1-abs(cos(t*4.5*3.1416))*exp(-t*6)'

Back Easing (Overshoot)

Ease Out (Slight overshoot then settle):

f(t) = 1 + c3 * (t-1)³ + c1 * (t-1)²
where c1 = 1.70158, c3 = c1 + 1

FFmpeg approximation:

# Simplified overshoot (10% beyond target):
alpha='if(lt(t,0.7),t*1.3,1+(1-t)*0.3)'

Spring Physics Mathematical Reference

Standard Spring System (Mass-Spring-Damper)

Differential equation:

m * x''(t) + c * x'(t) + k * x(t) = 0

Where:
m = mass
c = damping coefficient
k = spring stiffness (Hooke's constant)
x(t) = position at time t
x'(t) = velocity
x''(t) = acceleration

Key Parameters

Natural frequency:

ω_n = sqrt(k/m)

Damping ratio:

ζ = c / (2 * sqrt(k * m))

Damping Cases

Under-damped (0 < ζ < 1) - Bouncy, overshoots:

x(t) = e^(-ζ*ω_n*t) * [A*cos(ω_d*t) + B*sin(ω_d*t)]

Where:
ω_d = ω_n * sqrt(1 - ζ²)  (damped frequency)

Critically damped (ζ = 1) - No overshoot, fastest settle:

x(t) = (A + B*t) * e^(-ω_n*t)

Over-damped (ζ > 1) - Slow, sluggish:

x(t) = A*e^(r1*t) + B*e^(r2*t)
Where r1, r2 are real roots

Simplified Spring for UI Animation

Two-parameter approach (bounce + duration):

# Convert bounce and duration to spring parameters
mass = 1  # Normalized
stiffness = (2*π / duration)²

if bounce >= 0:
    damping = (1 - bounce) * 4*π / duration
else:
    damping = 4*π / (duration * (1 + bounce))

Bounce parameter mapping:

  • bounce = 0: Critically damped (no overshoot)
  • 0 < bounce < 1: Under-damped (1 = undamped oscillation)
  • bounce < 0: Over-damped (negative = slower settling)

FFmpeg Spring Implementation

Basic under-damped spring (stiffness=100, damping=10, mass=1):

# Calculate natural frequency and damping ratio:
# ω_n = sqrt(100/1) = 10
# ζ = 10 / (2*sqrt(100*1)) = 10/20 = 0.5 (under-damped)
# ω_d = 10 * sqrt(1 - 0.5²) = 10 * 0.866 = 8.66

# Position formula:
-vf "drawtext=text='SPRING':\
     y='(h-th)/2-50*exp(-5*t)*cos(8.66*t)':\
     fontsize=80:fontcolor=white:x=(w-tw)/2"

# Breakdown:
# -50 = initial displacement (50px below center)
# exp(-5*t) = exponential decay (damping term: ζ*ω_n = 0.5*10 = 5)
# cos(8.66*t) = oscillation at damped frequency

Tunable spring parameters for FFmpeg:

# Low bounce (ζ=0.8, quick settle):
y='(h-th)/2+amplitude*exp(-8*t)*sin(10*t)'

# Medium bounce (ζ=0.5, balanced):
y='(h-th)/2+amplitude*exp(-5*t)*sin(12*t)'

# High bounce (ζ=0.3, very bouncy):
y='(h-th)/2+amplitude*exp(-3*t)*sin(14*t)'

# Critical damping (ζ=1, no overshoot):
y='(h-th)/2+amplitude*exp(-10*t)*(1+10*t)'

Oscillation and Wave Formulas

Basic Trigonometric Functions

Sine wave (smooth oscillation):

y = A * sin(ω*t + φ)

Where:
A = amplitude (peak height)
ω = angular frequency (rad/s)
t = time (seconds)
φ = phase offset (radians)

Frequency conversion:

ω = 2πf
where f = frequency in Hz (cycles/second)

Examples:
1 Hz = 6.28 rad/s (ω = 2π * 1)
2 Hz = 12.56 rad/s (ω = 2π * 2)
3 Hz = 18.85 rad/s (ω = 2π * 3)

FFmpeg examples:

# 2 Hz oscillation (2 cycles/second):
y='50*sin(12.56*t)'

# 1 Hz with phase offset (starts at peak):
y='50*sin(6.28*t+1.571)'  # φ = π/2 = 1.571

# Cosine (90° phase shifted sine):
y='50*cos(6.28*t)'  # equivalent to sin(t + π/2)

Amplitude Modulation (AM)

Variable amplitude sine wave:

y = A(t) * sin(ω*t)

FFmpeg decaying oscillation:

# Exponential amplitude decay:
y='50*exp(-2*t)*sin(10*t)'

# Linear amplitude decay:
y='50*max(0,1-t)*sin(10*t)'

# Pulsing amplitude (low frequency modulates high frequency):
y='(30+20*sin(2*t))*sin(20*t)'
#    ↑ envelope     ↑ carrier wave

Frequency Modulation (FM)

Variable frequency sine wave:

y = A * sin(ω(t)*t)

FFmpeg examples:

# Accelerating oscillation (siren effect):
y='50*sin(5*t*t)'  # frequency increases linearly

# Decelerating oscillation:
y='50*sin(20*t-5*t*t)'  # frequency decreases

# Vibrato (musical wobble):
y='50*sin(10*t+2*sin(3*t))'
#          ↑ base  ↑ vibrato modulation

Lissajous Curves (2D Parametric Motion)

Circular motion:

x = r * cos(ω*t)
y = r * sin(ω*t)

FFmpeg circular orbit:

-vf "drawtext=text='○':\
     x='(w/2)+200*cos(2*t)':\
     y='(h/2)+200*sin(2*t)':\
     fontsize=40:fontcolor=white"

Elliptical motion:

# a=200 (horizontal radius), b=100 (vertical radius)
x='(w/2)+200*cos(2*t)'
y='(h/2)+100*sin(2*t)'

Figure-8 motion (Lissajous 1:2 ratio):

x='(w/2)+150*sin(1*t)'
y='(h/2)+150*sin(2*t)'

Noise and Randomness Functions

Pseudo-Random with Sine

FFmpeg doesn't have true random(), but we can approximate:

# Pseudo-random using high-frequency sine:
'10*sin(t*137.5)'  # 137.5 is irrational, appears random

# Multi-layered pseudo-random:
'5*sin(t*137.5)+3*sin(t*241.3)+2*sin(t*89.7)'

Perlin-like Noise (Smooth Random)

# Smooth noise using multiple sine waves:
noise = 'sin(t*2.3)+0.5*sin(t*5.1)+0.25*sin(t*11.7)'

# Normalized to 0-1 range:
normalized_noise = '(sin(t*2.3)+0.5*sin(t*5.1)+0.25*sin(t*11.7)+1.75)/3.5'

Jitter/Shake Effects

Continuous shake:

# High frequency, small amplitude:
x='(w-tw)/2+5*sin(t*50)'
y='(h-th)/2+5*cos(t*47)'  # Different freq for 2D randomness

Decaying shake (impact):

# Shake that settles over time:
x='(w-tw)/2+10*exp(-t*3)*sin(t*50)'
y='(h-th)/2+10*exp(-t*3)*cos(t*47)'

Triggered shake (specific moments):

# Shake only between t=2s and t=2.5s:
x='(w-tw)/2+if(between(t,2,2.5),15*sin(t*60),0)'

Practical Animation Cookbook

Fade Transitions

Fade in (0 to 1 over duration):

# Linear: alpha='min(1,t/duration)'
alpha='min(1,t/0.5)'  # 0.5s fade in

# Ease out: alpha='1-exp(-k*t)'
alpha='1-exp(-5*t)'  # Smooth fade in

# Cubic: alpha='min(1,t/duration)^3'
alpha='min(1,(t/0.5)*(t/0.5)*(t/0.5))'

Fade out (1 to 0):

# Assuming video duration = 10s, fade out in last 2s:
alpha='if(gt(t,8),1-(t-8)/2,1)'

# Exponential fade out:
alpha='if(gt(t,8),exp(-(t-8)*3),1)'

Fade in and out:

# Fade in 0-1s, hold 1-9s, fade out 9-10s:
alpha='if(lt(t,1),t,if(gt(t,9),10-t,1))'

Scale Animations

Pop in (scale 0 to 100%):

# FFmpeg drawtext (no scale support, use ASS instead)

# ASS:
{\fscx0\fscy0\t(0,300,\fscx100\fscy100)}Text

Pulse (continuous breathing):

# ASS:
fontsize='72+8*sin(t*6.28)'  # 1 Hz pulse, ±8px

# ASS pulse with hold:
{\t(0,300,\fscx110\fscy110)\t(300,600,\fscx100\fscy100)}

Bounce scale:

# ASS overshoot bounce:
{\fscx50\fscy50\t(0,150,\fscx115\fscy115)\t(150,300,\fscx95\fscy95)\t(300,450,\fscx100\fscy100)}

Position Animations

Slide in from right:

x='if(lt(t,1),w-(w-target_x)*t,target_x)'
# Example: target_x = (w-tw)/2 (center)
x='if(lt(t,1),w-((w-(w-tw)/2)*t),(w-tw)/2)'

Slide in with ease-out:

x='if(lt(t,1),w-((w-(w-tw)/2)*(1-exp(-5*t))),(w-tw)/2)'

Bounce in from bottom:

# ASS:
{\move(540,1920,540,960,0,400)\t(0,150,\fscy115)\t(150,300,\fscy95)\t(300,400,\fscy100)}

Circular path:

x='(w/2)+radius*cos(speed*t)'
y='(h/2)+radius*sin(speed*t)'

Rotation Animations

FFmpeg drawtext doesn't support rotation. Use ASS:

; Continuous spin (360° over 2 seconds):
{\t(0,2000,\frz360)}Text

; Wobble rotation:
{\t(0,200,\frz15)\t(200,400,\frz-10)\t(400,600,\frz5)\t(600,800,\frz0)}

Timing Psychology and Perception

Human Perception Thresholds

Threshold Duration Perception Use Case
Flicker fusion 16-20ms Below this: perceived as continuous 60fps = 16.67ms/frame
Preattentive 20-50ms Detected but not consciously processed Subliminal cues
Attention capture 50-100ms Minimum for conscious recognition Flash effects
Pattern interrupt 100-200ms Breaks expectation, grabs attention Hook effects
Comfortable transition 200-400ms Natural UI timing Standard animations
Deliberate motion 400-800ms Noticeable, purposeful Dramatic emphasis
Sustained attention 800ms-2s Holds focus Title cards, captions
Cognitive processing 2-5s Complex information Infographic reveals

Animation Duration Guidelines by Distance

Relationship between distance and duration for perceived constant speed:

duration = sqrt(distance) * k

Where:
distance = pixels traveled
k = speed constant (typically 5-15)

Example:
100px move: duration = sqrt(100) * 10 = 100ms
400px move: duration = sqrt(400) * 10 = 200ms
(Appears same speed despite 4x distance)

FFmpeg implementation:

# Move text 500px in 224ms (sqrt(500)*10):
-vf "drawtext=text='MOVE':\
     x='if(lt(t,0.224),(w-500)+500*t/0.224,w)':\
     y=(h-th)/2:fontsize=80:fontcolor=white"

Biological Rhythms

Natural timing that feels "right":

Rhythm Rate Use Case
Resting heartbeat 60-80 BPM (1-1.3 Hz) Calm, meditative pulse
Walking pace 100-120 BPM (1.7-2 Hz) Comfortable, steady rhythm
Excited/anxious 120-160 BPM (2-2.7 Hz) Energetic, urgent feeling
Breathing 12-20/min (0.2-0.33 Hz) Slow, natural oscillation

FFmpeg examples:

# Heartbeat pulse (70 BPM = 1.17 Hz):
fontsize='72+6*max(0,sin(t*7.33))'

# Walking pace pulse (110 BPM = 1.83 Hz):
fontsize='72+4*abs(sin(t*11.5))'

# Breathing (15 breaths/min = 0.25 Hz):
fontsize='72+10*sin(t*1.57)'

Sources

This comprehensive timing reference compiled from:


Section 7: Audio-Video Sync Tolerances

Synchronization Thresholds

Sync Type Maximum Tolerance Recommended Notes
Lip sync ±80ms ±40ms Human perception limit
Music beat sync ±50ms ±20ms Musical precision
Karaoke lyrics ±100ms ±30ms Comfortable singing
Sound effects ±30ms ±10ms Impact synchronization
Transition + audio ±100ms ±50ms Cross-fade sync

Practical Guidelines

Lip Sync

Tolerance: ±80ms (audio can lead or lag video by 80ms)
Recommendation: Keep within ±40ms for professional quality

Audio Leading (negative offset): Less noticeable, up to -80ms acceptable
Audio Lagging (positive offset): More noticeable, keep under +40ms

Music Sync

# Calculate beat timing:
# 120 BPM = 2 beats/second = 500ms per beat
# 140 BPM = 2.33 beats/second = 429ms per beat

# Align transitions to beat:
# At 120 BPM, beats fall at: 0ms, 500ms, 1000ms, 1500ms, 2000ms...

Karaoke Timing

Word highlight should START when word begins (not before)
Early highlight: Confusing, breaks immersion
Late highlight: Frustrating for singers

Recommendation: Highlight 0-50ms AFTER word starts (slight lag preferred)

Section 8: Frame Rate Considerations

Timing Precision Limits

Frame Rate Frame Duration Precision Limit
24 fps 41.67ms ~40ms increments
25 fps 40ms 40ms increments
30 fps 33.33ms ~33ms increments
60 fps 16.67ms ~17ms increments

Implications

Animation Smoothness

For smooth animation, use durations that are multiples of frame duration:

30fps:
- 100ms = 3 frames (smooth)
- 200ms = 6 frames (smooth)
- 333ms = 10 frames (smooth)
- 150ms = 4.5 frames (may stutter)

60fps:
- 100ms = 6 frames (smooth)
- 200ms = 12 frames (smooth)
- 167ms = 10 frames (smooth)

Minimum Visible Duration

Animation duration must be at least 2-3 frames to be perceived:
- 30fps minimum: ~67-100ms
- 60fps minimum: ~33-50ms

Very short effects (<50ms) may not render consistently

Frame-Safe Duration Table

Desired Duration 30fps Safe 60fps Safe
~100ms 100ms (3f) 100ms (6f)
~150ms 167ms (5f) 150ms (9f)
~200ms 200ms (6f) 200ms (12f)
~250ms 233ms (7f) 250ms (15f)
~300ms 300ms (9f) 300ms (18f)
~500ms 500ms (15f) 500ms (30f)

Section 9: Quick Copy-Paste Reference

FFmpeg Common Timing Patterns

# 2-second fade in:
-vf "fade=t=in:d=2"

# Text visible from 1s to 5s:
-vf "drawtext=text='Hello':enable='between(t,1,5)':..."

# 1.5s xfade starting at 4s:
-filter_complex "[0:v][1:v]xfade=duration=1.5:offset=4"

# 2-second zoom at 30fps (60 frames):
-vf "zoompan=z='1.5':d=60:s=1080x1920"

# Fade text in over 0.5s, hold, fade out over 0.3s:
-vf "drawtext=text='Hello':alpha='if(lt(t,0.5),t/0.5,if(lt(t,4.7),1,(5-t)/0.3))':enable='lt(t,5)':..."

ASS Common Timing Patterns

; Word karaoke (centiseconds): 0.5s + 0.4s + 0.6s + 0.5s
{\k50}This {\k40}is {\k60}the {\k50}test

; 200ms pop animation (milliseconds):
{\fscx80\fscy80\t(0,200,\fscx100\fscy100)}Pop

; 500ms slide + 300ms fade:
{\move(0,1920,540,960,0,500)\fad(300,0)}Slide in

; Bounce: 150ms up, 100ms overshoot, 150ms settle (total 400ms)
{\fscx90\fscy90\t(0,150,\fscx110\fscy110)\t(150,250,\fscx95\fscy95)\t(250,400,\fscx100\fscy100)}Bounce

Duration Cheat Sheet

Duration Use For
50-100ms Glitch, flash
100-200ms Quick UI feedback
200-300ms Standard animation
300-500ms Smooth transition
500-800ms Noticeable movement
800-1500ms Dramatic effect
1.5-3s Caption display
3-5s Long text reading

Related Skills

  • ffmpeg-karaoke-animated-text - Karaoke subtitle creation
  • viral-video-animated-captions - CapCut-style animations
  • ffmpeg-transitions-effects - Video transitions
  • viral-video-hook-templates - Hook timing patterns
  • ffmpeg-captions-subtitles - Subtitle fundamentals