Como posso extrair uma imagem JPEG de boa qualidade de um arquivo de vídeo H264 com ffmpeg?

108

Atualmente estou usando este comando para extrair as imagens:

ffmpeg.exe -i 10fps.h264 -r 10 -f image2 10fps.h264_% 03d.jpeg

Mas como posso melhorar a qualidade da imagem JPEG?

Daniel Gartmann
fonte
1
O que há de errado com a qualidade atual, além de não ser "boa"?
bjoernz

Respostas:

215

Usar -qscale:v

Use -qscale:v(ou o alias-q:v ) como uma opção de saída. O intervalo efetivo para JPEG é de 2 a 31, com 31 sendo a pior qualidade. Eu recomendo tentar valores de 2-5.

Para produzir uma série de imagens:

ffmpeg -i input.mp4 -qscale:v 2 output_%03d.jpg

Para gerar uma única imagem com duração de aproximadamente 60 segundos:

ffmpeg -ss 60 -i input.mp4 -qscale:v 4 -frames:v 1 output.jpg

Isso funcionará com qualquer entrada de vídeo. Veja abaixo se sua entrada é MJPEG.


MJPEG

Se a sua entrada for MJPEG (Motion JPEG), as imagens podem ser extraídas sem qualquer perda de qualidade.

A saída do console ffmpegou ffprobepode dizer se sua entrada é MJPEG:

$ ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=nw=1 input.avi
codec_name=mjpeg

Em seguida, você pode extrair os quadros usando o mjpeg2jpegfiltro de fluxo de bits :

$ ffmpeg -i input.avi -codec:v copy -bsf:v mjpeg2jpeg output_%03d.jpg

Veja também

llogan
fonte
Isso parece não ter nenhum efeito para mim - qscale 1 e 2 fornecem tamanhos de arquivo idênticos e (a olho nu) parecem o mesmo que sem qscale.
felwithe
Você pode postar a linha de comando completa que está usando? Além disso, publique a saída completa e sem cortes do ffmpeg na linha de comando. Observe que o posicionamento das opções é relevante, portanto -qscale: v 2 precisa ser colocado após a opção -i inputfile, mas antes da opção do arquivo de saída, para ter algum efeito.
Ronald S. Bultje,
1
Para mim, adicionar -qmin 1 -qmax 1além do -q:v 1dobro do tamanho do arquivo. E também posso ver uma ligeira melhora.
complacente
1
@complistic: -qmin 1 -qmax 1resultou em um arquivo maior, mas me dá exatamente a mesma imagem. Eu validei isso via photoshop, 2 camadas e filtro de diferença. Os pixels são iguais.
Cherouvim
@Kostanos Você pode tentar -qmin 1 -q:v 1.
llogan
0

Envie as imagens em um formato sem perdas, como PNG:

ffmpeg.exe -i 10fps.h264 -r 10 -f image2 10fps.h264_%03d.png

Em seguida, use outro programa (onde você pode especificar com mais precisão a qualidade, subamostragem e método DCT - por exemplo, GIMP) para converter os PNGs que deseja em JPEG.

É possível obter imagens um pouco mais nítidas no formato JPEG desta forma do que com -qmin 1 -q:v 1e saída como JPEG diretamente do ffmpeg.

Jake
fonte
ffmpegproduz PNG8arquivos que usam apenas 256 cores (igual ao GIF). portanto, é realmente muito prejudicial.
lapin
@lapin Os PNGs que extraí usando esse método são de 24 bits (mesmo para quadros com menos de 256 cores, embora outros tenham muito mais). Isso estava usando a versão 4.2.1 x64 no Windows. Também está escrito aqui : "Se eu puxar png de um mp4, com este ffmpegcomando [ ], obtenho png de alta qualidade que são de qualidade idêntica ao vídeo original." Qual versão do ffmpegvocê está usando que está gerando PNG8arquivos e qual é o seu formato de entrada?
Jake
Na verdade, acho que você está certo, o problema é que identify image.pngdá o resultado "8 bits" quando na verdade não é realmente um único canal de 8 bits, mas de 8 bits para R, G e B. IDK como o identifyusuário comum deve entender aquele tho.
lapin de