I have a dilemma.. I've had a script for a while now that downloads pictures from a webcam every few minutes. The naming convention just does new_image((len(files(dir))+1) + '.jpg') and that's all fine.. until today..

I've had a Python script that loads the images based on creation date and renders them and i take the OpenGL data and dump it into a movie, which isn't hard and it's all ok.. Except now i have a few thousand images and it's quite ineffective to go on about it this way (even tho it's cool because i can build my own GUI and overlay etc).. anyway, i'm using ffmpeg to combine the images into a slideshow, like so:

ffmpeg -f image2 -r 25 -pattern_type glob -i '*.jpg' -qscale 3 -s 1920x1080 -c:v wmv1 video.wmv

The ffmpeg works fine, except that -pattern_type glob takes the images in naming order which doesn't work because the way the files get fed is similar if not the same as ls, which looks like:

user@host:/storage/photos$ ls
0.jpg     1362.jpg  1724.jpg  2086.jpg  2448.jpg  280.jpg   3171.jpg  3533.jpg  3896.jpg  4257.jpg  4619.jpg  4981.jpg  5342.jpg  5704.jpg  6066.jpg  650.jpg
1000.jpg  1363.jpg  1725.jpg  2087.jpg  2449.jpg  2810.jpg  3172.jpg  3534.jpg  3897.jpg  4258.jpg  461.jpg   4982.jpg  5343.jpg  5705.jpg  6067.jpg  651.jpg

0, 1000, 1, 2000, 2... this is the logic of ls so the image sequence (timelapse) will be all f-ed up..

Any ideas on how to use ffmpeg to load the images in a more sorted manner?


ffmpeg concat same file types

You could use a command like this to concatenate the list of files any way you want:

ffmpeg -f concat -i <( for f in *.wav; do echo "file '$(pwd)/$f'"; done ) \

The above can only work if the files you're concatenating are all the same codecs. So they'd all have to be .wav or .mpg for example.

NOTE: You need to have ffmpeg v1.1 or higher to use the concat demuxer, you can read more about the above example and also how to concatenate different codecs using this technique on the ffmpeg website.

ffmpeg using printf formatters

Ffmpeg can also take input using the printf formatters such as %d. This matches digits starting at 0 and going up from there in order. If the numbers were structured like this, 000 - 099, you could use this formatter, %03d, which means a series of 3 digits, zero padded.

So you could do something like this:

ffmpeg -r 25 -i %d.png -qscale 3 -s 1920x1080 -c:v wmv1 video.wmv

The above didn't quite work for me, ffmpeg was complaining about the option -c:v. I simply omitted that option and this version of the command worked as expected.

ffmpeg -r 25 -i %d.png -qscale 3 -s 1920x1080 video.wmv
  • I actually love your idea, unfortunately i get: [concat @ 0xac21ce0] Line 1: unknown keyword '0.jpg' /dev/fd/63: Invalid data found when processing input any ideas to why?
    – Torxed
    May 24 '13 at 23:45
  • 1
    Give me a bit, I'll have to setup a fake dataset to try this out.
    – slm
    May 24 '13 at 23:47
  • I was standing in the wrong folder executing the command, but never the less, see below comment.
    – Torxed
    May 24 '13 at 23:48
  • Altho, still getting /dev/fd/63: Invalid data found when processing input If you solve that, you'll get the points, because i'm afraid of renaming files of this magnitude, had bad experiences before.
    – Torxed
    May 24 '13 at 23:50
  • 1
    @Torxed, check the updates, had to change tactics slightly.
    – slm
    May 25 '13 at 0:20

The simplest way would be to rename the short filename to have leading zeros, using the rename tool. However there are two standard rename tools out there - the one I am describing is described as from the Perl Programmers Reference Guide in the man page. This is the version on Debian and derived distributions.

rename 's/^/000/' [0-9].jpg
rename 's/^/00/' [0-9][0-9].jpg
rename 's/^/0/' [0-9][0-9][0-9].jpg

The filenames should then collate correctly using globs.

However if you do not want to rename the files, you cannot use globs, as the expand in lexicographic order, not numeric.

So, don't use globs. Get rid of -pattern_type glob and use -i %d.jpg instead of -i *.jpg. This uses a numeric pattern and in my quick testing does what you want.

  • 1
    @Torxed: Updated my answer with a non-renaming solution. Except it looks like you may have gaps in your sequence, in which case this wont work. Do you actually have gaps?
    – camh
    May 25 '13 at 3:53
  • Correct, that works and i'll give you a point for it, but slm got there quicker this time :) I love you all equally tho and if i could you both would get the correct answer!
    – Torxed
    May 25 '13 at 12:05

The best way is to rename the file so that they all have the same number of digits. With zsh (4 is the maximum number of digits):

autoload zmv     # put this in your ~/.zshrc
zmv '(<->).jpg' '${(l:4::0:)1}.jpg'

With other shells (continue and add 0's as necessary if there are file names with more than 4 digits):

for x in [0-9].jpg; do mv "$x" "000$x"; done
for x in [0-9][0-9].jpg; do mv "$x" "00$x"; done
for x in [0-9][0-9][0-9].jpg; do mv "$x" "0$x"; done

If you can't rename the files, another option is to create symbolic links in some other directory. With zsh:

zmv -Ls '$PWD/(<->).jpg' '/somewhere/writable/${(l:4::0:)1}.jpg'

With any shell:

for x in [0-9].jpg; do ln -s "$PWD/$x" "/somewhere/writable/000$x"; done
for x in [0-9][0-9].jpg; do ln -s "$PWD/$x" "/somewhere/writable/00$x"; done
for x in [0-9][0-9][0-9].jpg; do ln -s "$PWD/$x" "/somewhere/writable/0$x"; done

An alternative approach is to give the symbolic links consecutive numbers. This approach generalizes to other situations where the order of the original files isn't right, as long as you create the symlinks in the desired order. Starting the counter at 10000 and removing the leading 1 is a convenient way of obtaining a counter with leading zeroes.

for x in [0-9].jpg [0-9][0-9].jpg [0-9][0-9][0-9].jpg; do
  ln -s "$PWD/$x" /somewhere/writable/${i#1}.jpg

If you really don't want to do any writing, you can pass successive -i options with increasing file name lengths.

ffmpeg -pattern_type glob -i '[0-9].jpg' -i '[1-9][0-9].jpg' -i '[1-9][0-9][0-9].jpg' -i '[1-9][0-9][0-9][0-9].jpg' …
  • I'll not downvote this because it is generally a better option to rename files, but in my specific usage case that's not possible. And for anyone ending up here from google this might help. But this won't solve my issue.
    – Torxed
    May 26 '13 at 9:50
  • @Torxed “If you really don't want to rename, …” May 26 '13 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.