¿Quién está haciendo el trabajo: ffmpeg o el shell?

8

Primera parte de mi pregunta:

Leí en la documentación de ffmpeg ( section 3.2 How do I encode single pictures into movies?) lo siguiente:

Para codificar imágenes individuales en películas, ejecute el comando:

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

Tenga en cuenta que `% d 'se reemplaza por el número de imagen: img% 03d.jpg significa la secuencia img001.jpg, img002.jpg, etc.

Mi pregunta es: ¿Quién está haciendo la traducción entre img%03d.jpgy img001.jpg, img002.jpg, etc? ¿Es la cáscara o ffmpeg?

Segunda parte:

Me gustaría pedirle a ffmpeg que codifique una secuencia de imágenes en un video. Sin embargo, mis secuencias a menudo comienzan con un índice diferente de 1 (por ejemplo, podemos llamarlo start_index) y terminan en un índice al que podemos llamar end_index. Además, la secuencia utiliza incrementos de valor increment, por ejemplo:

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

donde start_indexera 25, end_indexera 100 y incrementera 5.

Me gustaría alimentar una secuencia de imágenes como la anterior para ffmpeg sin tener que cambiar el nombre de la secuencia primero. La documentación explica cómo hacer esto con enlaces simbólicos, pero me preguntaba si hay una manera de evitarlos por completo, tal vez usando el globbing avanzado en zsh.

Amelio Vazquez-Reina
fuente

Respuestas:

8

Parte 1: % no es un carácter especial, por lo img%d.jpgque se pasa el argumento tal ffmpegcual "hace el trabajo" en sí.

Parte 2: mirando la ffmpegdocumentación, no creo que haya otra forma de proporcionar archivos de entrada, por lo que es posible que tenga que usar enlaces simbólicos o esperar la "solución":

Si el patrón contiene "% d" o "% 0Nd", el primer nombre de archivo de la lista de archivos especificada por el patrón debe contener un número incluido entre 0 y 4, todos los siguientes números deben ser secuenciales. Es de esperar que esta limitación se solucione.

Stéphane Gimenez
fuente
5

Se puede hacer usando tuberías solamente, es decir. sin renombrar y sin enlaces simbólicos.

Aquí hay un guión que preparé, comentarios y todo.
Lo configuré para jugar a 1 fotograma por segundo.
El procesamiento de imágenes usa el paquetenetpbm

p.ej: 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 \
          images.avi
}
Peter.O
fuente
Gracias @fered, esto es muy útil. Tu guión hace incluso más de lo que quería, lo cual es genial. Ahora estoy tratando de adaptar el script a mis necesidades. Si reemplazo el ciclo while por un ciclo simple, eso no preescala ni agrega color de fondo: while IFS= read -d $'\0' -r file ;do pnmcomp -align=center -valign=middle <(anytopnm "$file" 2>/devnull) doneel script deja de funcionar (es decir, obtengo pipe: could not find codec parameters). ¿Sabes por qué? ¿Necesito pnmscaleo debo ppmmakealimentarme necesariamente ffmpegcon pnmimágenes?
Amelio Vazquez-Reina
1
@intrpc. La elaboración de imágenes de diferentes tamaños fue solo mi inclinación personal sobre el tema. He estado queriendo hacer eso desde que perdí la capacidad de usar avisynth(un poderoso entorno de secuencias de comandos de video; avisynth es solo para Windows :( La razón principal por la que usé un netpbmformato es que seguía viendo publicaciones sobre problemas para alimentar jpegs a la tubería, así que simplemente elegí el camino de menor resistencia. La codificación de video será el paso que causará la pérdida de calidad, pero aumentar el tamaño del cuadro ayuda ... Supongo que tienes tus razones específicas para usar un video, pero una simple presentación de diapositivas puede funcionar para usted.
Peter.O
3

Solo para la primera parte: es ffmpeg haciendo el trabajo. El shell no entiende la %dcadena como un patrón especial en los nombres de archivo.

Kusalananda
fuente