videos vidcutter stories recortar rapido programas para online imagen gratuito cortar como app aplicacion video ffmpeg split keyframe

vidcutter - recortar video online rapido



¿Cómo dividir un video usando FFMPEG para que cada fragmento comience con un fotograma clave? (6)

Necesitamos dividir una gran transmisión de video WMV en vivo en trozos pequeños del mismo tamaño. Hicimos un script que funciona bien haciendo esto, excepto por una cosa: los fragmentos de video no comienzan con un fotograma clave, por lo que cuando reproducen la mayoría de los fragmentos de video, no muestran ninguna imagen hasta que un fotograma clave del video original es finalmente alcanzado.

¿No hay una manera de decirle a ffmpeg que el video de salida comience con un fotograma clave?

Así es como se ven nuestras líneas de comando en este momento:

ffmpeg.exe -i "C:/test.wmv" -ss 00:00:00 -t 00:00:05 -acodec copy -vcodec copy -async 1 -y "0000.wmv" ffmpeg.exe -i "C:/test.wmv" -ss 00:00:05 -t 00:00:05 -acodec copy -vcodec copy -async 1 -y "0001.wmv"

y así...


Aquí está la solución que podría obtener para trabajar:

Como lo sugirieron av501 y d33pika, utilicé ffprobe para encontrar dónde están los cuadros clave. Como ffprobe es muy detallado y puede tomar varios segundos o incluso minutos para generar todos los fotogramas clave y no hay forma de abarcar el rango de fotogramas que queremos de un video extenso, procedo en 5 pasos:

  1. Exporte un fragmento de video del archivo original, alrededor del doble del tamaño del fragmento deseado.

    ffmpeg -i source.wmv -ss 00:00:00 -t 00:00:06 -acodec copy -vcodec copy -async 1 -y 0001.wmv

  2. Use ffprobe para encontrar dónde están los fotogramas clave. Elija el fotograma clave más cercano después del tamaño del fragmento deseado.

    ffprobe -show_frames -select_streams v -print_format json=c=1 0001.wmv

  3. Desde la salida de ffprobe obtén pkt_dts_time del cuadro justo antes de ese fotograma clave.

  4. ffmpeg en el fragmento exportado del paso 1, especificando el mismo archivo de entrada y salida, y especificando -ss 00:00:00 y -t [valor encontrado en el paso 3].

    ffmpeg -i 0001.wmv -ss 00:00:00 -t 00:00:03.1350000 -acodec copy -vcodec copy -async 1 -y 0001.wmv

  5. Reinicie en el paso 1, usando -ss [suma acumulada de los valores encontrados en el paso 3 sobre las iteraciones].

Procediendo de esta manera, pude tener una manera eficiente y robusta de dividir el video en cuadros clave.


Como se indica en los documentos oficiales de FFMPEG , me ha funcionado mejor especificar -ss timestart before -i input_file.ext , porque establece (o al menos eso entiendo) el comienzo del video generado en el fotograma clave más cercano encontrado antes de la marca de tiempo especificada .

Cambie su ejemplo a:

ffmpeg.exe -ss 00:00:00 -i "C:/test.wmv" -t 00:00:05 -acodec copy -vcodec copy -async 1 -y "0000.wmv"

He probado este método trabajando en archivos .flv y .mp4 .


Las últimas versiones de FFMPEG incluyen una nueva opción "segmento" que hace exactamente lo que creo que necesita.

ffmpeg -i INPUT.mp4 -acodec copy -f segment -vcodec copy -reset_timestamps 1 -map 0 OUTPUT%d.mp4

Esto produce una serie de archivos de salida numerados que se dividen en segmentos basados ​​en fotogramas clave. En mis propias pruebas, funcionó bien, aunque no lo he usado en más de unos pocos minutos y solo en formato MP4.


Si está dispuesto a hacer algunos scripts y quiere I frames en un intervalo particular, la única forma de hacerlo es

  1. Ejecute ffprobe y recopile las ubicaciones de los cuadros I de la salida

    ffprobe -show_streams

  2. Ejecute una serie de comandos -ss -t utilizando el mismo script para obtener los fragmentos que desee.

A continuación, puede hacer que su secuencia de comandos decida un número mínimo de fotogramas [supongamos que hay dos imágenes I a 10 fotogramas entre sí, realmente no desea fragmentarlo allí].

La otra forma de hacerlo es usar el multisfilesink de gstreamer y establecer el modo en el fotograma clave [sin embargo, eso afectará a cada fotograma clave, por lo que puede no ser ideal]


Usando una compilación más nueva de ffmpeg, puede lograr esto utilizando ffprobe y el muxer de segmento ffmpeg.

1.Utilice ffprobe y awk para identificar los fotogramas clave lo más cerca posible de su longitud de fragmento deseada.

ffprobe -show_frames -select_streams v:0 -print_format csv **[SOURCE_VIDEO]** 2>&1 | grep -n frame,video,1 | awk ''BEGIN { FS="," } { print $1 " " $5 }'' | sed ''s/:frame//g'' | awk ''BEGIN { previous=0; frameIdx=0; size=0; } { split($2,time,"."); current=time[1]; if (current-previous >= **[DURATION_IN_SECONDS]**){ a[frameIdx]=$1; frameIdx++; size++; previous=current;} } END { str=a[0]; for(i=1;i<size;i++) { str = str "," a[i]; } print str;}''

Dónde

  • [SOURCE_VIDEO] = ruta al video que deseas segmentar
  • [DURATION_IN_SECONDS] = longitud del segmento deseada en segundos

El resultado es una cadena delimitada por comas de fotogramas clave.

2. Utilice la salida de fotogramas clave anterior como entrada a ffmpeg.

ffmpeg -i [SOURCE_VIDEO] -codec copy -map 0 -f segment -segment_frames [OUTPUT_OF_STEP_1] ​​[SEGMENT_PREFIX] _% 03d. [SOURCE_VIDEO_EXTENSION]

Dónde

  • [SOURCE_VIDEO] = ruta al video que deseas segmentar
  • [OUTPUT_OF_STEP_1] = cadena delimitada por comas de fotogramas clave
  • [SEGMENT_PREFIX] = nombre de la salida del segmento
  • [SOURCE_VIDEO_EXTENSION] = extensión del video fuente (p. Ej., Mp4, mkv)

Utilice ffprobe -show_frames -pretty <stream> para identificar los cuadros clave.