First part of my question:

I read on the ffmpeg documentation (section 3.2 How do I encode single pictures into movies?) the following:

To encode single pictures into movies, run the command:

  ffmpeg -f image2 -i img%d.jpg movie.mpg    

Notice that `%d' is replaced by the image number: img%03d.jpg means the sequence img001.jpg, img002.jpg, etc...

My question is: Who is doing the translation between img%03d.jpg and img001.jpg, img002.jpg, etc? Is it the shell or ffmpeg?

Second part:

I would like to ask ffmpeg to encode a sequence of images into a video. However, my sequences often start with an index different from 1, (e.g. we can call it start_index) and end on an index that we can call end_index. Moreover, the sequence uses increments of value increment, e.g.:

img_0025.png, img_0030.png, img_0035.png, ... img_0100.png

where start_index was 25, end_index was 100, and increment was 5.

I would like feed an image sequence like the above to ffmpeg without having to rename the sequence first. The documentation explains how to do this with symbolic links, but I was wondering if there is a way to avoid them altogether, maybe using advanced globbing on zsh.

3 Answers 3


Part 1: % is not a special character, so the img%d.jpg argument is passed as is to ffmpeg which “does the job” itself.

Part 2: Looking at ffmpeg documentation, I don't think there is another way to provide input files, so you may have to use symlinks or wait for the “fix”:

If the pattern contains "%d" or "%0Nd", the first filename of the file list specified by the pattern must contain a number inclusively contained between 0 and 4, all the following numbers must be sequential. This limitation may be hopefully fixed.


It can be done using pipes only, ie. without renaming and without symlinks.

Here is a script I put together, comments and all.
I've set it up to play at 1 frame per second.
The image processing uses package netpbm

eg: images-to-vid '$HOME/images" '\./img_[0-9]{4}[^/0-9]*' 1024 768

# Make a video from images whose sizes and aspect-ratios may vary.
# Each image is resized to fit maximized within the video frame.  
# The images are positioned centrally and padded (when required) 
# Images are sourced using 'find'.  
# They are selected according to a regular expression.   
# Symbolic links are ignored.  
# Output from 'find' is sorted by path, ie. not by name alone,
#  but with a -maxlevel 1, this is typically the same...
#  You will need to customize the sort if this is not suitable.       
# Note about 'find':  
#    This script uses 'find -regex' instead of 'find -name'. 
#    The pattern must match the whole returned path, 
#       from ^ to $ inclusive  
#    The -regextype option is: posix-extended 
srceD="${1}"        # Source Directory
srceR="${2}"        # Source imaage extended Regex pattern
targW="${3:-800}"   # Target pixel Width
targH="${4:-600}"   # Target pixel Height
targB="${5:-black}" # Target Background colour (X11 colours)
targM="${6:-4}"     # Target screen geometry Modulo (as required by Target codec)
TARGw=$((targW-(targW%targM))); ((TARGw==targW)) || { echo "Target Width  must be divisible by $targM. Rounding down to $TARGw" 1>&2 ; targW=$TARGw; }
TARGh=$((targH-(targH%targM))); ((TARGh==targH)) || { echo "Target Height must be divisible by $targM. Rounding down to $TARGh" 1>&2 ; targH=$TARGh; }
# TODO: test for W/H == 0

cd "$srceD" || exit 2
find . -maxdepth 1 \
    \( -type f \) -and -not \
    \( -type l \) \
       -regextype posix-extended \
       -regex "$srceR" \
       -print0 | 
  sort -z | 
  while IFS= read -d $'\0' -r file ;do
      # make Composite image on coloured Background
      pnmcomp -align=center -valign=middle \
              <(anytopnm "$file" 2>/dev/null |
                pnmscale -xysize $targW $targH) \
              <(ppmmake "$targB" $targW $targH) 
  done |
  ffmpeg -r 1 \
         -f image2pipe \
         -vcodec ppm \
         -i - \
         -y -s ${targW}x${targH} \
         -vcodec mjpeg \
  • Thanks @fered, this is very helpful. Your script does even more than what I wanted, which is great. I am now trying to adapt the script to my needs. If I replace the while loop by a simple loop, that does not prescale nor adds background color: while IFS= read -d $'\0' -r file ;do pnmcomp -align=center -valign=middle <(anytopnm "$file" 2>/devnull) done, the script stops working (i.e. I get pipe: could not find codec parameters). Do you know why? Do I necessarily need pnmscale or ppmmake to feed ffmpeg with pnm images? Oct 9, 2011 at 21:43
  • 1
    @intrpc. The framing of different size pics was just my personal bent on the issue. I've been wanting to do that ever since I lost the ability to use avisynth (a powerful video scripting environment - avisynth is Windows only :( The main reason I used a netpbm format is that I kept seeing postings about problems feeding jpegs to the pipe, so I just chose the path of least resistance. The video encoding will be the step that causes loss of quality, but ramping up the frame size helps... I suppose you have your specific reasons for using a video, but a simple slide show may work for you.
    – Peter.O
    Oct 10, 2011 at 9:06

For the first part only: It's ffmpeg doing the job. The shell does not understand the %d string as a special pattern in file names.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .