¿Deseas eliminar cada fotograma par o impar usando FFmpeg?

14

¿Existe una manera precisa de tomar video en bruto y extraer de él un video nuevo que contenga solo fotogramas impares o incluso fotogramas (por elección)?

Por ejemplo:

Tengo "blah.yuv" con 400 cuadros (0-399). Quiero crear "blahOdd.yuv" que contiene marcos 1-399 (1,3,5,7 ... 399) y "blahEven" que contiene marcos 0-398 (0,2,4,6 ... 398).

¿Alguna idea de cómo hacerlo usando solo FFmpeg?

Mark
fuente

Respuestas:

11

Para trabajar con precisión, primero convierta el video al flujo de bits RAW YUV (si aún no lo está) mediante:

ffmpeg -i input.mp4 -an -vcodec rawvideo -pix_fmt yuv420p rawbitstream.yuv

Siguiente paso: el select filtrar toma una expresión , dónde n es el numero de cuadro

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="mod(n-1\,2)" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="not(mod(n-1\,2))" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an even.yuv

Tener ffmpeg no duplicar cuadros, tiene que forzar la mitad de la tasa de cuadros de su entrada, por lo que establece "2" como entrada y "1" en la salida. No olvide reemplazar el WxH con las dimensiones reales de su clip porque el flujo de bits sin formato no tiene un encabezado que lleve esta información.

En lugar de lo anterior, otra posibilidad sería agregar el setpts Filtro para establecer nuevas marcas de tiempo para la salida. Pero ten cuidado ya que no deja cuadros con precisión. Aquí, 25 es la velocidad de fotogramas de salida real que desea:

ffmpeg -i input.mp4 -filter:v select="mod(n-1\,2)",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -i input.mp4 -filter:v select="not(mod(n-1\,2))",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an even.yuv

Por supuesto, puede elegir otro formato de píxel (cualquiera de ffmpeg -pix_fmts ). Asegúrese de que al leer el archivo sepa el tamaño de píxel y el formato de píxel:

ffmpeg -f rawvideo -s:v 1280x720 -pix_fmt yuv420p input.yuv …
slhck
fuente
Gracias, para las nuevas versiones de FFMPEG debería ser -vf en lugar de -filter: v. Además, debería ser mod (n-1 \, 2) porque la cuenta n parece comenzar desde 1, mientras que la cuenta de cuadros desde 0 (de lo contrario, el primer cuadro se duplica 3 veces). Pero todavía hay un problema, duplica los cuadros mientras quiero deshacerme de ellos, por ejemplo. El clip final contendrá solo la mitad de los fotogramas.
Mark
-vf es un alias de -filter:v. No puedo probarlo de forma confiable ahora, pero veré esto más adelante cuando vuelva a mi máquina. Quizas el tinterlace filtrar puede hacer lo mismo?
slhck
He intentado '-r 2 -i blah.yuv -r 1' pero me muestra un error Opción framerate no encontrado.
Mark
Ah, lo siento ... Rasca eso, esto no funciona (¿ya?) Y solo para imágenes.
slhck
1
@AnmolSinghJaggi No, esto solo elimina fotogramas, pero no estoy seguro de que sea tan determinista (es decir, elimina todos los fotogramas impares). Se basará en códigos de tiempo, que pueden no ser exactos.
slhck
2

Si su ffmpeg fue construido con la bandera de AviSynth, entonces Yo creo puedes pasar un .avs expediente.

Puedes comprobarlo ejecutando ffmpeg y buscando --enable-avisynth en el configuración datos. --enable-avisynth

Si está ahí puedes usarlo así: ffmpeg -i blahEven.avs blahEven.yuv.

Dónde blahEven.avs es simple:

ffvideosource ("blah.yuv"). SelectEven ()

Para marcos impares, utilice SelectOdd().

Para un uso más avanzado, vea el SelectEvery documentación.

Louis
fuente
Esta es una excelente alternativa, pero como he mencionado, estoy limitado a usar solo ffmpeg. El motivo es que forma parte de un sistema automatizado que creará solo archivos .bat, sin posibilidad de agregar AVS.
Mark
@Mark estaba pensando que si --enable-avisynth estaba allí, lo que significaba que AviSynth estaba integrado en ffmpeg, pero no estoy seguro de eso.
Louis