Вероятная разница связана с кодеком copy
. В последнем случае вы указываете ffmpeg скопировать сегменты, но он не может сделать это в зависимости от вашего времени ввода.
Сначала он должен найти предыдущие I-кадры (кадр, который может быть декодирован без какой-либо ссылки на какой-либо предыдущий кадр) и начинается отсюда.
Чтобы получить то, что вам нужно, вам нужно либо перекодировать видео (как вы делали в 2 предыдущих примерах), либо изменить время, чтобы остановиться на I кадрах.
Чтобы подтвердить, что я правильно понял вашу проблему:
- У вас есть исходное видео (оно кодируется с переменной частотой кадров, близкой к 18fps)
- Вы хотите разделить исходное видео с помощью ffmpeg, увеличив частоту кадров до 24 кадров в секунду.
- Затем вы хотите объединить каждый сегмент.
Я думаю, что проблема в основном в том, что у вас есть некоторое расхождение во времени (если я разделю индекс кадра на время, которое вы дали, я получу от 16 до 18 кадров в секунду). Когда вы конвертируете их на шаге 2, время вывода видео будет 24 кадра в секунду. ffmpeg не выполняет повторную выборку по оси времени, поэтому, если вы установите скорость видео, видео будет ускоряться или замедляться.
Существует также проблема согласованности для потока:
Как правило, видеопоток должен начинаться с I-кадра, поэтому при разделении FFMPEG должен найти предыдущий I-кадр (при использовании кодека copy
, и это изменяет длительность сегмента).
Когда вы объединяете, у вас также может возникнуть проблема согласованности (то есть, если объединяемый сегмент действительно заканчивается I-кадром, а следующий начинается с I-кадра, возможно, FFMPEG удалит один, хотя я не помню, какое сейчас поведение сейчас)
Итак, чтобы решить вашу проблему, на вашем месте я бы избежал шага 2 (в любом случае это плохо для качества). То есть я бы использовал ffmpeg для разделения интересующих сегментов на основе номера кадра (это единственное значение, которое не приблизительное в вашей схеме) в png или ppm кадрах (или в трубу, если вы не позаботьтесь о сохранении их), а затем объедините все кадры, кодируя их на последнем шаге с ожидаемой скоростью, установленной на totalVideoTime
/ totalFrameCount
.
Вы получите финальное видео меньшего и более высокого качества.
Если по какой-то причине вы не можете сделать то, что я сказал, по крайней мере для ввода concat, вам следует использовать формат ffconcat:
ffconcat version 1.0
file segment1
duration 12.2
file segment2
duration 10.3
Это даст вам ожидаемую продолжительность, обрезая каждый сегмент, если он длиннее
Для выбора по номеру кадра (вместо времени, поскольку время трудно получить право на видео с переменной частотой кадров), вы должны использовать фильтр select
, например:
-vf select=“between(n\,start_frame_num\,end_frame_num),setpts=STARTPTS"