Modulate FFmpeg Volume Based on Time
This article explains how to dynamically modulate audio volume over
time using FFmpeg’s volume audio filter. You will learn the
correct syntax to enable continuous evaluation, the key variables
available for your mathematical formulas, and practical command-line
examples for creating fades and oscillating tremolo effects.
Enabling Time-Based Evaluation
By default, FFmpeg evaluates the volume filter’s
expression only once at the beginning of the stream. To change the
volume dynamically as the file plays, you must set the eval
parameter to frame. This forces FFmpeg to re-evaluate your
equation for every audio frame.
The basic filter syntax is:
-af "volume='EXPRESSION':eval=frame"
Key Variables for Equations
Within your expression, you can use several built-in FFmpeg
variables: * t: The current timestamp of
the audio frame in seconds. * n: The
sequential number of the audio frame. *
pos: The position of the frame in the
input file (in bytes). * PI: The
mathematical constant \(\pi\) (approx.
3.14159).
Practical Examples
1. Simple Tremolo (Sinusoidal Modulation)
To create an undulating volume effect (tremolo) that oscillates between 20% and 100% volume at a frequency of 2 Hz (twice per second), use the sine function:
ffmpeg -i input.mp3 -af "volume='0.6+0.4*sin(2*PI*2*t)':eval=frame" output.mp30.6is the baseline volume offset.0.4is the amplitude of the oscillation (modulating the volume by \(\pm 0.4\)).2*PI*2*tdefines the frequency of 2 Hz.
2. Custom Fade-In
While FFmpeg has a dedicated afade filter, you can
achieve a custom mathematical fade-in using the volume filter. To
linearly increase the volume from 0 to 1 over the first 5 seconds of a
file:
ffmpeg -i input.mp3 -af "volume='min(t/5, 1)':eval=frame" output.mp3t/5increases the volume from 0 at \(t=0\) to 1 at \(t=5\).min(..., 1)ensures the volume caps at 100% (1.0) and does not continue to increase after 5 seconds.
3. Delayed Fade-Out
To keep the volume at 100% for the first 10 seconds, and then linearly fade out to silent over the next 5 seconds (ending at 15 seconds):
ffmpeg -i input.mp3 -af "volume='clip(1 - (t-10)/5, 0, 1)':eval=frame" output.mp3t-10shifts the start of the fade to the 10-second mark.clip(..., 0, 1)restricts the output volume strictly between 0 (complete silence) and 1 (original volume), preventing negative volume values as time continues past 15 seconds.