Created
December 6, 2018 15:09
-
-
Save tanersener/fb856529ca09785db461a4ae96eaf470 to your computer and use it in GitHub Desktop.
push_vertical.sh script in reverse order, images pushed/pulled from bottom to top
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# ffmpeg video slideshow script with vertical push transition v2 (01.12.2018) | |
# | |
# Copyright (c) 2017-2018, Taner Sener (https://github.com/tanersener) | |
# | |
# This work is licensed under the terms of the MIT license. For a copy, see <https://opensource.org/licenses/MIT>. | |
# | |
# SCRIPT OPTIONS - CAN BE MODIFIED | |
WIDTH=1280 | |
HEIGHT=720 | |
FPS=30 | |
TRANSITION_DURATION=1 | |
PHOTO_DURATION=2 | |
BACKGROUND_COLOR="black" | |
# PHOTO OPTIONS - ALL FILES UNDER photos FOLDER ARE USED - USE sort TO SPECIFY A SORTING MECHANISM | |
# PHOTOS=`find ../photos/* | sort -r` | |
PHOTOS=`find ../photos/*` | |
############################ | |
# DO NO MODIFY LINES BELOW | |
############################ | |
# CALCULATE LENGTH MANUALLY | |
let PHOTOS_COUNT=0 | |
for photo in ${PHOTOS}; do (( PHOTOS_COUNT+=1 )); done | |
if [[ ${PHOTOS_COUNT} -lt 2 ]]; then | |
echo "Error: photos folder should contain at least two photos" | |
exit 1; | |
fi | |
# INTERNAL VARIABLES | |
TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) | |
PHOTO_FRAME_COUNT=$(( PHOTO_DURATION*FPS )) | |
TOTAL_DURATION=$(( (PHOTO_DURATION+TRANSITION_DURATION)*PHOTOS_COUNT - TRANSITION_DURATION )) | |
TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) | |
echo -e "\nVideo Slideshow Info\n------------------------\nPhoto count: ${PHOTOS_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: 30\nPhoto duration: ${PHOTO_DURATION} s\n\ | |
Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" | |
START_TIME=$SECONDS | |
# 1. START COMMAND | |
FULL_SCRIPT="ffmpeg -y " | |
# 2. ADD INPUTS | |
for photo in ${PHOTOS}; do | |
FULL_SCRIPT+="-loop 1 -i ${photo} " | |
done | |
# 3. ADD BACKGROUND COLOR SCREEN INPUT | |
FULL_SCRIPT+="-f lavfi -i color=${BACKGROUND_COLOR}:s=${WIDTH}x${HEIGHT} " | |
# 4. ADD TRANSPARENT SCREEN INPUT | |
FULL_SCRIPT+="-f lavfi -i nullsrc=s=${WIDTH}x${HEIGHT} " | |
# 5. START FILTER COMPLEX | |
FULL_SCRIPT+="-filter_complex \"" | |
# 6. PREPARING SCALED INPUTS | |
for (( c=0; c<${PHOTOS_COUNT}; c++ )) | |
do | |
FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),min(iw,${WIDTH}),-1)':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,min(ih,${HEIGHT}))',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" | |
done | |
# 7. OVERLAY INPUTS ON TOP OF BACKGROUND COLOR SCREEN | |
for (( c=1; c<=${PHOTOS_COUNT}; c++ )) | |
do | |
# NOTE THAT threads=1 is a workaround for ffmpeg v4.1 | |
FULL_SCRIPT+="[${PHOTOS_COUNT}:v][stream${c}out1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:threads=1:format=rgb,trim=duration=${PHOTO_DURATION},select=lte(n\,${PHOTO_FRAME_COUNT})[stream${c}overlaid];" | |
if [[ ${c} -eq 1 ]]; then | |
if [[ ${PHOTOS_COUNT} -gt 1 ]]; then | |
FULL_SCRIPT+="[${PHOTOS_COUNT}:v][stream${c}out2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:threads=1:format=rgb,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" | |
fi | |
elif [[ ${c} -lt ${PHOTOS_COUNT} ]]; then | |
FULL_SCRIPT+="[${PHOTOS_COUNT}:v][stream${c}out2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:threads=1:format=rgb,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" | |
elif [[ ${c} -eq ${PHOTOS_COUNT} ]]; then | |
FULL_SCRIPT+="[${PHOTOS_COUNT}:v][stream${c}out2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:threads=1:format=rgb,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" | |
fi | |
done | |
# 8. CREATING TRANSITIONS 1 | |
for (( c=1; c<${PHOTOS_COUNT}; c++ )) | |
do | |
FULL_SCRIPT+="[$((PHOTOS_COUNT+1)):v][stream${c}ending]overlay=y='-t/${TRANSITION_DURATION}*${HEIGHT}':x=0:threads=1,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}moving];" | |
done | |
# 9. CREATING TRANSITIONS 2 | |
for (( c=1; c<${PHOTOS_COUNT}; c++ )) | |
do | |
FULL_SCRIPT+="[stream${c}moving][stream$((c+1))starting]overlay=y='h-t/${TRANSITION_DURATION}*${HEIGHT}':x=0:threads=1:shortest=1,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" | |
done | |
# 10. BEGIN CONCAT | |
for (( c=1; c<${PHOTOS_COUNT}; c++ )) | |
do | |
FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" | |
done | |
# 11. END CONCAT | |
FULL_SCRIPT+="[stream${PHOTOS_COUNT}overlaid]concat=n=$((2*PHOTOS_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" | |
# 12. END | |
FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_push_vertical.mp4" | |
eval ${FULL_SCRIPT} | |
ELAPSED_TIME=$(($SECONDS - $START_TIME)) | |
echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment