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.
-
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
Find the frames per second
it's 24
-
Add fade in/out
ffmpeg -i clip.mp4 -vf "fade=in:0:24,fade=out:5106:24" -acodec copy clip-out.mp4
Done