Сбрасывать каждые четные или нечетные кадры с помощью FFmpeg?

14

Есть ли точный способ взять необработанное видео и извлечь из него новое видео, которое содержит только нечетные или четные кадры (по выбору)?

Например:

У меня "бла.юв" с 400 кадрами (0-399). Я хочу создать «blahOdd.yuv», который содержит кадры 1-399 (1,3,5,7 ... 399) и «blahEven», который содержит кадры 0-398 (0,2,4,6 ... 398) ).

Есть идеи, как это сделать, используя только FFmpeg?

отметка
источник

Ответы:

11

Для точной работы сначала преобразуйте видео в битовый поток RAW YUV (если его еще нет) с помощью:

ffmpeg -i input.mp4 -an -vcodec rawvideo -pix_fmt yuv420p rawbitstream.yuv

Следующий шаг: selectфильтр принимает выражение , где nнаходится номер кадра.

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="mod(n-1\,2)" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="not(mod(n-1\,2))" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an even.yuv

Чтобы ffmpegне дублировать кадры, вы должны принудительно установить половину частоты кадров вашего входа - поэтому вы устанавливаете «2» в качестве входа и «1» для выхода. Не забудьте заменить WxH фактическими размерами вашего клипа, потому что необработанный поток битов не имеет заголовка, который несет эту информацию.

Вместо вышесказанного, другой возможностью было бы добавить setptsфильтр для установки новых временных меток для вывода. Но будьте осторожны, так как кадры сбрасывают не точно. Здесь 25 - это фактическая частота кадров на выходе, которую вы хотите:

ffmpeg -i input.mp4 -filter:v select="mod(n-1\,2)",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -i input.mp4 -filter:v select="not(mod(n-1\,2))",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an even.yuv

Конечно, вы можете выбрать другой формат пикселей (любой из ffmpeg -pix_fmts). Убедитесь, что при чтении файла вы знаете размер и формат пикселя:

ffmpeg -f rawvideo -s:v 1280x720 -pix_fmt yuv420p input.yuv …
slhck
источник
Спасибо, для новых версий FFMPEG это должен быть -vf вместо -filter: v. Кроме того, это должен быть mod (n-1 \, 2), потому что число n, кажется, начинается с 1, а число кадров с 0 (в противном случае первый кадр дублируется 3 раза). Но есть проблема: дублируются кадры, а я хочу от них избавиться - например, конечный клип будет содержать только половину кадров.
Марка
-vfэто псевдоним -filter:v. Я не могу надежно проверить это сейчас, но разберусь с этим позже, когда вернусь на свою машину. Может быть, tinterlaceфильтр может сделать то же самое?
slhck
Я пробовал '-r 2 -i blah.yuv -r 1', но он показывает мне ошибку Option framerate not found.
Марка
Ах, извините .. Поцарапайте это, это не работает (больше?) И только для изображений.
slhck
1
@AnmolSinghJaggi Нет, это просто отбрасывает кадры, но я не уверен, что это так детерминировано (то есть отбрасывает каждый нечетный кадр). Он будет основан на временных кодах, которые могут быть неточными.
slhck
2

Если ваш ffmpeg был собран с флагом AviSynth, то я считаю, что вы можете передать .avsфайл.

Вы можете проверить, запустив ffmpegи ища --enable-avisynthв данных конфигурации . --enable-AviSynth

Если там вы можете использовать его , например , так: ffmpeg -i blahEven.avs blahEven.yuv.

Где blahEven.avsпросто:

ffvideosource ( "blah.yuv"). SelectEven ()

Для нечетных кадров используйте SelectOdd().

Для более выгодного использования см. Документацию SelectEvery .

Луис
источник
Это отличная альтернатива, но, как я уже говорил, я ограничен использованием только ffmpeg. Причина в том, что это часть автоматизированной системы, которая будет создавать только файлы .bat, без возможности добавления AVS.
Mark
@ Марк, я думал, что если бы --enable-avisynthтам было, это означало, что AviSynth был встроен в ffmpeg, но я не уверен в этом.
Луи