Cómo crear una miniatura desde la mitad de un vídeo con FFmpeg

Cómo crear una miniatura desde la mitad de un vídeo con FFmpeg

¿Hay alguna manera de obtener una miniatura de video en FFmpeg?

Me gustaría tomar el fotograma del medio como video y usarlo como miniatura. Se desconoce la duración del vídeo.

También sería útil la posibilidad de especificar las dimensiones de la miniatura.

Respuesta1

Comando de una línea:

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

El subcomando obtiene la duración total del vídeo de entrada.

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

Y canalícelo para awkcalcular la duración/2 de esta manera

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

Entonces le da esta opción entre segundos a -ss y listo.

Si desea especificar el tamaño, agregue la opción -s como esa WxH donde W y H son valores enteros (por ejemplo: -s 800x600 o -s svga) o lea la página de manual de ffmpeg para ver otras opciones o formatos disponibles.

Respuesta2

Aquí hay un método que usa:

  • ffprobepara obtener la duración
  • bcpara calcular la mitad de la duración
  • ffmpegpara hacer la imagen en miniatura

Ejemplo:

input=input.mp4; ffmpeg -ss "$(bc -l <<< "$(ffprobe -loglevel error -of csv=p=0 -show_entries format=duration "$input")*0.5")" -i "$input" -frames:v 1 half.png

Respuesta3

En primer lugar, utilice siempre la última versión de FFmpeg.

Si tiene acceso a PHP, su pregunta está perfectamente respondida en Stack Overflow:¿Usar FFMpeg para obtener el fotograma medio de un vídeo?

$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}"; 

Lo que hará es simplemente extraer la duración de la salida de FFmpeg y usarla para determinar el código de tiempo del fotograma medio.

Puede adaptarlo fácilmente a otros shells y simplemente insertarlo en el siguiente comando, donde el marco del medio está aproximadamente en 534segundos:

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

Siempre puedes cambiar el tamaño con -s 480x320o similar, dependiendo del tamaño que quieras, insertado en algún lugar después de la -i input.mp4opción.


La solución anterior es un poco inexacta. Inmediatamente le dará un resultado, pero no podrá especificar qué fotograma desea. Si ya conoce el fotograma exacto que desea extraer, utilice el selectfiltro, por ejemplo con el número de fotograma 12345:

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

Tenga en cuenta que este comando puede tardar un poco, ya que debe saltar al marco especificado antes de poder extraerlo.

Respuesta4

La solución sencilla es:

 ffmpeg -i l1.mp4 -ss 00:00:14.435 -vframes 1 out.png

información relacionada