venerdì 24 aprile 2026

RTMP Stream da drone DJI

Per prima cosa, per avere uno stream dal drone si crea un server RTMP tramite il docker di Mediamtx mettendo i seguenti files nella stessa cartella 

docker-compose.yml

================================== 

version: "3.8"
services:
  mediamtx:
    image: bluenviron/mediamtx:latest
    container_name: mediamtx
    restart: unless-stopped
    ports:
      - "8554:8554"   # RTSP
      - "8888:8888"   # HTTP / WebRTC
      - "8889:8889"   # HTTPS
      - "1935:1935"   # RTMP
    volumes:
      - ./mediamtx.yml:/mediamtx.yml:ro

================================== 

mediamtx.yml

================================== 

# Porte
rtmpAddress: :1935
rtspAddress: :8554
hlsAddress: :8888
webrtcAddress: :8889
apiAddress: :9997

# Configurazione HLS (bassa latenza)
hlsSegmentDuration: 1s
hlsPartDuration: 200ms
hlsSegmentMaxSize: 50MB

# Path dello stream
paths:
  mystream:
    # Permessi semplificati (versioni recenti)
    source: publisher

    # Lancia ffmpeg automaticamente quando arriva uno stream
    runOnReady: >
      ffmpeg -i rtmp://localhost:1935/mystream
      -vf fps=1 -q:v 2 /tmp/frames/frame_%04d.jpg
    runOnReadyRestart: yes
 

================================== 

e lanciando 

docker run -d --name mediamtx -p 0.0.0.0:1935:1935 -p 8554:8554 -p 8888:8888 bluenviron/mediamtx:latest 

Lo stream si puo' visualizzare con FFMpeg direttamente sulla macchina docker 

ffplay -fflags nobuffer \
       -flags low_delay \
       -framedrop \
       -sync ext \
       rtmp://localhost:1935/luca

e si possono salvare anche i frame ad intervalli prefissati

ffmpeg -i rtmp://localhost:1935/live/mystream \ -vf fps=1 \ -q:v 2 \ /tmp/frames/frame_%04d.jpg 

per semplificare lo sviluppo si puo' usare un cellulare al posto del drone usando la app RMTP Streamer

si va nel pulsante Server e si impostano i parametri del docker server

si torna indietro e si preme Go Stream in basso a destra
 

altrimenti da DJI Flight queste sono le schermate per impostare lo stream


 


 

a questo punto puo' essere interessante uno script che legga il flusso e salva un fotogramma quando c'e' una differenza compresa tra il 65% ed il 75% dal precedente salvato in modo da poi dare in pasto a Opendronemap per la ricostruzione 

 

import cv2
import numpy as np
import os

def main():
# Inserisci qui l'indirizzo del tuo server RTMP
rtmp_url = "rtmp://192.168.1.79:1935/luca"
# Inizializzazione cattura video
cap = cv2.VideoCapture(rtmp_url)

# Buffer setting: utile per stream di rete per ridurre la latenza
cap.set(cv2.CAP_PROP_BUFFERSIZE, 3)

if not cap.isOpened():
print(f"Errore: Impossibile connettersi al server RTMP: {rtmp_url}")
return

output_dir = "catture_rtmp"
if not os.path.exists(output_dir):
os.makedirs(output_dir)

print("Connessione stabilita. In attesa del primo frame...")

# 1. Leggi e salva il primo fotogramma come riferimento iniziale
ret, first_frame = cap.read()
if not ret:
print("Errore: Impossibile ricevere dati dallo stream.")
return

# Funzione di utility per preparare l'immagine al confronto
def prepare_frame(f):
gray = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
return cv2.GaussianBlur(gray, (21, 21), 0)

ref_gray = prepare_frame(first_frame)
count = 0
# Salva il primo riferimento
cv2.imwrite(f"{output_dir}/ref_iniziale.jpg", first_frame)
print("Primo frame salvato. Monitoraggio differenze (65%-75%) avviato...")

try:
while True:
ret, frame = cap.read()
if not ret:
print("Perdita del segnale RTMP...")
break

# Preparazione frame corrente
current_gray = prepare_frame(frame)

# 2. Calcolo della differenza
# absdiff calcola la differenza assoluta pixel per pixel
diff_frame = cv2.absdiff(ref_gray, current_gray)
# Applichiamo una soglia: se la differenza di un pixel è > 25, diventa bianco (255)
_, thresh = cv2.threshold(diff_frame, 25, 255, cv2.THRESH_BINARY)
# 3. Calcolo percentuale di cambiamento
# Rapporto tra pixel bianchi e numero totale di pixel
change_pixels = np.count_nonzero(thresh)
total_pixels = thresh.size
diff_percentage = (change_pixels / total_pixels) * 100

# 4. Logica di salvataggio e aggiornamento riferimento
if 65.0 <= diff_percentage <= 75.0:
count += 1
filename = f"{output_dir}/cambiamento_{count}.jpg"
cv2.imwrite(filename, frame)
# Il frame attuale diventa il nuovo riferimento
ref_gray = current_gray
print(f"[{count}] Salvato! Differenza: {diff_percentage:.2f}%. Nuovo riferimento impostato.")

# Visualizzazione a schermo
cv2.putText(frame, f"Diff: {diff_percentage:.1f}%", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.imshow("RTMP Monitor - Press 'q' to stop", frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

except KeyboardInterrupt:
print("\nChiusura forzata dall'utente.")
finally:
cap.release()
cv2.destroyAllWindows()
print("Risorse liberate correttamente.")

if __name__ == "__main__":
main()


Per procedere da linea di comando alla creazione di un modello 3d si puo' usare il docker di opendronemap (le impostazioni sono volutamente per la creazione di un modello speditivo da usare in campagna...per il perfezionamento si puo' fare in ufficio(

docker run -ti --rm \
  -v /home/luca/Downloads/immagini:/datasets/immagini \
  opendronemap/odm \
  --project-path /immagini \
  --pc-quality low \
  --pc-sample 0.01 \
  --resize-to 2000 \
  --feature-quality low \
  --skip-orthophoto
 

 

 

Nessun commento:

Posta un commento

RTMP Stream da drone DJI

Per prima cosa, per avere uno stream dal drone si crea un server RTMP tramite il docker di Mediamtx mettendo i seguenti files nella stessa c...