Change Audio Volume Over Time with FFmpeg sendcmd

This article explains how to dynamically alter the volume of an audio track at specific timestamps using FFmpeg’s sendcmd filter. You will learn how to format the command text file, construct the FFmpeg command line, and apply precise volume transitions to your audio files without needing to split and re-merge them.

Understanding the sendcmd and volume Filters

The sendcmd (send command) filter in FFmpeg allows you to pass commands to other filters at precise time intervals during processing. When paired with the volume filter, you can instruct FFmpeg to change the audio level at specific seconds or frames.

To make this work, the volume filter must be set to evaluate the volume parameter on every frame using eval=frame. By default, the volume filter only calculates the volume level once at the start of the stream.


Step 1: Create the Commands File

The cleanest way to use sendcmd is by writing your time-based instructions in a separate text file. Create a file named commands.txt and define your volume changes using the following syntax:

[time] [filter_target] [parameter] [value];

For example, to start the audio at full volume, drop it to 20% at 2 seconds, and bring it back to full volume at 5 seconds, write the following inside commands.txt:

0.0 volume volume 1.0;
2.0 volume volume 0.2;
5.0 volume volume 1.0;

Step 2: Run the FFmpeg Command

Once your commands.txt file is saved in the same directory, run the following FFmpeg command to apply the changes:

ffmpeg -i input.mp3 -filter_complex "sendcmd=f=commands.txt,volume=eval=frame" output.mp3

Command breakdown: * -i input.mp3: Your input audio file. * -filter_complex: Invokes the filter graph. * sendcmd=f=commands.txt: Points FFmpeg to your command file. * volume=eval=frame: Enables the volume filter and forces it to listen for real-time command updates on a per-frame basis. * output.mp3: Your processed audio file with dynamic volume changes.


Alternative: Writing Commands Inline (No File Required)

If you only have one or two quick volume changes, you can write the commands directly into the terminal string using the c (command) argument instead of f (file).

Use semicolons to separate multiple commands:

ffmpeg -i input.mp3 -filter_complex "sendcmd=c='2.0 volume volume 0.1; 6.0 volume volume 1.0',volume=eval=frame" output.mp3

This inline command keeps the volume at its original level until the 2-second mark, lowers it to 10%, and then restores it to 100% at the 6-second mark.