Вопрос или проблема
В качестве фона для вопроса я использую программно сгенерированный сложный фильтр для составления видео из множества входных данных. Небольшие ошибки накапливаются, и поэтому мне нужны точные обрезки (перекодирование приемлемо).
Например, мне нужно 44 кадра из ссылочного видео (FPS=30), начиная с заданного кадра.
Вот две попытки (с ffmpeg
версии 6.1.1):
Попытка 1:
ffmpeg -i input.mp4 -vf "trim=start=3.2666666666666666:end=4.7333,setpts=PTS-STARTPTS" -an output.mp4
Попытка 2:
ffmpeg -i input.mp4 -vf "trim=start=3.2666666666666666:end=4.7334,setpts=PTS-STARTPTS" -an output.mp4
Хотя разница во времени end
составляет всего 0.0001, первая попытка дает 43 кадра (продолжительность 1.433333 секунды), а вторая – 45 кадров (продолжительность 1.50 секунды). Независимо от того, что я ставлю в метку времени end
, я не могу получить 44 кадра…
Я получаю количество кадров с помощью:
ffprobe -show_frames output.mp4 | grep FRAME | wc -l
(деля это число на два, так как оно считает как [FRAME]
, так и [/FRAME]
)
Каково объяснение этого поведения и как я могу предсказуемо обрезать необходимые мне кадры?
ОБНОВЛЕНИЕ То же самое поведение наблюдается, если я использую start_frame
и end_frame
. Для диапазона от 98 до 141 я получаю 43 кадра. Для диапазона от 98 до 142 я получаю 45 кадров. Я не могу получить 44…
Ответ или решение
Ответ на вопрос о проблемах с использованием FFMPEG для точного обрезания видео
Введение
Работа с видеофайлами требует высокой степени точности, особенно при использовании инструментов, таких как FFMPEG. В данном случае, вы столкнулись с проблемой, где небольшое изменение в метках времени приводит к различиям в количестве кадров при обрезке. Рассмотрим причины данной проблемы и возможные решения для точного обрезания видео.
Объяснение проблемы
Кадры и временные метрики
При работе с видео, срок между кадрами может быть разным в зависимости от используемого кодека и формата. Ваша задача заключается в обрезке видео так, чтобы получить точное количество кадров, например, 44 кадра, из видео с частотой 30 кадров в секунду. Это означает, что вам потребуется выделить 1,46667 секунды материала (44 кадра / 30 кадров в секунду).
Когда вы используете trim
с параметрами start
и end
в формате времени, FFMPEG часто округляет временные метрики до ближайшего ключевого кадра. Это может привести к тому, что вы получите больше или меньше кадров, чем ожидали.
Различия в попытках обрезки
-
В первой попытке: Используя диапазон от 3,26667 до 4,7333, вы получили 43 кадра. Это может быть связано с тем, что конечная временная метрика приводила к тому, что FFMPEG останавливается на ближайшем ключевом кадре, который находится за пределами желаемого диапазона.
-
Во второй попытке: Увеличив конечное время всего на 0,0001 секунды, вы получаете 45 кадров. Это указывает на то, что добавленное время привело к захвату еще одного кадра из-за поведения кодера и того, как он обрабатывает временные метрики.
Как достичь желаемых результатов
Рекомендации для точного обрезания
-
Постоянная частота кадров: Убедитесь, что ваше видео имеет постоянную частоту кадров (CFR). Это обеспечит лучшую предсказуемость при обрезке.
-
Использование ключевых кадров (keyframes): Определите, где расположены ключевые кадры в вашем видео с помощью
ffprobe
. Это поможет вам точно понять, в каких временных метках можно производить обрезку.Пример команды:
ffprobe -select_streams v -show_entries frame=pkt_pts_time,pkt_duration_time,key_frame -of csv input.mp4
-
Пробные обрезания: Поскольку вы хотите получить точное количество кадров, вы можете применять метод проб и ошибок, начиная с диапазона, который уже дал вам результат. Например, если ваши предыдущие попытки дали 43 и 45 кадров, попробуйте установить
end
в 4.73325 илиstart
в 3.26675. -
Используете флаги: Флаги, такие как
-ss
для начала обрезки и-t
для указания времени, могут помочь в точном получении необходимого диапазона. Однако помните, что их применение также может привести к выбору ближайшего ключевого кадра.
Примеры корректных команд
Чтобы избежать проблем с кадрами, попробуйте следующее:
ffmpeg -i input.mp4 -ss 3.267 -t 1.46667 -c copy output.mp4
Или, если вам нужно больше контроля:
ffmpeg -i input.mp4 -vf "trim=start=3.2667:end=4.7333,setpts=PTS-STARTPTS" -an output.mp4
Не забывайте также проверять информацию о кадрах после обрезки, используя ffprobe
, чтобы быть уверенным в результате.
Заключение
Точное обрезание видео в FFMPEG может быть достаточно сложной задачей. Следуя вышеописанным рекомендациям, можно значительно уменьшить вероятность возникновения ошибок и случайных изменений в количестве кадров. С учетом использования ключевых кадров и точных временных метрик, достижение требуемого результата станет более предсказуемым процессом.