Chcę zakodować po wyszukaniu określonej pozycji i chcę, aby pierwsza klatka była klatką kluczową, tutaj użyłem polecenia:
ffmpeg -ss 300 -i howimet.mp4 -acodec libfaac -ar 48000 -ab 128k -ac 2 -vcodec libx264 -vf "scale=480:270" -f mpegts -force_key_frames 300 -t 120 howimet2.ts
-force_key_frames jest ustawiony na szukanie pozycji, aby utworzyć tam klatkę kluczową. Używam następującego skryptu ( stąd ), aby sprawdzić, czy pierwsza klatka jest klatką kluczową
ffprobe -show_frames -v quiet howimet2.ts | awk -F= ' /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } }
/pkt_pts_time/ { if (i && ($2 >= 0)) print $2; }
' | head -n 1
Wynik pokazuje, że pierwsza klatka kluczowa nie jest zlokalizowana w drugim 0.
Wydaje mi się, że moje polecenie jest nieprawidłowe. czego mi brakuje?
-force_key_frames
powinno być względne w stosunku do danych wejściowych, więc 300 też nie ma sensu - powinno być 0, jeśli się nie mylę. Czy wideo jest w porządku, czy dlaczego pytasz? (Innymi-force_key_frames 0
. Powodem, dla którego tego chcę, jest implementacja segmentatora ffmpeg, który będzie generował segment HSL w locie. Gdy użytkownik szuka pozycji, segmentator powinien być w stanie wygenerować odpowiedni segment; segment zostanie wysłany do odtwarzacza klienta (odtwarzacz filmów na iOS); domyślnie odtwarzacz rozpocznie odtwarzanie od pierwszej klatki kluczowej w odebranym segmencie. Chcę, aby gracz zaczął grać od pierwszej klatki. Mam nadzieję, że moje wyjaśnienie ma sens-vcodec libx264
, FFmpeg zrobi to, co otrzyma zdekodowane zdjęcie, poda je do x264, a pierwszą rzeczą, którą zrobi x264, jest utworzenie klatki kluczowej. Nie można rozpocząć filmu z ramką bez odniesienia. Jeśli ręcznie sprawdzisz wynikffprobe
, co to powie o pierwszej ramce?ffprobe -v quiet -print_format json -show_streams howimet2.ts
mówi mi to"start_time": "1.400000"
, czy to jest powód?Odpowiedzi:
Podczas kodowania wideo pierwsza klatka musi być klatką kluczową. Będzie to pierwsza w pełni zakodowana, a kolejne ramki mogą jej używać do przewidywania między ramkami. Ponadto na początku zakodowanej sekwencji wideo będzie dostępna jednostka dostępu H.264, która nakazuje dekoderowi odświeżenie.
Niezależnie od tego, co robisz: chyba że skopiujesz strumień bitów, ponownie kodujesz wideo, a Twoja pierwsza klatka musi być klatką kluczową.
Teraz, z jakiegokolwiek powodu, twój strumień ma przesunięcie w czasie rozpoczęcia. Oznacza to, że wszystkie znaczniki czasu prezentacji są również przesuwane zgodnie z tym przesunięciem. Jeśli sprawdzisz nagłówek
ffprobe -show_frames
wyjścia, zobaczysz, że klatka 0 rzeczywiście będzie klatką kluczową, ale z innym PTS.Aby to zrekompensować, możesz odjąć czas rozpoczęcia od wszystkich PTS.
źródło
Jak wspomniano, pierwszą klatką filmu musi być I-Frame. Twój problem pochodzi nie z kodowania (lub kopiowania, jeśli taki jest twój gust), ale z dekodowania. Posiadanie -ss przed wejściem jest niedokładne, więc ffmpeg robi wszystko, co w jego mocy, aby dostać się tam, gdzie chcesz. Ffmpeg przekazał tę lokalizację, a zatem podaje niezerowy pierwszy znacznik czasu.
Poleciłbym wypróbowanie drugiego -ss po twoim -i. Wzdłuż linii -ss 299 -i wpisz -ss 1.
Oznacza to, że przejdź do wybranej lokalizacji, a następnie dekoduj przez 1 sekundę przed przetworzeniem. Nie jestem pewien, czy to rozwiąże problem z pts, ale mam nadzieję, że poprowadzi cię we właściwym kierunku.
Aby wskazać, nie sądzę, że polecenie force_key_frames robi to, co myślisz. Jeśli coś robi, prawdopodobnie po prostu każe mu dodawać klatkę kluczową do wyjścia co 300 sekund, ale to tylko przypuszczenie. Oznacza to, że tylko pierwsza ramka wyniku byłaby ramką kluczową (t = 120).
https://ffmpeg.org/ffmpeg.html
źródło
Ustaw rozmiar GOP za pomocą „-g”
Aby pokazać dokładność, oto 1-sekundowy segment
Oto jak wygląda m3u8:
źródło