Изменить частоту кадров в ffmpeg без перекодирования

14

У меня есть видео mkv (h264), которое составляет 23,976 к / с (24000/1001), но я хочу преобразовать его в 25 к / с без перекодирования и потери качества. Я знаю, что mkvmerge может это сделать (с опцией --default-duration '0: 25fps'), но я бы хотел сделать это напрямую из ffmpeg, если это возможно. Согласно документации это должно работать:

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

но когда я выполняю его, я получаю только те же кадры видео в секунду. Какой правильный способ сделать это (если существует) в ffmpeg?

phate89
источник
1
Я считаю, что это невозможно с FFmpeg на данный момент. -rнесовместим с потоковым копированием, и нет битовых фильтров для изменения частоты кадров.
Ely
1
жаль. Мне придется использовать mkvmerge каждый раз. спасибо
phate89
1
Существует запутанный способ сделать это с помощью обычного ffmpeg и прямой способ сделать это со старой модифицированной версией ffmpeg. Если вам интересно, я напишу это как ответ.
Гьян
1
Да, спасибо .. Я хотел бы сделать это без дополнительных инструментов (мне уже нужен ffmpeg)
phate89
1
@ Мульвя, ты говоришь об этом, верно? Я не решался связать это, но сейчас оно старое. Заинтересован в замысловатом способе сделать это с обычным FFmpeg.
Ely

Ответы:

15

Вот метод, использующий текущие версии FFmpeg. Он опирается на демультиплексор concat, который не пересчитывает PTS входов после первого файла, а просто применяет фиксированное смещение. Допустим, у вас есть поток 30 кадров в секунду с временной шкалой 15360(типично для вывода FFmpeg). Это означает, что у кадра 0есть PTS, 0а у кадра 30- PTS 15360. Это стало бы потоком в 45 кадров в секунду, если бы мы могли изменить шкалу времени, 23040не влияя на значения PTS.

По сути, это то, что делает метод ниже.

1 . Определите исходные свойства.

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

Вы хотите отметить свойства источника, особенно разрешение и tbn.


. (Необязательно) Измените шкалу времени на более удобную, чтобы упростить вычисления.

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

Это нас заводит

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

Если вы выполните этот шаг, новая шкала времени должна быть равна или кратна исходной частоте кадров.

. Вычислите необходимую временную шкалу, чтобы для целевой частоты кадров xPTS кадра # xв источнике имел то же значение, что и новый tbn. Если вы выполнили шаг 2а, это очень просто, и это просто новая частота кадров. Таким образом, для целевых кадров в секунду 45, новое tbnдолжно быть 45.


3 . Генерация фиктивного видео.

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

Все свойства должны быть такими же, как разрешение, профиль H.264, формат пикселей, количество ссылок ... и т. Д. Для достижения наилучших результатов.


4 Конкат видео.

Сначала создайте текстовый файл

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

Затем конкат

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

Выходной файл будет иметь второе видео, воспроизводимое со скоростью 45 кадров в секунду.

5 . Теперь отколоть манекен preroll

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

и у тебя есть

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

Я сказал, что это было запутанным!

Gyan
источник
1
очень умный, хороший ответ.
Роу