├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── advanced_scripts ├── .gitignore ├── README.md ├── blurred_background.sh ├── logo_overlay_and_zoom.sh ├── moving_text.sh ├── object_animation.sh ├── photo_collection.sh ├── push_horizontal_film.sh ├── push_vertical_film.sh ├── zoom_in_and_pan_with_fade_in_out_one.sh ├── zoom_in_and_pan_with_fade_in_out_two.sh ├── zoom_out_and_pan_with_fade_in_out_one.sh └── zoom_out_and_pan_with_fade_in_out_two.sh ├── advanced_video_scripts ├── LICENSE.Commercial.txt └── README.md ├── docs ├── .gitignore ├── advanced_blurred_background.gif ├── advanced_blurred_background_small.gif ├── advanced_logo_overlay_and_zoom.gif ├── advanced_media_blurred_background.gif ├── advanced_media_blurred_background_small.gif ├── advanced_media_logo_overlay_and_zoom.gif ├── advanced_media_moving_text.gif ├── advanced_media_moving_text_small.gif ├── advanced_media_object_animation.gif ├── advanced_media_object_animation_small.gif ├── advanced_media_zoom_in_and_pan_with_fade_in_out_one.gif ├── advanced_media_zoom_in_and_pan_with_fade_in_out_one_small.gif ├── advanced_media_zoom_in_and_pan_with_fade_in_out_two.gif ├── advanced_media_zoom_out_and_pan_with_fade_in_out_one.gif ├── advanced_media_zoom_out_and_pan_with_fade_in_out_two.gif ├── advanced_moving_text.gif ├── advanced_moving_text_small.gif ├── advanced_object_animation.gif ├── advanced_object_animation_small.gif ├── advanced_photo_collection.gif ├── advanced_photo_collection_small.gif ├── advanced_push_horizontal_film.gif ├── advanced_push_horizontal_film_small.gif ├── advanced_push_vertical_film.gif ├── advanced_zoom_in_and_pan_with_fade_in_out_one.gif ├── advanced_zoom_in_and_pan_with_fade_in_out_one_small.gif ├── advanced_zoom_in_and_pan_with_fade_in_out_two.gif ├── advanced_zoom_out_and_pan_with_fade_in_out_one.gif ├── advanced_zoom_out_and_pan_with_fade_in_out_two.gif ├── ffmpeg-video-slideshow-scripts-logo-v1.png ├── ffmpeg-video-slideshow-scripts-logo-v2.png ├── transition_bars_horizontal_one.gif ├── transition_bars_horizontal_two.gif ├── transition_bars_horizontal_two_small.gif ├── transition_bars_vertical_one.gif ├── transition_bars_vertical_two.gif ├── transition_box_in_horizontal.gif ├── transition_box_in_vertical.gif ├── transition_checkerboard.gif ├── transition_checkerboard_small.gif ├── transition_clock.gif ├── transition_clock_small.gif ├── transition_collapse_both.gif ├── transition_collapse_circular.gif ├── transition_collapse_horizontal.gif ├── transition_collapse_horizontal_small.gif ├── transition_collapse_vertical.gif ├── transition_cover_horizontal.gif ├── transition_cover_horizontal_small.gif ├── transition_cover_vertical.gif ├── transition_expand_both.gif ├── transition_expand_circular.gif ├── transition_expand_circular_small.gif ├── transition_expand_horizontal.gif ├── transition_expand_vertical.gif ├── transition_fade_in_one.gif ├── transition_fade_in_two.gif ├── transition_fade_in_two_small.gif ├── transition_media_bars_horizontal_one.gif ├── transition_media_bars_horizontal_two.gif ├── transition_media_bars_horizontal_two_small.gif ├── transition_media_bars_vertical_one.gif ├── transition_media_bars_vertical_two.gif ├── transition_media_box_in_horizontal.gif ├── transition_media_box_in_vertical.gif ├── transition_media_checkerboard.gif ├── transition_media_checkerboard_small.gif ├── transition_media_clock.gif ├── transition_media_clock_small.gif ├── transition_media_collapse_both.gif ├── transition_media_collapse_circular.gif ├── transition_media_collapse_horizontal.gif ├── transition_media_collapse_horizontal_small.gif ├── transition_media_collapse_vertical.gif ├── transition_media_cover_horizontal.gif ├── transition_media_cover_horizontal_small.gif ├── transition_media_cover_vertical.gif ├── transition_media_expand_both.gif ├── transition_media_expand_circular.gif ├── transition_media_expand_circular_small.gif ├── transition_media_expand_horizontal.gif ├── transition_media_expand_vertical.gif ├── transition_media_fade_in_one.gif ├── transition_media_fade_in_two.gif ├── transition_media_fade_in_two_small.gif ├── transition_media_moving_bars_horizontal.gif ├── transition_media_moving_bars_horizontal_small.gif ├── transition_media_moving_bars_vertical.gif ├── transition_media_push_box_horizontal.gif ├── transition_media_push_box_horizontal_small.gif ├── transition_media_push_box_vertical.gif ├── transition_media_push_horizontal.gif ├── transition_media_push_horizontal_small.gif ├── transition_media_push_vertical.gif ├── transition_media_rotate_one.gif ├── transition_media_rotate_one_small.gif ├── transition_media_rotate_two.gif ├── transition_media_rotate_two_small.gif ├── transition_media_sliding_bars_horizontal.gif ├── transition_media_sliding_bars_horizontal_small.gif ├── transition_media_sliding_bars_vertical.gif ├── transition_media_spin_blur_rotation.gif ├── transition_media_spin_blur_rotation_small.gif ├── transition_media_wipe_in_horizontal.gif ├── transition_media_wipe_in_horizontal_small.gif ├── transition_media_wipe_in_vertical.gif ├── transition_media_wipe_out_horizontal.gif ├── transition_media_wipe_out_vertical.gif ├── transition_push_box_horizontal.gif ├── transition_push_box_horizontal_small.gif ├── transition_push_box_vertical.gif ├── transition_push_horizontal.gif ├── transition_push_horizontal_small.gif ├── transition_push_vertical.gif ├── transition_rotate_one.gif ├── transition_rotate_one_small.gif ├── transition_sliding_bars_horizontal.gif ├── transition_sliding_bars_horizontal_small.gif ├── transition_sliding_bars_vertical.gif ├── transition_spin_blur_rotation.gif ├── transition_spin_blur_rotation_small.gif ├── transition_stack_horizontal.gif ├── transition_stack_horizontal_small.gif ├── transition_stack_vertical.gif ├── transition_wipe_in_horizontal.gif ├── transition_wipe_in_horizontal_small.gif ├── transition_wipe_in_vertical.gif ├── transition_wipe_out_horizontal.gif ├── transition_wipe_out_vertical.gif └── vssg │ ├── vssg-audio.png │ ├── vssg-background-audio.png │ ├── vssg-example.gif │ ├── vssg-fonts.png │ ├── vssg-gui.png │ ├── vssg-image.png │ ├── vssg-menu.png │ ├── vssg-move.png │ ├── vssg-overlay.png │ ├── vssg-preferences.png │ ├── vssg-settings.png │ ├── vssg-text.png │ ├── vssg-transition.png │ ├── vssg-video.png │ └── vssg-welcome-screen.png ├── fonts └── FallingSkyBd.otf ├── media ├── 1.jpg ├── 1.mp4 ├── 2.jpg ├── 2.mp4 ├── 3.jpg ├── 3.mp4 ├── 4.jpg └── 5.jpg ├── objects ├── .gitignore ├── film_strip.png ├── film_strip_vertical.png ├── heart.png └── snow-flake.png ├── transition_scripts ├── README.md ├── bars_horizontal_one.sh ├── bars_horizontal_two.sh ├── bars_vertical_one.sh ├── bars_vertical_two.sh ├── box_in_horizontal.sh ├── box_in_vertical.sh ├── checkerboard.sh ├── clock.sh ├── collapse_both.sh ├── collapse_circular.sh ├── collapse_horizontal.sh ├── collapse_vertical.sh ├── cover_horizontal.sh ├── cover_vertical.sh ├── expand_both.sh ├── expand_circular.sh ├── expand_horizontal.sh ├── expand_vertical.sh ├── fade_in_one.sh ├── fade_in_two.sh ├── push_box_horizontal.sh ├── push_box_vertical.sh ├── push_horizontal.sh ├── push_vertical.sh ├── rotate_one.sh ├── sliding_bars_horizontal.sh ├── sliding_bars_vertical.sh ├── spin_blur_rotation.sh ├── stack_horizontal.sh ├── stack_vertical.sh ├── wipe_in_horizontal.sh ├── wipe_in_vertical.sh ├── wipe_out_horizontal.sh └── wipe_out_vertical.sh ├── transition_video_scripts ├── LICENSE.Commercial.txt └── README.md └── video_slideshow_script_generator ├── LICENSE.Commercial.txt ├── LICENSE.Personal.txt ├── README.md └── example.vssg /.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | /*.mp4 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | branches: 2 | only: 3 | - main 4 | - v2.x 5 | sudo: false 6 | git: 7 | quiet: true 8 | addons: 9 | apt: 10 | packages: 11 | - ffmpeg 12 | matrix: 13 | include: 14 | - name: "Advanced scripts" 15 | dist: xenial 16 | language: generic 17 | before_script: 18 | - cd advanced_scripts 19 | after_script: 20 | - cd .. 21 | script: 22 | - bash ./push_horizontal_film.sh 23 | - bash ./push_vertical_film.sh 24 | - name: "Transition scripts" 25 | dist: xenial 26 | language: generic 27 | before_script: 28 | - cd transition_scripts 29 | after_script: 30 | - cd .. 31 | script: 32 | - bash ./stack_horizontal.sh 33 | - bash ./stack_vertical.sh -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## - 2023-07-16 5 | - master branch renamed as main 6 | 7 | ## - 2019-09-08 8 | - Updated the license of scripts with video support 9 | 10 | ## - 2019-08-24 11 | - Added video slideshow script generator 12 | 13 | ## - 2019-08-10 14 | - Added audio support for video inputs 15 | 16 | ## - 2019-07-24 17 | - Added scripts with video input support 18 | 19 | ## - 2019-06-25 20 | - Enabled travis configuration. 21 | 22 | ## - 2019-06-08 23 | - Added small gif samples in main README in v2.x branch. 24 | 25 | ## - 2019-06-04 26 | - Renamed rotate transition as rotate #1 in v2.x branch. 27 | 28 | ## - 2019-05-26 29 | - Renamed PHOTO_DURATION parameter as IMAGE_DURATION in v2.x branch. 30 | - Moved advanced scripts for push box and sliding bars to transition folder in v2.x branch. 31 | 32 | ## - 2019-05-25 33 | - Renamed PHOTO_MODE as SCREEN_MODE in v2.x branch. 34 | - Replaced photos folder with media folder in v2.x branch. 35 | 36 | ## - 2019-05-22 37 | - Updated position formulas in advanced zoom in/out transitions in v2.x branch. 38 | 39 | ## - 2019-05-21 40 | - Implemented PHOTO_MODE and BACKGROUND_COLOR options in advanced zoom in/out transitions in v2.x branch. 41 | 42 | ## - 2019-05-19 43 | - Implemented PHOTO_MODE option for rotate transition in v2.x branch. 44 | 45 | ## - 2019-05-18 46 | - Removed checkpoint phase from box in transition in v2.x branch. 47 | 48 | ## - 2019-04-12 49 | - Zoom speed parameter introduced for zoom & pan with fade in/out transition #1 in v2.x branch. 50 | 51 | ## - 2019-03-28 52 | - Added support for transparent input photos on push scripts in v2.x branch. 53 | 54 | ## - 2019-03-27 55 | - Added support for file names with space character in v2.x branch. 56 | 57 | ## - 2019-02-16 58 | - Zoom & Pan with Fade In/Out Transition #2 scripts added in v2.x branch. 59 | 60 | ## - 2019-01-23 61 | - Circular collapse and circular expand transitions added. 62 | 63 | ## - 2018-12-15 64 | - Tips section added in README. 65 | 66 | ## - 2018-12-11 67 | - Stack transition implemented in v2.x. 68 | 69 | ## - 2018-12-10 70 | - Push box moved under advanced scripts in v2.x. 71 | - Direction parameter implemented in v2.x. 72 | 73 | ## - 2018-12-09 74 | - Photo mode parameter implemented in v2.x. 75 | 76 | ## - 2018-12-06 77 | - v1.x and v2.x branch documentations updated. 78 | 79 | ## - 2018-11-30 80 | - v1.x branch created. 81 | 82 | ## - 2018-08-29 83 | - v1.0 tag created from master. 84 | - Development branch renamed to v2.x. 85 | - Project log added. 86 | 87 | ## - 2018-08-19 88 | - Spin blur rotation transition implemented. 89 | - Logo Overlay script renamed as Logo Overlay & Zoom. 90 | 91 | ## - 2018-06-28 92 | - Box In transitions implemented. 93 | - Push Box transitions implemented. 94 | 95 | ## - 2018-06-27 96 | - Object Move script renamed to Object Animation. New script uses a new snowflake image. Snowflakes are both rotating and falling. 97 | - Logo Overlay updated. New script overlays a beating heart animation instead of static camera image. 98 | 99 | ## - 2018-06-23 100 | - Wipe In Horizontal with Vertical Panning and Wipe In Vertical with Horizontal Panning scripts updated as gists. 101 | and removed from Advanced Scripts section. 102 | - Zoom In & Pan with Fade In/Out Transition and Zoom Out & Pan with Fade In/Out Transition scripts added in Advanced Scripts. 103 | 104 | ## - 2018-06-21 105 | - Wipe In Horizontal with Vertical Panning script added in Advanced Scripts. 106 | - Wipe In Vertical with Horizontal Panning script added in Advanced Scripts. 107 | 108 | ## - 2018-06-16 109 | - Existing bars transition scripts renamed as bars transition #1. 110 | - Bars transition #2 implemented. 111 | - Clock transition added. 112 | - Advanced sliding bars added. 113 | 114 | ## - 2018-04-07 115 | - Bars transition implemented. 116 | 117 | ## - 2018-02-06 118 | - Transition and advanced scripts added. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Taner Sener 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /advanced_scripts/.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | -------------------------------------------------------------------------------- /advanced_scripts/blurred_background.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with advanced blurred background v3 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | 17 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 18 | 19 | # FILE OPTIONS 20 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 21 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 22 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 23 | 24 | ############################ 25 | # DO NO MODIFY LINES BELOW 26 | ############################ 27 | 28 | # CALCULATE LENGTH MANUALLY 29 | let IMAGE_COUNT=0 30 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 31 | 32 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 33 | echo "Error: media folder should contain at least two images" 34 | exit 1; 35 | fi 36 | 37 | # INTERNAL VARIABLES 38 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 39 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 40 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 41 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 42 | 43 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 44 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 45 | 46 | START_TIME=$SECONDS 47 | 48 | # 1. START COMMAND 49 | FULL_SCRIPT="ffmpeg -y " 50 | 51 | # 2. ADD INPUTS 52 | for IMAGE in ${FILES[@]}; do 53 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 54 | done 55 | 56 | # 3. START FILTER COMPLEX 57 | FULL_SCRIPT+="-filter_complex \"" 58 | 59 | # 4. PREPARE BLURRED INPUTS 60 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 61 | do 62 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,format=rgba,boxblur=100,setsar=sar=1/1,fps=${FPS}[stream$((c+1))blurred];" 63 | done 64 | 65 | # 5. PREPARE INPUTS 66 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 67 | do 68 | FULL_SCRIPT+="[${c}:v]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[stream$((c+1))raw];" 69 | done 70 | 71 | # 6. OVERLAY BLURRED AND SCALED INPUTS 72 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 73 | do 74 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream${c}out1][stream${c}out2];" 75 | done 76 | 77 | # 7. APPLY PADDING 78 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 79 | do 80 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2,trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 81 | if [[ ${c} -eq 1 ]]; then 82 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 83 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 84 | fi 85 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 86 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 87 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 89 | fi 90 | done 91 | 92 | # 8. CREATE TRANSITION FRAMES 93 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 94 | do 95 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='A*(if(gte(T,${TRANSITION_DURATION}),${TRANSITION_DURATION},T/${TRANSITION_DURATION}))+B*(1-(if(gte(T,${TRANSITION_DURATION}),${TRANSITION_DURATION},T/${TRANSITION_DURATION})))',select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 96 | done 97 | 98 | # 9. BEGIN CONCAT 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 102 | done 103 | 104 | # 10. END CONCAT 105 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 106 | 107 | # 11. END 108 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../advanced_blurred_background.mp4" 109 | 110 | eval ${FULL_SCRIPT} 111 | 112 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 113 | 114 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 115 | 116 | unset $IFS -------------------------------------------------------------------------------- /advanced_scripts/photo_collection.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script for advanced photo collection v3 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | MAX_IMAGE_ANGLE=25 17 | BACKGROUND_COLOR="#00000000" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. ADD BACKGROUND COLOR SCREEN INPUT 59 | FULL_SCRIPT+="-f lavfi -i color=${BACKGROUND_COLOR}:s=${WIDTH}x${HEIGHT},fps=${FPS} " 60 | 61 | # 4. START FILTER COMPLEX 62 | FULL_SCRIPT+="-filter_complex \"" 63 | 64 | # 5. PREPARE BACKGROUND 65 | FULL_SCRIPT+="[${IMAGE_COUNT}:v]trim=duration=${TOTAL_DURATION}[stream0collected];" 66 | 67 | # 6. PREPARE INPUTS 68 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 69 | do 70 | 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,fps=${FPS},format=rgba,pad=width=$((WIDTH*4)):height=${HEIGHT}:x=($((WIDTH*4))-iw)/2:y=(${HEIGHT}-ih)/2:color=#00000000,trim=duration=$(( (c+1)*(TRANSITION_DURATION+IMAGE_DURATION) )),setpts=PTS-STARTPTS[stream$((c+1))];" 71 | 72 | ANGLE_RANDOMNESS=$(( (RANDOM % MAX_IMAGE_ANGLE) + 1 )); 73 | 74 | FULL_SCRIPT+="[stream$((c+1))]rotate=if(between(t\,$(( (TRANSITION_DURATION+IMAGE_DURATION)*c ))\,$(( (TRANSITION_DURATION+IMAGE_DURATION)*c+TRANSITION_DURATION )))\,2*PI*t+if(eq(mod(${c}\,2)\,0)\,1\,-1)*${ANGLE_RANDOMNESS}*PI/180\,if(eq(mod(${c}\,2)\,0)\,1\,-1)*${ANGLE_RANDOMNESS}*PI/180):ow=$((WIDTH*4)):c=#00000000,[stream${c}collected]overlay=x=if(gt(t\,$(( (TRANSITION_DURATION+IMAGE_DURATION)*c )))\,if(lt(t\,$(( (TRANSITION_DURATION+IMAGE_DURATION)*c+TRANSITION_DURATION )))\,$((WIDTH*3/2))-w+(t-$(( c*(TRANSITION_DURATION+IMAGE_DURATION) )))/${TRANSITION_DURATION}*${WIDTH}\,(main_w-overlay_w)/2)\,-w):(main_h-overlay_h)/2" 75 | 76 | if [[ $((c+1)) -eq ${IMAGE_COUNT} ]]; then 77 | FULL_SCRIPT+=",format=yuv420p[video]\"" 78 | else 79 | FULL_SCRIPT+="[stream$((c+1))collected];" 80 | fi 81 | done 82 | 83 | # 7. END 84 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../advanced_photo_collection.mp4" 85 | 86 | eval ${FULL_SCRIPT} 87 | 88 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 89 | 90 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 91 | 92 | unset $IFS -------------------------------------------------------------------------------- /advanced_scripts/zoom_in_and_pan_with_fade_in_out_two.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with zoom in and pan and fade in/out #2 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=2 15 | IMAGE_DURATION=1 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+2*TRANSITION_DURATION)*IMAGE_COUNT )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS & FADE IN/OUT PARTS & ZOOM & PAN EACH STREAM 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | POSITION_NUMBER=$((RANDOM % 5)); 65 | 66 | case ${POSITION_NUMBER} in 67 | 0) 68 | POSITION_FORMULA="x='iw/2':y='-${HEIGHT}-(ih/zoom/2)'" # TOP RIGHT 69 | ;; 70 | 1) 71 | POSITION_FORMULA="x='iw/2':y='(ih/zoom/2)'" # BOTTOM RIGHT 72 | ;; 73 | 2) 74 | POSITION_FORMULA="x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)'" # CENTER 75 | ;; 76 | 3) 77 | POSITION_FORMULA="x='${WIDTH}-(iw/zoom/2)':y='-${HEIGHT}-(ih/zoom/2)'" # TOP LEFT 78 | ;; 79 | 4) 80 | POSITION_FORMULA="x='${WIDTH}-(iw/zoom/2)':y='${HEIGHT}+(ih/zoom/2)'" # BOTTOM LEFT 81 | ;; 82 | esac 83 | 84 | case ${SCREEN_MODE} in 85 | 1) 86 | 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,fps=${FPS},format=rgba,pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR}" 87 | ;; 88 | 2) 89 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba" 90 | ;; 91 | 3) 92 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba" 93 | ;; 94 | 4) 95 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 96 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 97 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS" 98 | ;; 99 | esac 100 | 101 | FULL_SCRIPT+=",trim=start_frame=0:end_frame=${TRANSITION_FRAME_COUNT},setpts=PTS-STARTPTS,scale=${WIDTH}*5:-1,zoompan=z='pzoom+0.004':d=1:${POSITION_FORMULA}:fps=${FPS}:s=${WIDTH}x${HEIGHT},split=2[stream$((c+1))out1][stream$((c+1))out2];" 102 | 103 | FULL_SCRIPT+="[stream$((c+1))out1]trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),fade=t=in:s=0:d=${TRANSITION_DURATION}[stream$((c+1))fadeinandzoom];" 104 | FULL_SCRIPT+="[stream$((c+1))out2]trim=start_frame=${TRANSITION_FRAME_COUNT}-1:end_frame=${TRANSITION_FRAME_COUNT},setpts=PTS-STARTPTS,split=2[stream$((c+1))pre][stream$((c+1))preout];" 105 | 106 | FULL_SCRIPT+="[stream$((c+1))pre]loop=loop=${IMAGE_FRAME_COUNT}:size=1:start=0,trim=duration=${IMAGE_DURATION},setpts=PTS-STARTPTS[stream$((c+1))];" 107 | FULL_SCRIPT+="[stream$((c+1))preout]loop=loop=${TRANSITION_FRAME_COUNT}:size=1:start=0,trim=duration=${TRANSITION_DURATION},setpts=PTS-STARTPTS,fade=t=out:s=0:d=${TRANSITION_DURATION}[stream$((c+1))fadeout];" 108 | 109 | FULL_SCRIPT+="[stream$((c+1))fadeinandzoom][stream$((c+1))][stream$((c+1))fadeout]concat=n=3:v=1:a=0[stream$((c+1))panning];" 110 | done 111 | 112 | # 5. BEGIN CONCAT 113 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 114 | do 115 | FULL_SCRIPT+="[stream${c}panning]" 116 | done 117 | 118 | # 6. END CONCAT 119 | FULL_SCRIPT+="concat=n=${IMAGE_COUNT}:v=1:a=0,format=yuv420p[video]\"" 120 | 121 | # 7. END 122 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../advanced_zoom_in_and_pan_with_fade_in_out_two.mp4" 123 | 124 | eval ${FULL_SCRIPT} 125 | 126 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 127 | 128 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 129 | 130 | unset $IFS -------------------------------------------------------------------------------- /advanced_scripts/zoom_out_and_pan_with_fade_in_out_two.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with zoom out and pan and fade in/out #2 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=3 15 | IMAGE_DURATION=1 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+2*TRANSITION_DURATION)*IMAGE_COUNT )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS & FADE IN/OUT PARTS & ZOOM & PAN EACH STREAM 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | POSITION_NUMBER=$((RANDOM % 5)); 65 | 66 | case ${POSITION_NUMBER} in 67 | 0) 68 | POSITION_FORMULA="x='iw/2':y='-${HEIGHT}-(ih/zoom/2)'" # TOP RIGHT 69 | ;; 70 | 1) 71 | POSITION_FORMULA="x='iw/2':y='(ih/zoom/2)'" # BOTTOM RIGHT 72 | ;; 73 | 2) 74 | POSITION_FORMULA="x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)'" # CENTER 75 | ;; 76 | 3) 77 | POSITION_FORMULA="x='${WIDTH}-(iw/zoom/2)':y='-${HEIGHT}-(ih/zoom/2)'" # TOP LEFT 78 | ;; 79 | 4) 80 | POSITION_FORMULA="x='${WIDTH}-(iw/zoom/2)':y='${HEIGHT}+(ih/zoom/2)'" # BOTTOM LEFT 81 | ;; 82 | esac 83 | 84 | case ${SCREEN_MODE} in 85 | 1) 86 | 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,fps=${FPS},format=rgba,pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR}" 87 | ;; 88 | 2) 89 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba" 90 | ;; 91 | 3) 92 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba" 93 | ;; 94 | 4) 95 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 96 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 97 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS" 98 | ;; 99 | esac 100 | 101 | FULL_SCRIPT+=",trim=start_frame=0:end_frame=${TRANSITION_FRAME_COUNT},setpts=PTS-STARTPTS,scale=${WIDTH}*5:-1,zoompan=z='if(lte(in,0),1.5,pzoom-0.004)':d=1:${POSITION_FORMULA}:fps=${FPS}:s=${WIDTH}x${HEIGHT},split=2[stream$((c+1))out1][stream$((c+1))out2];" 102 | 103 | FULL_SCRIPT+="[stream$((c+1))out1]trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),fade=t=in:s=0:d=${TRANSITION_DURATION}[stream$((c+1))fadeinandzoom];" 104 | FULL_SCRIPT+="[stream$((c+1))out2]trim=start_frame=${TRANSITION_FRAME_COUNT}-1:end_frame=${TRANSITION_FRAME_COUNT},setpts=PTS-STARTPTS,split=2[stream$((c+1))pre][stream$((c+1))preout];" 105 | 106 | FULL_SCRIPT+="[stream$((c+1))pre]loop=loop=${IMAGE_FRAME_COUNT}:size=1:start=0,trim=duration=${IMAGE_DURATION},setpts=PTS-STARTPTS[stream$((c+1))];" 107 | FULL_SCRIPT+="[stream$((c+1))preout]loop=loop=${TRANSITION_FRAME_COUNT}:size=1:start=0,trim=duration=${TRANSITION_DURATION},setpts=PTS-STARTPTS,fade=t=out:s=0:d=${TRANSITION_DURATION}[stream$((c+1))fadeout];" 108 | 109 | FULL_SCRIPT+="[stream$((c+1))fadeinandzoom][stream$((c+1))][stream$((c+1))fadeout]concat=n=3:v=1:a=0[stream$((c+1))panning];" 110 | done 111 | 112 | # 5. BEGIN CONCAT 113 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 114 | do 115 | FULL_SCRIPT+="[stream${c}panning]" 116 | done 117 | 118 | # 6. END CONCAT 119 | FULL_SCRIPT+="concat=n=${IMAGE_COUNT}:v=1:a=0,format=yuv420p[video]\"" 120 | 121 | # 7. END 122 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../advanced_zoom_out_and_pan_with_fade_in_out_two.mp4" 123 | 124 | eval ${FULL_SCRIPT} 125 | 126 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 127 | 128 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 129 | 130 | unset $IFS -------------------------------------------------------------------------------- /advanced_video_scripts/LICENSE.Commercial.txt: -------------------------------------------------------------------------------- 1 | ARTHENICA Commercial License 2 | 3 | Copyright (c) 2019, Taner Sener (https://github.com/tanersener), All rights reserved. 4 | 5 | Permission is hereby granted, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, merge, distribute, sublicense, and/or sell copies of the Software, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | -------------------------------------------------------------------------------- /docs/advanced_blurred_background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_blurred_background.gif -------------------------------------------------------------------------------- /docs/advanced_blurred_background_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_blurred_background_small.gif -------------------------------------------------------------------------------- /docs/advanced_logo_overlay_and_zoom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_logo_overlay_and_zoom.gif -------------------------------------------------------------------------------- /docs/advanced_media_blurred_background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_blurred_background.gif -------------------------------------------------------------------------------- /docs/advanced_media_blurred_background_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_blurred_background_small.gif -------------------------------------------------------------------------------- /docs/advanced_media_logo_overlay_and_zoom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_logo_overlay_and_zoom.gif -------------------------------------------------------------------------------- /docs/advanced_media_moving_text.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_moving_text.gif -------------------------------------------------------------------------------- /docs/advanced_media_moving_text_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_moving_text_small.gif -------------------------------------------------------------------------------- /docs/advanced_media_object_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_object_animation.gif -------------------------------------------------------------------------------- /docs/advanced_media_object_animation_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_object_animation_small.gif -------------------------------------------------------------------------------- /docs/advanced_media_zoom_in_and_pan_with_fade_in_out_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_zoom_in_and_pan_with_fade_in_out_one.gif -------------------------------------------------------------------------------- /docs/advanced_media_zoom_in_and_pan_with_fade_in_out_one_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_zoom_in_and_pan_with_fade_in_out_one_small.gif -------------------------------------------------------------------------------- /docs/advanced_media_zoom_in_and_pan_with_fade_in_out_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_zoom_in_and_pan_with_fade_in_out_two.gif -------------------------------------------------------------------------------- /docs/advanced_media_zoom_out_and_pan_with_fade_in_out_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_zoom_out_and_pan_with_fade_in_out_one.gif -------------------------------------------------------------------------------- /docs/advanced_media_zoom_out_and_pan_with_fade_in_out_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_media_zoom_out_and_pan_with_fade_in_out_two.gif -------------------------------------------------------------------------------- /docs/advanced_moving_text.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_moving_text.gif -------------------------------------------------------------------------------- /docs/advanced_moving_text_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_moving_text_small.gif -------------------------------------------------------------------------------- /docs/advanced_object_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_object_animation.gif -------------------------------------------------------------------------------- /docs/advanced_object_animation_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_object_animation_small.gif -------------------------------------------------------------------------------- /docs/advanced_photo_collection.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_photo_collection.gif -------------------------------------------------------------------------------- /docs/advanced_photo_collection_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_photo_collection_small.gif -------------------------------------------------------------------------------- /docs/advanced_push_horizontal_film.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_push_horizontal_film.gif -------------------------------------------------------------------------------- /docs/advanced_push_horizontal_film_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_push_horizontal_film_small.gif -------------------------------------------------------------------------------- /docs/advanced_push_vertical_film.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_push_vertical_film.gif -------------------------------------------------------------------------------- /docs/advanced_zoom_in_and_pan_with_fade_in_out_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_zoom_in_and_pan_with_fade_in_out_one.gif -------------------------------------------------------------------------------- /docs/advanced_zoom_in_and_pan_with_fade_in_out_one_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_zoom_in_and_pan_with_fade_in_out_one_small.gif -------------------------------------------------------------------------------- /docs/advanced_zoom_in_and_pan_with_fade_in_out_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_zoom_in_and_pan_with_fade_in_out_two.gif -------------------------------------------------------------------------------- /docs/advanced_zoom_out_and_pan_with_fade_in_out_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_zoom_out_and_pan_with_fade_in_out_one.gif -------------------------------------------------------------------------------- /docs/advanced_zoom_out_and_pan_with_fade_in_out_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/advanced_zoom_out_and_pan_with_fade_in_out_two.gif -------------------------------------------------------------------------------- /docs/ffmpeg-video-slideshow-scripts-logo-v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/ffmpeg-video-slideshow-scripts-logo-v1.png -------------------------------------------------------------------------------- /docs/ffmpeg-video-slideshow-scripts-logo-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/ffmpeg-video-slideshow-scripts-logo-v2.png -------------------------------------------------------------------------------- /docs/transition_bars_horizontal_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_bars_horizontal_one.gif -------------------------------------------------------------------------------- /docs/transition_bars_horizontal_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_bars_horizontal_two.gif -------------------------------------------------------------------------------- /docs/transition_bars_horizontal_two_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_bars_horizontal_two_small.gif -------------------------------------------------------------------------------- /docs/transition_bars_vertical_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_bars_vertical_one.gif -------------------------------------------------------------------------------- /docs/transition_bars_vertical_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_bars_vertical_two.gif -------------------------------------------------------------------------------- /docs/transition_box_in_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_box_in_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_box_in_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_box_in_vertical.gif -------------------------------------------------------------------------------- /docs/transition_checkerboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_checkerboard.gif -------------------------------------------------------------------------------- /docs/transition_checkerboard_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_checkerboard_small.gif -------------------------------------------------------------------------------- /docs/transition_clock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_clock.gif -------------------------------------------------------------------------------- /docs/transition_clock_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_clock_small.gif -------------------------------------------------------------------------------- /docs/transition_collapse_both.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_collapse_both.gif -------------------------------------------------------------------------------- /docs/transition_collapse_circular.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_collapse_circular.gif -------------------------------------------------------------------------------- /docs/transition_collapse_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_collapse_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_collapse_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_collapse_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_collapse_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_collapse_vertical.gif -------------------------------------------------------------------------------- /docs/transition_cover_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_cover_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_cover_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_cover_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_cover_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_cover_vertical.gif -------------------------------------------------------------------------------- /docs/transition_expand_both.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_expand_both.gif -------------------------------------------------------------------------------- /docs/transition_expand_circular.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_expand_circular.gif -------------------------------------------------------------------------------- /docs/transition_expand_circular_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_expand_circular_small.gif -------------------------------------------------------------------------------- /docs/transition_expand_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_expand_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_expand_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_expand_vertical.gif -------------------------------------------------------------------------------- /docs/transition_fade_in_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_fade_in_one.gif -------------------------------------------------------------------------------- /docs/transition_fade_in_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_fade_in_two.gif -------------------------------------------------------------------------------- /docs/transition_fade_in_two_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_fade_in_two_small.gif -------------------------------------------------------------------------------- /docs/transition_media_bars_horizontal_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_bars_horizontal_one.gif -------------------------------------------------------------------------------- /docs/transition_media_bars_horizontal_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_bars_horizontal_two.gif -------------------------------------------------------------------------------- /docs/transition_media_bars_horizontal_two_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_bars_horizontal_two_small.gif -------------------------------------------------------------------------------- /docs/transition_media_bars_vertical_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_bars_vertical_one.gif -------------------------------------------------------------------------------- /docs/transition_media_bars_vertical_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_bars_vertical_two.gif -------------------------------------------------------------------------------- /docs/transition_media_box_in_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_box_in_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_box_in_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_box_in_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_checkerboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_checkerboard.gif -------------------------------------------------------------------------------- /docs/transition_media_checkerboard_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_checkerboard_small.gif -------------------------------------------------------------------------------- /docs/transition_media_clock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_clock.gif -------------------------------------------------------------------------------- /docs/transition_media_clock_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_clock_small.gif -------------------------------------------------------------------------------- /docs/transition_media_collapse_both.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_collapse_both.gif -------------------------------------------------------------------------------- /docs/transition_media_collapse_circular.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_collapse_circular.gif -------------------------------------------------------------------------------- /docs/transition_media_collapse_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_collapse_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_collapse_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_collapse_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_collapse_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_collapse_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_cover_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_cover_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_cover_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_cover_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_cover_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_cover_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_expand_both.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_expand_both.gif -------------------------------------------------------------------------------- /docs/transition_media_expand_circular.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_expand_circular.gif -------------------------------------------------------------------------------- /docs/transition_media_expand_circular_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_expand_circular_small.gif -------------------------------------------------------------------------------- /docs/transition_media_expand_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_expand_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_expand_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_expand_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_fade_in_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_fade_in_one.gif -------------------------------------------------------------------------------- /docs/transition_media_fade_in_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_fade_in_two.gif -------------------------------------------------------------------------------- /docs/transition_media_fade_in_two_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_fade_in_two_small.gif -------------------------------------------------------------------------------- /docs/transition_media_moving_bars_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_moving_bars_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_moving_bars_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_moving_bars_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_moving_bars_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_moving_bars_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_push_box_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_push_box_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_push_box_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_push_box_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_push_box_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_push_box_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_push_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_push_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_push_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_push_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_push_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_push_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_rotate_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_rotate_one.gif -------------------------------------------------------------------------------- /docs/transition_media_rotate_one_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_rotate_one_small.gif -------------------------------------------------------------------------------- /docs/transition_media_rotate_two.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_rotate_two.gif -------------------------------------------------------------------------------- /docs/transition_media_rotate_two_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_rotate_two_small.gif -------------------------------------------------------------------------------- /docs/transition_media_sliding_bars_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_sliding_bars_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_sliding_bars_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_sliding_bars_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_sliding_bars_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_sliding_bars_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_spin_blur_rotation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_spin_blur_rotation.gif -------------------------------------------------------------------------------- /docs/transition_media_spin_blur_rotation_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_spin_blur_rotation_small.gif -------------------------------------------------------------------------------- /docs/transition_media_wipe_in_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_wipe_in_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_wipe_in_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_wipe_in_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_media_wipe_in_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_wipe_in_vertical.gif -------------------------------------------------------------------------------- /docs/transition_media_wipe_out_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_wipe_out_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_media_wipe_out_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_media_wipe_out_vertical.gif -------------------------------------------------------------------------------- /docs/transition_push_box_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_push_box_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_push_box_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_push_box_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_push_box_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_push_box_vertical.gif -------------------------------------------------------------------------------- /docs/transition_push_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_push_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_push_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_push_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_push_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_push_vertical.gif -------------------------------------------------------------------------------- /docs/transition_rotate_one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_rotate_one.gif -------------------------------------------------------------------------------- /docs/transition_rotate_one_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_rotate_one_small.gif -------------------------------------------------------------------------------- /docs/transition_sliding_bars_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_sliding_bars_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_sliding_bars_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_sliding_bars_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_sliding_bars_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_sliding_bars_vertical.gif -------------------------------------------------------------------------------- /docs/transition_spin_blur_rotation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_spin_blur_rotation.gif -------------------------------------------------------------------------------- /docs/transition_spin_blur_rotation_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_spin_blur_rotation_small.gif -------------------------------------------------------------------------------- /docs/transition_stack_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_stack_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_stack_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_stack_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_stack_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_stack_vertical.gif -------------------------------------------------------------------------------- /docs/transition_wipe_in_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_wipe_in_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_wipe_in_horizontal_small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_wipe_in_horizontal_small.gif -------------------------------------------------------------------------------- /docs/transition_wipe_in_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_wipe_in_vertical.gif -------------------------------------------------------------------------------- /docs/transition_wipe_out_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_wipe_out_horizontal.gif -------------------------------------------------------------------------------- /docs/transition_wipe_out_vertical.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/transition_wipe_out_vertical.gif -------------------------------------------------------------------------------- /docs/vssg/vssg-audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-audio.png -------------------------------------------------------------------------------- /docs/vssg/vssg-background-audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-background-audio.png -------------------------------------------------------------------------------- /docs/vssg/vssg-example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-example.gif -------------------------------------------------------------------------------- /docs/vssg/vssg-fonts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-fonts.png -------------------------------------------------------------------------------- /docs/vssg/vssg-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-gui.png -------------------------------------------------------------------------------- /docs/vssg/vssg-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-image.png -------------------------------------------------------------------------------- /docs/vssg/vssg-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-menu.png -------------------------------------------------------------------------------- /docs/vssg/vssg-move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-move.png -------------------------------------------------------------------------------- /docs/vssg/vssg-overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-overlay.png -------------------------------------------------------------------------------- /docs/vssg/vssg-preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-preferences.png -------------------------------------------------------------------------------- /docs/vssg/vssg-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-settings.png -------------------------------------------------------------------------------- /docs/vssg/vssg-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-text.png -------------------------------------------------------------------------------- /docs/vssg/vssg-transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-transition.png -------------------------------------------------------------------------------- /docs/vssg/vssg-video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-video.png -------------------------------------------------------------------------------- /docs/vssg/vssg-welcome-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/docs/vssg/vssg-welcome-screen.png -------------------------------------------------------------------------------- /fonts/FallingSkyBd.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/fonts/FallingSkyBd.otf -------------------------------------------------------------------------------- /media/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/1.jpg -------------------------------------------------------------------------------- /media/1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/1.mp4 -------------------------------------------------------------------------------- /media/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/2.jpg -------------------------------------------------------------------------------- /media/2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/2.mp4 -------------------------------------------------------------------------------- /media/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/3.jpg -------------------------------------------------------------------------------- /media/3.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/3.mp4 -------------------------------------------------------------------------------- /media/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/4.jpg -------------------------------------------------------------------------------- /media/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/media/5.jpg -------------------------------------------------------------------------------- /objects/.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | -------------------------------------------------------------------------------- /objects/film_strip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/objects/film_strip.png -------------------------------------------------------------------------------- /objects/film_strip_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/objects/film_strip_vertical.png -------------------------------------------------------------------------------- /objects/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/objects/heart.png -------------------------------------------------------------------------------- /objects/snow-flake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanersener/ffmpeg-video-slideshow-scripts/91d766eb231566215f66204a34bcc2b7221c2648/objects/snow-flake.png -------------------------------------------------------------------------------- /transition_scripts/bars_horizontal_one.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal bars #1 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2018-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BAR_COUNT=10 # HEIGHT SHOULD BE DIVISIBLE BY BAR_COUNT. IF NOT HORIZONTAL LINES MAY APPEAR ON TRANSITION 18 | BACKGROUND_COLOR="#00000000" 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((lte(mod(Y,(${HEIGHT}/${BAR_COUNT})),(${HEIGHT}/${BAR_COUNT})*T/${TRANSITION_DURATION})),A,B)':shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_bars_horizontal_one.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/bars_horizontal_two.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal bars #2 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2018-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BAR_COUNT=10 # HEIGHT SHOULD BE DIVISIBLE BY BAR_COUNT. IF NOT HORIZONTAL LINES MAY APPEAR ON TRANSITION 18 | BACKGROUND_COLOR="#00000000" 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((lte(mod(Y,(${HEIGHT}/${BAR_COUNT})),(${HEIGHT}/${BAR_COUNT})/2-((${HEIGHT}/${BAR_COUNT})/2)*T/${TRANSITION_DURATION}))+(gte(mod(Y,(${HEIGHT}/${BAR_COUNT})),((${HEIGHT}/${BAR_COUNT})/2)+((${HEIGHT}/${BAR_COUNT})/2)*T/${TRANSITION_DURATION})),B,A)':shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_bars_horizontal_two.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/bars_vertical_one.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical bars #1 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2018-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BAR_COUNT=16 # WIDTH SHOULD BE DIVISIBLE BY BAR_COUNT. IF NOT VERTICAL LINES MAY APPEAR ON TRANSITION 18 | BACKGROUND_COLOR="#00000000" 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((lte(mod(X,(${WIDTH}/${BAR_COUNT})),(${WIDTH}/${BAR_COUNT})*T/${TRANSITION_DURATION})),A,B)':shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_bars_vertical_one.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/bars_vertical_two.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical bars #2 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2018-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BAR_COUNT=16 # WIDTH SHOULD BE DIVISIBLE BY BAR_COUNT. IF NOT VERTICAL LINES MAY APPEAR ON TRANSITION 18 | BACKGROUND_COLOR="#00000000" 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((lte(mod(X,(${WIDTH}/${BAR_COUNT})),(${WIDTH}/${BAR_COUNT})/2-((${WIDTH}/${BAR_COUNT})/2)*T/${TRANSITION_DURATION}))+(gte(mod(X,(${WIDTH}/${BAR_COUNT})),((${WIDTH}/${BAR_COUNT})/2)+((${WIDTH}/${BAR_COUNT})/2)*T/${TRANSITION_DURATION})),B,A)':shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_bars_vertical_two.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/checkerboard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with checkerboard transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | CELL_SIZE=64 18 | BACKGROUND_COLOR="#00000000" 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((lte(mod(X,${CELL_SIZE}),${CELL_SIZE}/2-(${CELL_SIZE}/2)*T/${TRANSITION_DURATION})+lte(mod(Y,${CELL_SIZE}),${CELL_SIZE}/2-(${CELL_SIZE}/2)*T/${TRANSITION_DURATION}))+(gte(mod(X,${CELL_SIZE}),(${CELL_SIZE}/2)+(${CELL_SIZE}/2)*T/${TRANSITION_DURATION})+gte(mod(Y,${CELL_SIZE}),(${CELL_SIZE}/2)+(${CELL_SIZE}/2)*T/${TRANSITION_DURATION})),B,A)':shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_checkerboard.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/collapse_both.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal & vertical collapse transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="#00000000" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((gte(X,(W/2)*T/${TRANSITION_DURATION})*gte(Y,(H/2)*T/${TRANSITION_DURATION}))*(lte(X,W-(W/2)*T/${TRANSITION_DURATION})*lte(Y,H-(H/2)*T/${TRANSITION_DURATION})),B,A)':shortest=1[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_collapse_both.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/collapse_circular.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with circular collapse transition v2 (25.05.2019) 4 | # 5 | # Copyright (c) 2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="#00000000" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting]geq=lum='p(X,Y)':a='if(lte(pow(sqrt(pow(W/2,2)+pow(H/2,2))-sqrt(pow(T/${TRANSITION_DURATION}*W/2,2)+pow(T/${TRANSITION_DURATION}*H/2,2)),2),pow(X-(W/2),2)+pow(Y-(H/2),2)),255,0)'[stream$((c+1))circularstarting];" 101 | FULL_SCRIPT+="[stream${c}ending][stream$((c+1))circularstarting]overlay=0:0:shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_collapse_circular.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/collapse_horizontal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal collapse transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="#00000000" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(gte(X,(W/2)*T/${TRANSITION_DURATION})*lte(X,W-(W/2)*T/${TRANSITION_DURATION}),B,A)':shortest=1[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_collapse_horizontal.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/collapse_vertical.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical collapse transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="#00000000" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(gte(Y,(H/2)*T/${TRANSITION_DURATION})*lte(Y,H-(H/2)*T/${TRANSITION_DURATION}),B,A)':shortest=1[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_collapse_vertical.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/cover_horizontal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal cover transition v5 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="#00000000" 18 | DIRECTION=1 # 1=LEFT TO RIGHT, 2=RIGHT TO LEFT 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | case ${DIRECTION} in 102 | 1) 103 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(gte(X,W*T/${TRANSITION_DURATION}),B,A)':shortest=1[stream$((c+1))blended];" 104 | ;; 105 | *) 106 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(gte(X,W - W*T/${TRANSITION_DURATION}),A,B)':shortest=1[stream$((c+1))blended];" 107 | ;; 108 | esac 109 | done 110 | 111 | # 7. BEGIN CONCAT 112 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 113 | do 114 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 115 | done 116 | 117 | # 8. END CONCAT 118 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 119 | 120 | # 9. END 121 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_cover_horizontal.mp4" 122 | 123 | eval ${FULL_SCRIPT} 124 | 125 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 126 | 127 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 128 | 129 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/cover_vertical.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical cover transition v5 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="#00000000" 18 | DIRECTION=2 # 1=TOP TO BOTTOM, 2=BOTTOM TO TOP 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | case ${DIRECTION} in 102 | 1) 103 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(gte(Y,H*T/${TRANSITION_DURATION}),B,A)':shortest=1[stream$((c+1))blended];" 104 | ;; 105 | *) 106 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(gte(Y,H - H*T/${TRANSITION_DURATION}),A,B)':shortest=1[stream$((c+1))blended];" 107 | ;; 108 | esac 109 | done 110 | 111 | # 7. BEGIN CONCAT 112 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 113 | do 114 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 115 | done 116 | 117 | # 8. END CONCAT 118 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 119 | 120 | # 9. END 121 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_cover_vertical.mp4" 122 | 123 | eval ${FULL_SCRIPT} 124 | 125 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 126 | 127 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 128 | 129 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/expand_both.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal & vertical expand transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if((lte(X,(W/2)-(W/2)*T/${TRANSITION_DURATION})+lte(Y,(H/2)-(H/2)*T/${TRANSITION_DURATION}))+(gte(X,(W/2)+(W/2)*T/${TRANSITION_DURATION})+gte(Y,(H/2)+(H/2)*T/${TRANSITION_DURATION})),B,A)':shortest=1[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_expand_both.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/expand_circular.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with circular expand transition v2 (25.05.2019) 4 | # 5 | # Copyright (c) 2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting]geq=lum='p(X,Y)':a='if(lte(pow(sqrt(pow(T/${TRANSITION_DURATION}*W/2,2)+pow(T/${TRANSITION_DURATION}*H/2,2)),2),pow(X-(W/2),2)+pow(Y-(H/2),2)),0,255)'[stream$((c+1))circularstarting];" 101 | FULL_SCRIPT+="[stream${c}ending][stream$((c+1))circularstarting]overlay=0:0:shortest=1[stream$((c+1))blended];" 102 | done 103 | 104 | # 7. BEGIN CONCAT 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 108 | done 109 | 110 | # 8. END CONCAT 111 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 112 | 113 | # 9. END 114 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_expand_circular.mp4" 115 | 116 | eval ${FULL_SCRIPT} 117 | 118 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 119 | 120 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 121 | 122 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/expand_horizontal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal expand transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(lte(X,(W/2)-(W/2)*T/${TRANSITION_DURATION})+gte(X,(W/2)+(W/2)*T/${TRANSITION_DURATION}),B,A)':shortest=1[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_expand_horizontal.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/expand_vertical.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical expand transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='if(lte(Y,(H/2)-(H/2)*T/${TRANSITION_DURATION})+gte(Y,(H/2)+(H/2)*T/${TRANSITION_DURATION}),B,A)':shortest=1[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_expand_vertical.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/fade_in_one.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with fade in #1 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 86 | if [[ ${c} -eq 1 ]]; then 87 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 88 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 89 | fi 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 94 | fi 95 | done 96 | 97 | # 6. CREATE TRANSITION FRAMES 98 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 99 | do 100 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]blend=all_expr='A*(if(gte(T,${TRANSITION_DURATION}),1,T/${TRANSITION_DURATION}))+B*(1-(if(gte(T,${TRANSITION_DURATION}),1,T/${TRANSITION_DURATION})))',select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 101 | done 102 | 103 | # 7. BEGIN CONCAT 104 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 105 | do 106 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 107 | done 108 | 109 | # 8. END CONCAT 110 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 111 | 112 | # 9. END 113 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_fade_in_one.mp4" 114 | 115 | eval ${FULL_SCRIPT} 116 | 117 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 118 | 119 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 120 | 121 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/fade_in_two.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with fade in #2 transition v4 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. START FILTER COMPLEX 59 | FULL_SCRIPT+="-filter_complex \"" 60 | 61 | # 4. PREPARE INPUTS 62 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 63 | do 64 | case ${SCREEN_MODE} in 65 | 1) 66 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 67 | ;; 68 | 2) 69 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 70 | ;; 71 | 3) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 73 | ;; 74 | 4) 75 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 76 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 77 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 78 | ;; 79 | esac 80 | done 81 | 82 | # 5. APPLY PADDING 83 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 84 | do 85 | 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | 88 | if [[ ${c} -eq 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),fade=t=out:s=0:n=${TRANSITION_FRAME_COUNT}[stream${c}fadeout];" 90 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 91 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 92 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 93 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),fade=t=in:s=0:n=${TRANSITION_FRAME_COUNT}[stream${c}fadein];" 94 | fi 95 | 96 | if [[ ${c} -ne 1 ]] && [[ ${c} -ne ${IMAGE_COUNT} ]]; then 97 | 98 | FULL_SCRIPT+="[stream${c}starting]fade=t=in:s=0:n=${TRANSITION_FRAME_COUNT}[stream${c}fadein];" 99 | FULL_SCRIPT+="[stream${c}ending]fade=t=out:s=0:n=${TRANSITION_FRAME_COUNT}[stream${c}fadeout];" 100 | 101 | fi 102 | done 103 | 104 | # 6. CREATE TRANSITION FRAMES 105 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 106 | do 107 | FULL_SCRIPT+="[stream$((c+1))fadein][stream${c}fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 108 | done 109 | 110 | # 7. BEGIN CONCAT 111 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 112 | do 113 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 114 | done 115 | 116 | # 8. END CONCAT 117 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 118 | 119 | # 9. END 120 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_fade_in_two.mp4" 121 | 122 | eval ${FULL_SCRIPT} 123 | 124 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 125 | 126 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 127 | 128 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/rotate_one.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with rotate #1 transition v5 (04.06.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | SCREEN_MODE=4 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 16 | IMAGE_DURATION=2 17 | BACKGROUND_COLOR="black" 18 | 19 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 20 | 21 | # FILE OPTIONS 22 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 23 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 24 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 25 | 26 | ############################ 27 | # DO NO MODIFY LINES BELOW 28 | ############################ 29 | 30 | # CALCULATE LENGTH MANUALLY 31 | let IMAGE_COUNT=0 32 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 33 | 34 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 35 | echo "Error: media folder should contain at least two images" 36 | exit 1; 37 | fi 38 | 39 | # INTERNAL VARIABLES 40 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 41 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 42 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT)) 43 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 44 | 45 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 46 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 47 | 48 | START_TIME=$SECONDS 49 | 50 | # 1. START COMMAND 51 | FULL_SCRIPT="ffmpeg -y " 52 | 53 | # 2. ADD INPUTS 54 | for IMAGE in ${FILES[@]}; do 55 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 56 | done 57 | 58 | # 3. ADD BACKGROUND COLOR SCREEN INPUT 59 | FULL_SCRIPT+="-f lavfi -i color=${BACKGROUND_COLOR}:s=${WIDTH}x${HEIGHT},fps=${FPS} " 60 | 61 | # 4. START FILTER COMPLEX 62 | FULL_SCRIPT+="-filter_complex \"" 63 | 64 | # 5. PREPARE INPUTS 65 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 66 | do 67 | case ${SCREEN_MODE} in 68 | 1) 69 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))pre1][stream$((c+1))pre2];" 70 | ;; 71 | 2) 72 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',[${IMAGE_COUNT}:v]overlay,crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))pre1][stream$((c+1))pre2];" 73 | ;; 74 | 3) 75 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))pre1][stream$((c+1))pre2];" 76 | ;; 77 | 4) 78 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 79 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 80 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))pre1][stream$((c+1))pre2];" 81 | ;; 82 | esac 83 | done 84 | 85 | # 6. APPLY PADDING 86 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 87 | do 88 | 89 | if [[ ${c} -eq ${IMAGE_COUNT} ]]; then 90 | SPLIT_COUNT="2" 91 | else 92 | SPLIT_COUNT="3" 93 | fi 94 | 95 | FULL_SCRIPT+="[stream${c}pre1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=#00000000,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}out1];" 96 | 97 | FULL_SCRIPT+="[stream${c}pre2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=${SPLIT_COUNT}[stream${c}out2][stream${c}out3]" 98 | 99 | if [[ ${c} -eq ${IMAGE_COUNT} ]]; then 100 | FULL_SCRIPT+=";" 101 | else 102 | FULL_SCRIPT+="[stream${c}out4];" 103 | fi 104 | done 105 | 106 | # 7. CREATE ROTATION FRAMES 107 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 108 | do 109 | if [[ ${c} -eq 1 ]]; then 110 | OVERLAY_FRAME="${IMAGE_COUNT}:v" 111 | else 112 | OVERLAY_FRAME="stream$((c-1))out2" 113 | fi 114 | 115 | FULL_SCRIPT+="[stream${c}out1]rotate=2*PI*t:ow=4*${WIDTH}:c=#00000000,[${OVERLAY_FRAME}]overlay=x='${WIDTH}*3/2-w+t/${TRANSITION_DURATION}*${WIDTH}':y=0,trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}rotating];" 116 | done 117 | 118 | # 8. BEGIN CONCAT 119 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 120 | do 121 | FULL_SCRIPT+="[stream${c}rotating][stream${c}out3][stream${c}out4]" 122 | done 123 | 124 | # 9. END CONCAT 125 | FULL_SCRIPT+="[stream${IMAGE_COUNT}rotating][stream${IMAGE_COUNT}out2][stream${IMAGE_COUNT}out3]concat=n=$((3*IMAGE_COUNT)):v=1:a=0,format=yuv420p[video]\"" 126 | 127 | # 10. END 128 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_rotate_one.mp4" 129 | 130 | eval ${FULL_SCRIPT} 131 | 132 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 133 | 134 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 135 | 136 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/spin_blur_rotation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with spin blur rotation transition v3 (25.05.2019) 4 | # 5 | # Copyright (c) 2018-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | IMAGE_DURATION=2 15 | 16 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 17 | 18 | # FILE OPTIONS 19 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 20 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 21 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 22 | 23 | ############################ 24 | # DO NO MODIFY LINES BELOW 25 | ############################ 26 | 27 | # CALCULATE LENGTH MANUALLY 28 | let IMAGE_COUNT=0 29 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 30 | 31 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 32 | echo "Error: media folder should contain at least two images" 33 | exit 1; 34 | fi 35 | 36 | # INTERNAL VARIABLES 37 | TRANSITION_FRAME_COUNT=$(( 1*FPS )) 38 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 39 | TOTAL_DURATION=$(( (IMAGE_DURATION+1)*IMAGE_COUNT - 1 )) 40 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 41 | 42 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 43 | Transition duration: 1 s\nTotal duration: ${TOTAL_DURATION} s\n" 44 | 45 | START_TIME=$SECONDS 46 | 47 | # 1. START COMMAND 48 | FULL_SCRIPT="ffmpeg -y " 49 | 50 | # 2. ADD INPUTS 51 | for IMAGE in ${FILES[@]}; do 52 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 53 | done 54 | 55 | # 3. START FILTER COMPLEX 56 | FULL_SCRIPT+="-filter_complex \"" 57 | 58 | # 4. PREPARE INPUTS 59 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 60 | do 61 | if [[ $((c+1)) -eq 1 ]] || [[ $((c+1)) -eq ${IMAGE_COUNT} ]]; then 62 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,fps=${FPS},format=rgba,trim=duration=${IMAGE_DURATION},crop=${WIDTH}:${HEIGHT},split=2[stream$((c+1))][stream$((c+1))sample];" 63 | else 64 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,fps=${FPS},format=rgba,trim=duration=${IMAGE_DURATION},crop=${WIDTH}:${HEIGHT},split=3[stream$((c+1))][stream$((c+1))sample][stream$((c+1))sample2];" 65 | fi 66 | done 67 | 68 | # 5. ROTATE & BLUR 69 | for (( c=2; c<=${IMAGE_COUNT}; c++ )) 70 | do 71 | FULL_SCRIPT+="[stream${c}sample]rotate=PI,split=2[stream${c}rotate_in_background][stream${c}pre_rotate_in];" 72 | FULL_SCRIPT+="[stream${c}pre_rotate_in]boxblur=luma_radius=10:luma_power=3,rotate=2*PI*t/0.6:c=none[stream${c}rotate_in];" 73 | done 74 | 75 | # 6. CREATE TRANSITION FRAMES 76 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 77 | do 78 | FULL_SCRIPT+="[stream${c}pre_rotate_out]boxblur=luma_radius=10:luma_power=3,rotate=2*PI*t/0.4:c=none[stream${c}rotate_out];" 79 | 80 | if [[ ${c} -eq 1 ]]; then 81 | FULL_SCRIPT+="[stream${c}sample]split=2[stream${c}rotate_out_background][stream${c}pre_rotate_out];" 82 | else 83 | FULL_SCRIPT+="[stream${c}sample2]split=2[stream${c}rotate_out_background][stream${c}pre_rotate_out];" 84 | fi 85 | 86 | FULL_SCRIPT+="[stream${c}rotate_out_background][stream${c}rotate_out]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,crop=${WIDTH}:${HEIGHT},trim=duration=0.2[transition${c}part1];" 87 | 88 | FULL_SCRIPT+="[stream$((c+1))rotate_in_background][stream$((c+1))rotate_in]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,crop=${WIDTH}:${HEIGHT},trim=duration=0.3[transition${c}part2];" 89 | 90 | done 91 | 92 | # 7. BEGIN CONCAT 93 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 94 | do 95 | FULL_SCRIPT+="[stream${c}][transition${c}part1][transition${c}part2]" 96 | done 97 | 98 | # 8. END CONCAT 99 | FULL_SCRIPT+="[stream${IMAGE_COUNT}]concat=n=$((3*IMAGE_COUNT-2)):v=1:a=0,format=yuv420p[video]\"" 100 | 101 | # 9. END 102 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_spin_blur_rotation.mp4" 103 | 104 | eval ${FULL_SCRIPT} 105 | 106 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 107 | 108 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 109 | 110 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/stack_horizontal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal stack transition v2 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TOTAL_DURATION=10 # ALSO CONTROLS THE SPEED 15 | BACKGROUND_COLOR="black" 16 | DIRECTION=2 # 1=LEFT TO RIGHT, 2=RIGHT TO LEFT 17 | INCLUDE_INTRO=1 # START WITH EMPTY SCREEN 18 | INCLUDE_OUTRO=0 # END WITH EMPTY SCREEN 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nTotal duration: ${TOTAL_DURATION} s\n" 41 | 42 | START_TIME=$SECONDS 43 | 44 | # 1. START COMMAND 45 | FULL_SCRIPT="ffmpeg -y " 46 | 47 | # 2. ADD INPUTS 48 | for IMAGE in ${FILES[@]}; do 49 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 50 | done 51 | 52 | # 3. ADD BACKGROUND COLOR SCREEN INPUT 53 | FULL_SCRIPT+="-f lavfi -i color=${BACKGROUND_COLOR}:s=${WIDTH}x${HEIGHT},fps=${FPS} " 54 | 55 | # 4. START FILTER COMPLEX 56 | FULL_SCRIPT+="-filter_complex \"" 57 | 58 | # 5. PREPARE INPUTS 59 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 60 | do 61 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=trunc(iw/2)*2:trunc(ih/2)*2,scale=-1:${HEIGHT},setsar=sar=1/1,fps=${FPS}[stream$((c+1))];" 62 | done 63 | 64 | STACKED_INPUTS="" 65 | declare -i INTRO_OUTRO_COUNT=0 66 | 67 | # 6. BEGIN STACK INPUTS 68 | if [[ ${INCLUDE_INTRO} -eq 1 ]]; then 69 | STACKED_INPUTS+="[${IMAGE_COUNT}:v]" 70 | INTRO_OUTRO_COUNT+=1; 71 | fi 72 | 73 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 74 | do 75 | STACKED_INPUTS+="[stream${c}]" 76 | done 77 | 78 | if [[ ${INCLUDE_OUTRO} -eq 1 ]]; then 79 | STACKED_INPUTS+="[${IMAGE_COUNT}:v]" 80 | INTRO_OUTRO_COUNT+=1; 81 | fi 82 | 83 | # 7. END STACK INPUTS 84 | FULL_SCRIPT+="${STACKED_INPUTS}hstack=inputs=$((${IMAGE_COUNT}+${INTRO_OUTRO_COUNT}))[stack];" 85 | 86 | # 8. SLIDE STACK 87 | case ${DIRECTION} in 88 | 1) 89 | FULL_SCRIPT+="[${IMAGE_COUNT}:v][stack]overlay=x='-(overlay_w-${WIDTH})+(overlay_w-${WIDTH})*t/${TOTAL_DURATION}':y=0,trim=duration=${TOTAL_DURATION},format=yuv420p[video]\"" 90 | ;; 91 | *) 92 | FULL_SCRIPT+="[${IMAGE_COUNT}:v][stack]overlay=x='-(overlay_w-${WIDTH})*t/${TOTAL_DURATION}':y=0,trim=duration=${TOTAL_DURATION},format=yuv420p[video]\"" 93 | ;; 94 | esac 95 | 96 | # 9. END 97 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_stack_horizontal.mp4" 98 | 99 | eval ${FULL_SCRIPT} 100 | 101 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 102 | 103 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 104 | 105 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/stack_vertical.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical stack transition v2 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TOTAL_DURATION=10 # ALSO CONTROLS THE SPEED 15 | BACKGROUND_COLOR="black" 16 | DIRECTION=2 # 1=TOP TO BOTTOM, 2=BOTTOM TO TOP 17 | INCLUDE_INTRO=1 # START WITH EMPTY SCREEN 18 | INCLUDE_OUTRO=0 # END WITH EMPTY SCREEN 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nTotal duration: ${TOTAL_DURATION} s\n" 41 | 42 | START_TIME=$SECONDS 43 | 44 | # 1. START COMMAND 45 | FULL_SCRIPT="ffmpeg -y " 46 | 47 | # 2. ADD INPUTS 48 | for IMAGE in ${FILES[@]}; do 49 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 50 | done 51 | 52 | # 3. ADD BACKGROUND COLOR SCREEN INPUT 53 | FULL_SCRIPT+="-f lavfi -i color=${BACKGROUND_COLOR}:s=${WIDTH}x${HEIGHT},fps=${FPS} " 54 | 55 | # 4. START FILTER COMPLEX 56 | FULL_SCRIPT+="-filter_complex \"" 57 | 58 | # 5. PREPARE INPUTS 59 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 60 | do 61 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=trunc(iw/2)*2:trunc(ih/2)*2,scale=${WIDTH}:-1,setsar=sar=1/1,fps=${FPS}[stream$((c+1))];" 62 | done 63 | 64 | STACKED_INPUTS="" 65 | declare -i INTRO_OUTRO_COUNT=0 66 | 67 | # 6. BEGIN STACK INPUTS 68 | if [[ ${INCLUDE_INTRO} -eq 1 ]]; then 69 | STACKED_INPUTS+="[${IMAGE_COUNT}:v]" 70 | INTRO_OUTRO_COUNT+=1; 71 | fi 72 | 73 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 74 | do 75 | STACKED_INPUTS+="[stream${c}]" 76 | done 77 | 78 | if [[ ${INCLUDE_OUTRO} -eq 1 ]]; then 79 | STACKED_INPUTS+="[${IMAGE_COUNT}:v]" 80 | INTRO_OUTRO_COUNT+=1; 81 | fi 82 | 83 | # 7. END STACK INPUTS 84 | FULL_SCRIPT+="${STACKED_INPUTS}vstack=inputs=$((${IMAGE_COUNT}+${INTRO_OUTRO_COUNT}))[stack];" 85 | 86 | # 8. SLIDE STACK 87 | case ${DIRECTION} in 88 | 1) 89 | FULL_SCRIPT+="[${IMAGE_COUNT}:v][stack]overlay=x=0:y='-(overlay_h-${HEIGHT})+(overlay_h-${HEIGHT})*t/${TOTAL_DURATION}',trim=duration=${TOTAL_DURATION},format=yuv420p[video]\"" 90 | ;; 91 | *) 92 | FULL_SCRIPT+="[${IMAGE_COUNT}:v][stack]overlay=x=0:y='-(overlay_h-${HEIGHT})*t/${TOTAL_DURATION}',trim=duration=${TOTAL_DURATION},format=yuv420p[video]\"" 93 | ;; 94 | esac 95 | 96 | # 9. END 97 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_stack_vertical.mp4" 98 | 99 | eval ${FULL_SCRIPT} 100 | 101 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 102 | 103 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 104 | 105 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/wipe_in_horizontal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with horizontal wipe in transition v5 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | DIRECTION=2 # 1=LEFT TO RIGHT, 2=RIGHT TO LEFT 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | case ${DIRECTION} in 102 | 1) 103 | FULL_SCRIPT+="[stream${c}ending][stream$((c+1))starting]overlay=x='-w+t/${TRANSITION_DURATION}*${WIDTH}':y=0,select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 104 | ;; 105 | *) 106 | FULL_SCRIPT+="[stream${c}ending][stream$((c+1))starting]overlay=x='w-t/${TRANSITION_DURATION}*${WIDTH}':y=0,select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 107 | ;; 108 | esac 109 | done 110 | 111 | # 7. BEGIN CONCAT 112 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 113 | do 114 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 115 | done 116 | 117 | # 8. END CONCAT 118 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 119 | 120 | # 9. END 121 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_wipe_in_horizontal.mp4" 122 | 123 | eval ${FULL_SCRIPT} 124 | 125 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 126 | 127 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 128 | 129 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/wipe_in_vertical.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical wipe in transition v5 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | 8 | # SCRIPT OPTIONS - CAN BE MODIFIED 9 | WIDTH=1280 10 | HEIGHT=720 11 | FPS=30 12 | TRANSITION_DURATION=1 13 | IMAGE_DURATION=2 14 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 15 | BACKGROUND_COLOR="black" 16 | DIRECTION=1 # 1=TOP TO BOTTOM, 2=BOTTOM TO TOP 17 | 18 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 19 | 20 | # FILE OPTIONS 21 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 22 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 23 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 24 | 25 | ############################ 26 | # DO NO MODIFY LINES BELOW 27 | ############################ 28 | 29 | # CALCULATE LENGTH MANUALLY 30 | let IMAGE_COUNT=0 31 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 32 | 33 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 34 | echo "Error: media folder should contain at least two images" 35 | exit 1; 36 | fi 37 | 38 | # INTERNAL VARIABLES 39 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 40 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 41 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 42 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 43 | 44 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 45 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 46 | 47 | START_TIME=$SECONDS 48 | 49 | # 1. START COMMAND 50 | FULL_SCRIPT="ffmpeg -y " 51 | 52 | # 2. ADD INPUTS 53 | for IMAGE in ${FILES[@]}; do 54 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 55 | done 56 | 57 | # 3. START FILTER COMPLEX 58 | FULL_SCRIPT+="-filter_complex \"" 59 | 60 | # 4. PREPARE INPUTS 61 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 62 | do 63 | case ${SCREEN_MODE} in 64 | 1) 65 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 66 | ;; 67 | 2) 68 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 69 | ;; 70 | 3) 71 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 72 | ;; 73 | 4) 74 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 75 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 76 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 77 | ;; 78 | esac 79 | done 80 | 81 | # 5. APPLY PADDING 82 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 83 | do 84 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 85 | if [[ ${c} -eq 1 ]]; then 86 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 87 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 88 | fi 89 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 90 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 91 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 93 | fi 94 | done 95 | 96 | # 6. CREATE TRANSITION FRAMES 97 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 98 | do 99 | case ${DIRECTION} in 100 | 1) 101 | FULL_SCRIPT+="[stream${c}ending][stream$((c+1))starting]overlay=y='-h+t/${TRANSITION_DURATION}*${HEIGHT}':x=0,select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 102 | ;; 103 | *) 104 | FULL_SCRIPT+="[stream${c}ending][stream$((c+1))starting]overlay=y='h-t/${TRANSITION_DURATION}*${HEIGHT}':x=0,select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 105 | ;; 106 | esac 107 | done 108 | 109 | # 7. BEGIN CONCAT 110 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 111 | do 112 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 113 | done 114 | 115 | # 8. END CONCAT 116 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 117 | 118 | # 9. END 119 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_wipe_in_vertical.mp4" 120 | 121 | eval ${FULL_SCRIPT} 122 | 123 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 124 | 125 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 126 | 127 | unset $IFS -------------------------------------------------------------------------------- /transition_scripts/wipe_out_vertical.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # ffmpeg video slideshow script with vertical wipe out transition v5 (25.05.2019) 4 | # 5 | # Copyright (c) 2017-2019, Taner Sener (https://github.com/tanersener) 6 | # 7 | # This work is licensed under the terms of the MIT license. For a copy, see . 8 | # 9 | 10 | # SCRIPT OPTIONS - CAN BE MODIFIED 11 | WIDTH=1280 12 | HEIGHT=720 13 | FPS=30 14 | TRANSITION_DURATION=1 15 | IMAGE_DURATION=2 16 | SCREEN_MODE=2 # 1=CENTER, 2=CROP, 3=SCALE, 4=BLUR 17 | BACKGROUND_COLOR="black" 18 | DIRECTION=1 # 1=TOP TO BOTTOM, 2=BOTTOM TO TOP 19 | 20 | IFS=$'\t\n' # REQUIRED TO SUPPORT SPACES IN FILE NAMES 21 | 22 | # FILE OPTIONS 23 | # FILES=`find ../media/*.jpg | sort -r` # USE ALL IMAGES UNDER THE media FOLDER SORTED 24 | # FILES=('../media/1.jpg' '../media/2.jpg') # USE ONLY THESE IMAGE FILES 25 | FILES=`find ../media/*.jpg` # USE ALL IMAGES UNDER THE media FOLDER 26 | 27 | ############################ 28 | # DO NO MODIFY LINES BELOW 29 | ############################ 30 | 31 | # CALCULATE LENGTH MANUALLY 32 | let IMAGE_COUNT=0 33 | for IMAGE in ${FILES[@]}; do (( IMAGE_COUNT+=1 )); done 34 | 35 | if [[ ${IMAGE_COUNT} -lt 2 ]]; then 36 | echo "Error: media folder should contain at least two images" 37 | exit 1; 38 | fi 39 | 40 | # INTERNAL VARIABLES 41 | TRANSITION_FRAME_COUNT=$(( TRANSITION_DURATION*FPS )) 42 | IMAGE_FRAME_COUNT=$(( IMAGE_DURATION*FPS )) 43 | TOTAL_DURATION=$(( (IMAGE_DURATION+TRANSITION_DURATION)*IMAGE_COUNT - TRANSITION_DURATION )) 44 | TOTAL_FRAME_COUNT=$(( TOTAL_DURATION*FPS )) 45 | 46 | echo -e "\nVideo Slideshow Info\n------------------------\nImage count: ${IMAGE_COUNT}\nDimension: ${WIDTH}x${HEIGHT}\nFPS: ${FPS}\nImage duration: ${IMAGE_DURATION} s\n\ 47 | Transition duration: ${TRANSITION_DURATION} s\nTotal duration: ${TOTAL_DURATION} s\n" 48 | 49 | START_TIME=$SECONDS 50 | 51 | # 1. START COMMAND 52 | FULL_SCRIPT="ffmpeg -y " 53 | 54 | # 2. ADD INPUTS 55 | for IMAGE in ${FILES[@]}; do 56 | FULL_SCRIPT+="-loop 1 -i '${IMAGE}' " 57 | done 58 | 59 | # 3. START FILTER COMPLEX 60 | FULL_SCRIPT+="-filter_complex \"" 61 | 62 | # 4. PREPARE INPUTS 63 | for (( c=0; c<${IMAGE_COUNT}; c++ )) 64 | do 65 | case ${SCREEN_MODE} in 66 | 1) 67 | 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,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 68 | ;; 69 | 2) 70 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=w='if(gte(iw/ih,${WIDTH}/${HEIGHT}),-1,${WIDTH})':h='if(gte(iw/ih,${WIDTH}/${HEIGHT}),${HEIGHT},-1)',crop=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 71 | ;; 72 | 3) 73 | FULL_SCRIPT+="[${c}:v]setpts=PTS-STARTPTS,scale=${WIDTH}:${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,split=2[stream$((c+1))out1][stream$((c+1))out2];" 74 | ;; 75 | 4) 76 | FULL_SCRIPT+="[${c}:v]scale=${WIDTH}x${HEIGHT},setsar=sar=1/1,fps=${FPS},format=rgba,boxblur=100,setsar=sar=1/1[stream${c}blurred];" 77 | FULL_SCRIPT+="[${c}:v]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,fps=${FPS},format=rgba[stream${c}raw];" 78 | FULL_SCRIPT+="[stream${c}blurred][stream${c}raw]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:format=rgb,setpts=PTS-STARTPTS,split=2[stream$((c+1))out1][stream$((c+1))out2];" 79 | ;; 80 | esac 81 | done 82 | 83 | # 5. APPLY PADDING 84 | for (( c=1; c<=${IMAGE_COUNT}; c++ )) 85 | do 86 | FULL_SCRIPT+="[stream${c}out1]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${IMAGE_DURATION},select=lte(n\,${IMAGE_FRAME_COUNT})[stream${c}overlaid];" 87 | if [[ ${c} -eq 1 ]]; then 88 | if [[ ${IMAGE_COUNT} -gt 1 ]]; then 89 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}ending];" 90 | fi 91 | elif [[ ${c} -lt ${IMAGE_COUNT} ]]; then 92 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT}),split=2[stream${c}starting][stream${c}ending];" 93 | elif [[ ${c} -eq ${IMAGE_COUNT} ]]; then 94 | FULL_SCRIPT+="[stream${c}out2]pad=width=${WIDTH}:height=${HEIGHT}:x=(${WIDTH}-iw)/2:y=(${HEIGHT}-ih)/2:color=${BACKGROUND_COLOR},trim=duration=${TRANSITION_DURATION},select=lte(n\,${TRANSITION_FRAME_COUNT})[stream${c}starting];" 95 | fi 96 | done 97 | 98 | # 6. CREATE TRANSITION FRAMES 99 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 100 | do 101 | case ${DIRECTION} in 102 | 1) 103 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]overlay=y='t/${TRANSITION_DURATION}*${HEIGHT}':x=0,select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 104 | ;; 105 | *) 106 | FULL_SCRIPT+="[stream$((c+1))starting][stream${c}ending]overlay=y='-t/${TRANSITION_DURATION}*${HEIGHT}':x=0,select=lte(n\,${TRANSITION_FRAME_COUNT})[stream$((c+1))blended];" 107 | ;; 108 | esac 109 | done 110 | 111 | # 7. BEGIN CONCAT 112 | for (( c=1; c<${IMAGE_COUNT}; c++ )) 113 | do 114 | FULL_SCRIPT+="[stream${c}overlaid][stream$((c+1))blended]" 115 | done 116 | 117 | # 8. END CONCAT 118 | FULL_SCRIPT+="[stream${IMAGE_COUNT}overlaid]concat=n=$((2*IMAGE_COUNT-1)):v=1:a=0,format=yuv420p[video]\"" 119 | 120 | # 9. END 121 | FULL_SCRIPT+=" -map [video] -vsync 2 -async 1 -rc-lookahead 0 -g 0 -profile:v main -level 42 -c:v libx264 -r ${FPS} ../transition_wipe_out_vertical.mp4" 122 | 123 | eval ${FULL_SCRIPT} 124 | 125 | ELAPSED_TIME=$(($SECONDS - $START_TIME)) 126 | 127 | echo -e '\nSlideshow created in '$ELAPSED_TIME' seconds\n' 128 | 129 | unset $IFS -------------------------------------------------------------------------------- /transition_video_scripts/LICENSE.Commercial.txt: -------------------------------------------------------------------------------- 1 | ARTHENICA Commercial License 2 | 3 | Copyright (c) 2019, Taner Sener (https://github.com/tanersener), All rights reserved. 4 | 5 | Permission is hereby granted, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, merge, distribute, sublicense, and/or sell copies of the Software, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /video_slideshow_script_generator/LICENSE.Commercial.txt: -------------------------------------------------------------------------------- 1 | ARTHENICA Commercial License 2 | 3 | Copyright (c) 2019-2022, Taner Sener (https://github.com/tanersener), All rights reserved. 4 | 5 | Permission is hereby granted, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, merge, distribute, sublicense, and/or sell copies of the Software, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /video_slideshow_script_generator/LICENSE.Personal.txt: -------------------------------------------------------------------------------- 1 | ARTHENICA Personal License 2 | 3 | Copyright (c) 2019-2022, Taner Sener (https://github.com/tanersener), All rights reserved. 4 | 5 | Permission is hereby granted, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify and merge, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /video_slideshow_script_generator/example.vssg: -------------------------------------------------------------------------------- 1 | ¨<¨TRANSITION¨1¨>¨ 2 | intro 3 | 6 4 | 1 5 | 6 | 7 | 8 | 128 9 | 10 | 11 | ¨<¨IMAGE¨1¨>¨ 12 | image-1 13 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/media/1.jpg 14 | 1 15 | 16 | true 17 | 1 18 | 3 19 | 1.5 20 | true 21 | 0 22 | false 23 | 0 24 | 0 25 | 5 26 | ¨<<¨TEXT¨1¨>>¨ 27 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/fonts/FallingSkyBd.otf 28 | 30 29 | Zooming out and moving objects 30 | white 31 | 100 32 | 555 33 | black 34 | 1.0 35 | 80 36 | 540 37 | 460 38 | 60 39 | ¨<<¨OVERLAY¨OBJECT¨1¨>>¨ 40 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/objects/snow-flake.png 41 | colorchannelmixer=.3:.4:.3:0:.3:.4:.3:0:.3:.4:.3 42 | 1.0 43 | 1000 44 | -190+t/3*1100 45 | 3 46 | 70 47 | 70 48 | ¨<<¨OVERLAY¨OBJECT¨1¨>>¨ 49 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/objects/snow-flake.png 50 | 51 | 1.0 52 | 100 53 | -200+t/3*600 54 | 3 55 | 80 56 | 80 57 | ¨<¨TRANSITION¨1¨>¨ 58 | transition-one 59 | 25 60 | 2 61 | 10 62 | 0 63 | 64 | 65 | 66 | 67 | ¨<¨VIDEO¨1¨>¨ 68 | video-1 69 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/media/2.mp4 70 | 1 71 | 72 | false 73 | 0 74 | 3 75 | 1.5 76 | false 77 | 0 78 | false 79 | 0 80 | 0 81 | false 82 | 0 83 | 3 84 | ¨<<¨TEXT¨1¨>>¨ 85 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/fonts/FallingSkyBd.otf 86 | 45 87 | Multiple text messages 88 | white 89 | 450 90 | 640 91 | 92 | 93 | 94 | 95 | 96 | 97 | ¨<<¨TEXT¨1¨>>¨ 98 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/fonts/FallingSkyBd.otf 99 | 20 100 | Text #1 101 | black 102 | 920 103 | 120 104 | white 105 | 0.6 106 | 900 107 | 100 108 | 100 109 | 60 110 | ¨<<¨TEXT¨1¨>>¨ 111 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/fonts/FallingSkyBd.otf 112 | 20 113 | Text #2 114 | white 115 | 920 116 | 520 117 | red 118 | 0.4 119 | 900 120 | 500 121 | 100 122 | 60 123 | ¨<¨TRANSITION¨1¨>¨ 124 | transition-two 125 | 29 126 | 1 127 | 128 | 129 | 1 130 | 131 | 132 | 133 | ¨<¨VIDEO¨1¨>¨ 134 | video-2 135 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/media/1.mp4 136 | 1 137 | 138 | true 139 | 0 140 | 3 141 | 1.5 142 | true 143 | 6 144 | false 145 | 0 146 | 0 147 | false 148 | 0 149 | 3 150 | ¨<<¨TEXT¨1¨>>¨ 151 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/fonts/FallingSkyBd.otf 152 | 40 153 | Zoom & pan with moving text 154 | white 155 | 260-t/5*160 156 | 574 157 | black 158 | 0.7 159 | 0 160 | 560 161 | 1280 162 | 60 163 | ¨<¨TRANSITION¨1¨>¨ 164 | transition-three 165 | 20 166 | 1 167 | 168 | 0 169 | 170 | 171 | 172 | 6 173 | ¨<¨VIDEO¨1¨>¨ 174 | video-3 175 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/media/3.mp4 176 | 1 177 | 178 | false 179 | 0 180 | 3 181 | 1.5 182 | false 183 | 0 184 | false 185 | 0 186 | 0 187 | false 188 | 0 189 | 3 190 | ¨<<¨TEXT¨1¨>>¨ 191 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/fonts/FallingSkyBd.otf 192 | 40 193 | Video inside a frame 194 | white 195 | 500 196 | 560 197 | 198 | 199 | 200 | 201 | 202 | 203 | ¨<<¨OVERLAY¨OBJECT¨1¨>>¨ 204 | /Users/taner/Projects/ffmpeg-video-slideshow-scripts/objects/film_strip.png 205 | 206 | 1.0 207 | 0 208 | 0 209 | 2 210 | 211 | 212 | ¨<¨TRANSITION¨1¨>¨ 213 | outro 214 | 15 215 | 2 216 | 217 | 218 | 219 | 220 | 221 | 222 | ¨<¨AUDIO¨1¨>¨ 223 | aac 224 | 225 | fltp 226 | 11025 227 | stereo 228 | ¨<¨SETTINGS¨1¨>¨ 229 | script-example.sh 230 | slideshow-example.mp4 231 | true 232 | false 233 | black 234 | 235 | 0 236 | 1280 237 | 720 238 | 30 239 | libx264 240 | -crf 20 241 | yuv420p 242 | -profile:v high -level 42 243 | -rc-lookahead 0 -g 0 244 | --------------------------------------------------------------------------------