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

14917
phate89

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

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

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

8
Я считаю, что это невозможно с FFmpeg на данный момент. `` `-r``` несовместимо с потоковым копированием, и нет никаких фильтров битового потока для изменения частоты кадров. Ely 7 лет назад 1
очень плохо. Мне придется использовать mkvmerge каждый раз. Спасибо phate89 7 лет назад 1
Существует запутанный способ сделать это с помощью обычного ffmpeg, а прямой способ сделать это со старой модифицированной версией ffmpeg. Если вам интересно, я напишу это как ответ. Gyan 7 лет назад 1
Да, спасибо .. Я хотел бы сделать это без дополнительных инструментов (мне уже нужен ffmpeg) phate89 7 лет назад 1
@ Мульвя, ты говоришь об этом (http://forum.doom9.org/showthread.php?t=152419), верно? Я не решался связать это, но сейчас оно старое. Заинтересован в замысловатом способе сделать это с обычным FFmpeg. Ely 7 лет назад 1
Да, это тот Ответ с запутанным методом добавил. Gyan 7 лет назад 1

1 ответ на вопрос

8
Gyan

Here's the method using current versions of FFmpeg. It relies on the concat demuxer not rescaling the PTS of inputs after the first file, but simply applying a fixed offset. Let's say you have a 30 fps stream with a timescale of 15360 (typical of FFmpeg output). That means frame 0 has PTS 0 and frame 30 has PTS 15360. This would become a 45 fps stream if we could change the timescale to 23040 without affecting the PTS values.

Essentially, that's what the method below does.

1. Identify the source properties.

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

You want to note the source properties, especially resolution and tbn.


2a. (Optional) Change the timescale to something convenient, to make calculations simpler.

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

This gets us

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

If you do this step, the new timescale should be equal or an integral multiple of the original framerate.

2b. Calculate the timescale needed, so that for target framerate x, PTS of frame # x in the source should have the same value as the new tbn. If you carried out step 2a, this is very easy and it's simply the new framerate. So, for target fps 45, new tbn should be 45.


3. Generate dummy video.

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

All properties should be same like resolution, H.264 profile, pixel format, refs count..etc for best results.


4 Concat the videos.

First make a text file

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

Then, the concat

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

The output file will have the 2nd video playing at 45 fps.

5. Now, cleave off the dummy preroll

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

and you have

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

I did say this was convoluted!

очень умный, хороший ответ. Rowe Morehouse 6 лет назад 0

Похожие вопросы