Использование FFMPEG: как выполнить обнаружение изменения сцены? с временным кодом?

На основании этой статьи кажется, что FFMPEG можно использовать для обнаружения смены сцены в видео: http://www.luckydinosaur.com/u/ffmpeg-scene-change-detector

Теперь у меня есть видео, которое отображает текст книги, и когда говорят текст (слово или предложение), он подсвечивается. Что-то вроде этой аудиокниги: https://youtu.be/lA7L6ZNVKjc

Мне нужно знать временную метку, когда текст будет подсвечен (следовательно, смена сцены), это позволит мне добавлять метки времени на моем видео на YouTube, поэтому слушателям легче перемещаться по аудиокниге.

Какая магическая командная строка будет делать это?

Большое спасибо!

Ответ 1

Объединение фильтра сцены (для обнаружения изменений сцены) и фильтра showinfo должно достичь того, что вы хотите:

ffmpeg -i input.flv  \
       -filter:v "select='gt(scene,0.4)',showinfo" \
       -f null \
       - 2> ffout

Эта команда извлекает все кадры, которые отличаются от предыдущего кадра более чем на (gt) 0.4 (в масштабе от 0 до 1). Для этих кадров информация распечатывается (showinfo) следующим образом

[Parsed_showinfo_1 @ 0x2d85e60] n:   0 pts:2537204 pts_time:2.5372  pos:  2998114 fmt:rgb24 sar:1/1 s:1920x1200 i:P iskey:1 type:I checksum:5616582E plane_checksum:[5616582E]

Теперь вам нужно только извлечь метку времени. Я думаю, что вы заинтересованы в pts_time. Вы можете сделать это так:

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep [0-9.]* -o > timestamps

Это даст вам список всех временных меток:

2.5372
4.37799
6.65301
8.09344

Чтобы этот подход работал, у вас должна быть версия FFmpeg, которая реализует обнаружение сцены. Кроме того, вы должны выбрать подходящее значение для порога (0.4 в первой команде). Вы можете попытаться найти оптимальный порог, извлекая кадры для различных пороговых значений (а затем проверяя кадры вручную), как это

ffmpeg -i input.flv \
       -filter:v "select='gt(scene,0.1)',showinfo" \
       -vsync 0 frames/%05d.jpg

Просто для пояснения: grep [0-9.]* Не исключает целых чисел, как указано в другом ответе. Он соответствует любой последовательности символов, состоящей из цифр и точек, но он также соответствует не числам, таким как "4.4.4". Однако ffmpeg не должен выводить такие плохо сформированные временные метки.

Ответ 2

У меня нет ответа, чтобы опубликовать комментарий к вышеуказанному ответу, но я хотел указать, что grep, отправленный как @ckoehn, так и @keypulsations, будет захватывать только метки времени, которые являются плавающей запятой. Чтобы захватить как временные метки с плавающей точкой, так и целые, используйте следующее регулярное выражение

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep -E '[0-9]+(?:\.[0-9]*)?' -o > timestamps

Ответ 3

Я пытался ответить @ckoehn, и он работал, пока не перестал работать, звездочка в последнем grep вызывала проблемы. Чтобы избежать этого, я рекомендую использовать двойные кавычки в предложениях grep, таких как:

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep "[0-9.]*" -o > timestamps