Como desenhar um retículo em vídeo ao vivo com ffmpeg?

Como desenhar um retículo em vídeo ao vivo com ffmpeg?

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 xe yexternamente 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.

informação relacionada