Crop Video Using Time Variables in FFmpeg
Cropping a video dynamically based on playback time allows you to
create effects like panning, tracking, and smooth transitions without
third-party video editors. In FFmpeg, this is achieved using the native
crop video filter combined with internal evaluation
variables like t (current timestamp in seconds) and
n (current frame number). This guide demonstrates the
syntax, core variables, and real-world command examples for animating
crop coordinates over time.
The Crop Filter Syntax
The standard FFmpeg crop filter takes four primary parameters:
crop=w:h:x:yw: Output width.h: Output height.x: Horizontal position of the top-left corner of the crop area.y: Vertical position of the top-left corner of the crop area.
While w and h generally remain static to
prevent stream-level dimension mismatches, the x and
y offsets are evaluated per frame. This makes them capable
of evaluating mathematical expressions that change as playback
progresses.
Key Dynamic Variables
FFmpeg exposes several built-in variables inside crop filter expressions:
t: The current presentation timestamp in seconds.n: The sequential index of the current input frame (starting at 0).in_woriw: Input video width.in_horih: Input video height.out_worow: Output crop width.out_horoh: Output crop height.
Example 1: Linear Pan Across the Video
To move the crop window horizontally from left to right at a constant
speed, multiply t by a velocity value (pixels per
second):
ffmpeg -i input.mp4 -vf "crop=1280:720:'t*100':0" -c:a copy output.mp4In this command:
- The cropped resolution is fixed at
1280x720. - The horizontal coordinate
xadvances by 100 pixels for every second of video (t*100). - The vertical coordinate
yremains fixed at0.
To prevent the crop box from moving beyond the edge of the source
video, wrap the expression with min():
ffmpeg -i input.mp4 -vf "crop=1280:720:'min(t*100, in_w-out_w)':0" -c:a copy output.mp4Example 2: Oscillating (Back and Forth) Pan
You can use trigonometric functions like sin() or
cos() to create a looping, pendulum-style movement:
ffmpeg -i input.mp4 -vf "crop=1280:720:'(in_w-out_w)/2 + ((in_w-out_w)/2)*sin(t)':0" -c:a copy output.mp4Here, sin(t) fluctuates between -1 and
1 based on elapsed seconds, causing the horizontal crop
frame to oscillate smoothly across the entire width of the input
frame.
Example 3: Conditional Movement Based on Time Windows
You can shift crop positions only during specific segments of the
video using the if() and between()
functions.
To hold the crop box at x=0 for the first 5 seconds,
move it to x=300 between seconds 5 and 10, and center it
afterward:
ffmpeg -i input.mp4 -vf "crop=1280:720:'if(lt(t,5), 0, if(between(t,5,10), 300, (in_w-out_w)/2))':0" -c:a copy output.mp4Important Practical Considerations
- Quoting Expressions: Always enclose expressions
containing mathematical symbols or variable names in single quotes
inside the filter string (e.g.,
'min(t*50, in_w-out_w)') to prevent the shell from interpreting operators or commas. - Dimension Parity: Many video codecs (such as
H.264/AVC with
yuv420ppixel format) require even dimensions. When dynamically computing offsets, ensure resulting coordinates stay valid, or enforce even values usingtrunc(expr/2)*2. - Static Dimensions: The
wandhparameters should remain constant. If you need dynamic zooming (changing width and height over time), use thezoompanfilter instead ofcrop.