
Estou tentando adicionar um retículo a um feed de vídeo ao vivo e preciso que o retículo possa se mover com base em alguns dados externos.
Posso desenhar uma caixa no vídeo com ffmpeg:
ffmpeg -i input.mpg -vf drawbox=x=100:y=100:w=20:h=20:c=red output.mpg
(Observe que, por enquanto, estou apenas testando arquivos de vídeo, pois isso simplifica algumas partes.)
No entanto, não parece haver uma maneira de ajustar os valores x
e y
externamente depois que o comando for iniciado. Isso seria ideal se houvesse uma maneira de lê-los facilmente, por exemplo, em stdin ou /dev/shm/reticle-pos.txt
, mas não consigo encontrar uma maneira de fazer isso.
Outra opção que tentei é desenhar o retículo externamente com o imagemagick e depois sobrepô-lo com o 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
No entanto, isso não funciona, pois parece que o ffmpeg lê o arquivo de imagem apenas uma vez, e não em cada quadro.
Como posso desenhar um retículo por cima do vídeo, de uma forma que me permita controlar a posição do retículo?
Responder1
usando a opção de loop:
ffmpeg -i input.mpg -loop 1 -f image2 -i /dev/shm/reticle.png -filter_complex overlay output.mpg
- ffmpeg lê reticle.png em cada quadro usando a opção loop do demuxer image2.
- Atualize rectile.png atomicamente, gravando primeiro um novo retículo em um arquivo temporário e depois renomeando para rectile.png.
- Para detalhes:https://ffmpeg.org/ffmpeg-formats.html#image2-1
Responder2
Eu descobri uma maneira de fazer isso. Provavelmente não é a melhor maneira, mas 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
Isso funciona fazendo com que o imagemagick produza dados brutos de pixel ( -size 1080x720 -depth 8 rgba:-
). Os dados de pixel de cada quadro são concatenados com o restante em um único fluxo de vídeo bruto. O ffmpeg é então capaz de ler esse fluxo de vídeo bruto ( -f rawvideo -pixel_format bgr32 -video_size 1080x720 -framerate 30 -i pipe:0
) e sobrepô-lo ao vídeo principal.