Skip to content

Instantly share code, notes, and snippets.

@coderofsalvation
Last active December 17, 2023 06:45
Show Gist options
  • Save coderofsalvation/8dd3cafd0d21d1fa6dd9cb0de8e58628 to your computer and use it in GitHub Desktop.
Save coderofsalvation/8dd3cafd0d21d1fa6dd9cb0de8e58628 to your computer and use it in GitHub Desktop.
ffmpeg commandline crossfade-looped video
#!/bin/bash
[[ ! -n $3 ]] && { echo "Usage: crossfadevideo <input.mp4> <fade in seconds> <output.mp4> [looptimes]"; exit; }
input="$1"
fade="$2"
duration="$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 "$input")"
duration=$(echo "$duration-($fade)" | bc | sed 's/\..*//g')
[[ ${duration:0:1} == "." ]] && duration="0$duration"
output="$3"
[[ -n $4 ]] && loop=$4 && output="${output}.mkv"
set -x
ffmpeg -y -i "$input" -filter_complex '
[0]split[body][pre];
[pre]trim=duration='$fade',format=yuva420p,fade=d='$fade':alpha=1,setpts=PTS+('$(($duration-$fade))'/TB)[jt];
[body]trim='$fade',setpts=PTS-STARTPTS[main];
[main][jt]overlay' "$output"
# we use mkv for looping since ffmpeg loops mp4 badly
[[ -n $loop ]] && ffmpeg -y -stream_loop $loop -i $output -c copy ${output/\.mkv/}
@pigubaoza
Copy link

pigubaoza commented Dec 17, 2023

im getting a freeze for fade seconds at the end of the video (if i do not provide looptimes), and also between every loop when i do provide looptimes. any idea how i can fix this?

this is my ffmpeg version

ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers
built with Apple clang version 14.0.3 (clang-1403.0.22.14.1)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/6.0_1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
libavutil      58.  2.100 / 58.  2.100
libavcodec     60.  3.100 / 60.  3.100
libavformat    60.  3.100 / 60.  3.100
libavdevice    60.  1.100 / 60.  1.100
libavfilter     9.  3.100 /  9.  3.100
libswscale      7.  1.100 /  7.  1.100
libswresample   4. 10.100 /  4. 10.100
libpostproc    57.  1.100 / 57.  1.100

EDIT: i think this is because im using a file with two streams. removing the audio stream fixes the problem. would be great if we can detect and handle such files in the script

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp42mp41
    creation_time   : 2021-12-11T19:25:10.000000Z
  Duration: 00:00:10.00, start: 0.000000, bitrate: 100323 kb/s
  Stream #0:0[0x1](eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160, 99986 kb/s, 30 fps, 30 tbr, 30k tbn (default)
    Metadata:
      creation_time   : 2021-12-11T19:25:10.000000Z
      handler_name    : ?Mainconcept Video Media Handler
      vendor_id       : [0][0][0][0]
      encoder         : AVC Coding
  Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 316 kb/s (default)
    Metadata:
      creation_time   : 2021-12-11T19:25:10.000000Z
      handler_name    : #Mainconcept MP4 Sound Media Handler
      vendor_id       : [0][0][0][0]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment