coco
coco

Reputation: 3136

Complex audio volume changes with ffmpeg

Using ffmpeg, how much control can we have over the audio levels? For example, I would like to map an "M" shape over the program's timeline:

t0 - t1 : fade in from 0 to 1
t1 - t2 : play at full volume
t2 - t3 : fade out to 25%
t3 - t4 : play at 25% volume
t4 - t5 : fade in (from 25%) to full volume
t5 - t6 : play at full volume
t6 - t7 : fade out from 1 to 0

Can this be done? The combinations I've tried (of afade and volume, and using timeline editing) have not been successful so far.

Here is something that is close:

ina="infile.caf"
out="outfile.mp3"

time ffmpeg -i $ina -af \
"afade=enable='between(t,0,3)':t=in:ss=0:d=3, \
afade=enable='between(t,7,8)':t=out:st=7:d=1, \
volume=enable='between(t,8,12)':volume=.25:eval=frame, \
afade=enable='between(t,12,13)':t=in:st=12:d=1, \
afade=enable='between(t,15,18)':t=out:st=15:d=3" \
$out

.. but at the two middle points (the point where it fades out to 25%, and the point where it fades back in to full volume) there are glitches - audible sound clicks.

Upvotes: 9

Views: 3085

Answers (2)

coco
coco

Reputation: 3136

As an alternative to the (great) answer by @Mulvya, here is a method using the volume filter that produces the same output:

infile="infile.caf"
outfile="outfile.mp3"

ffmpeg -i $ina -af \
"volume=enable='between(t,0,3)':volume='t / 3.0':eval=frame, \
volume=enable='between(t,3,7)':volume='1':eval=frame, \
volume=enable='between(t,7,8)':volume='1 - 0.75 * (t - 7)':eval=frame, \
volume=enable='between(t,8,12)':volume='0.25':eval=frame, \
volume=enable='between(t,12,13)':volume='.25 + 0.75 * (t - 12)':eval=frame, \
volume=enable='between(t,13,15)':volume='1':eval=frame, \
volume=enable='between(t,15,18)':volume='1 - (t - 15) / 3.0':eval=frame" \
$out

Upvotes: 8

Gyan
Gyan

Reputation: 93048

I was going to suggest to do it entirely using volume filters, but it can be done the current way with minor modifications.

ffmpeg -i $ina -af \
"afade=enable='between(t,0,3)':t=in:ss=0:d=3, \
afade=enable='between(t,7,8)':t=out:st=7:d=1.333, \
volume=enable='between(t,8,12)':volume=.25:eval=frame, \
afade=enable='between(t,12,13)':t=in:st=11.6667:d=1.333, \
afade=enable='between(t,15,18)':t=out:st=15:d=3" \
$out

Fade filters go to or start from zero, so the trick is to set your fade start time, duration, and enabled range such that the volume at the range start and end time is at the level desired. The default curve is linear, so the calculations should be simple.

Upvotes: 6

Related Questions