Extraindo o índice de quadros-chave de um vídeo usando ffmpeg

17

Estou usando o ffmpeg para extrair quadros-chave de um vídeo. Este é o comando:

ffmpeg -i test2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 160x90 -f image2 thumbnails-%02d.jpeg

Como posso obter o índice de cada quadro-chave extraído no vídeo? Por exemplo, para o primeiro quadro I, o índice seria 0, para o segundo, 24, etc.

Faten Khalifa
fonte
possível duplicação de superuser.com/questions/669716/…
user236012 4/15
Olhe para usar o ffprobe e depois processe a saída para obter o índice?
dstob
@dstob você poderia explicar mais sobre o que você quer dizer? como eu sou novo no ffmpeg.
Faten Khalifa 04/03
@LordNeckbeard O número do quadro nos quadros de vídeo, ex. o primeiro quadro do vídeo estaria no índice 0. Quero saber o índice de cada quadro-chave nos quadros de vídeo.
Faten Khalifa 04/03
Deseja que o número do quadro seja impresso na miniatura (na própria imagem)?
Llogan 4/03

Respostas:

21

Como o @dstob mencionado, você pode usar ffprobepara obter os quadros I e as informações associadas. ffprobevem com algumas das compilações estáticas na página de download e também pode ser criada a partir da fonte.

Isso pressupõe que você esteja no Linux / Unix:

Extrair quadros e tipos de quadros

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1

O grepcomando filtra as linhas com Ielas e conta seu índice (usando a -nopção). O cutcomando seleciona apenas a primeira coluna da saída (o índice). Observe que esse índice é baseado em 1, não em 0.

Renomear arquivos de saída com base no índice

Na verdade, você pode canalizar esses índices para uma lista:

ffprobe -select_streams v -show_frames \
-show_entries frame=pict_type \
-of csv bbb480.avi \
| grep -n I | cut -d ':' -f 1 > frame_indices.txt

Em seguida, faça uma lista de todas as miniaturas:

ls -1 thumbnails*.jpeg > thumbnails.txt

Em seguida, cole os dois juntos:

paste thumbnails.txt frame_indices.txt > combined.txt

A lista agora contém o nome da miniatura e o índice. Execute uma renomeação com base nisso:

while read -r thumbnail index; do
  newIndex=$(echo $index - 1 | bc) # subtract 1 from the index
  mv -- "$thumbnail" "thumbnail-$newIndex.jpeg"  # rename file
done < combined.txt

O acima será renomeado thumbnail-01.jpegpara thumbnail-0.jpeg. Observe que não há preenchimento zero no índice de saída. Se você deseja zerar com, digamos, 5 dígitos, use printf:

newIndex=$(printf '%05d' $(echo $index - 1 | bc))

No Windows, você faria exatamente o mesmo com, ffprobemas analisará a saída de maneira diferente. No entanto, não faço ideia de como renomear lá.

slhck
fonte
Este erro é exibido: 'grep' não é reconhecido como um comando interno ou externo, programa operável ou arquivo em lote.
Faten Khalifa 05/03
2
Isso é porque você está no Windows. Como eu disse, esta resposta assume Linux ou Unix. Você não estava sendo mais específico em sua pergunta. Você pode obter o mesmo no Windows usando o Cygwin ou camadas similares do GNU / Linux para Windows.
slhck
Esta é uma grande ajuda, obrigado. Uma correção: acho que os índices no seu primeiro comando estão fora de um fator de três, porque há uma [FRAME]linha e uma [/FRAME]linha para cada pict_typelinha.
Jack O'Connor
2
@ JackO'Connor Existe apenas uma linha por quadro se você usar a -of csvopção ffprobe. O que você está descrevendo é o formato de saída padrão.
slhck
0

Se você deseja usar o FFMPEG como indicado originalmente, é possível listar a listagem total ou parcial, além de criar jpg com o seguinte:

ffmpeg.exe \
  -i "C:\Users\UserName\Desktop\jpegs and list\VideoName.mp4" \
  -t 15 \
  -vf select="eq(pict_type\,PICT_TYPE_I)" \
  -vsync 2 \
  -s 160x90 \
  -f image2 thumbnails-%02d.jpeg \
  -loglevel debug 2>&1| for /f "tokens=4,8,9 delims=. " %d in ('findstr "pict_type:I"') do echo %d %e.%f>>"keyframe_list.txt"

Remova -t 15sem limite de tempo ou mude para se adequar. Remova -s 160x90 -f image2 thumbnail-%02d.jpegou altere para se adequar à remoção de miniaturas.

Budman1
fonte
No Windows 7 CMD, isso falha no \. Alterar \ a ^ provoca uma falha na: I" Você tem uma versão que funciona em Windows.?
ChrisJJ