¿Cómo dibujar una retícula sobre video en vivo con ffmpeg?

¿Cómo dibujar una retícula sobre video en vivo con ffmpeg?

Estoy intentando agregar una retícula a una transmisión de video en vivo y necesito que la retícula pueda moverse en función de algunos datos externos.

Puedo dibujar un cuadro en el video con ffmpeg:

ffmpeg -i input.mpg -vf drawbox=x=100:y=100:w=20:h=20:c=red output.mpg

(Tenga en cuenta que por ahora solo estoy probando con archivos de video, ya que eso simplifica algunas partes).

Sin embargo, no parece haber una manera de ajustar los valores xy yexternamente una vez que se ha iniciado el comando. Esto sería ideal si hubiera una manera de leerlos fácilmente, por ejemplo, desde stdin o /dev/shm/reticle-pos.txt, pero no puedo encontrar una manera de hacerlo.

Otra opción que probé es dibujar la retícula externamente con imagemagick y luego superponerla con ffmpeg:

while true; do
    for x in {100..500..1}; do
        convert -size 1080x720 xc:none -fill none -stroke red -strokewidth 2 \
            -draw "ellipse $x,100 10,10 0,360" -scale 1080x720 /dev/shm/newreticle.png
        cp /dev/shm/newreticle.png /dev/shm/reticle.png
        sleep 0.001
    done
done &

ffmpeg -i input.mpg -i /dev/shm/reticle.png -filter_complex overlay output.mpg

Sin embargo, esto no funciona, ya que parece que ffmpeg solo lee el archivo de imagen una vez, en lugar de cada cuadro.

¿Cómo puedo dibujar una retícula sobre la parte superior del video, de manera que me permita controlar la posición de la retícula?

Respuesta1

usando la opción de bucle:

ffmpeg -i input.mpg -loop 1 -f image2 -i /dev/shm/reticle.png -filter_complex overlay output.mpg
  • ffmpeg lee reticle.png en cada fotograma utilizando la opción de bucle de image2 demuxer.
  • Actualice rectile.png atómicamente escribiendo primero una nueva retícula en un archivo temporal y luego cambie el nombre a rectile.png.
  • Para detalles:https://ffmpeg.org/ffmpeg-formats.html#image2-1

Respuesta2

He descubierto una manera de hacer esto. Probablemente no sea la mejor manera, pero funciona:

reticle(){
    convert -size 1080x720 xc:none \
        -fill none -stroke red -strokewidth 2 -draw "ellipse $1,$2 10,10 0,360" \
        -size 1080x720 -depth 8 rgba:-
}
export -f reticle

parallel -k reticle {} 100 ::: {100..500} \
| ffmpeg \
    -i input.mpg \
    -f rawvideo -pixel_format bgr32 -video_size 1080x720 -framerate 30 -i pipe:0 \
    -filter_complex overlay \
    -y -c libx264 output.mpg

Esto funciona haciendo que imagemagick genere datos de píxeles sin procesar ( -size 1080x720 -depth 8 rgba:-). Los datos de píxeles de cada cuadro se concatenan con el resto en una única secuencia de video sin procesar. Luego, ffmpeg puede leer esa transmisión de video sin procesar ( -f rawvideo -pixel_format bgr32 -video_size 1080x720 -framerate 30 -i pipe:0) y superponerla al video principal.

información relacionada