Quem está fazendo o trabalho: ffmpeg ou o shell?

8

Primeira parte da minha pergunta:

Eu li na documentação do ffmpeg ( section 3.2 How do I encode single pictures into movies? ) o seguinte:

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...

Minha pergunta é: quem está fazendo a tradução entre img%03d.jpg e img001.jpg, img002.jpg, etc ? É o shell ou ffmpeg?

Segunda parte:

Gostaria de pedir ao ffmpeg para codificar uma seqüência de imagens em um vídeo. No entanto, minhas sequências geralmente começam com um índice diferente de 1 (por exemplo, podemos chamá-lo de start_index ) e terminam em um índice que podemos chamar de end_index . Além disso, a sequência usa incrementos do valor increment , por exemplo:

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

em que start_index era 25, end_index era 100 e increment era 5.

Eu gostaria de alimentar uma sequência de imagens como a acima para ffmpeg sem ter que renomear a sequência primeiro. A documentação explica como fazer isso com links simbólicos, mas eu queria saber se existe uma maneira de evitá-los completamente, talvez usando globbing avançado no zsh.

    
por Amelio Vazquez-Reina 05.10.2011 / 23:52

3 respostas

8

Parte 1: % não é um caractere especial, portanto, o argumento img%d.jpg é passado como é para ffmpeg , que "faz o trabalho" em si.

Parte 2: Analisando a documentação ffmpeg , não acho que exista outra maneira de fornecer arquivos de entrada, então você pode ter que usar links simbólicos ou esperar pela "correção":

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.

    
por 06.10.2011 / 00:14
5

Isso pode ser feito usando somente pipes, ie. sem renomear e sem links simbólicos.

Aqui está um script que eu coloquei juntos, comentários e tudo. Eu configurei para jogar a 1 frame por segundo. O processamento de imagens usa o pacote netpbm

por exemplo: 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 $'
# 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 $'%pre%' -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 \
          images.avi
}
' -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 \ images.avi }
    
por 08.10.2011 / 07:52
3

Somente para a primeira parte: é o ffmpeg fazendo o trabalho. O shell não entende a string %d como um padrão especial em nomes de arquivos.

    
por 06.10.2011 / 00:13

Tags