2009-06-30 32 views
8

Me pregunto cómo usar FFMpeg para graficar el fotograma medio de un video. Ya he escrito el C# para tomar un fotograma en un momento determinado (es decir, tirar de un fotograma en el segundo 3). Pero todavía tengo que descubrir cómo encontrar el medio del video usando los comandos FFMpeg.¿Utiliza FFMpeg para obtener el fotograma medio de un video?

Respuesta

8

Esto podría simplificarse, pero aquí hay un viejo código PHP que tenía por ahí que debería ser el truco. (Agrega la ubicación a ffmpeg si no es en su camino)

$output = shell_exec("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("ffmpeg -y -i {$path} -f mjpeg -vframes 1 -ss " . ($total_seconds/2) . " -s {$w}x{$h} {$output_filename}"); 
+0

Gracias, eso es justo lo que estaba buscando! –

+0

@Derek Gathright Por favor, dame los detalles básicos para empezar a trabajar con ffmpeg. Por favor, eche un vistazo a mi [pregunta] (http://stackoverflow.com/questions/10071408/how-to-get-frames-of-video-file-in-android). –

4

FFmpeg te ayuda a obtener la velocidad de fotogramas y la duración del video, para que puedas multiplicar uno por el otro y dividir por 2 para obtener el número del fotograma medio.

es decir, para un video de 30 segundos que se ejecuta a 15 cuadros por segundo: 30 * 15 = 450/2 = 225, lo que significa que debe tomar el marco 225o.

0

comando funciona este golpe como un encanto (probado):

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 
2

Ejemplo

Suponiendo que está usando Linux se puede utilizar para obtener ffprobe duración, bc para calcular medio punto, entonces ffmpeg para hacer el marco:

eval "$(ffprobe -v error -of flat=s=_ -show_entries format=duration input.mp4)" 
ffmpeg -ss "$(echo "$format_duration/2" | bc)" -i input.mp4 -q:v 2 -frames:v 1 half.jpg 

Esto elimina cualquier necesidad de utilizar awk, tr, grep, sed, etc.

Como alternativa, puede utilizar el select filter y eliminar bc, pero el filtro de selección puede ser lento.

Una nota acerca de la duración

La duración de ffprobe podría ser incorrecta si el archivo está dañado o trunca incorrectamente. La duración puede ser confirmada mediante la decodificación por completo la entrada con ffmpeg continuación, tomando nota de la time= en la segunda a la última línea de la salida de la consola:

ffmpeg -i input -f null - 
… 
frame= 2600 fps=569 q=-0.0 Lsize=N/A time=00:01:48.50 bitrate=N/A 
video:244kB audio:20344kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown 
+0

En Windows/Cygwin tuve que hacer un feo procesamiento de texto kludge de la salida de eval/ffprobe para eliminar una nueva línea de Windows desde el final de $ format_duration: 'eval" $ (ffprobe -v error -of flat = s = _ -show_entries format = duración tmp.mp4) "' ' echo $ format_duration> tmp.txt' ' eco/2 >> tmp.txt' 'dos2unix tmp.txt' format_duration =' 'tr -d '\ n'

+0

Hay un conjunto de backticks que rodean la asignación de variables después de format_duration en la última parte de mi comentario (que se elimina aquí mediante el análisis de rebajas). –

Cuestiones relacionadas