Jak mogę zmniejszyć rozmiar wideo za pomocą ffmpeg?


201

Jak mogę użyć, ffmpegaby zmniejszyć rozmiar filmu, obniżając jego jakość (naturalnie tak minimalnie, jak to możliwe, ale muszę go uruchomić na urządzeniu mobilnym, które nie ma dużo dostępnego miejsca)?

Zapomniałem jeszcze napisać jedną rzecz. Gdy wideo może używać napisów (* .srt lub * .sub), chciałbym je również przekonwertować, aby pasowały do ​​parametrów przekonwertowanego pliku wideo.


4
Nie korzystałem z niego, ale ffmpegstrona podręcznika pokazuje -fsopcję ograniczenia rozmiaru wyjściowego, czy coś takiego ffmpeg -i in.avi -fs 100M out.avidziała?
Kevin,

1
Nie będę przekierowywać cię do strony man:man ffmpeg | wc -l --> 5254

3
To .avinie jest główny problem .. avito tylko pojemnik. Głównym problemem jest to, jakich kodeków używasz. Wiele (większość?) .aviFilmów wykorzystuje kodeki starszego stylu (np. XviD), które są w porządku, ale są większe dla tej samej jakości w porównaniu z kodekami nowej generacji. Zazwyczaj można uzyskać ścisłe kodowanie przy użyciu H.264standardu kompresji wideo (np. kodeka x264) i aackompresji dźwięku. Użyty kontener i kodeki zależy od Ciebie i Twojego telefonu ... .mp4Kontener jest dobrze przyjęty .. (ale Twój telefon może go obsłużyć: zobacz ten link
Peter.O

@Kevin To chce więcej parametrów do konwersji.
xralf

@hesse Co to znaczy?
xralf

Odpowiedzi:


277

Zobacz odpowiedź. Cytowany poniżej dla wygody:

Oblicz potrzebną szybkość transmisji, dzieląc 1 GB przez długość filmu w sekundach. Tak więc w przypadku filmu o długości 16:40 (1000 sekund) użyj przepływności 1000000 bajtów / s:

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

Dodatkowymi opcjami, które mogą być warte rozważenia, jest ustawienie współczynnika stałej szybkości, który obniża średnią szybkość transmisji, ale zachowuje lepszą jakość. Zmieniaj CRF między około 18 a 24 - im niższy, tym wyższa przepływność.

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

Zmieniaj kodek zgodnie z potrzebami - libx264 może być dostępny, jeśli nie ma libx265, kosztem nieco większego rozmiaru pliku wynikowego.


Rozmiar wideo 338 MB został zmniejszony do rozmiaru 130 MB. Jakość gwałtownie obniżyła się. Czy jest jakieś wytłumaczenie dla tego procesu? Oryginalny autor nie wyjaśnia swojej wytycznej.
xralf

13
Drugie polecenie, przy użyciu -crf 24wziąłem wideo o wielkości 255,3 MB i zmniejszyłem je do 72,7 MB bez zauważalnego obniżenia jakości. Zyskaj głos!
Patrick Roberts,

2
Imponująco zmniejszyłem ~ 2G wideo do 14 MB, nadal wygląda dobrze, to był pierwszy wynik wyszukiwania i właśnie tego szukałem, dzięki!
sinisterstuf

5
Warto zauważyć, że możesz teraz użyć libx265do jeszcze większego zmniejszenia rozmiaru.
ZN13

6
Stosowane ffmpeg -i input.avi -vcodec libx264 -crf 24 output.avi. Zmniejszyło wideo 100 MB do 9 MB. Bardzo niewielka zmiana jakości wideo. Dziękuję Ci!
alpha_989

32

Jeśli nie szukasz określonej szybkości transmisji, polecam tę -crfopcję. Jest to najczęściej używane do x264kodowania: http://slhck.info/articles/crf

W skrócie: CRF wynoszący 23 sprawiłby, że film w jakości „DVD” (~ 700 MB-1 GB), a niższe wartości CRF byłyby wyższej jakości (większe pliki).


3
Podaj przykłady pełnej komendy zamiast linku do zewnętrznej strony internetowej (która może kiedyś się zepsuć :)
Jake Berger

1
@ Vicky Chijwani podaje kod z powyższego przykładu. To lepiej pasuje do komentarza, ale była to moja pierwsza aktywność na tej stronie. Link zawiera więcej wyjaśnień na temat opcji crf, ale nie jest konieczny do uruchomienia kodu.
Tom Kelly,

27

Wspomniałeś, że chcesz zmniejszyć rozmiar pliku, aby zmieścił się w nim więcej filmów na urządzeniu mobilnym, co również jest moją sprawą. Wszystkie odpowiedzi tutaj dotyczą obniżenia jakości kompresji, ale nikt nie wspomniał o zmniejszeniu rozmiaru klatki wideo. Jest o wiele szybszy, od około 3 do 5 razy szybszy niż ponowne kompresowanie z mojego doświadczenia. Aby uzyskać więcej informacji, zobacz dokumentację ffmpeg dotyczącą skalowania .

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

Testowałem większość innych proponowanych odpowiedzi na to pytanie. Wnioski z danych testowych są poniżej. Oto proponowane odpowiedzi, które przetestowałem:

(BR) Zmodyfikuj szybkość transmisji, używając:

ffmpeg -i $infile -b $bitrate $newoutfile 

(CR) Zmieniaj współczynnik stałej szybkości, używając:

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

(SZ) Zmień rozmiar ekranu wideo (na przykład na połowę jego rozmiaru w pikselach), używając:

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

(BL) Zmień profil H.264 na „podstawowy”, używając:

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

(DF) Użyj domyślnego przetwarzania ffmpeg, używając:

ffmpeg -i $infile $outfile

DANE

  • „rozmiar” - procentowy rozmiar pikseli przekonwertowanego wideo w stosunku do oryginału.
  • „bitrate” - szybkość transmisji oryginalnych i przekonwertowanych filmów.
  • „definicja” - rozmiar filmu w pikselach.
  • „konwersja” - czas na konwersję wideo w kilka sekund.

Obliczyłem docelową szybkość transmisji dla (BL) przy użyciu proponowanej metody.

=== Plik A - Jak węzeł pomaga napędzać 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

=== Plik B - Korzystanie z GraphQL z Angular _ By - 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

WNIOSKI

  • Metoda (SZ) jest zdecydowanie najszybszą metodą. Było 2 do 4 razy szybsze. Może to stanowić poważny problem w przypadku filmów o wysokiej rozdzielczości, ponieważ konwersja wszystkich innych metod trwała dłużej niż rzeczywista długość filmu! Na przykład metoda (CR) zajęła 53 minuty, aby przekonwertować 21-minutowe wideo.

  • Metoda (SZ) jest zdecydowanie najlepszą metodą, jeśli definicja wideo jest większa niż definicja ekranu, na którym będzie wyświetlany. Na przykład, jeśli Twój telefon może wyświetlać tylko obraz 1080p, wysyłanie go do filmu o rozdzielczości 3840 x 2160 jest po prostu marnotrawstwem. Najlepiej byłoby zmniejszyć jego połowę do 1080p.

  • Niektóre z proponowanych odpowiedzi W rzeczywistości ZWIĘKSZYŁY rozmiar niektórych filmów. Na przykład metoda (BR) ponad dwukrotnie zwiększyła rozmiar próbki 1080p. Sprawił jednak, że rozmiar 2160p stanowił jedną trzecią. W przypadku próbki o wysokiej rozdzielczości wszystkie metody (CR), (BL) i (DF) ZWIĘKSZYŁY rozmiar filmu.

Prawidłowa (lub najlepsza) odpowiedź

Zawsze najlepiej jest najpierw obniżyć rozdzielczość do maksimum obsługiwanego przez docelowy ekran.

Jeśli chcesz jeszcze bardziej zmniejszyć rozmiar pliku, będzie to zależeć od osobistych wyborów. Możesz zmniejszyć zawartość informacji lub zwiększyć kompresję.

  • Możesz bardziej obniżyć rozdzielczość, jeśli nie dotyczy to ciebie.

  • Jeśli wideo nie zawiera scen szybkiej akcji, możesz zmniejszyć szybkość klatek.

  • Jeśli masz wydajny procesor, a jedynym problemem jest miejsce, możesz zwiększyć współczynnik kompresji.

  • Szybkość transmisji jest kombinacją wielu czynników. Więc samo powiedzenie ffmpeg, aby obniżyło szybkość transmisji, może nie dać oczekiwanych rezultatów.

  • Innym sposobem obniżenia zawartości informacji jest zmniejszenie głębi kolorów. Jak to zrobić, nie zostało jeszcze omówione.


13

Zauważ, że wydaje się, że ffmpeg już działa optymalizacja, gdy jest uruchamiany bez opcji, więc zanim spróbujesz użyć ustawień, których nie rozumiesz lub zdecydujesz się jawnie stracić informacje, wypróbuj domyślną konwersję:

ffmpeg -i input.mp4 output.mp4

W moim przypadku zmniejszyło to przepływność zarówno wideo, jak i audio (możesz sprawdzić i porównać plik wejściowy i wyjściowy, uruchamiając ffprobeje), przekształcając 700 Mb wideo w 60 Mb jeden z pozornie podobnej jakości.


1
Dzięki temu przeszliśmy z 4 Gb na 2 Gb, dzięki !!
Sam Hosseini,

1
(z 10Mo na 1,2Mb, ffmpeg automatycznie przekonwertowało moje wideo, które było w VP8 na VP9 )
sodimel

To zwiększyło rozmiar mojego filmu z
10,8

3

Mam przepis, który pierwotnie opracowałem dla siebie w celu konwersji filmów Motion JPEG, które generuje mój stary aparat (są to bardzo duże filmy, ponieważ każda klatka to cały obraz JPEG) do h264. Oto adaptacja do innych rodzajów filmów (kursów itp.).

Nie używam ffmpeg , ale mplayer i mencoder . Najpierw musimy demuxować audio za pomocą mplayera:

mplayer -vo null -ao pcm:fast:file=<audio_pcm.wav> <video>
  • -vo nullI -ao nullparametry Informuje MPlayera by nie wyodrębnić wideo.

W następnych krokach wykonamy 3-etapową kompresję z mencoderem. Przy pierwszym przejściu wybierzemy odpowiednią kompresję w trybie stałej jakości ( parametr crf ) jako punkt początkowy:

mencoder <video> -ovc x264 \ 
         -x264encopts ratetol=100:preset=veryslow:crf=<value>:pass=1 \
         -nosound -o video1.h264
  • Możesz dodać parametr slow_firstpass do -x264encopts, jeśli jesteś paranoikiem z ostateczną jakością wideo. Podręcznik Mencodera mówi, że ta opcja wyłącza niektóre parametry, które „znacznie poprawiają prędkość kodowania, a jednocześnie mają niewielki lub żaden wpływ na jakość końcowego przejścia”. Dlatego używaj go tylko na ostatnim etapie.

  • Powinieneś wypróbować kilka wartości dla CRF - spróbuj od 25 i dalej ją zwiększaj, aż zauważysz artefakty w wynikowym wideo (wyższe wartości kompresują więcej). Pamiętaj, że kolejne przejścia kodowania poprawią jakość, którą wybrałeś dla CRF .

  • Alternatywy dla veryslow presetu są wolniej , powolny , średnie itp Patrz podręcznik mencoder dla kompletnej listy.

  • ratetol kontroluje zmienność przepływności - nie jestem pewien, czy robię to dobrze, ale ustawiłem ją na maksymalną wartość, aby zapewnić całkowitą swobodę mencodera w wyborze właściwej przepływności dla każdej sceny.

Po pierwszym przejściu zauważysz, że ostatni wiersz podaje średnią szybkość transmisji bitów, której użyjesz w następnych krokach:

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

Zmień parametr crf , zalecany przy pierwszym przejściu, na bitrate , wymagany przy kolejnych przebiegach:

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

To kodowanie drugiego przejścia odczyta statystyki wygenerowane przy pierwszym przejściu ( divx2pass.logi divx2pass.log.mbtree) w celu zoptymalizowania kompresji.

  • Pamiętaj, że użyjesz tego samego wejścia wideo, a nie generowanego przy pierwszym przejściu - wyjściowe wideo pierwszego przejścia jest przydatne tylko do sprawdzenia początkowej jakości.

  • Zauważ też, że pass=3( nie pass=2 ) wygeneruje nowy plik statystyk, więc możesz powtórzyć ostatni krok tyle razy, ile chcesz. Zwykle robię to pass=3dwa razy, zawsze zwracając uwagę na przepływność wyniku.

W międzyczasie możesz również skompresować dźwięk, używając lamelub oggenc:

oggenc -q<n> <audio_pcm.wav>

Na koniec przemienimy audio i wideo

mencoder -audiofile <audio>.ogg video2.h264 -oac copy -ovc copy \
         -of lavf -lavfopts format=mp4 -o <video>.mp4
  • -of lavf -lavfopts format=mp4Generuje mp4format pliku za pomocą lavopts mukserów.

3

Skompresowałem 40-minutową prezentację wideo HD z 505 MB do 183 MB
To tak, jakby przejść ze 100 MB → 36 MB.
Oryginalne wideo było HD, a wyjściowa różnica była prawie zerowa.
To plik wideo „Chciałbym się zatrzymać, ale HD to przesada”.
Oto polecenie, którego użyłem z powodów:

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

  • -n: unikaj nadpisywania plików wyjściowych (bezpieczniejsze do testowania niż do grupowania)
  • -loglevel error : pokaż błędy i ukryj wiersze postępu
  • -i inputfile.mp4 : nazwa pliku wejściowego
  • -vcodec libx264: przesunięto od górnej odpowiedzi powyżej
  • -crf 28: Kompresja jednoprzebiegowego z niewielkimi zauważalnej różnicy ( „0 = bezstratny, 23 = domyślne 51 najgorszym =; subiektywnie rozsądny zakres wynosi 17- 28 ) Dokumenty ref
  • -preset faster: wygląda 2x szybciej niż domyślny czas kodowania dokumentów referencyjnych „średnich”
  • -tune film: określ dane wejściowe to wideo HQ (inne opcje to „kreskówka”, „nieruchomy obraz” ..) dokumenty referencyjne
  • outputfilename.mp4 : Nazwa pliku wyjściowego

W przypadku katalogu plików wideo:

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

Zagadnienia:

  • czystszy sposób na gromadzenie „wszystkich plików wideo” bez posiadania wszystkich rozszerzeń w poleceniu
  • czystszy sposób na wydrukowanie nazwy pliku bez prefiksu „cc” ORAZ możliwość potwierdzenia wideo przed usunięciem
  • .webmpliki nie działają z poleceniem. Musiałem zamienić "cc${i}""${i%.*}.mp4"

Hamulec ręczny to alternatywa typu open source z interfejsem użytkownika


To działa. ale zajmuje to zbyt wiele czasu. Czy jest jakaś poprawa na krótszy czas wykonania
Nirali


1

Napisałem skrypt bash do zmniejszania rozmiaru wideo i automatycznego wypróbowywania różnych wartości CRF.

Zasadniczo będziesz

  • wybierz zakres wartości CRF
  • uruchom skrypt
  • sprawdź rozmiar wygenerowanych filmów i wybierz ten, który chcesz

Jest to bardzo przydatne, gdy masz limit rozmiaru, który chcesz osiągnąć i nie wiesz, jaka jest wartość crf, która pozwoli ci to zrobić.

Mam nadzieję, że to komuś pomoże. Dzieliłem się z kolegami i wszyscy uznali to za pomocne.

#!/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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.