Ponowne kodowanie biblioteki wideo w x265 (HEVC) bez utraty jakości


43

Próbuję przekonwertować moją bibliotekę wideo do formatu HEVC, aby uzyskać miejsce. Uruchomiłem następujące polecenie na wszystkich plikach wideo w mojej bibliotece:

#!/bin/bash
for i in *.mp4;
do 
    #Output new files by prepending "X265" to the names
    avconv -i "$i" -c:v libx265 -c:a copy X265_"$i"
done

Teraz większość filmów konwertuje się dobrze, a jakość jest taka sama jak poprzednio. Jednak kilka filmów, które są bardzo wysokiej jakości (np. Jeden wydruk filmu, który ma 5 GB) traci jakość - wszystko jest w pikselach.

Nie jestem pewien, co robić w tym przypadku. Czy muszę zmodyfikować crfparametr w wierszu polecenia? Albo coś innego?

Chodzi o to, że robię masową konwersję. Potrzebuję więc metody, w której avconvautomatycznie dostosowuje się każdy parametr, który wymaga dostosowania, dla każdego filmu.

AKTUALIZACJA-1

Odkryłem, że crfto pokrętło muszę wyregulować. Domyślny CRF to 28. Aby uzyskać lepszą jakość, mógłbym użyć czegoś mniejszego niż 28. Na przykład:

avconv -i input.mp4 -c:v libx265 -x265-params crf=23 -c:a copy output.mp4

Problem polega jednak na tym, że w przypadku niektórych filmów wartość CRF wynosząca 28 jest wystarczająca, natomiast w przypadku niektórych filmów wymagana jest niższa wartość CRF. Jest to coś, co muszę sprawdzić ręcznie, konwertując małe sekcje dużych filmów. Ale w przypadku konwersji zbiorczej, w jaki sposób sprawdzać ręcznie każdy film? Czy w jakiś sposób avconvmogą inteligentnie dostosować CRF do wejściowego wideo?

AKTUALIZACJA-2

Odkryłem, że istnieje --losslessopcja w x265: http://x265.readthedocs.org/en/default/lossless.html .

Nie wiem jednak, jak poprawnie go używać. Próbowałem użyć go w następujący sposób, ale przyniosło to odwrotne wyniki (film był jeszcze bardziej pikselowany):

avconv -i input.mp4 -c:v libx265 -x265-params lossless -c:a copy output.mp4

1
--losslessmoże faktycznie powiększyć plik, jeśli dekoduje poprzednio stratny kodek, a następnie szyfruje to, co dekodował bezstratnie. Jakość pozostanie dokładnie taka sama jak na wejściu.
Golar Ramblar

2
Jeśli twoje źródła są zakodowane w stratnej (co najprawdopodobniej), to to, co próbujesz osiągnąć, jest niemożliwe. Każde transkodowanie, które nie jest bezstratne, spowoduje dalsze pogorszenie jakości (nawet jeśli nie będzie od razu widoczne), a jeśli zmienisz z stratnego na bezstratny, otrzymasz większe rozmiary plików.
Sarge Barszcz

Odpowiedzi:


58

Z własnego doświadczenia wynika, że ​​jeśli nie chcesz absolutnie żadnej utraty jakości, to bezstratne jest to, czego szukasz.

Nie jestem pewien, avconvale wpisane polecenie wygląda identycznie jak to, co robię FFmpeg. W FFmpegmożna przekazać parametr w ten sposób:

ffmpeg -i INPUT.mkv -c:v libx265 -preset ultrafast -x265-params lossless=1 OUTPUT.mkv

Większość x265przełączników (opcje bez wartości) można określić w ten sposób (z wyjątkiem tych tylko z interfejsem CLI, które są używane tylko z x265plikiem binarnym).

W tym miejscu chciałbym podzielić się moim doświadczeniem z x265kodowaniem. Do większości filmów (WMV, MPEG lub AVC / H.264) używam crf=23. x265decyduje o pozostałych parametrach i zwykle wykonuje wystarczająco dobrą pracę.

Jednak często zanim zdecyduję się na transkodowanie wideo w całości, testuję moje ustawienia, konwertując niewielką część danego wideo. Oto przykład, załóżmy, że plik mkv ze strumieniem 0 to wideo, strumień 1 to dźwięk DTS, a strumień 2 to podtytuł:

ffmpeg -hide_banner \
-ss 0 \
-i "INPUT.mkv" \
-attach "COVER.jpg" \
-map_metadata 0 \
-map_chapters 0 \
-metadata title="TITLE" \
-map 0:0 -metadata:s:v:0 language=eng \
-map 0:1 -metadata:s:a:0 language=eng -metadata:s:a:0 title="Surround 5.1 (DTS)" \
-map 0:2 -metadata:s:s:0 language=eng -metadata:s:s:0 title="English" \
-metadata:s:t:0 filename="Cover.jpg" -metadata:s:t:0 mimetype="image/jpeg" \
-c:v libx265 -preset ultrafast -x265-params \
crf=22:qcomp=0.8:aq-mode=1:aq_strength=1.0:qg-size=16:psy-rd=0.7:psy-rdoq=5.0:rdoq-level=1:merange=44 \
-c:a copy \
-c:s copy \
-t 120 \
"OUTPUT.HEVC.DTS.Sample.mkv"

Zauważ, że linia odwrotnego ukośnika przerywa linię długiego polecenia, robię to, aby pomóc mi śledzić różne bity złożonego wejścia CLI. Zanim wyjaśnię to wiersz po wierszu, część, w której konwertujesz tylko niewielką część wideo, to druga linia i druga ostatnia linia: -ss 0oznacza szukanie do 0 sekund przed rozpoczęciem dekodowania wejścia i -t 120oznacza przestanie zapisywać na wyjściu po 120 sekundach. Możesz także użyć formatu czasu hh: mm: ss lub hh: mm: ss.sss.

Teraz linia po linii:

  1. -hide_bannerzapobiega FFmpegwyświetlaniu informacji o kompilacji przy starcie. Po prostu nie chcę tego widzieć, kiedy przewijam konsolę w górę;
  2. -ss 0szuka 0 sekund przed rozpoczęciem dekodowania wejścia. Zauważ, że jeśli ten parametr jest podany po pliku wejściowym i przed plikiem wyjściowym, staje się on opcją wyjściową i każe ffmpegdekodować i ignorować dane wejściowe do x sekund, a następnie rozpocząć zapis do pliku wyjściowego. Jako opcja wprowadzania jest mniej dokładna (ponieważ wyszukiwanie nie jest dokładne w większości formatów kontenerów), ale prawie nie zajmuje czasu. Jako opcja wyjściowa jest bardzo precyzyjna, ale odkodowanie całego strumienia przed określonym czasem zajmuje dużo czasu, a do celów testowych nie chcesz tracić czasu;
  3. -i "INPUT.mkv": Określ plik wejściowy;
  4. -attach "COVER.jpg": Dołącz okładkę (miniaturę, plakat, cokolwiek) do wydruku. Okładka jest zwykle pokazywana w eksploratorach plików;
  5. -map_metadata 0: Skopiuj wszystkie metadane z wejścia 0, które w tym przykładzie jest tylko wejściem;
  6. -map_chapters 0: Skopiuj informacje o rozdziale (jeśli są obecne) z wejścia 0;
  7. -metadata title="TITLE": Ustaw tytuł wideo;
  8. -map 0:0 ...: Mapuj strumień 0 wejścia 0, co oznacza, że ​​chcemy, aby pierwszy strumień z wejścia został zapisany na wyjściu. Ponieważ ten strumień jest strumieniem wideo, jest to pierwszy strumień wideo na wyjściu , stąd specyfikator strumienia :s:v:0. Ustaw tag języka na angielski;
  9. -map 0:1 ...: Podobnie jak w wierszu 8, zamapuj drugi strumień (dźwięk DTS) oraz ustaw jego język i tytuł (dla łatwiejszej identyfikacji przy wyborze z odtwarzaczy);
  10. -map 0:2 ...: Podobne do wiersza 9, z tym wyjątkiem, że ten strumień jest podtytułem;
  11. -metadata:s:t:0 ...: Ustaw metadane okładki. Jest to wymagane w przypadku formatu kontenera mkv;
  12. -c:v libx265 ...: Opcje kodeków wideo. Jest tak długi, że podzieliłem go na dwie linie. To ustawienie jest dobre dla wysokiej jakości rozmycia wideo (1080p) z minimalnym pasmowaniem w gradiencie (do którego x265 jest do bani). Najprawdopodobniej jest to przesada w przypadku płyt DVD i programów telewizyjnych oraz filmów z telefonu. To ustawienie zostało w większości skradzione z tego posta w Doom9 ;
  13. crf=22:...: Kontynuacja parametrów kodeka wideo. Zobacz wyżej wspomniany post na forum;
  14. -c:a copy: Kopiuj audio;
  15. -c:s copy: Kopiuj napisy;
  16. -t 120: Przestań zapisywać na wyjściu po 120 sekundach, co daje nam 2-minutowy klip do podglądu jakości transkodowania;
  17. "OUTPUT.HEVC.DTS.Sample.mkv": Nazwa pliku wyjściowego. Nazwy moich plików oznaczam kodekiem wideo i podstawowym kodekiem audio.

Uff To jest moja pierwsza odpowiedź, więc jeśli coś mi umknęło, zostaw komentarz. Nie jestem ekspertem od produkcji wideo, jestem po prostu facetem, który jest zbyt leniwy, aby obejrzeć film, wkładając płytę do odtwarzacza.

PS. Być może to pytanie należy do kogoś innego, ponieważ nie jest ściśle związane z Uniksem i Linuksem.


2
Dokładnie tego szukałem! Niezły zasięg opcji. Czy wiesz, czy ffmpeg będzie walczył, c:s copyjeśli nie będzie napisów?
Starszy Geek

1
@ElderGeek Nie, ffmpeg powie coś tylko, jeśli ta opcja ma jakikolwiek efekt.
Yifeng Mu

Czy ta opcja generuje najmniejszy możliwy rozmiar pliku dla naprawdę bezluzowego kodowania h265? Jeśli nie, to czy mogę to zrobić?
Bufor przed

1
@TheBitByte Nie sądzę, że w h265 jest bezstratny poziom kompresji. W przypadku opcji bez kompresji jest to po prostu --lossless. Na próżno szukałem bezstratnej konwersji z h264 na h265, a to, czego się nauczyłem, mówi mi, że jest to matematycznie niemożliwe.
Yifeng Mu

1
Naprawdę powinieneś edytować polecenie zawierające --losslessprzełącznik tej odpowiedzi, ponieważ umieszczenie go jako odpowiedzi na to pytanie brzmi tak, jakbyś powiedział, że jest to kompresja bezstratna, co jest mylące.
Hashim

8

Niedawno miałem problem z transkodowaniem całego mojego katalogu wideo na HEVC. Korzystam z https://github.com/FallingSnow/h265ize z następującymi ustawieniami.

h265ize -v -m średni -q 20 -x - no-sao - aq-mode 3 - usuń --stats

-v - Wyjściowe wyjście
-m średnie - Średnia szybkość kodowania (mniejsza wyższa jakość, cokolwiek wolniej znajduję nie jest warte różnicy czasu / jakości)
-q 20 - użyty CRF, 20 jest podobny do 18 w x264, ale hej. Dotyczy to treści 1080p (90% mojego telewizora). Zwykle używam 22 do filmów 4K
-x - Używaj centralnie zdefiniowanych poleceń x265 - no
-sao wyłącza przykładowe przesunięcie adaptacyjne (poprawia prędkość kodowania)
- tryb aq 3 - użyj kwantyzacji adaptacyjnej z automatyczną wariancją, pomaga w kodowaniu 8-bitowym, szczególnie w ciemnych obszarach, zatrzymuje większość pasmowania, które mogą się zdarzyć (kosztem czasu kodowania) -
usuń - zamień plik kodowania na kodowany (przetestuj przed użyciem ) -
stany - Zapisz statystyki do pliku csv w katalogu głównym ścieżki, z której uciekłeś.

Prędkości kodowania wynoszą około 30 klatek na sekundę (dla większości rzeczy 1080p) na moim urządzeniu. Dual Xeon E5 2687W v2, ale zmuszam proces FFMPEG, aby nie używał pierwszej strony jednego z procesorów (jest to mój serwer Plex, więc w razie potrzeby podczas odtwarzania itp. Należy upewnić się, że istnieje transkodowanie)

Tak, zajęło trochę czasu, aby przekonwertować większość z nich, a teraz mam zaplanowane zadanie, które uruchamia się dwa razy dziennie, aby zakodować rzeczy z tego dnia do x265.

Oszczędności miejsca były ogromne. Mój początkowy SAN był w użyciu 20 TB, teraz jest około 12, ale oczywiście został również dodany z 6 miesiącami więcej treści.

Zacząłem też transkodować wszystkie moje filmy, ale jest to proces ciągły, ponieważ muszę zidentyfikować poziomy jakości (na szczęście Radarr ładnie oznacza wtedy etykiety) i użyć jednego z trzech ustawień transkodowania:

-m slower -q 18 -x --no-sao --aq-mode 3dla transkodów 720p
-m medium -q 20 -x --no-sao --aq-mode 3dla 1080p
-m medium -q 22 -x --no-saodla 2160p

Mam nadzieję, że pomaga niektórym ludziom. Krzycz, jeśli ktoś potrzebuje ręki, aby to wszystko skonfigurować. I zanim zakodujesz wszystko na x265, pomyśl o odtwarzaniu, jeśli klient nie obsługuje natywnego x265, transkada może być kosztowna pod względem procesora i jakości.


W przypadku wersji x265 2.4 i nowszych (z nowymi tabelami lambda, które dają ostrzejsze kodowanie), SAO jest zwykle dobrą rzeczą pod względem jakości na bitrate. Nadal lekko się rozmazuje, ale zmniejsza na tyle inne artefakty, że warto.
Peter Cordes

-q 20to nie CRF 20, to stała kontrola tempa QP . Tryb domyślny i zalecany, CRF, podnosi QP w scenach o dużej złożoności, więc nie wydaje zbyt wielu bitów na sceny, które są zbyt trudne do zakodowania. (Jeśli chcesz zbliżyć się do jednolitego QP, podnieś qcompz domyślnego 0.6 do może 0.7 lub 0.8. Bliżej 1.0 jest bliższy CQP.)
Peter Cordes

3

Prawidłowa składnia umożliwiająca włączenie trybu bezstratnego dla enkodera x265 w ffmpeg to -x265-params lossless=1(musisz dołączyć =1).

Jednak w przypadku kodowania bezstratnego istnieją lepsze możliwości wyboru kodeków. Przekonałem się, że FFV1 kompresuje się znacznie lepiej (rozmiar pliku = ~ 80% x265) przynajmniej na niektórych rodzajach wideo (jeśli wybrane zostaną najlepsze ustawienia dla obu kodeków). Działa również szybciej, a (AFAIK) nie jest obciążony patentami. Oznacza to, że pod każdym względem jest lepszy niż bezstratny H.265 do archiwizacji wideo.

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.