Quem está fazendo o trabalho: ffmpeg ou 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:

Para codificar imagens únicas em filmes, execute o comando:

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

Observe que `% d 'é substituído pelo número da imagem: img% 03d.jpg significa a sequência img001.jpg, img002.jpg, etc ...

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

Segunda parte:

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

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

onde start_indexera 25, end_indexera 100 e incrementera 5.

Gostaria de alimentar uma sequência de imagens como a acima para ffmpeg sem precisar 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.

Amelio Vazquez-Reina
fonte

Respostas:

8

Parte 1: % não é um caractere especial; portanto, o img%d.jpgargumento é passado para o ffmpegqual "faz o trabalho".

Parte 2: Examinando a ffmpegdocumentação, acho que não há outra maneira de fornecer arquivos de entrada; portanto, você pode precisar usar links simbólicos ou aguardar a "correção":

Se o padrão contiver "% d" ou "% 0Nd", o primeiro nome de arquivo da lista de arquivos especificado pelo padrão deverá conter um número inclusivo entre 0 e 4, todos os números a seguir deverão ser seqüenciais. Esperamos que esta limitação possa ser corrigida.

Stéphane Gimenez
fonte
5

Isso pode ser feito usando apenas tubos, ou seja. sem renomear e sem links simbólicos.

Aqui está um script que eu montei, comentários e tudo.
Eu o configurei para tocar em 1 quadro por segundo.
O processamento de imagem usa o pacotenetpbm

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 $'\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
fonte
Obrigado @fered, isso é muito útil. Seu script faz ainda mais do que eu queria, o que é ótimo. Agora estou tentando adaptar o script às minhas necessidades. Se eu substituir o loop while por um loop simples, que não pré-escala nem adiciona cor de fundo:, while IFS= read -d $'\0' -r file ;do pnmcomp -align=center -valign=middle <(anytopnm "$file" 2>/devnull) doneo script para de funcionar (ou seja, eu entendo pipe: could not find codec parameters). Você sabe por quê? Preciso necessariamente pnmscaleou ppmmakealimentar ffmpegcom pnmimagens?
Amelio Vazquez-Reina
1
@intrpc. O enquadramento de fotos de tamanhos diferentes foi apenas minha inclinação pessoal para o assunto. Estou querendo fazer isso desde que perdi a capacidade de usar avisynth(um poderoso ambiente de script de vídeo - o avisynth é apenas para Windows :( A principal razão pela qual usei um netpbmformato é que eu continuava vendo postagens sobre problemas de alimentação de jpegs no pipe, então escolhi o caminho de menor resistência.A codificação de vídeo será a etapa que causa perda de qualidade, mas aumentar o tamanho do quadro ajuda ... Suponho que você tenha seus motivos específicos para usar um vídeo, mas uma apresentação de slides simples pode funcionar para você.
Peter.O
3

Apenas para a primeira parte: o ffmpeg está fazendo o trabalho. O shell não entende a %dcadeia como um padrão especial nos nomes dos arquivos.

Kusalananda
fonte