3

Terminal can generate video from PNG seguence (0001.png, 0002.png, ...) via ffmpeg:

ffmpeg -i %04d.png -r 24 -codec prores output.mov 

But how can I tell ffmpeg use for input image sequence in Automator? With this variable it's not working:

for f in "$@" do /opt/local/bin/ffmpeg -i "$f" -r 24 -codec prores ~/Desktop/output.mov done 

Looks like variable is for file than for sequence ... Log list looks like script runs 10 times for sequence of 10 images. Error probably comes from second and all others loops where is asking for overwriting existing. I was able to create video only with full path to image sequence like ~/Desktop/PNG_Folder/%04d.png, but thats not solution. Script was asking 9 times for overwriting anyway (skipping error with -y hides error but keep loop process) and I need of course to use files selected from Finder, not specified in full path written in a script :) Here is a screen of Automator just to be sure other things are set right. Thank you for help.

enter image description here

Plus: original Terminal command lets generate video into image sequence directory. Is this possible also with Automator's Shell? Also variable would be better if can be set for any file name and more formats than PNG (JPEG, EXR, ...?) t be more versatile. Thank you.

0

    1 Answer 1

    3

    After doing a bit of research, it turns out that the -ioption for ffmpeg takes a single filename and when converting a number of image files to a .mov file, it has to be in the form of e.g. %05d.png. Obviously the padding of the sequential numbering can be a different number of digits and the image type extension can vary as well.

    Then to that end, the following examplebashcode works for me:

    Method 1:

    The following assumes the sequential numbered files are four digits, starting at 0001, add all files have the same extension.

    It will process all four digit sequential numbered files in the same directory while overwriting the output.movfile, if it already exists.

    Change Service receives selectedfiles or foldersinFinder to:

    Service receives selectedfoldersinFinder

    Remove the Get Selected Finder Itemsaction,

    Set Pass input: to as arguments in the Run Shell Scriptaction.

    Replace the default code with the following examplebashcode:

    cd "$1" || exit ext="$(file="$(ls 0001.*)"; echo "${file##*.}")" /opt/local/bin/ffmpeg -y -i %04d.${ext} -r 24 -codec prores output.mov 

    The examplebashcode above assumes you are selecting only one folder in Finder. For multiple folder selections, use the following examplebashcode:

    for f in "$@"; do cd "$f" || exit ext="$(file="$(ls 0001.*)"; echo "${file##*.}")" /opt/local/bin/ffmpeg -y -i %04d.${ext} -r 24 -codec prores output.mov done 

    Note: The examplebashcode contains limited error handling. The onus is upon the user to add any error handling as may be appropriate, needed or wanted.


    Method 2:

    Service receives selectedfiles or foldersinFinder

    Remove the Get Selected Finder Itemsaction,

    Set Pass input: to as arguments in the Run Shell Scriptaction.

    Assuming the selected image files in Finder are all the same type, in the same folder and the e.g. output.movfile will be created in the same folder of the selected image files...

    Then to that end, the following examplebashcode works for me:

    o="output" e="mov" d="$(dirname "$1")" cd "$d" || exit if [[ ! -e "${o}.${e}" ]]; then o="${o}.${e}" else n=2 for f in ${o} *.${e}; do if [[ "${o} ${n}.${e}" == "$f" ]]; then n="$(( n + 1 ))" fi done o="${o} ${n}.${e}" fi foo="$(date +%s)" mkdir "/tmp/${foo}" || exit cd "/tmp/${foo}" || exit i=1 for f in "$@"; do ln -s "$f" "$(printf "%05d" $i).${f##*.}" (( i++ )) done /opt/local/bin/ffmpeg -i %05d."${f##*.}" -r 24 -codec prores "${d}/${o}" rm -r "/tmp/${foo}" 

    Note: The examplebashcode contains limited error handling. The onus is upon the user to add any error handling as may be appropriate, needed or wanted.

    Method 2 Notes:

    • If the e.g. output.movfile already exists, an incremented filename is used, starting at, e.g. output 2.mov and continuing to increment as needed so the AutomatorService doesn't fail because the output file already exists. This is primarily handled in the if...else...thenblock; however, the lines of code prior to it are a part of it as well.
    • In order to accomplish the goal, a temporary directory is created in /tmp, named for the number of seconds since the Unix epoch, e.g. /tmp/1574058046 and is handle by foo="$(date +%s)" and mkdir "/tmp/${foo}".
    • Within this temporary directory a sequential numbered symlink is created for each of the selected image files, and is handled primarily by the for f in "$@"; do ... doneloop.
    • ffmpeg then creates the e.g. output.movfile.
    • The temporary directory, e.g, /tmp/1574058046 is removed.
    • Note that the selected image files must all be of the same type per run, however, each run can use a different supported image file type as long as all are the same type per run. As currently coded you can not mix different image file types per each run of the service.

    Note: The Get Specified Finder Itemsaction is just for testing purposes and would be deleted before saving the AutomatorService.

    enter image description here

    4
    • I'm surprised one can't do this: cd "$(dirname "$1")"; for f in "$@"; do input="$input -i \"$f\""; done; eval "ffmpeg$input -r 24 -codec prores output.mov". I thought ffmpeg could accept multiple input files by using the -i flag in multiple.
      – CJK
      CommentedNov 18, 2019 at 9:02
    • @vklidu, Doesn't matter the naming convention of the source image files. The script is coded to take the selected items in Finder and create a .mov file from them. So e.g. Screen Shot 2019-11-18 at 2.01.33 AM.png becomes 00001.pngsysmlink and Screen Shot 2019-11-18 at 2.02.00 AM.png becomes 00002.pngsysmlinkor0001.png becomes 00001.pngsysmlink and 0002.png becomes 00002.pngsysmlink, etc. This is code this way to handle both scenarios as well as allowing for passing all selected files to ffmpeg using -i %05d."${f##*.}" As you see @CJK's code doesn't work.CommentedNov 18, 2019 at 18:51
    • 1
      I'd like to point out I made no assertion as to the effectiveness of, what was after all, a query. I thought (from some vague past memory) that it might have been possible, and wanted to check with @user3439894, who is by far the more experienced shell scripter. Had I felt with any confidence that mine would be the way to go, I would have offered it as a second answer. Anyway, +1 to this solution, which must have been a mare to conceive, write and test.
      – CJK
      CommentedNov 19, 2019 at 1:08
    • @CJK, After you posted the original comment I tested it and while it did create a .mov file I did not play it and just assumed it worked. I have to admin I was socked it worked (I thought) because the research I did didn't show that -i could be used more than once and it only took one file, with the exception of using the e.g. -i %04d.png form to use a set of sequentially numbered files. I certainly didn't mean the comment I made about your code to be harsh, was at the character limit so it came off terse, sorry. It actually was very easy to conceive, write and test, but thanks for the +1!CommentedNov 19, 2019 at 1:53

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.