Como posso reduzir o tamanho de um vídeo com ffmpeg?


201

Como posso usar ffmpegpara reduzir o tamanho de um vídeo, diminuindo a qualidade (o mínimo possível, naturalmente), mas preciso que ele seja executado em um dispositivo móvel que não tenha muito espaço disponível?

Eu esqueci de escrever uma coisa ainda. Quando o vídeo puder usar legendas (* .srt ou * .sub), gostaria de convertê-las também para ajustar os parâmetros do arquivo de vídeo convertido.


4
Eu não o usei, mas a ffmpegpágina de manual mostra uma -fsopção para limitar o tamanho da saída, algo como ffmpeg -i in.avi -fs 100M out.avifunciona?
Kevin

1
Não o redirecionarei para a página de manual:man ffmpeg | wc -l --> 5254

3
A .aviquestão não é a principal. aviÉ apenas um contêiner. A principal questão é quais codecs você usa. Muitos (a maioria?) .aviVídeos usam codecs de estilo mais antigo (por exemplo, XviD), que são bons, mas são maiores para a mesma qualidade quando comparados à geração posterior de codecs. Você normalmente pode obter um codificação rígida usando o H.264padrão de compactação de vídeo (por exemplo, codec x264) e aaccompactação para áudio. O contêiner e os codecs que você usa dependem de você e do seu telefone ... O .mp4contêiner é bem aceito .. (mas o seu telefone pode lidar com isso: veja este link
Peter.O

@ Kevin Isso quer mais parâmetros para conversão.
xralf

@hesse O que isso significa?
precisa saber é

Respostas:


277

Veja esta resposta. Citado abaixo por conveniência:

Calcule a taxa de bits necessária dividindo 1 GB pela duração do vídeo em segundos. Portanto, para um vídeo com duração de 16:40 (1000 segundos), use uma taxa de bits de 1000000 bytes / s:

ffmpeg -i input.mp4 -b 1000000 output.mp4

Opções adicionais que podem ser consideradas são a configuração do fator de taxa constante, que reduz a taxa de bits média, mas mantém uma qualidade melhor. Varie a CRF entre 18 e 24 - quanto menor, maior a taxa de bits.

ffmpeg -i input.mp4 -vcodec libx265 -crf 20 output.mp4

Varie o codec conforme necessário - a libx264 pode estar disponível se a libx265 não estiver, à custa de um tamanho de arquivo resultante um pouco maior.


O vídeo de tamanho 338 MB foi reduzido no tamanho 130 MB. A qualidade diminuiu rapidamente. Existe alguma explicação para esse processo? O autor original não explica sua linha de orientação.
Xralf

13
Segundo comando, -crf 24usei um vídeo de 255,3MB que eu tinha e reduzi-o para 72,7MB sem diminuir a qualidade visivelmente. Tenha um voto positivo!
Patrick Roberts

2
Impressionantemente reduzi um vídeo ~ 2G para 14 MB, ainda parece bom, este foi o primeiro resultado de pesquisa e é exatamente o que eu estava procurando, obrigado!
sinisterstuf

5
Pode ser bom observar que agora você pode usar libx265para reduzir ainda mais o tamanho.
ZN13 13/04

6
Usado ffmpeg -i input.avi -vcodec libx264 -crf 24 output.avi. Reduziu um vídeo de 100mb para 9mb. Pouca mudança na qualidade do vídeo. Obrigado!
Alpha_989

32

A menos que você esteja procurando uma taxa de bits específica, recomendo a -crfopção. Este é o mais comumente usado para x264codificação: http://slhck.info/articles/crf

Resumindo: um CRF de 23 gravaria filme com qualidade "DVD" (~ 700 MB-1 GB) e valores mais baixos de CRF seriam de qualidade superior (arquivos maiores).


3
Por favor, dar exemplos do comando completo em vez de ligar para um site externo (o que poderia quebrar um dia :)
Jake Berger

1
@Vicky Chijwani fornece o código no exemplo acima. Isso é mais adequado para um comentário, mas foi minha primeira atividade neste site. O link tem mais explicações sobre a opção crf, mas não é necessário para que o código funcione.
Tom Kelly

27

Você mencionou querer reduzir o tamanho do arquivo para caber mais vídeos em um dispositivo móvel, que também é meu caso. Todas as respostas aqui são para reduzir a qualidade da compactação, mas ninguém mencionou a redução do tamanho do quadro de vídeo. É muito mais rápido, cerca de 3 a 5 vezes mais rápido do que recomprimir na minha experiência. Consulte os documentos do ffmpeg sobre dimensionamento para obter mais informações.

ffmpeg -i input.mkv -vf "scale=iw/2:ih/2" half_the_frame_size.mkv
ffmpeg -i input.mkv -vf "scale=iw/3:ih/3" a_third_the_frame_size.mkv
ffmpeg -i input.mkv -vf "scale=iw/4:ih/4" a_fourth_the_frame_size.mkv

20

Testei a maioria das outras respostas propostas para essa pergunta. As conclusões dos dados do teste estão abaixo. Estas são as respostas propostas que eu testei:

(BR) Modifique a taxa de bits usando:

ffmpeg -i $infile -b $bitrate $newoutfile 

(CR) Varie o fator de taxa constante usando:

ffmpeg -i $infile -vcodec libx264 -crf 23 $outfile

(SZ) Altere o tamanho da tela do vídeo (por exemplo, para metade do tamanho de pixel), usando:

ffmpeg -i $infile -vf "scale=iw/2:ih/2" $outfile

(BL) Altere o perfil H.264 para "linha de base", usando:

ffmpeg -i $infile -profile:v baseline $outfile

(DF) Use o processamento ffmpeg padrão, usando:

ffmpeg -i $infile $outfile

DADOS

  • "tamanho" - tamanho percentual do pixel do vídeo convertido em relação ao original.
  • "taxa de bits" - taxa de bits de vídeos originais e convertidos.
  • "definição" - tamanho de pixel dos vídeos.
  • "converter" - tempo para converter o vídeo em segundos.

Calculei a taxa de bits alvo para (BL) usando o método proposto.

=== Arquivo A - Como o nó está ajudando a impulsionar o Angular-Fnbixa7Ts6M.mkv ===

            original    BR         CR         SZ         BL         DF
            --------    ---        --         --         --         --
size        64152 kb    214%       76%        40%        83%        76%
bitrate     411 kb/s    883        313        165        342        313
definition  1920x1080   1920x1080  1920x1080  960x540    1920x1080  1920x1080
convert     --          648        509        225        427        510

=== Arquivo B - Usando o GraphQL com Angular _ Por - Lee Costello-OGyFxqt5INw.mkv ===

            original    BR         CR         SZ         BL         DF
            --------    ---        --         --         --         --
size        410301 kb   33%        109%       28%        143%       109%
bitrate     2687 kb/s   880        2920       764        3843       2920
definition  3840x2160   3840x2160  3840x2160  1920x1080  3840x2160  3840x2160   
convert     --           2307       3188       1116       2646       3278

CONCLUSÕES

  • O método (SZ) é definitivamente o método mais rápido. Foi 2X a 4X mais rápido. Isso pode ser um problema em vídeos de alta definição, já que todos os outros métodos levaram mais tempo para serem convertidos do que a duração real do vídeo! Por exemplo, o método (CR) levou 53 minutos para converter o vídeo de 21 minutos.

  • O método (SZ) é definitivamente o melhor método se a definição do vídeo for maior que a definição da tela que o exibirá. Por exemplo, se o telefone puder exibir apenas uma imagem de 1080p, enviar um vídeo de 3840x2160 é apenas um desperdício. Seria melhor metade do seu tamanho para 1080p.

  • Algumas das respostas propostas realmente aumentaram o tamanho de alguns vídeos. Por exemplo, o método (BR) mais que dobrou o tamanho da amostra de 1080p. No entanto, fez do tamanho do 2160p um terço. Para a amostra de alta definição, os métodos (CR), (BL) e (DF) aumentaram o tamanho do vídeo.

Resposta correta (ou melhor)

É sempre melhor primeiro diminuir a resolução para o máximo suportado pela tela de destino.

Se você quiser reduzir ainda mais o tamanho do arquivo, isso dependerá de escolhas pessoais. Você pode reduzir o conteúdo das informações ou aumentar a compactação.

  • Você pode diminuir mais a resolução se isso não for algo que lhe preocupa.

  • Se o vídeo não incluir cenas de ação rápida, convém diminuir a taxa de quadros.

  • Se você possui um processador poderoso e o espaço é o único problema, você pode aumentar a taxa de compactação.

  • A taxa de bits é uma combinação de vários fatores. Portanto, apenas dizer ao ffmpeg para diminuir a taxa de bits pode não dar os resultados desejados.

  • Outra maneira de diminuir o conteúdo das informações é diminuir a profundidade da cor. Como fazer isso ainda não foi discutido.


13

Observe que parece que ffmpeg realiza alguma otimização quando executado sem opções; portanto, antes de tentar usar as configurações que você não entende ou decidir perder explicitamente as informações, tente uma conversão padrão:

ffmpeg -i input.mp4 output.mp4

No meu caso, reduziu a taxa de bits do vídeo e do áudio (você pode verificar e comparar os arquivos de entrada e saída executando ffprobe-os), transformando um vídeo de 700 Mb em um de 60 Mb com qualidade aparentemente semelhante.


1
Passou de 4Gb para 2Gb com isso, obrigado !!
Sam Hosseini

1
(de 10Mo para 1.2Mb, o ffmpeg converteu automaticamente meu vídeo que estava no VP8 para o VP9 )
sodimel

Isso aumentou o tamanho do meu vídeo de 10,8MB para 14MB
pjtnt11 20/09

3

Tenho uma receita que forjei originalmente para converter os vídeos Motion JPEG que minha câmera antiga gera (são vídeos muito grandes, já que cada quadro é uma imagem JPEG inteira) para h264. Aqui está uma adaptação para outros tipos de vídeos (cursos, etc.).

Eu não estou usando ffmpeg , mas mplayer e mencoder . Primeiro, precisamos desmuxar o áudio com o mplayer:

mplayer -vo null -ao pcm:fast:file=<audio_pcm.wav> <video>
  • Os parâmetros -vo nulle -ao nulldizem ao mplayer para não extrair o vídeo.

Nas próximas etapas, faremos uma compactação de 3 passagens com o mencoder. Na primeira passagem, escolheremos uma compactação do modo de qualidade constante ( parâmetro crf ) adequada como ponto de partida:

mencoder <video> -ovc x264 \ 
         -x264encopts ratetol=100:preset=veryslow:crf=<value>:pass=1 \
         -nosound -o video1.h264
  • Você pode adicionar o parâmetro slow_firstpass aos -x264encopts se estiver paranóico com a qualidade final do vídeo. O manual do Mencoder diz que esta opção desabilita alguns parâmetros que “melhoram significativamente a velocidade de codificação enquanto têm pouco ou nenhum impacto na qualidade da passagem final”. Portanto, use-o apenas na última etapa.

  • Você deve tentar vários valores para crf - tente começar a partir de 25 e continue aumentando até notar os artefatos no vídeo resultante (valores mais altos compactam mais). Lembre-se de que os passes de codificação subsequentes melhorarão a qualidade que você escolheu para o crf .

  • As alternativas para a predefinição do veryslow são mais lentas , lentas , médias etc. Veja o manual do mencoder para obter a lista completa.

  • O ratetol controla a variação da taxa de bits - não tenho certeza se estou fazendo a coisa certa aqui, mas defino-o no valor máximo para permitir total liberdade ao codificador para escolher a taxa de bits correta para cada cena.

Após a primeira passagem, você notará que a última linha fornece a taxa de bits média que você usará nas próximas etapas:

(...)
x264 [info]: kb/s:526.43

Altere o parâmetro crf , recomendado na primeira passagem, para a taxa de bits , necessária nas passagens subsequentes:

mencoder <video> -ovc x264 \
       -x264encopts slow_firstpass:ratetol=100:preset=veryslow:bitrate=526:pass=3 \
       -nosound -o video2.h264

Essa codificação da segunda passagem lerá as estatísticas geradas na primeira passagem ( divx2pass.loge divx2pass.log.mbtree) para otimizar a compactação.

  • Observe que você usará a mesma entrada de vídeo, e não o gerado pelo vídeo de saída da primeira passagem - primeira passagem é útil apenas para verificar a qualidade inicial.

  • Observe também que o pass=3( not pass=2 ) irá gerar um novo arquivo de estatísticas, para que você possa repetir a última etapa quantas vezes quiser. Eu costumo fazer pass=3duas vezes, sempre prestando atenção à taxa de bits do resultado.

Enquanto isso, você pode compactar o áudio também, usando lameou oggenc:

oggenc -q<n> <audio_pcm.wav>

Por fim, remuxaremos áudio e vídeo

mencoder -audiofile <audio>.ogg video2.h264 -oac copy -ovc copy \
         -of lavf -lavfopts format=mp4 -o <video>.mp4
  • O -of lavf -lavfopts format=mp4gera mp4o formato do arquivo usando os lavopts muxers.

3

Compactei uma apresentação de vídeo em HD de 40 minutos de 505
MB a 183 MB. É como passar de 100 MB → 36 MB.
O vídeo original era HD e a saída era quase zero de diferença perceptível.
É um arquivo de vídeo "Eu gostaria de acompanhar, mas o HD é um exagero".
Aqui está o comando que usei com motivos:

ffmpeg -n -loglevel error -i inputfile.mp4 -vcodec libx264 -crf 28 -preset faster -tune film outputfilename.mp4

  • -n: evite sobrescrever arquivos de saída (mais seguro para teste e depois para lote)
  • -loglevel error : mostra erros e oculta as linhas e linhas de progresso
  • -i inputfile.mp4 : nome do arquivo de entrada
  • -vcodec libx264: deslocado da resposta superior acima
  • -crf 28: compactação de passagem única com menor diferença perceptível ( "0 = sem perdas, 23 = padrão, 51 = pior; a faixa subjetivamente sã é de 17 a 28 " ) ref docs
  • -preset faster: parece 2x mais rápido que o tempo de codificação padrão dos documentos de referência 'médios'
  • -tune film: especificar entrada é um vídeo HQ (outras opções incluem 'desenho animado', 'imagem parada' ..) ref docs
  • outputfilename.mp4 : nome do arquivo de saída

Para um diretório de arquivos de vídeo:

for i in *.{avi,flv,m4v,mov,wmv,mp4,MP4,TS,mkv}; do ffmpeg -n -loglevel error -i "$i" -vcodec libx264 -crf 28 -preset faster -tune film "cc${i}"; done

Problemas:

  • uma maneira mais limpa de coletar "todos os arquivos de vídeo" sem ter todas as extensões no comando
  • uma maneira mais limpa de gerar o nome do arquivo sem o prefixo "cc" E poder confirmar o vídeo antes de excluir
  • .webmarquivos não funcionam com o comando Teve que trocar "cc${i}""${i%.*}.mp4"

O Handbrake é uma alternativa de código aberto com uma interface do usuário


Funciona. mas leva muito tempo. Existe alguma melhoria por menos tempo de execução
Nirali 22/06


1

Eu escrevi um script bash para reduzir o tamanho do vídeo e tentar automaticamente diferentes valores de CRF.

Basicamente você

  • escolha um intervalo de valores de crf
  • execute o script
  • verifique o tamanho dos vídeos gerados e escolha o que deseja

Isso é realmente útil quando você tem um limite de tamanho que deseja atingir e não sabe qual é o valor de CRF que permitirá que você faça isso.

Espero que isso ajude alguém. Compartilhei com meus colegas e todos acharam útil.

#!/bin/bash

# bigger values of crf will lead to a bigger compression (smaller video size)
#for i in 1 2 3 4 5
for i in {25..28}
do
# you can remove the option -y if you want to be asked if to overwrite a file with the same name (leave the -y only if you understand what you are doing, otherwise you might rewrite an important file)
   ffmpeg -y -i NAMEOFTHEVIDEOTOCOMPRESS.mp4 -c:v libx264 -crf $i -preset veryfast -profile:v baseline -level 3.0 -strict -2 out_$i.mp4
   printf "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Done compression at crf=$i \n\n"
done
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.