How do I add a 1 second fade out effect to the end of a video with ffmpeg?

For a 10 second duration video, 1 second fade in in beginning, 1 second fade out in the ending use the fade filter:

ffmpeg -i input.mp4 -vf "fade=type=in:duration=1,fade=type=out:duration=1:start_time=9" -c:a copy output.mp4

If you want to fade audio too then add the afade filter:

ffmpeg -i input.mp4 -filter_complex "[0:v]fade=type=in:duration=1,fade=type=out:duration=1:start_time=9[v];[0:a]afade=type=in:duration=1,afade=type=out:duration=1:start_time=9[a]" -map "[v]" -map "[a]" output.mp4

To automate it use ffprobe to get the duration and bc to calculate the start time for the fade out at the end:

#!/bin/bash
mkdir fade
for f in *.mp4; do
  dur=$(ffprobe -loglevel error -show_entries format=duration -of default=nk=1:nw=1 "$f")
  offset=$(bc -l <<< "$dur"-1)
  ffmpeg -i "$f" -filter_complex "[0:v]fade=type=in:duration=1,fade=type=out:duration=1:start_time='$offset'[v];[0:a]afade=type=in:duration=1,afade=type=out:duration=1:start_time='$offset'[a]" -map "[v]" -map "[a]" fade/"$f"
done

This assumes all inputs have video and audio. If not you can use an if/then statement in conjunction with ffprobe to determine if there is audio.

...and keep everything else the same (codec,quality)

Filtering requires encoding. You can't keep the quality when outputting a lossy format. Either output a lossless format (not recommended, huge files, compatibility issues), or accept some amount of loss. Luckily you probably won't notice. Just use the -crf option when outputting H.264 video. Use the highest value that still looks good enough. See FFmpeg Wiki: H.264 for more details.


  1. find out the number of frames in the video clip. Command:

    ffmpeg -i clip.mp4 -vcodec copy -f rawvideo -y /dev/null 2>&1 | tr ^M '\n' | awk '/^frame=/ {print $2}'|tail -n 1
    5130
    
  2. Find the frames per second

fps

it's 24

  1. Add fade in/out

    ffmpeg -i clip.mp4 -vf "fade=in:0:24,fade=out:5106:24" -acodec copy clip-out.mp4
    

Done