Create Video From PDF with ImageMagick and FFMPEG

Sample Script cutAndPastePdfPage.bat.
This script splits a tall pdf into 2 and arrange sidewise, so it can be nicely seen in screen.
You need to download and install

  1. GhostScript for PDF to image conversion , ref
  2. ImageMagick for cutting PDF page image and arranging sidewise.
  3. FFMPEG to create videos

Word of Caution: ImageMagick installs its own ffmpeg which could be older version lacking filters like xfade. So rename the ffmpeg.exe of ImageMagick and use your own by setting the path appropriatesly for %PATH% env variable

@echo off
setlocal
rem USAGE
rem get <total_pagenum> with : magick magick identify -format %n\n presentation.pdf
rem create pages with : magick -density 150 presentation.pdf -quality 90 -resize 75% pdfPage-%d.png
rem create cut& paste images with : cutAndPastePdfPage <total_pageNum - 1>

rem old
rem set PAGE_NUM=%1
rem magick "pdfPage-%PAGE_NUM%.png" -crop "100%%x50%%"  "%PAGE_NUM%-halfPage.png"
rem magick -density 150 presentation.pdf -quality 90 -resize 75% pdfPage-%%d.png
rem new with loop
set TOTAL_PAGE_NUM=%1
set CUT_PASTED_PAGE_IMAGE=cutPastedPageImage.png
rem magick pdfPdge-1.png -crop 100%x50%  output.png
rem FOR /L %%y IN (0, 1, %TOTAL_PAGE_NUM%) DO magick "pdfPage-%%y.png" -crop "100%%x50%%"  "%%y-halfPage.png"

rem Batch file for loop – looping through files http://www.trytoprogram.com/batch-file-for-loop/
rem FOR %y IN (pdfPage-*.png) DO @ECHO %y

echo magick -density 150 presentation.pdf -quality 90 -resize 75%% pdfPage-%%d.png
rem magick -density 150 presentation.pdf -quality 90 -resize 75%% pdfPage-%%d.png
rem set /p id="Press any key to continue: "
rem exit
FOR %%f IN (./pdfPage-*.png) do call :onefile %%f   ← subroutine called here
rem to use  subroutine
rem https://www.informit.com/articles/article.aspx?p=1154761&seqNum=11

rem FOR /L %%y IN (0, 1, %TOTAL_PAGE_NUM%) do call :onefile %%y   ← subroutine called here

rem main program must end with exit /b or goto :EOF
exit /b

rem SUBROUTINE "ONEFILE" ---------------------------
:onefile
rem https://stackoverflow.com/questions/2772456/string-replacement-in-batch-file
setlocal ENABLEDELAYEDEXPANSION
rem %1 will be pdfPage-0.png
rem remove pdfPage- and .png
set fileNamePassed="%1"
echo fileName passed is %fileNamePassed%
if %fileNamePassed%=="" exit /b   ← some sort of bug
set str=%1
rem set str=pdfPage-0.png
set str=%str:pdfPage-=%
set str=%str:.png=%
set fileNum=%str%
rem echo fileNum is %fileNum%

echo Processing file %fileNum%...
rem echo ... commands go here ...
rem magick "pdfPage-%fileNum%.png" -crop "100%%x50%%"  "%fileNum%-halfPage.png"
magick -size 1366x768 xc:white %fileNum%-%CUT_PASTED_PAGE_IMAGE%
set /a  "isOdd=%fileNum% %% 2"
echo isOdd is %isOdd%

if %isOdd%==1 goto :processOdd
magick %fileNum%-%CUT_PASTED_PAGE_IMAGE% ( pdfPage-%fileNum%.png -crop 655x658+39+0  ) -geometry +60+0 -composite %fileNum%-%CUT_PASTED_PAGE_IMAGE%
magick %fileNum%-%CUT_PASTED_PAGE_IMAGE% ( pdfPage-%fileNum%.png -crop 655x650+39+659  ) -geometry +705+50 -composite %fileNum%-%CUT_PASTED_PAGE_IMAGE%
exit /b
:processOdd
magick %fileNum%-%CUT_PASTED_PAGE_IMAGE% ( pdfPage-%fileNum%.png -crop 600x658+266+0  ) -geometry +60+0 -composite %fileNum%-%CUT_PASTED_PAGE_IMAGE%
magick %fileNum%-%CUT_PASTED_PAGE_IMAGE% ( pdfPage-%fileNum%.png -crop 600x650+266+659  ) -geometry +705+50 -composite %fileNum%-%CUT_PASTED_PAGE_IMAGE%
exit /b

concatWithMultipleTransitions.bat

@echo OFF
setlocal ENABLEDELAYEDEXPANSION
GOTO algorithmCommentBlockEnd
cd /d D:\babluMunji\AlbumPDF
echo %PATH% > pathVars.txt
ffmpeg -filters > filtersAvailable.txt
concatWithMultipleTransitions > concatOP.txt
## [FFmpeg-user] Install issues - old version still shows up
[ref](https://ffmpeg.org/pipermail/ffmpeg-user/2014-September/023656.html)
turned out to be another piece of software that I had installed,
specifically Image Magick, that had added it’s own directory to the Windows
PATH and just happened to have a version of ffmpeg for itself to use as
well. So from that point on, unbeknownst to me, I was running a much older
version of ffmpeg.
Solution : rename to ffmpeg in iIMageMagick folder , make sure %PATH% is updated with new version of ffmpeg
## Basic Sequence
1. get all transitions & %NO_OF_TRANSITIONS% from config.bat
2. get %TOTAL_IMAGE_FILES%
3. get names of all files in fileName[] array
4. create mp4 for each images in `VIDS` folder as `%IMAGE_NAME%_SILENT.mp4`
5. call `concat` subroutine which ill create final image `videoFromImages.mp4`
6. to add audio use the command
ffmpeg -i videoFromImages.mp4 -filter_complex "amovie=upanayanamBG.mp4:loop=0,asetpts=N/SR/TB[a]" -map 0:v -map [a] -c:v copy -c:a aac -b:a 256k  -shortest videoFromImagesMultiTransWithAudio.mp4 -y
## `concat` subroutine
1. if only one file exit
2. if more than one files copy %IMAGE_NAME%_SILENT.mp4 concatStart.mp4 
3. if %FILE_NUM% GTR 1  (
    ffmpeg -i concatStart.mp4 -i "%IMAGE_NAME%" -filter_complex "[0:v][1:v]xfade=transition=!TRANSITION_2_USE!:duration=%TRANSITION_DURATION%:offset=!TRANSITION_OFFSET!,format=yuv420p" -map  -an -y vtrimmedConcat.mp4    
    copy vtrimmedConcat.mp4 concatStart.mp4
    if %FILE_NUM% EQU %TOTAL_IMAGE_FILES% (
        copy concatStart.mp4 videoFromImages.mp4 
        del concatStart.mp4 
        del vtrimmedConcat.mp4 
    )

    )

:algorithmCommentBlockEnd

rem 1366x768
set BG_W=1316
set BG_H=930
set SLIDE_DURATION=3
set TRANSITION_DURATION=1
set IMG_TYPE=PNG
set FILE_PREFIX_B4_NUMBER=pdfPage-
set FILE_PREFIX_AFTER_NUMBER=.png
set /a TOTAL_IMAGE_FILES=0
set PICS_FOLDER=PICS
set VIDS_FOLDER=VIDS
set /a TRANSITION_OFFSET=0
set TRANSITION_2_USE=fade
rem https://stackoverflow.com/a/2763907
call config.bat  & :: load transistions & set NO_OF_TRANSITIONS
for %%f in (./%PICS_FOLDER%/*.%IMG_TYPE%)  do (
    set /a TOTAL_IMAGE_FILES=TOTAL_IMAGE_FILES+1   & :: no need to use %%
    rem https://stackoverflow.com/a/2919699
    rem echo TOTAL_IMAGE_FILES is !TOTAL_IMAGE_FILES!
    rem echo file name is %%f
     rem https://stackoverflow.com/a/45811503

    rem set /a ID+=1
)

set /a TOTAL_IMAGE_FILES_MINUS_ONE=%TOTAL_IMAGE_FILES%-1
echo TOTAL_IMAGE_FILES is %TOTAL_IMAGE_FILES%
echo TOTAL_IMAGE_FILES_MINUS_ONE is %TOTAL_IMAGE_FILES_MINUS_ONE%
:: exit /b
for /L %%i in (0,1,%TOTAL_IMAGE_FILES_MINUS_ONE%) do (  
rem  file names will be like pdfPage-[Num].png
    set filename[%%i]=%FILE_PREFIX_B4_NUMBER%%%i%FILE_PREFIX_AFTER_NUMBER%
    rem echo filename[%%i] is !%filename[%%i]%!
)
rem for /L %%i in (1,1,%TOTAL_IMAGE_FILES%) do (
for /L %%i in (0,1,%TOTAL_IMAGE_FILES_MINUS_ONE%) do (
    echo [%%i] "!filename[%%i]!"
)
::exit /b
:: GOTO ignoreCreateMp4
FOR %%f IN (./%PICS_FOLDER%/*.%IMG_TYPE%) do call :createmp4 %%f   ← subroutine called here
:ignoreCreateMp4
for /L %%n in (0,1,%TOTAL_IMAGE_FILES_MINUS_ONE%)  do call :concat %%n  ← subroutine called here
set /p id="Press any key to continue: "
exit /b
:increaseby1
set /a "TOTAL_IMAGE_FILES+=1"
exit /b
:createmp4
set IMAGE_NAME=%1
echo IMAGE_NAME IS %IMAGE_NAME%
echo ffmpeg -f lavfi -i color=size=%BG_W%x%BG_H%:duration=%SLIDE_DURATION%:rate=25:color=0xFFFFF0 -i %PICS_FOLDER%/%IMAGE_NAME% -filter_complex "[1:v]scale=iw*min(%BG_W%/iw\,%BG_H%/ih):ih*min(%BG_W%/iw\,%BG_H%/ih)[ovrl1],[0:v][ovrl1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[v0]" -map "[vo]" -y %VIDS_FOLDER%/%IMAGE_NAME%_SILENT.mp4*************************************************************************************
rem set /p id="Press any key to continue: "
ffmpeg -f lavfi -i color=size=%BG_W%x%BG_H%:duration=%SLIDE_DURATION%:rate=25:color=0xFFFFF0 -i %PICS_FOLDER%/%IMAGE_NAME% -filter_complex "[1:v]scale=iw*min(%BG_W%/iw\,%BG_H%/ih):ih*min(%BG_W%/iw\,%BG_H%/ih)[ovrl1],[0:v][ovrl1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[v0]" -map "[v0]" -y %VIDS_FOLDER%/%IMAGE_NAME%_SILENT.mp4
exit /b
:concat
if %TOTAL_IMAGE_FILES% EQU 1 (  
    exit /b
)
set FILE_NUM=%1
rem set /a FILE_NO_MINUS_ONE=%FILE_NUM%-1
set /a FILE_NO_MINUS_ONE=%FILE_NUM%
echo FILE_NUM is %FILE_NUM%
echo FILE_NO_MINUS_ONE is %FILE_NO_MINUS_ONE%
rem set IMAGE_NAME="%FILE_PREFIX%-%FILE_NUM%.jpeg_SILENT.mp4"
set FILE_NAME=!filename[%FILE_NUM%]!
set IMAGE_NAME=%VIDS_FOLDER%\%FILE_NAME%_SILENT.mp4
echo IMAGE_NAME is %IMAGE_NAME%*************************************************************************************
if %FILE_NUM% EQU %TOTAL_IMAGE_FILES% (
    exit /b  rem filenos are from 0 to n-1
)
if %FILE_NUM% EQU 0 (   
    rem echo copy %IMAGE_NAME% %VIDS_FOLDER%\concatStart.mp4*************************************************************************************
    rem copy "VIDS\DSC01276.jpg_SILENT.mp4" "concatStart.mp4"
    echo copy %IMAGE_NAME% concatStart.mp4
    copy %IMAGE_NAME% concatStart.mp4
    rem set /p id="Press any key to continue: "
)
if %TOTAL_IMAGE_FILES% EQU 1 (
    if %FILE_NUM% GEQ 0 (
     exit /b
     )
)
rem set /a FILE_NO_MINUS_ONE=%FILE_NUM%-%TRANSITION_DURATION%
echo NO_OF_TRANSITIONS is %NO_OF_TRANSITIONS%
set /a TRANSISITION_REMAINDER="!FILE_NO_MINUS_ONE! %% %NO_OF_TRANSITIONS%"
rem set /a TRANSISITION_REMAINDER="%FILE_NUM% %% %NO_OF_TRANSITIONS%"
echo TRANSISITION_REMAINDER is !TRANSISITION_REMAINDER!
if !TRANSISITION_REMAINDER! EQU 0 (
    rem set /a TRANSISITION_REMAINDER=1
    set /a TRANSISITION_REMAINDER=%NO_OF_TRANSITIONS%
)
echo TRANSISITION_REMAINDER is !TRANSISITION_REMAINDER!
rem set /p id="Press any key to continue: "
set IMAGE_NAME=%VIDS_FOLDER%/%FILE_NAME%_SILENT.mp4
if %FILE_NUM% GTR 0 (
    echo ffmpeg -i "concatStart.mp4" -i "%IMAGE_NAME%" -filter_complex ^
"[0:v][1:v]concat=n=2:v=1 [v]" -map "[v]"  -r 30 -y  vtrimmedConcat.mp4
    rem set /p id="Press any key to continue: "
rem !TRANSITION_OFFSET! will be ((%FILE_NUM%-1)*%SLIDE_DURATION%)-(%FILE_NUM%-1)
echo FILE_NO_MINUS_ONE is !FILE_NO_MINUS_ONE!
set /a OFFSET_INTERIM_VAL=!FILE_NO_MINUS_ONE!*%SLIDE_DURATION%
echo OFFSET_INTERIM_VAL is !OFFSET_INTERIM_VAL!
set /a TRANSITION_OFFSET=!OFFSET_INTERIM_VAL!-!FILE_NO_MINUS_ONE!
echo TRANSITION_OFFSET is !TRANSITION_OFFSET!
rem set TRANSITION_2_USE=!TRANSITION[%FILE_NUM%]!
set TRANSISTION_VAR=TRANSITION!FILE_NO_MINUS_ONE!
echo TRANSISTION_VAR is !TRANSISTION_VAR!
set TRANSITION_2_USE=!TRANSISTION_VAR!
rem https://stackoverflow.com/a/14339439
rem call  :callbyrefernce !FILE_NO_MINUS_ONE!
call  :callbyrefernce !TRANSISITION_REMAINDER!
echo TRANSITION_2_USE is !TRANSITION_2_USE!
rem set /p id="Press any key to continue: "

rem https://stackoverflow.com/a/70198046 
echo ffmpeg -i concatStart.mp4 -i "%IMAGE_NAME%" -filter_complex "[0:v][1:v]xfade=transition=!TRANSITION_2_USE!:duration=%TRANSITION_DURATION%:offset=!TRANSITION_OFFSET!,format=yuv420p" -map  -an -y vtrimmedConcat.mp4
rem set /p id="Press any key to continue: "
ffmpeg -i concatStart.mp4 -i "%IMAGE_NAME%" -filter_complex "[0:v][1:v]xfade=transition=!TRANSITION_2_USE!:duration=%TRANSITION_DURATION%:offset=!TRANSITION_OFFSET!,format=yuv420p" -map  -an -y vtrimmedConcat.mp4
rem ffmpeg -y -i concatStart.mp4 -i "%IMAGE_NAME%" -filter_complex ^
rem "[0:v][1:v]xfade=transition=circlecrop:duration=2:offset=!TRANSITION_OFFSET![outv]" -map [outv]   -y  vtrimmedConcat.avi
rem set /p id="Press any key to continue: "
)
if %FILE_NUM% GTR 0 (
     copy vtrimmedConcat.mp4 concatStart.mp4
     rem del vtrimmedConcat.mp4 
    if %FILE_NUM% EQU %TOTAL_IMAGE_FILES_MINUS_ONE% (
        copy concatStart.mp4 videoFromImages.mp4 
        del concatStart.mp4 
        del vtrimmedConcat.mp4 
    )
 )
:: del %IMAGE_NAME%
rem echo ffmpeg -i "concatStart.mp4" -i %IMAGE_NAME% -filter_complex "[0:v][1:v]concat=n=2:v=1 [v]" -map "[v]"  -r 30 -y  vtrimmedConcat.mp4
exit /b
rem https://stackoverflow.com/a/14339439
:callbyrefernce
REM Now %1 contains the value "parm"
rem set "%1=!%1! world"
REM Now variable "parm" contains "Hello world"
set TRANSITION_2_USE=!TRANSITION%1!
exit /b

config.bat

@echo OFF
set TRANSITION1=fade
set TRANSITION2=fadeblack
set TRANSITION3=fadewhite
set TRANSITION4=distance
set TRANSITION5=wipeleft
set TRANSITION6=wiperight
set TRANSITION7=wipeup
set TRANSITION8=wipedown
set TRANSITION9=slideleft
set TRANSITION10=slideright
set TRANSITION11=slideup
set TRANSITION12=slidedown
set TRANSITION13=smoothleft
set TRANSITION14=smoothright
set TRANSITION15=smoothup
set TRANSITION16=smoothdown
set TRANSITION17=rectcrop
set TRANSITION18=circlecrop
set TRANSITION19=circleclose
set TRANSITION20=circleopen
set TRANSITION21=horzclose
set TRANSITION22=horzopen
set TRANSITION23=vertclose
set TRANSITION24=vertopen
set TRANSITION25=diagbl
set TRANSITION26=diagbr
set TRANSITION27=diagtl
set TRANSITION28=diagtr
set TRANSITION29=hlslice
set TRANSITION30=hrslice
set TRANSITION31=vuslice
set TRANSITION32=vdslice
set TRANSITION33=dissolve
set TRANSITION34=pixelize
set TRANSITION35=radial
set TRANSITION36=hblur
set TRANSITION37=wipetl
set TRANSITION38=wipetr
set TRANSITION39=wipebl
set TRANSITION40=wipebr
set TRANSITION41=fadegrays
set TRANSITION42=squeezev
set TRANSITION43=squeezeh
set TRANSITION44=zoomin
set NO_OF_TRANSITIONS=0
FOR /L %%I IN (1,1,1000) DO (
    echo TRANSITION%%I
    rem https://stackoverflow.com/a/37073832
    rem https://www.robvanderwoude.com/battech_defined.php
    IF DEFINED TRANSITION%%I (
        echo TRANSITION%%I is defined
    ) ELSE (
        ECHO  TRANSITION%%I is NOT defined
        set /a NO_OF_TRANSITIONS=%%I-1
        GOTO :ENDOF_TRANSITIONS
    )
    rem call :callbyrefernce %%I
    rem IF %%I==5 exit /b
)
:ENDOF_TRANSITIONS
echo NO_OF_TRANSITIONS is %NO_OF_TRANSITIONS%

rem set FILENO_4_TRANSITION=19
rem set /a TRANSISITION_REMAINDER="%FILENO_4_TRANSITION% %% %NO_OF_TRANSITIONS%"
rem echo %TRANSISITION_REMAINDER%
rem set /p id="Press any key to continue:"
rem exit /b