Zmień ilość klatek na sekundę w ffmpeg bez ponownego kodowania

14

Mam wideo mkv (h264), które ma 23,976 fps (24000/1001), ale chcę przekonwertować je na 25 fps bez ponownego kodowania i utraty jakości. Wiem, że mkvmerge może to zrobić (z opcją --default-duration '0: 25fps'), ale chciałbym to zrobić bezpośrednio z ffmpeg, jeśli to możliwe. Według dokumentów to powinno działać:

ffmpeg -i input.mkv -r 25 -vcodec copy output.mkv

ale kiedy go wykonuję, dostaję tylko te same fps wideo. Jaka jest poprawna metoda, aby to zrobić (jeśli istnieje) w ffmpeg?

phate89
źródło
1
Uważam, że obecnie nie jest to możliwe z FFmpeg. -rnie jest zgodny z funkcją kopiowania strumienia i nie ma filtrów strumienia bitów, które zmieniłyby szybkość klatek.
Ely,
1
szkoda. Będę musiał używać mkvmerge za każdym razem. dzięki
phate89,
1
Istnieje skomplikowany sposób, aby to zrobić za pomocą zwykłej wersji ffmpeg i bezpośredni sposób, aby to zrobić za pomocą starej, zmodyfikowanej wersji ffmpeg. Jeśli jesteś zainteresowany, napiszę to jako odpowiedź.
Gyan
1
Tak, dziękuję. Chciałbym to zrobić bez dodatkowych narzędzi (już potrzebuję ffmpeg)
phate89,
1
@Mulvya, mówisz o tym, prawda? Wahałem się, czy go połączyć, ale teraz jest już stary. Zainteresowany zawiłym sposobem na zrobienie tego ze zwykłym FFmpeg.
Ely,

Odpowiedzi:

15

Oto metoda wykorzystująca bieżące wersje FFmpeg. Polega on na tym, że demultiplekser konkat nie przeskalowuje PTS danych wejściowych po pierwszym pliku, ale po prostu stosuje stałe przesunięcie. Załóżmy, że masz strumień 30 fps ze skalą czasu 15360(typową dla wyjścia FFmpeg). Oznacza to, że ramka 0ma PTS, 0a ramka 30ma PTS 15360. Byłby to strumień 45 fps, gdybyśmy mogli zmienić skalę czasu na 23040bez wpływu na wartości PTS.

Zasadniczo właśnie to robi poniższa metoda.

1 . Zidentyfikuj właściwości źródła.

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s,
       30 fps, 30 tbr, 15360 tbn (default)

Chcesz zwrócić uwagę na właściwości źródła, zwłaszcza rozdzielczość i tbn.


2a . (Opcjonalnie) Zmień skalę czasową na wygodną, ​​aby ułatwić obliczenia.

ffmpeg -i in.mp4 -c copy -an -video_track_timescale 30 in-v30.mp4

To nas dopada

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s, \
       30 fps, 30 tbr, 30 tbn (default

Jeśli wykonasz ten krok, nowa skala czasu powinna być równa lub stanowić całkowitą wielokrotność pierwotnej liczby klatek na sekundę.

2b . Oblicz potrzebną skalę czasu, aby dla docelowej prędkości klatek xPTS ramki nr xw źródle miał taką samą wartość jak nowy tbn. Jeśli wykonałeś krok 2a, jest to bardzo łatwe i jest to po prostu nowa liczba klatek na sekundę. Tak więc dla docelowego fps powinno być 45nowe .tbn45


3 . Wygeneruj atrapę wideo.

ffmpeg -f lavfi -i color=s=1280x720:r=45:d=1 -profile:v main -video_track_timescale 45 0.mp4

Wszystkie właściwości powinny być takie same jak rozdzielczość, profil H.264, format pikseli, liczba odwołań .. etc dla uzyskania najlepszych wyników.


4 Połącz filmy.

Najpierw utwórz plik tekstowy

file '0.mp4'
file 'in-v30.mp4'

Następnie konkat

ffmpeg -f concat -i list.txt -c copy -video_track_timescale 45 45fps.mp4

Plik wyjściowy będzie odtwarzany 2. wideo przy 45 fps.

5 . Teraz odetnij manekin

ffmpeg -ss 1.1 -i 45fps.mp4 -c copy -avoid_negative_ts make_zero in45.mp4

i Ty masz

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1757 kb/s, \
       45 fps, 45 tbr, 11520 tbn (default)

Powiedziałem, że to było zawiłe!

Gyan
źródło
1
bardzo sprytna, dobra odpowiedź.
Rowe Morehouse,