
Я пытаюсь добавить сетку к видеотрансляции в реальном времени и мне нужно, чтобы сетка могла двигаться в зависимости от некоторых внешних данных.
Я могу нарисовать рамку на видео с помощью 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
) и наложить его на основное видео.