4

Моя цель; экспортируйте серию изображений из видеофайла с помощью ffmpeg. Я думаю, что моя проблема связана с кадрами в секунду и скоростью передачи данных.

Я попробовал следующую команду:ffmpeg -i myVideo.mp4 -r 1 images_%04d.jpg но почему-то в 45-секундном видео я получаю 47 изображений. Очень важно, чтобы я понял это точно. Я не буду знать заранее, что такое соответствующий FPS или битрейт, если мне нужны эти значения при запуске команды, мне нужно каким-то образом получить их из ffmpeg.

Я также рассмотрел возможность экспорта ВСЕХ изображений в видео с помощью ffmpeg -i myVideo images_%04d.jpg и деления количества изображений на общее количество секунд в видео. Это даст мне что-то вроде 24,97, и я округлю до 25 и удалю 24 из каждых 25 кадров. Я боюсь, что если файл VBR и части с высокой скоростью передачи данных находятся в начале видео, кадры, которые я заканчиваю, не будут точно соответствовать 1 в секунду. Например, 30-е изображение может фактически появиться в видео ближе ко второму 31.

 running ffmpeg -> ffmpeg -i "/videos/11.mp4" -s "352x264" "/images/image%06d.jpg"
FFmpeg version 0.6-4:0.6-2ubuntu6.1, Copyright (c) 2000-2010 the FFmpeg developers
  built on Mar 31 2011 18:43:47 with gcc 4.4.5
  configuration: --extra-version=4:0.6-2ubuntu6.1 --prefix=/usr --enable-avfilter --enable-avfilter-lavf 
--enable-vdpau --enable-bzlib --enable-libgsm --enable-libschroedinger --enable-libspeex 
--enable-libtheora --enable-libvorbis --enable-vaapi --enable-pthreads --enable-zlib --enable-libvpx 
--disable-stripping --enable-runtime-cpudetect --enable-gpl --enable-postproc --enable-x11grab 
--enable-libdc1394 --enable-shared --disable-static
  libavutil     50.15. 1 / 50.15. 1
  libavcodec    52.72. 2 / 52.72. 2
  libavformat   52.64. 2 / 52.64. 2
  libavdevice   52. 2. 0 / 52. 2. 0
  libavfilter    1.19. 0 /  1.19. 0
  libswscale     0.11. 0 /  0.11. 0
  libpostproc   51. 2. 0 / 51. 2. 0

Seems stream 1 codec frame rate differs from container frame rate: 49938.00 (49938/1) -> 24.97 (24969/1000)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/videos/11.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
  Duration: 00:00:32.60, start: 0.000000, bitrate: 433 kb/s
    Stream #0.0(und): Audio: aac, 44100 Hz, stereo, s16, 127 kb/s
    Stream #0.1(und): Video: h264, yuv420p, 352x264 [PAR 1:1 DAR 4:3], 303 kb/s, 24.97 fps, 24.97 tbr, 24969 tbn, 49938 tbc
Output #0, image2, to '/images/image%06d.jpg':
  Metadata:
    encoder         : Lavf52.64.2
    Stream #0.0(und): Video: mjpeg, yuvj420p, 352x264 [PAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 90k tbn, 24.97 tbc
Stream mapping:
  Stream #0.1 -> #0.0
Press [q] to stop encodingframe=  176 fps=  0 q=24.8 size=      -0kB time=7.05 bitrate=  
-0.0kbits/s    ^Mframe=  312 fps=236 q=24.8 size=      -0kB time=12.50 bitrate=  -0.0kbits/s    
^Mframe=  316 fps=112 q=24.8 size=      -0kB time=12.66 bitrate=  -0.0kbits/s    ^Mframe=  322 
fps= 55 q=24.8 size=      -0kB time=12.90 bitrate=  -0.0kbits/s    ^Mframe=  327 fps= 39 q=24.8 
size=      -0kB time=13.10 bitrate=  -0.0kbits/s    ^Mframe=  331 fps= 33 q=24.8 size=      
-0kB time=13.26 bitrate=  -0.0kbits/s    ^Mframe=  336 fps= 31 q=24.8 size=      -0kB time=13.46 
bitrate=  -0.0kbits/s    ^Mframe=  339 fps= 27 q=24.8 size=      -0kB 
time=13.58 bitrate=  -0.0kbits/s    ^Mframe=  344 fps= 22 q=24.8 size=      -0kB 
time=13.78 bitrate=  -0.0kbits/s 

У кого-нибудь есть идеи, как получить точные по времени результаты экспорта изображений из видео с помощью ffmpeg?? Спасибо!

3 ответа3

1

Вам нужно вручную указать значение -vsync . Несоответствие, скорее всего, связано с разницей в переменной / постоянной частоте кадров и временных отметках кадров. Если у вас есть источник VFR, ffmpeg по умолчанию будет пытаться нацелить на предполагаемую скорость (значение tbr ) и будет отбрасывать или дублировать кадры, чтобы "сгладить" движение. Экспорт кадров в виде изображений также следует за этим поведением. Некоторая информация из документации:

-vsync параметр

Метод синхронизации видео. По причинам совместимости старые значения могут быть указаны в виде чисел. Вновь добавленные значения должны быть указаны как строки всегда.

0, сквозной

Каждый кадр передается со своей временной меткой от демультиплексора к мультиплексору.

1, ср

Кадры будут продублированы и отброшены для достижения требуемой постоянной частоты кадров.

2, VFR

Кадры пропускаются с их отметкой времени или удаляются, чтобы предотвратить одновременную отметку 2 кадров.

падение

Проходя, но уничтожая все временные метки, заставляя мультиплексор генерировать новые временные метки на основе частоты кадров.

-1, авто

Выбирает от 1 до 2 в зависимости от возможностей мультиплексора. Это метод по умолчанию.

Как сказано здесь, ffmpeg выберет -vsync -1 по умолчанию (как для кодирования видео, так и для экспорта изображений). То, что вы хотите, это прямой проход без изменений. Используйте -vsync 0 если вы хотите, чтобы каждый кадр оставался без изменений или без дублирования. Вы, вероятно, получите сообщения о немонотонном DTS, но это можно в значительной степени игнорировать. Вот пример команды для точного вывода всех кадров из видео:

ffmpeg -i video.nut -f image2 -vsync 0 frame-%03d.tiff
1

Вы уверены, что теряете кадры? Ваше входное видео - h264, которое поддерживает переменную частоту кадров. чтобы получить подробную информацию о каждом кадре, я бы порекомендовал использовать следующее:

ffmpeg -i inputvideo -vf showinfo -acodec copy -vcodec mpeg2video temp.mp4

Таким образом, вы будете знать, сколько кадров в вашем фильме.

Вы можете избежать переменной частоты кадров, преобразовав свой фильм в видео с переменной частотой кадров, используя аргумент -r float , а затем экспортировав фотографии (как вы делали в своей команде).

0

Я наблюдал подобное ошибочное поведение при извлечении изображений с аргументом -r.

Я нашел решение, которое работало для меня, используя вместо этого параметр -vf fps = X (с некоторыми важными примечаниями ниже). Хотите верьте, хотите нет, но поведение здесь кажется более предсказуемым, чем поведение с -r.

  1. Чтобы генерировать изображение каждые X секунд из входного видео, вычислите значение с плавающей запятой 1/X и запустите:

ffmpeg -i input.mp4 -vf fps=1.0/x image-%04d.jpg

например, чтобы получить 2 изображения в секунду:

ffmpeg -i input.mp4 fps=0.5 image-%04d.jpg

Это будет делать почти правильно, обратите внимание, что:

  1. Создается дополнительный первый кадр, который следует игнорировать.
  2. Кадры создаются каждые X секунд, где X - аргумент -vf fps=X , начиная с X/2 секунд.

Итак, работает:

ffmpeg -i input.mp4 fps=1 image-%04d.jpg

На 5-секундном видео будет 6 файлов, первый должен игнорироваться, а 2-6-й будет соответствовать меткам времени: 0,5, 1,5, 2,5, 3,5 и 4,5.

Вот полезное тестовое видео для отладки такого рода вещей:

https://drive.google.com/file/d/0B56RokrDs3xabS1TS19wRjlBaVk/view?usp=sharing

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .