Как нарисовать сетку прицела поверх живого видео с помощью ffmpeg?

Как нарисовать сетку прицела поверх живого видео с помощью ffmpeg?

Я пытаюсь добавить сетку к видеотрансляции в реальном времени и мне нужно, чтобы сетка могла двигаться в зависимости от некоторых внешних данных.

Я могу нарисовать рамку на видео с помощью ffmpeg:

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

(Обратите внимание, что на данный момент я тестирую только видеофайлы, поскольку это упрощает некоторые части.)

Однако, похоже, нет способа настроить значения xи yизвне после запуска команды. Было бы идеально, если бы был способ легко прочитать их, например, из stdin или /dev/shm/reticle-pos.txt, но я не могу найти способ сделать это.

Другой вариант, который я попробовал, — это нарисовать сетку снаружи с помощью imagemagick, а затем наложить ее с помощью 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

Однако это не работает, поскольку, по-видимому, ffmpeg считывает файл изображения только один раз, а не в каждом кадре.

Как нарисовать прицельную сетку поверх видео так, чтобы можно было контролировать ее положение?

решение1

с использованием опции цикла:

ffmpeg -i input.mpg -loop 1 -f image2 -i /dev/shm/reticle.png -filter_complex overlay output.mpg
  • ffmpeg считывает reticle.png на каждом кадре, используя опцию цикла демультиплексора image2.
  • Обновите rectile.png атомарно, сначала записав новую сетку во временный файл, а затем переименовав в rectile.png.
  • Подробности:https://ffmpeg.org/ffmpeg-formats.html#image2-1

решение2

Я придумал, как это сделать. Возможно, это не лучший способ, но он работает:

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

Это работает за счет того, что imagemagick выводит необработанные пиксельные данные ( -size 1080x720 -depth 8 rgba:-). Пиксельные данные для каждого кадра объединяются с остальными в один необработанный видеопоток. Затем ffmpeg может прочитать этот необработанный видеопоток ( -f rawvideo -pixel_format bgr32 -video_size 1080x720 -framerate 30 -i pipe:0) и наложить его на основное видео.

Связанный контент