I'm trying to add a reticle to a live video feed, and need the reticle to be able to move based on some external data.

I can draw a box on the video with ffmpeg:

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

(Note that for now I'm just testing with video files since that makes some parts of it simpler.)

However, there doesn't appear to be a way to adjust the x and y values externally once the command has started. This would be ideal if there was a way to easily read them in e.g. from stdin or /dev/shm/reticle-pos.txt, but I can't find a way to do that.

Another option I've tried is to draw the reticle externally with imagemagick and then overlay it with 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 &

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

However this doesn't work, as it appears that ffmpeg only reads the image file once, rather than on each frame.

How can I draw a reticle over top of the video, in a way that lets me control the reticle's position?


using loop option:

ffmpeg -i input.mpg -loop 1 -f image2 -i /dev/shm/reticle.png -filter_complex overlay output.mpg
  • ffmpeg reads reticle.png on every frame by using loop option of image2 demuxer.
  • Update rectile.png atomically by writing a new reticle to a temp file first and then rename to rectile.png.
  • For details: https://ffmpeg.org/ffmpeg-formats.html#image2-1
| improve this answer | |

I've figured out a way to do this. It's probably not the best way, but it works:

    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

This works by having imagemagick output raw pixel data (-size 1080x720 -depth 8 rgba:-). The pixel data for each frame gets concatenated together with the rest into a single raw video stream. ffmpeg is then able to read that raw video stream (-f rawvideo -pixel_format bgr32 -video_size 1080x720 -framerate 30 -i pipe:0) and overlay it onto the main video.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.