#!/bin/bash # Example of concatenating multiple mp4s together with 1-second transitions between them. gltransition=( "angular" "Bounce" "BowTieHorizontal" "BowTieVertical" "BowTieWithParameter" "burn" "ButterflyWaveScrawler" "cannabisleaf" "circle" "CircleCrop" "circleopen" "colorphase" "ColourDistance" "CrazyParametricFun" "crosshatch" "crosswarp" "CrossZoom" "cube" "Directional" "directional-easing" "directionalwarp" "directionalwipe" "displacement" "DoomScreenTransition" "doorway" "Dreamy" "DreamyZoom" "fade" "fadecolor" "fadegrayscale" "FilmBurn" "flyeye" "GlitchDisplace" "GlitchMemories" "GridFlip" "heart" "hexagonalize" "InvertedPageCurl" "kaleidoscope" "LeftRight" "LinearBlur" "luma" "luminance_melt" "morph" "Mosaic" "multiply_blend" "perlin" "pinwheel" "pixelize" "polar_function" "PolkaDotsCurtain" "Radial" "randomNoisex" "randomsquares" "ripple" "rotate_scale_fade" "SimpleZoom" "squareswire" "squeeze" "StereoViewer" "swap" "Swirl" "tangentMotionBlur" "TopBottom" "undulatingBurnOut" "WaterDrop" "wind" "windowblinds" "windowslice" "wipeDown" "wipeLeft" "wipeRight" "wipeUp" "ZoomInCircles" ) length=${#gltransition[@]} interval=1 tpath="/ffmpeg/gl-transitions/transitions-20201217/" tpath="/ffmpeg/transitions/" x264="-look_ahead 0 -ac 2 -c:v h264_qsv -c:a aac -profile:v high -level 3.1 -preset:v veryfast" ki="-keyint_min 72 -g 72 -sc_threshold 0" br="-b:v 3000k -minrate 3000k -maxrate 6000k -bufsize 6000k -b:a 128k -avoid_negative_ts make_zero -fflags +genpts" duration=1 function get_duration_video_ffprobe(){ duration=$(ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=duration -of default=nokey=1:noprint_wrappers=1 "$1") duration=$(echo "scale=3; $duration/1"|bc -l) } function get_duration_audio_ffprobe(){ aduration=$(ffprobe -v error -count_frames -select_streams a:0 -show_entries stream=duration -of default=nokey=1:noprint_wrappers=1 "$1") aduration=$(echo "scale=3; $aduration/1"|bc -l) } MediaInfo="D:softMediaInfo_CLI_19.04_Windows_x64MediaInfo.exe" function get_duration_video_MediaInfo(){ # duration=$($MediaInfo --Inform="Video;%Duration/String3%" "$1") duration=$($MediaInfo --Inform="Video;%Duration%" "$1") duration=$(echo "scale=3; $duration/1000"|bc -l) } function get_duration_audio_MediaInfo(){ # duration=$($MediaInfo --Inform="Video;%Duration/String3%" "$1") aduration=$($MediaInfo --Inform="Audio;%Duration%" "$1") aduration=$(echo "scale=3; $aduration/1000"|bc -l) } # ls -u *.mp4 sort by time # ls *.mp4|sort sort by name line=-1 IFS=$(echo -en " ") for f in `ls *.mp4|sort`; do line=$((line+1)) get_duration_video_MediaInfo "${f}" get_duration_audio_MediaInfo "${f}" ifd=`echo "scale=0; ${aduration}*1000-${duration}*1000"|bc -l -q` ifd=${ifd/.000/} echo ${line} ${f} ${duration} - ${aduration} = $ifd if [[ ${ifd} -le 0 ]]; then duration=${aduration} fi #echo ${line} ${f} ${duration} duration_array[${line}]=${duration} filename_array[${line}]=${f} index_array[${line}]=${line} done vfstr="" for i in ${index_array[@]}; do catlen=0$(echo "scale=3; ${duration_array[$i]}-${interval}/2"|bc -l) catlen2=0$(echo "scale=3; ${duration_array[$i]}-${interval}"|bc -l) catlenhalf=0$(echo "scale=3; ${interval}/2"|bc -l) if [ ${i} -lt ${line} ] then if [ ${i} -eq 0 ] then vfstr=${vfstr}"[$i:a]atrim=0:$catlen[a$i];" else vfstr=${vfstr}"[$i:a]atrim=$catlenhalf:$catlen2[a$i];" fi else vfstr=${vfstr}"[$i:a]atrim=$catlenhalf:$catlen[a$i];" fi vfstr=${vfstr}"[$i:v]split[v${i}00][v${i}10];" done for i in ${index_array[@]}; do catlen=0$(echo ${duration_array[$i]}-${interval}|bc -l) vfstr=${vfstr}"[v${i}00]trim=0:$catlen[v${i}01];" vfstr=${vfstr}"[v${i}10]trim=$catlen:${duration_array[$i]}[v${i}11t];" vfstr=${vfstr}"[v${i}11t]setpts=PTS-STARTPTS[v${i}11];" done for ((i=0; i<$line; ++i)) ; do Index=$[i%(($length))] #Index=$[RANDOM%(($length))] echo ${gltransition[$Index]} vfstr=${vfstr}"[v${i}11][v$((i+1))01]gltransition=duration=${interval}:source=${tpath}${gltransition[$Index]}.glsl[vt${i}];" done vfstr=${vfstr}"[v001]" for ((i=0; i<$line; ++i)) ; do vfstr=${vfstr}"[vt${i}]" done vfstr=${vfstr}"[v${line}11]concat=n=$((line+2))[outv];" for i in ${index_array[@]}; do vfstr=${vfstr}"[a${i}]" done vfstr=${vfstr}"concat=n=$((line+1)):v=0:a=1[outa]" infile="" for i in ${filename_array[@]}; do infile=${infile}" -i "$i"" done if [ ! -d "merge" ];then mkdir merge fi echo ${vfstr} > _vfstr_.txt cmd="ffmpeg -hide_banner${infile} -filter_complex_script "_vfstr_.txt" -map [outv] -map [outa] ${x264} ${ki} ${br} -y ./merge/ffmpeg-gl-transition-concat.mp4" echo $cmd >_merge_.cmd #./_merge_.cmd echo ${cmd} bash -c "$cmd"
转场效果参考 https://v.huya.com/play/469910857.html
缺点:需要消耗大量内存,连接视频数量60个以上时可能提示内存不够
官方的 ffmpeg 不带这个滤镜,增加该滤镜参考 https://github.com/transitive-bullshit/ffmpeg-gl-transition