Как вырезать в точные кадры, используя ffmpeg?
Я пытаюсь использовать ffmpeg, чтобы вырезать видео файлы в точное время. Справка ffmpeg показывает опцию -timecode_frame_start, чтобы указать начальный кадр, но я не могу заставить эту команду работать. Полученное видео всегда начинается с начала исходного видео. Вот пример команды, которую я запускаю:
ffmpeg -i input.mpg -acodec copy -vcodec copy -timecode_frame_start 200 -vframes 210 -n ouput.mpg
Я переместил параметр timecode_frame_start до и после других параметров без изменений в результатах. Есть ли дополнительная опция, которую мне нужно указать? Я пробовал различные форматы файлов, mkv, avi, mp4, и, похоже, проблема не связана с кодеками. Вот один файл, который я пробовал:
http://www.seaotter.com/marine/movies/hermit-long-01.mpg
Я что-то пропустил?
4 ответа
Я только что узнал, что timecode_frame_start
не работает, как это. Единственный способ начать с определенных кадров - преобразовать количество кадров в ss.ms
синтаксис или hh:mm:ss.ms
, Итак, если ваше видео на скорости 25 кадров в секунду и вы хотите начать с 133 кадров, вам понадобится
133 / 25 = 5,32
Итак, беги
ffmpeg -ss 5.32 -i input.mp4 -c:v libx264 -c:a aac out.mp4
Обратите внимание, что вырезание на точных кадрах с битовой копией (-c:v copy
) невозможно, поскольку не все кадры являются внутренне кодированными и могут стоять самостоятельно.
-ss
всегда будет с точностью до кадра.
Если вы хотите кодировать определенное количество кадров, используйте -frames:v
, например:
ffmpeg -ss 5.32 -i input.mp4 -c:v libx264 -c:a aac -frames:v 60 out.mp4
У вас также есть выбор использования видеофильтров, но поддержка аудио может быть не точной. И, видимо, поиск по кадрам все еще не является особенностью. Вы можете следовать этой ветке списка рассылки FFmpeg-users для получения дополнительной информации:
вы можете использовать
-vf select
для точного выбора кадра (что-то вроде-vf 'select=gte(n\,100)'
пропустить 100 первых кадров)
Опция
-vf select= "между (n \, start_frame_num \, end_frame_num), setpts = PTS-STARTPTS"например,
-vf select=“between(n\,200\,300),setpts=PTS-STARTPTS"
вырезает видео из (включает) 200-й (включает) 300-й кадр, отсчет последовательности начинается с 0.
LosslessCut — это кроссплатформенный инструмент с графическим интерфейсом, который использует FFmpeg в качестве серверной части и обрезает ваше видео без потерь. Вы можете вырезать ключевой кадр или любой кадр.
У меня есть решение, но я не знаю, как это сделать, используя текущие команды ffmpeg (мои попытки копирования ключевых кадров тоже не дали точных результатов. Я хочу знать, как ffmpeg определяет точки обрезки).
Я предложил предложить этот алгоритм, чтобы разделить сегмент (t1, t2), который мы хотим скопировать, на 3 части:
- часть (t1-x, t1+y), которая представляет собой полный закодированный блок, который необходимо перекодировать, чтобы иметь возможность точно скопировать часть (t1, y).
- часть (t2-z, t3+w), которая представляет собой полный закодированный блок, который необходимо перекодировать, чтобы иметь возможность точно скопировать часть (z, t2).
- средняя часть (y, z), содержащая полные закодированные блоки, куда ее можно скопировать как есть.
- Соедините 3 части, полученные в результате описанных выше шагов.
Обратите внимание, что первые две части должны быть небольшими (и одна из них или обе могут иметь нулевую длину), поэтому процесс перекодирования будет быстрым. Это позволит нам выполнять точные обрезки с немного более медленной работой, но все же намного быстрее, чем перекодирование всего видео. Это может быть еще быстрее, если мы сможем выполнять несколько разрезов с помощью одной команды, поэтому мы проходим кадры один раз. Я надеюсь, что кто-нибудь сможет применить это и рассказать нам, как, или упомянуть кого-нибудь из команды ffmpeg, или каким-либо образом доставить им это.