7

Есть ли способ получить миниатюру видео в FFmpeg?

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

Возможность указать размеры миниатюры также будет полезна.

6 ответов6

9

Однострочная команда:

ffmpeg -i input.mp4 -vcodec mjpeg -vframes 1 -an -f rawvideo -ss `ffmpeg -i input.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}'` output.jpg

Подкоманда получает общую продолжительность входного видео

ffmpeg -i input.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d ,

И направить его в awk, чтобы вычислить продолжительность /2 следующим образом

echo '00:01:30.000' | awk -F ':' '{print ($3+$2*60+$1*3600)/2}'

Так что дайте это среди секунд опции -ss, и все готово.

Если вы хотите указать размер, добавьте опцию -s, например WxH, где W и H - целочисленные значения (например, -s 800x600 или -s svga) или прочитайте справочную страницу ffmpeg, чтобы увидеть другие доступные опции или формат.

5

Прежде всего, всегда используйте последнюю версию FFmpeg.

Если у вас есть доступ к PHP, на ваш вопрос отлично ответят по переполнению стека: используйте FFMpeg, чтобы получить средний кадр видео?

$output = shell_exec("/usr/local/bin/ffmpeg -i {$path}");
preg_match('/Duration: ([0-9]{2}):([0-9]{2}):([^ ,])+/', $output, $matches);
$time = str_replace("Duration: ", "", $matches[0]);
$time_breakdown = explode(":", $time);
$total_seconds = round(($time_breakdown[0]*60*60) + ($time_breakdown[1]*60) + $time_breakdown[2]);
shell_exec("/usr/local/bin/ffmpeg -y  -i {$path} -f mjpeg -vframes 1 -ss " . ($total_seconds / 2) . " -s {$w}x{$h} {$output_filename}"; 

Он просто извлекает длительность из вывода FFmpeg и использует ее для определения временного кода среднего кадра.

Вы можете легко адаптировать его к другим оболочкам и просто вставить в следующую команду, где средний кадр примерно равен 534 секундам:

ffmpeg -y  -i input.mp4 -f mjpeg -vframes 1 -ss 534 thumbnail.jpg

Вы всегда можете изменить размер с -s 480x320 или аналогичным, в зависимости от того, насколько он велик, вставленный где-то после опции -i input.mp4 .


Вышеупомянутое решение немного неточно. Это сразу даст вам результат, но вы не можете указать, какой кадр вы хотите. Если вы уже знаете точный кадр, который хотите извлечь, используйте фильтр select , например, с номером кадра 12345:

ffmpeg -i input.mp4 -filter:v select="eq(n\,12345)" -vframes 1 thumbnail.jpg

Обратите внимание, что эта команда может занять некоторое время, поскольку ей нужно перейти к указанному кадру, прежде чем она сможет извлечь его.

1

Вот метод, использующий:

  • ffprobe чтобы получить длительность
  • bc чтобы рассчитать половину продолжительности
  • ffmpeg чтобы сделать эскиз изображения

Пример:

input=video.mp4
duration=$(ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$input")
ffmpeg -ss "$(echo "$duration"/2 | bc)" -i "$input" -q:v 2 -vframes 1 output.jpg
  • Вы можете заменить мое ленивое использование bc вашей любимой альтернативой, такой как awk или printf , если хотите.

  • Вы можете масштабировать / изменять размер изображения, добавив фильтр масштабирования в качестве параметра вывода в вашей команде ffmpeg , например -vf scale=320:-1 .

  • Продолжительность, предоставляемая ffprobe не всегда может быть точной в зависимости от ввода. В маловероятном случае, если у вас возникнет такая проблема, вам придется полностью декодировать ввод, например, с помощью ffmpeg -i input -f null - , и проанализировать вывод, чтобы получить правильное значение длительности.

0

Простое решение:

 ffmpeg -i l1.mp4 -ss 00:00:14.435 -vframes 1 out.png
0
$currentVideoDuration =  shell_exec("$ffmpeg -i $videoPath 2>&1 | grep Duration");
  $actualDuration = substr($currentVideoDuration, 11, 12);
  $arrayWithHoursMinsAndSecs = explode(":", $actualDuration);
  $thisVideoDurationInSeconds = $arrayWithHoursMinsAndSecs[2] + $arrayWithHoursMinsAndSecs[1]*60 + $arrayWithHoursMinsAndSecs[0]*3600;
  $halfVideoDuration = $thisVideoDurationInSeconds/2;
  echo 'midpoint of this video: '. $halfVideoDuration;
  echo shell_exec("$ffmpeg -i $videoPath -y -ss 00:00:$halfVideoDuration -vframes 1 thumbnail.png 2>&1");

замените $ videopath на путь к вашему видео

-1

Эта команда bash работает как шарм:

avconv -i 'in.mpg' -vcodec mjpeg -vframes 1 -an -f rawvideo \
-s 420x300 -ss `avconv -i in.mpg 2>&1 | grep Duration \
| awk '{print $2}' | tr -d , \ 
| awk -F ':' '{print ($3+$2*60+$1*3600)/2}'` out.jpg

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