Como posso ajustar um vídeo a um determinado tamanho, mas não o aprimoro com o FFmpeg?

9

Preciso ajustar os vídeos a 640x360 (o máximo que o aparelho do meu celular pode suportar), além de preservar a proporção , mas também quero que o vídeo não seja alterado se for menor de 640x360 (não adianta aumentar a escala).

Existe uma maneira de obter esse comportamento usando a linha de comando do ffmpeg?

    
por sashoalm 16.03.2013 / 18:12

3 respostas

6

Com as versões mais recentes do ffmpeg, você pode usar a opção scale do filtro force_original_aspect_ratio . Por exemplo, para ajustar um vídeo em 1280 × 720, sem melhorar (consulte esta postagem para obter mais informações):

ffmpeg -i input.mp4 -filter:v "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Aqui, o filtro scale é dimensionado para 1280 × 720 se o vídeo de entrada for maior que isso. Se for menor, não será melhorado. O filtro pad é necessário para levar o vídeo de saída a 1280 × 720, caso sua proporção ou tamanho seja diferente do tamanho desejado.

Com as versões mais antigas do ffmpeg, há uma solução um tanto hacky. Primeiro, defina a largura, a altura e a proporção da sua saída. Isso nos poupará alguma digitação.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Agora, vamos aplicar o comando de filtro super complexo que Jim Worrall escreveu :

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

Eu não vou realmente explicar o que isso tudo faz, mas basicamente você pode alimentar qualquer vídeo, e ele só vai diminuir, não upscale. Se você está pronto para isso, você pode dissecar o filtro em suas expressões individuais. Talvez seja possível encurtar isso, mas também funciona assim.

    
por 18.03.2013 / 21:06
10

Uma versão mais legível pode se parecer com a seguinte:

-filter_complex "scale=iw*min(1\,min(640/iw\,360/ih)):-1"

640 / iw é o fator de escala horizontal e 360 / ih é o fator de escala vertical

Você deseja ajustar a imagem dimensionada dentro da caixa de saída e manter a proporção de (armazenamento). Você faz isso selecionando o menor fator de escala com a função mínima: min (640 / iw, 360 / ih)

Você deseja evitar qualquer aumento de escala (ou seja, um fator de escala > 1.0) para adicionar outra função mínima: min (1, min (640 / iw, 360 / ih))

O próximo passo é calcular a resolução de saída multiplicando o fator de escala por largura de entrada e altura de entrada:
largura de saıda = iw * min (1, min (640 / iw, 360 / ih))
saıda-altura = ih * min (1, min (640 / iw, 360 / ih))

O último passo é construir o comando filter. Não há necessidade de especificar a altura de saída, você pode especificar -1 e o ffmpeg manterá a proporção aplicando o mesmo fator de escala da largura.

    
por 10.08.2014 / 10:46
4

Eu também tive o mesmo problema, mas resolvi por encaixar o vídeo em um quadrado de 640x640 (por causa de vídeos verticais feitos com smartphones).

Então, usando a lógica immerzi e algumas pesquisas, acabo com isso:

-vf "scale=iw*min(1\,if(gt(iw\,ih)\,640/iw\,(640*sar)/ih)):(floor((ow/dar)/2))*2"

a última parte é para ter uma altura divisível por 2 que é necessária para muitos codificadores.

    
por 11.09.2015 / 17:19

Tags