Jaki jest prawidłowy sposób naprawy klatek kluczowych w FFmpeg dla DASH?

38

Podczas warunkowania strumienia do odtwarzania w trybie DASH losowe punkty dostępu muszą mieć dokładnie taki sam czas strumienia źródłowego we wszystkich strumieniach. Typowym sposobem na to jest wymuszenie stałej liczby klatek i stałej długości GOP (tj. Klatka kluczowa co N klatek).

W FFmpeg stała liczba klatek na sekundę jest łatwa (-r NUMBER).

Ale dla ustalonych lokalizacji klatek kluczowych (długość GOP) istnieją trzy metody ... która z nich jest „poprawna”? Dokumentacja FFmpeg jest frustrująco niejasna w tej kwestii.

Metoda 1: mieszanie się z argumentami libx264

-c:v libx264 -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE:scenecut=-1

Wydaje się, że toczy się debata, czy scenariusz powinien zostać wyłączony, czy nie, ponieważ nie jest jasne, czy „licznik” klatki kluczowej zostanie ponownie uruchomiony, gdy nastąpi wycięcie sceny.

Metoda 2: Ustawienie stałego rozmiaru GOP:

-g GOP_LEN_IN_FRAMES

Jest to niestety udokumentowane tylko w dokumentacji FFMPEG, a zatem efekt tego argumentu jest bardzo niejasny.

Metoda 3: wstaw klatkę kluczową co N sekund ( może? ):

-force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)

Jest to wyraźnie udokumentowane. Ale nadal nie jest od razu jasne, czy „licznik czasu” uruchamia się ponownie po każdej klatce kluczowej. Na przykład, jeśli w oczekiwanym 5-sekundowym GOP, jeśli scenecutlibx264 ma wstrzyknąć klatkę kluczową 3 sekundy, czy następna klatka kluczowa miałaby 5 sekund później czy 2 sekundy później?

W rzeczywistości dokumentacja FFmpeg rozróżnia tę -gopcję od opcji, ale tak naprawdę nie mówi, jak te dwie powyższe opcje są nieco inne (oczywiście -gbędzie wymagać stałej liczby klatek na sekundę).

Który jest poprawny?

Wydawałoby się, że -force_key_framesbyłby lepszy , ponieważ nie wymagałby stałej liczby klatek na sekundę. Wymaga to jednak tego

  • jest zgodny ze specyfikacjami GOP w H.264 ( jeśli istnieje )
  • GWARANTUJE, że istniałaby klatka kluczowa o stałej kadencji, niezależnie od scenecutklatek kluczowych libx264 .

Wydawałoby się również, że -gnie mogłoby działać bez wymuszenia stałej liczby klatek na sekundę ( -r) , ponieważ nie ma gwarancji, że wiele przebiegów ffmpegz różnymi argumentami kodeków zapewni tę samą chwilową liczbę klatek w każdej rozdzielczości. Stała liczba klatek na sekundę może obniżyć wydajność kompresji (WAŻNE w scenariuszu DASH!).

Wreszcie metoda po prostu wydaje się hackkeyint . Mam nadzieję, że nie jest to prawidłowa odpowiedź.

Referencje:

Przykład z wykorzystaniem -force_key_framesmetody

Przykład z wykorzystaniem keyintmetody

Sekcja zaawansowanych opcji wideo FFmpeg

Mark Gerolimatos
źródło

Odpowiedzi:

27

TL; DR

Poleciłbym następujące:

  • libx264: (i opcjonalnie dodaj )-g X -keyint_min X-force_key_frames "expr:gte(t,n_forced*N)"
  • libx265: -x265-params "keyint=X:min-keyint=X"
  • libvpx-vp9: -g X

gdzie Xjest interwałem w ramkach i Njest interwałem w sekundach. Na przykład dla 2-sekundowego interwału z 30 klatkami na sekundę, X= 60 iN = 2.

Uwaga na temat różnych typów ramek

Aby poprawnie wyjaśnić ten temat, musimy najpierw zdefiniować dwa typy ramek I / klatek kluczowych:

  • Natychmiastowe odświeżanie dekodera (IDR): Pozwalają one na niezależne dekodowanie następujących ramek, bez dostępu do ramek poprzedzających ramkę IDR.
  • Ramki inne niż IDR: Do działania dekodowania wymagana jest poprzednia ramka IDR. Ramki inne niż IDR mogą być używane do wycinania scen w środku GOP (grupy zdjęć).

Co jest zalecane do przesyłania strumieniowego?

W przypadku przesyłania strumieniowego chcesz:

  • Upewnij się, że wszystkie ramki IDR znajdują się w regularnych pozycjach (np. W 2, 4, 6,… sekundach), aby wideo można było podzielić na segmenty o równej długości.
  • Włącz wykrywanie wycięcia sceny, aby poprawić wydajność / jakość kodowania. Oznacza to zezwalanie na umieszczanie ramek I pomiędzy ramkami IDR. Nadal możesz pracować z wyłączonym wykrywaniem scen (i jest to wciąż część wielu przewodników), ale nie jest to konieczne.

Co robią parametry?

Aby skonfigurować enkoder, musimy zrozumieć, co robią parametry klatki kluczowej. Zrobiłem kilka testów i odkryliśmy, na potrzeby trzech przetworników libx264, libx265a libvpx-vp9w FFmpeg:

  • libx264:

    • -g ustawia interwał klatek kluczowych.
    • -keyint_min ustawia minimalny interwał klatek kluczowych.
    • -x264-params "keyint=x:min-keyint=y"jest taki sam jak -g x -keyint_min y.
    • Uwaga: Przy ustawianiu obu na tę samą wartość, minimum jest wewnętrznie ustawione na połowę maksymalnego interwału plus jeden, jak widać w x264kodzie:

      h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
      
  • libx265:

    • -g nie jest zaimplementowany.
    • -x265-params "keyint=x:min-keyint=y" Prace.
  • libvpx-vp9:

    • -g ustawia interwał klatek kluczowych.
    • -keyint_min ustawia minimalny interwał klatek kluczowych
    • Uwaga: Z powodu działania FFmpeg -keyint_minjest przesyłany do enkodera tylko wtedy, gdy jest taki sam jak -g. W kodzie z libvpxenc.cFFmpeg możemy znaleźć:

      if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
          enccfg.kf_min_dist = avctx->keyint_min;
      if (avctx->gop_size >= 0)
          enccfg.kf_max_dist = avctx->gop_size;
      

      Może to być błąd (lub brak funkcji?), Ponieważ libvpxzdecydowanie obsługuje ustawienie innej wartości kf_min_dist.

Powinieneś użyć -force_key_frames ?

-force_key_framesOpcja przymusowo wstawia klatki kluczowe w danym przedziale (wyrażenie). Działa to dla wszystkich koderów, ale może zepsuć się z mechanizmem kontroli prędkości. Zwłaszcza w przypadku VP9 zauważyłem poważne fluktuacje jakości, więc nie mogę zalecić używania go w tym przypadku.

slhck
źródło
Dziękuję Ci! To świetna opinia. Jedno z moich pytań dotyczy tego, jak wygenerowałeś ten niesamowity stół. Mógłbym całkowicie użyć czegoś takiego.
Mark Gerolimatos
(Wydaje się, że nie ma sposobu, aby napisać do ciebie bezpośrednio) Czy możesz wskazać mi linki do jakichkolwiek wątków w tej dyskusji ITU-T? Dzięki!
Mark Gerolimatos
2
Właśnie to zrobiłem w Excelu, wklejając dane wyjściowe z trzech serii ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_type, a następnie kolorując komórki. Obawiam się, że nie ma publicznych dyskusji, ale zobaczę, czy uda mi się wykopać niektóre linki, które wtedy znalazłem.
slhck 30.04.15
Czy możesz ponownie spróbować eksperymentu z -force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)formularzem? Właśnie go wypróbowałem i odkryłem, że chociaż w strumieniu były dodatkowe ramki I, wydaje się, że DID przestrzega mojej reguły. Program PERL pojawi się jako „odpowiedź”, ponieważ najwyraźniej nie można używać znaczników w komentarzach.
Mark Gerolimatos
Ciekawy. Uważam, że warto osobną „prawdziwą” odpowiedź, jeśli dowiesz się, że to działa. (Witryny stosu wymiany nie są naprawdę dobre dla tej odpowiedzi w stylu dyskusji). Ostatnim razem, gdy sprawdziłem, -force_key_framesnie działało dla mnie, więc nigdy więcej nie spróbowałem. To było ponad rok temu. Być może był to błąd. Spróbuję wkrótce.
slhck
12

Oto moje pięćdziesiąt centów za tę sprawę.

Metoda 1:

mieszanie się z argumentami libx264

-c: v libx264 -x264opts keyint = GOPSIZE: min-keyint = GOPSIZE: scenecut = -1

Generuj iframe tylko w pożądanych odstępach czasu.

Przykład 1:

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-x264opts "keyint=48:min-keyint=48:no-scenecut" \
-c:a copy \
-y test_keyint_48.mp4

Wygeneruj iframe zgodnie z oczekiwaniami:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
961         40
1009        42
1057        44
1105        46
1153        48
1201        50
1249        52
1297        54
1345        56
1393        58

Metoda 2 jest amortyzowana. Ommitted.

Metoda 3:

wstaw klatkę kluczową co N sekund (MAYBE):

-force_key_frames expr: gte (t, n_forced * GOP_LEN_IN_SECONDS)

Przykład 2

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-force_key_frames "expr:gte(t,n_forced*2)"
-c:a copy \
-y test_fkf_2.mp4

Wygeneruj iframe w nieco inny sposób:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
519         21.58333333
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
931         38.75
941         39.16666667
961         40
1008        42
1056        44
1104        46
1152        48
1200        50
1248        52
1296        54
1305        54.375
1344        56
1367        56.95833333
1392        58
1430        59.58333333
1440        60
1475        61.45833333
1488        62
1536        64
1544        64.33333333
1584        66
1591        66.29166667
1632        68
1680        70
1728        72
1765        73.54166667
1776        74
1811        75.45833333
1824        75.95833333
1853        77.16666667
1872        77.95833333
1896        78.95833333
1920        79.95833333
1939        80.75
1968        81.95833333

Jak widać, umieszcza iframe co 2 sekundy ORAZ w scenecut (sekundy z częścią ruchomą), co moim zdaniem jest ważne dla złożoności strumienia wideo.

Rozbierane rozmiary plików są prawie takie same. Bardzo dziwne, że nawet przy większej liczbie klatek kluczowych w Metodzie 3 generuje czasem mniej plików niż standardowy algorytm biblioteki x264.

Do generowania wielu plików bitrate dla strumienia HLS wybieramy metodę trzecią. Jest idealnie wyrównany z 2 sekundami między częściami, mają one iframe na początku każdej części i mają dodatkowe iframe w złożonych scenach, co zapewnia lepsze wrażenia dla użytkowników, którzy mają nieaktualne urządzenia i nie mogą odtwarzać wysokich profili x264.

Mam nadzieję, że to komuś pomoże.

Ara Saahov
źródło
Fantastycznie, dziękuję za twoje 50 centów!
BrunoFenzl,
7

Wydaje się zatem, że odpowiedź brzmi:

  • Metoda 1 została zweryfikowana pod libx264kątem działania, ale jest specyficzna i wiąże się z nią koszt wyeliminowania bardzo przydatnej scenecutopcji w libx264.
  • Metoda 3 działa od wersji FFMPEG z kwietnia 2015 r., Ale należy zweryfikować wyniki za pomocą skryptu zawartego na dole tego postu, ponieważ dokumentacja FFMPEG nie jest jasna co do efektu tej opcji. Jeśli to działa, jest lepszy od dwóch opcji.
  • NIE UŻYWAJ metody 2, -gwydaje się być przestarzała. Wydaje się, że nie działa, ani nie jest wyraźnie zdefiniowany w dokumentacji, ani nie znajduje się w pomocy, ani nie wydaje się, aby był używany w kodzie. Kontrola kodu pokazuje, że ta -gopcja jest prawdopodobnie przeznaczona dla strumieni MPEG-2 (istnieją nawet zwrotki kodu odnoszące się do PAL i NTSC!).

Również:

  • Pliki generowane metodą 3 mogą być nieco większe niż metoda 1, ponieważ dozwolone są ramki pełnoekranowe I (klatki kluczowe).
  • Powinieneś jawnie ustawić flagę „-r” w obu przypadkach, mimo że Metoda 3 umieszcza ramkę I w następnej szczelinie klatek w dniu lub później określonym czasie . Brak ustawienia flagi „-r” stawia na łasce pliku źródłowego, być może ze zmienną liczbą klatek na sekundę. Może to spowodować niekompatybilne przejścia DASH.
  • Pomimo ostrzeżeń w dokumentacji FFMPEG, metoda 3 NIE jest mniej wydajna niż inne. W rzeczywistości testy pokazują, że może być nieco WIĘCEJ wydajniejszy niż metoda 1.

Skrypt dla -force_key_framesopcji

Oto krótki program PERL, którego użyłem do weryfikacji kadencji I-frame na podstawie wyniku sugestii ffprobe z slhck. Wydaje się, że sprawdza, czy -force_key_framesmetoda będzie również działać, i ma dodatkową zaletę polegającą na umożliwieniuscenecut ramki. Absolutnie nie mam pojęcia, jak FFMPEG sprawia, że ​​to działa, czy po prostu jakoś mi się poszczęściło, ponieważ moje transmisje są dobrze warunkowane.

W moim przypadku zakodowałem przy 30 klatkach na sekundę z oczekiwanym rozmiarem GOP wynoszącym 6 sekund lub 180 klatek. Użyłem 180 jako argumentu gopsize dla tego programu, który weryfikował ramkę I przy każdej wielokrotności 180, ale ustawienie jej na 181 (lub dowolną inną liczbę nie będącą wielokrotnością 180) spowodowało, że narzeka.

#!/usr/bin/perl
use strict;
my $gopsize = shift(@ARGV);
my $file = shift(@ARGV);
print "GOPSIZE = $gopsize\n";
my $linenum = 0;
my $expected = 0;
open my $pipe, "ffprobe -i $file -select_streams v -show_frames -of csv -show_entries frame=pict_type |"
        or die "Blah";
while (<$pipe>) {
  if ($linenum > $expected) {
    # Won't catch all the misses. But even one is good enough to fail.
    print "Missed IFrame at $expected\n";
    $expected = (int($linenum/$gopsize) + 1)*$gopsize;
  }
  if (m/,I\s*$/) {
    if ($linenum < $expected) {
      # Don't care term, just an extra I frame. Snore.
      #print "Free IFrame at $linenum\n";
    } else {
      #print "IFrame HIT at $expected\n";
      $expected += $gopsize;
    }
  }
  $linenum += 1;
}
Mark Gerolimatos
źródło
Tylko uwaga: ponieważ jest to strona z pytaniami i odpowiedziami, a nie forum dyskusyjne, na którym posty są uporządkowane chronologicznie, najlepiej umieścić wszystkie informacje w jednej odpowiedzi, aby osoby szukające rozwiązania musiały przeczytać jeden post i nie patrzeć o tym, kto opublikował co, kiedy :) Połączyłem twoje odpowiedzi i dałem ci +1 w tym. Ponieważ krzyżowanie postów jest niedozwolone , radzę usunąć swoje pytanie z witryny wideo. Ludzie znajdą tutaj odpowiedzi.
slhck
1
Miałem jeszcze jedną myśl (tak naprawdę została podniesiona na liście mailingowej FFmpeg). Kiedy używasz force_key_frames, to w pewnym sensie psuje algorytm alokacji bitów x264, więc może dać gorszą jakość niż po prostu ustawienie stałego interwału klatki kluczowej.
slhck
O kurczę. Jeszcze jeden powód, dla którego FFMPEG zapewnia nieswoisty kodek, aby to zrobić, argument, który „zrobiłby najlepszą rzecz dla danego kodeka”. Próbowałem złożyć zgłoszenie do tego ze śledzeniem FFMPEG, ale odbiło się :-(
Mark Gerolimatos
@slhck: Czy możesz podać więcej szczegółów? Przeglądałem archiwa listy mailowej w maju 2015 roku, ale nic nie znalazłem. Najważniejsze byłoby zapomnieć o „metodzie 3” i trzymać się „metody 1”.
schieferstapel
3
@MarkGerolimatos: o -g, mówisz: „Wygląda na to, że nie działa, ... ani nie wydaje się, aby był używany w kodzie”. Sprawdziłem i wejście gjest przechowywany w avctx->gop_sizei że libx264 korzysta z niego: x4->params.i_keyint_max = avctx->gop_size;. Kiedy sonduję ten wygenerowany plik testowy: ffmpeg -i a-test-file.mp4 -g 37 -t 15 gtest.mp4otrzymuję klatki kluczowe dokładnie 0,37,74,111,148,185,222,259,296,333,370. GOP może zostać skrócony, jeśli nastąpi zmiana sceny, i -sc_thresholdmożna to ustawić, co jest również wychwytywane przez x264.
Gyan
4

Chciałem tutaj dodać trochę informacji, ponieważ mój googling dość mocno przywołał tę dyskusję w mojej próbie znalezienia informacji o próbie znalezienia sposobu na segmentację mojego kodowania DASH tak, jak chciałem, i żadna z tych informacji nie była całkowicie poprawna.

Najpierw kilka nieporozumień, aby pozbyć się:

  1. Nie wszystkie I-ramki są takie same. Istnieją duże ramki „I” i małe ramki „I”. Lub użyć poprawnej terminologii, ramek I IDR i ramek I innych niż IDR. Ramki I IDR (czasami nazywane „klatkami kluczowymi”) utworzą nowy GOP. Ramki inne niż IDR nie będą. Są przydatne, aby mieć wewnątrz GOP, gdzie następuje zmiana sceny.

  2. -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE← To nie robi tego, co myślisz. Zajęło mi to trochę czasu. Okazuje się, min-keyintże kod jest ograniczony. Nie może być większy niż (keyint / 2) + 1. Tak więc przypisanie tej samej wartości do tych dwóch zmiennych skutkuje wartością min-keyintprzewróconą o połowę podczas kodowania.

Oto rzecz: wycinanie scen jest naprawdę świetne, szczególnie w filmach z szybkimi cięciami. To sprawia, że ​​jest ładny i wyraźny, więc nie chcę go wyłączać, ale jednocześnie nie mogłem uzyskać ustalonego rozmiaru GOP, dopóki był włączony. Chciałem włączyć wycinanie scen, ale chcę, aby używało tylko ramek I bez IDR. Ale to nie działało. Dopóki nie zorientowałem się (z wielu lektur) o nieporozumieniu # 2.

Okazuje się, że musiałem ustawić keyintpodwoić mój pożądany rozmiar GOP. To znaczy żemin-keyint można ustawić żądany rozmiar GOP (bez wewnętrznego kodu dzielącego go na pół), co zapobiega wykrywaniu sceny przy użyciu ramek I IDR wewnątrz rozmiaru GOP, ponieważ liczba klatek od ostatniej ramki I IDR zawsze mniej niż min-keyinit.

I wreszcie ustawienie force_key_frameopcji zastępuje podwójny rozmiarkeyint . Oto co działa:

Wolę segmenty w 2-sekundowych porcjach, więc mój GOPSIZE = Framerate * 2

ffmpeg <other_options> -force_key_frames "expr:eq(mod(n,<GOPSIZE>),0)" -x264opts rc-lookahead=<GOPSIZE>:keyint=<GOPSIZE * 2>:min-keyint=<GOPSIZE> <other_options>

Możesz zweryfikować za pomocą ffprobe:

ffprobe <SRC_FLE> -select_streams v -show_frames -of csv -show_entries frame=coded_picture_number,key_frame,pict_type > frames.csv

W wygenerowanym pliku CSV każda linia powie frame, [is_an_IDR_?], [frame_type], [frame_number]:

frame,1,I,60  <-- frame 60, is I frame, 1 means is an IDR I-frame (aka KeyFrame)
frame,0,I,71  <-- frame 71, is I frame, 0 means not an IDR I_frame

Powoduje to, że powinieneś widzieć I-ramki IDR tylko w ustalonych GOPSIZEodstępach czasu, podczas gdy wszystkie inne ramki I są ramkami I innymi niż IDR wstawionymi w razie potrzeby przez wykrywanie wycięcia sceny.

Reuben
źródło
to było fantastyczne! To było bardzo sprzeczne z intuicją, dziękuję za włożenie wysiłku. Podsumowując, zakładam, że twoja definicja „I-ramek” i „i-ramek” jest pojęciowa (to znaczy nie jest jednoznacznie konfigurowalna w libx264) i że „max * 2” było tym, w jaki sposób je egzekwowałeś?
Mark Gerolimatos
Tak, to było pojęciowe, chociaż widziałem, jak ludzie używają „I” vs „i”, aby odróżnić I-ramki IDR od nie-IDR. I tak, ustawienie keyinit na pożądany rozmiar gop * 2 jest sposobem na wymuszenie, aby wszystkie ramki I wewnątrz gop były ramkami I bez IDR. Następnie ffmpeg -force-key-frames zastępuje key-init w x264opts. Zasadniczo jest to naprawdę wsteczny sposób, aby uzyskać pożądany wynik, który byłby możliwy, gdyby kod x264 pozwalał ci ustawić min-keyinit i keyinit na tę samą wartość.
Reuben
... jednocześnie będąc w stanie utrzymać wykrywanie wycięcia sceny włączone i uzyskać ustalony rozmiar GOP.
Reuben
jeszcze raz dziękuję za wspaniałą pracę! Wygląda na to, że potrzebujemy mniej „wstecznego”
efektu
Czy jest tu potrzebny rc-lookahead? Wpływa na mbtree i VBV, ale czy wpływa na generowanie i-frame?
Alexander Svetkin
0

Wygląda na to, że ta składnia nie zawsze działa. Testowałem całkiem sporo na naszej zawartości VOD, jak również na żywo (zrzuty plików), a czasami scenecut nie działa i wyzwala pomiędzy nimi iframe:

Składnia dla konwersji w górę i50-> p50, 2 sek. Gop / segment, IDR na początku, iframe pomiędzy nimi w razie potrzeby

ffmpeg.exe -loglevel verbose -i avc_50i.ts -pix_fmt yuv420p -filter_complex yadif=1,scale=1920:1080 -vcodec libx264 -preset fast -x264-params "rc-lookahead=100:keyint=200:min-keyint=100:hrd=1:vbv_maxrate=12000:vbv_bufsize=12000:no-open-gop=1" -r 50 -crf 22 -force_key_frames "expr:eq(mod(n,100),0)" -codec:a aac -b:a 128k -y target.ts
TEB
źródło
0

Twitch ma post na ten temat. Wyjaśniają, że postanowili skorzystać z własnego programu z kilku powodów; jednym z nich było to, że ffmpeg nie pozwala na uruchamianie różnych instancji x264 w różnych wątkach, ale zamiast tego poświęca wszystkie określone wątki jednej ramce na jednym wyjściu przed przejściem do następnego.

Jeśli nie korzystasz z transmisji strumieniowej w czasie rzeczywistym, masz więcej luksusu. „Prawidłowym” sposobem jest prawdopodobnie zakodowanie w jednej rozdzielczości tylko z rozmiarem GOP określonym za pomocą -g, a następnie zakodowanie innych rozdzielczości wymuszających klatki kluczowe w tych samych miejscach.

Jeśli chcesz to zrobić, możesz użyć ffprobe, aby uzyskać czasy klatki kluczowej, a następnie użyć skryptu powłoki lub rzeczywistego języka programowania, aby przekonwertować to na polecenie ffmpeg.

Jednak w przypadku większości treści różnica między jedną klatką kluczową co 5 sekund a dwiema klatkami kluczowymi co 5 sekund jest bardzo niewielka (jedna wymuszona, a druga ze scenariusza). Jest to około średniego rozmiaru ramki I w porównaniu do rozmiaru ramek P i ramek B. Jeśli używasz x264 z typowymi ustawieniami (jedyny powód, dla którego uważam, że powinieneś zrobić cokolwiek, aby na nie wpłynąć, to ustawienie -qmin, jako zły sposób na zapobieganie używaniu bitrate x264 dla łatwej zawartości; ogranicza to wszystkie typy ramek do tej samej wartości , Tak myślę) i uzyskaj wynik, taki jak średni rozmiar ramki I wynoszący 46 kB, ramkę P 24 kB, ramkę B 17 kB (o połowę częściej niż ramki P), a następnie dodatkową ramkę I co sekundę przy 30 fps to tylko 3% wzrost rozmiaru pliku. Różnica między h264 i h263 może składać się z 3% spadków, ale pojedynczy nie jest bardzo ważny.

W przypadku innych rodzajów treści rozmiary ramek będą się różnić. Szczerze mówiąc, chodzi o złożoność czasową, a nie złożoność przestrzenną, więc nie jest to po prostu łatwa zawartość a twarda treść. Ale ogólnie rzecz biorąc, witryny wideo z transmisją strumieniową mają limit bitrate, a treść ze stosunkowo dużymi ramkami I jest łatwą treścią, która będzie kodowana w wysokiej jakości bez względu na to, ile dodatkowych klatek kluczowych zostanie dodanych. To marnotrawstwo, ale marnotrawstwo zwykle nie zostanie zauważone. Najbardziej marnotrawnym przypadkiem jest prawdopodobnie wideo, które jest statycznym obrazem towarzyszącym utworowi, w którym każda klatka kluczowa jest dokładnie taka sama.

Jednej rzeczy, której nie jestem pewien, to jak wymuszone klatki kluczowe współdziałają z ogranicznikiem prędkości ustawionym za pomocą opcji -maxrate i -bufsize. Myślę, że nawet YouTube miał ostatnio problemy z prawidłową konfiguracją ustawień bufora, aby zapewnić stałą jakość. Jeśli używasz tylko średnich ustawień szybkości transmisji bitów, co widać na niektórych stronach (ponieważ możesz sprawdzić opcje x264 w nagłówku / mov atom? Za pomocą edytora szesnastkowego), to model bufora nie stanowi problemu, ale jeśli jesteś wyświetlając treści generowane przez użytkowników, średnia szybkość transmisji zachęca użytkowników do dodania czarnego ekranu na końcu filmu.

Opcja -g Ffmpeg lub dowolna inna używana opcja enkodera jest mapowana na opcję specyficzną dla enkodera. Zatem „-x264-params keyint = GOPSIZE” jest równoważne „-g GOPSIZE”.

Jednym z problemów z używaniem wykrywania scen jest to, że wolisz klatki kluczowe w pobliżu określonych liczb z jakiegokolwiek powodu. Jeśli określisz klatki kluczowe co 5 sekund i użyjesz wykrywania scen, a nastąpi zmiana sceny na 4.5, to powinna zostać wykryta, ale następna klatka kluczowa będzie na 9.5. Jeśli czas będzie się zwiększał w ten sposób, możesz skończyć z klatkami kluczowymi w 42,5, 47,5, 52,5 itd. Zamiast 40, 45, 50, 55. I odwrotnie, jeśli nastąpi zmiana sceny w 5.5, to będzie klatka kluczowa w 5 i 5,5 będzie za wcześnie na kolejną. Ffmpeg nie pozwala na określenie „utwórz tutaj klatkę kluczową, jeśli nie nastąpi zmiana sceny w ciągu następnych 30 klatek”. Jednak ktoś, kto rozumie C, może dodać tę opcję.

W przypadku wideo o zmiennej liczbie klatek na sekundę, gdy nie korzystasz z transmisji strumieniowej na żywo, takiej jak Twitch, powinieneś być w stanie korzystać ze zmian scen bez ciągłej konwersji na stałą częstotliwość klatek. Jeśli użyjesz filtru „select” w ffmpeg i użyjesz stałej „scene” w wyrażeniu, wówczas dane wyjściowe debugowania (-v debugowania lub naciśnij kilkakrotnie „+” podczas kodowania) pokazują numer zmiany sceny. Prawdopodobnie różni się to od liczby używanej przez x264 i nie jest tak przydatne, ale może być nadal przydatne.

Procedura prawdopodobnie polegałaby na zrobieniu filmu testowego, który dotyczyłby tylko zmian klatki kluczowej, ale może być wykorzystany do kontroli prędkości transmisji danych, jeśli używany jest 2-przebieg. (Nie jestem pewien, czy wygenerowane dane są w ogóle przydatne dla różnych rozdzielczości i ustawień; dane drzewa makrobloków nie będą.) Konwertuj je na wideo o stałej szybkości klatek, ale zobacz ten błąd dotyczący zacinania się wyjścia podczas zmniejszania liczby klatek na sekundę, jeśli kiedykolwiek zdecydujesz użyć filtra fps do innych celów. Uruchom go przez x264 z wybraną klatką kluczową i ustawieniami GOP.

Następnie użyj tych czasów klatek kluczowych z oryginalnym wideo o zmiennej liczbie klatek na sekundę.

Jeśli dopuścisz całkowicie szaloną zawartość generowaną przez użytkownika z 20-sekundową przerwą między ramkami, to w przypadku kodowania ze zmienną liczbą klatek na sekundę możesz podzielić dane wyjściowe, użyć filtra fps, w jakiś sposób użyć filtra select (być może zbudować naprawdę długie wyrażenie, które ma za każdym razem klatki kluczowej) ... a może możesz użyć testowego wideo jako wejścia i albo dekodować tylko klatki kluczowe, jeśli ta opcja ffmpeg działa, lub użyj filtra wyboru, aby wybrać klatki kluczowe. Następnie przeskaluj go do odpowiedniego rozmiaru (istnieje nawet filtr scale2ref) i nałóż na niego oryginalny film. Następnie użyj filtra przeplotu, aby połączyć te przeznaczone do wymuszenia klatki kluczowe z oryginalnym wideo. Jeśli wynikiem tego są dwie ramki, które są w odległości 0,001 s od siebie, że filtr przeplotu nie zapobiega, rozwiąż ten problem sam z innym wybranym filtrem. Głównym problemem może być obsługa limitów bufora ramki dla filtra przeplotu. Wszystko to może działać: użyć jakiegoś filtra do buforowania gęstszego strumienia (filtr FIFO?); odwołać się do pliku wejściowego wiele razy, więc jest dekodowany więcej niż jeden raz, a ramki nie muszą być przechowywane; użyj filtru „streamselect”, czego nigdy wcześniej nie robiłem, dokładnie w czasach klatek kluczowych; popraw filtr przeplotu, zmieniając jego domyślne zachowanie lub dodając opcję wyświetlania najstarszej ramki w buforze zamiast upuszczania ramki. czego nigdy nie zrobiłem, dokładnie w czasach klatek kluczowych; popraw filtr przeplotu, zmieniając jego domyślne zachowanie lub dodając opcję wyświetlania najstarszej ramki w buforze zamiast upuszczania ramki. czego nigdy nie zrobiłem, dokładnie w czasach klatek kluczowych; popraw filtr przeplotu, zmieniając jego domyślne zachowanie lub dodając opcję wyświetlania najstarszej ramki w buforze zamiast upuszczania ramki.

Misaki
źródło