Wie zeichnet man mit ffmpeg ein Fadenkreuz über ein Live-Video?

Wie zeichnet man mit ffmpeg ein Fadenkreuz über ein Live-Video?

Ich versuche, einem Live-Video-Feed ein Fadenkreuz hinzuzufügen. Das Fadenkreuz muss sich auf der Grundlage externer Daten bewegen können.

Ich kann mit ffmpeg ein Kästchen auf das Video zeichnen:

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

(Beachten Sie, dass ich derzeit nur mit Videodateien teste, da dies einige Teile einfacher macht.)

xEs scheint jedoch keine Möglichkeit zu geben, die und -Werte extern anzupassen, ynachdem der Befehl gestartet wurde. Dies wäre ideal, wenn es eine Möglichkeit gäbe, sie beispielsweise einfach von stdin oder einzulesen /dev/shm/reticle-pos.txt, aber ich kann keinen Weg finden, dies zu tun.

Eine andere Möglichkeit, die ich ausprobiert habe, besteht darin, das Fadenkreuz extern mit Imagemagick zu zeichnen und es dann mit ffmpeg zu überlagern:

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

Dies funktioniert jedoch nicht, da ffmpeg die Bilddatei anscheinend nur einmal und nicht bei jedem Frame liest.

Wie kann ich ein Fadenkreuz über das Video zeichnen, sodass ich die Position des Fadenkreuzes steuern kann?

Antwort1

Loop-Option verwenden:

ffmpeg -i input.mpg -loop 1 -f image2 -i /dev/shm/reticle.png -filter_complex overlay output.mpg
  • ffmpeg liest reticle.png in jedem Frame, indem es die Loop-Option des Image2-Demuxers verwendet.
  • Aktualisieren Sie rectile.png automatisch, indem Sie zuerst ein neues Fadenkreuz in eine temporäre Datei schreiben und es dann in rectile.png umbenennen.
  • Für Details:https://ffmpeg.org/ffmpeg-formats.html#image2-1

Antwort2

Ich habe eine Möglichkeit gefunden, dies zu tun. Es ist wahrscheinlich nicht die beste Methode, aber sie funktioniert:

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

Dies funktioniert, indem ImageMagick Rohpixeldaten ausgibt ( -size 1080x720 -depth 8 rgba:-). Die Pixeldaten für jedes Bild werden mit dem Rest zu einem einzigen Rohvideostream zusammengefügt. ffmpeg kann dann diesen Rohvideostream lesen ( -f rawvideo -pixel_format bgr32 -video_size 1080x720 -framerate 30 -i pipe:0) und ihn über das Hauptvideo legen.

verwandte Informationen