Site icon AranaCorp

Stream vidéo entre deux machines avec FFMPEG

Nous allons voir dans ce tutoriel, comment envoyer un stream vidéo d’une machine à une autre à l’aide de FFMPEG. Envoyer des données entre deux appareils, quelle qu’elles soient, est un des problèmes majeurs dans les objets connectés (IoT). Si vous souhaitez créer une caméra connectée qui envoie des vidéos à une machine distante, cet article devrait vous intéresser.

Installation de ffmpeg

Sur une machine Linux

sudo apt-get install ffmpeg

Sur une machine Windows, veuillez suivre cette procédure.

N.B.: si besoin sur une machine linux sudo apt-get install v4l-utils

Obtenir les informations nécessaire au streaming Vidéo

Pour créer un flux vidéo d’une machine à une autre, les machines doivent être connectées sur le même réseau (Wifi ou Ethernet)

Dans un premier temps, vous devez obtenir l’adresse IP de la machine cliente (qui reçoit le flux)

Entrez dans un terminal de commande

ifconfig #pour une machine linux
ip addr # si ifconfig n'est pas disponible 

ou

ipconfig #pour une machine windows

Vous devriez obtenir une adresse de la forme 192.168.X.X (dans notre cas 192.168.1.67)

Ensuite récupérer la source vidéo. Pour lister toutes les entrées vidéo sur une machine linux

ls -l /dev/video*
lsusb #list usb devices
v4l2-ctl --list-devices #list video devices

Ces commandes devrait vous aider à identifier la source vidéo. Dans notre cas, /dev/video5

Pour lister les sources vidéo sur une machine Windows, vous pouvez utiliser ffmpeg

ffmpeg -list_devices true -f dshow -i dummy

Dans notre cas, video= »USB2.0 HD UVC WebCam »

Récupérer les options et vérifier les formats et résolutions acceptés par la caméra

sous Linux

v4l2-ctl -d /dev/video0 --list-formats

sous Windows

ffmpeg -f dshow -list_options true -i video="USB2.0 HD UVC WebCam"

Une fois ces données enregistrées, nous allons pouvoir configurer le streaming.

Créer un stream vidéo avec ffmpeg

Pour créer un flux vidéo, il vous faut un émetteur (server) et un récepteur (client) qui seront joués par deux terminaux lancer sur deux ordinateurs différents.

ffmpeg -re -f v4l2 -i /dev/video5 -r 10 -f mpegts udp://192.168.1.67:8554?pkt_size=1316
ffmpeg -f dshow -i video="USB2.0 HD UVC WebCam" -r 10 -f mpegts udp://192.168.1.67:8554?pkt_size=1316
ffplay udp://127.0.0.1:8554
ou
ffplay udp://0.0.0.0:8554

N.B.: Vous pouvez tester le streaming sur une seule machine en utilisant l’adresse IP de la machine sur laquelle vous travaillez et en utilisant deux terminaux un pour le serveur et un pour le client

Pour récupérer les statistiques vidéo vous pouvez utiliser la commande ffprobe

ffprobe udp://127.0.0.1:8554

ou, pour plus de détails,

ffprobe -show_format -show_streams udp://127.0.0.1:8554

Réduire le délai de réception du flux vidéo entre deux machines

Nous pouvons observer un délai de 15 secondes environ entre l’émission vidéo et la réception. Il peut être intéressant de réduire ce délai selon les applications.

Côté serveur les paramètre qui jouent sur la vitesse de transmission sont:

Essayez de jouer avec ces paramètres pour réduire le délai tout en conservant une qualité suffisante.

ffmpeg -re  -thread_queue_size 64 -s800x600  -i /dev/video5 -r 5 -f mpegts udp://192.168.1.67:8554?pkt_size=1316

Côté client, il y a différentes options que vous pouvez tester de la documentation repris dans cette discussion.

ffplay -fflags nobuffer -probesize 32 -sync ext -vf setpts=0 udp://127.0.0.1:8554

Ces modifications d’options des commandes ffmpeg et ffplay permet de réduire le délai de 15 à 2 secondes environ le stream video.

Créer un stream HTTP avec ffmpeg

Il est possible de créer un serveur vidéo HTTP en passant par VLC. L’intérêt de cette méthode est qu’on peut transmettre le flux vidéo à n’importe quel appareil.

ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sout='#std{access=http,mux=ts,dst=:8554}'
ffplay http://192.168.1.9:8554

Créer un stream RTSP avec ffmpeg

Il est possible de créer un serveur vidéo HTTP en passant par VLC. L’intérêt de cette méthode est qu’on peut transmettre le flux vidéo à n’importe quel appareil.

ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sout='#rtp{sdp=rtsp://:8554/} --sout-all --sout-keep'
ffplay rtsp://192.168.1.9:8554/

Script Python pour lancer le streaming

Voici un script Python qui vous permettra de tester les différentes méthodes de streaming ainsi que les paramètre ffmpeg

import subprocess

#UDP
#input client ip address here 192.168.1.9
stream_video="ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts udp://192.168.1.9:8554?pkt_size=1316"
#on client side ffplay udp://127.0.0.1:8554

#HTTP
stream_video="ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sout='#std{access=http,mux=ts,dst=:8554}'"
#on client side ffplay http://192.168.1.73:8554

#RSTP
stream_video="ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sout='#rtp{sdp=rtsp://:8554/} --sout-all --sout-keep'"
#on client side ffplay rtsp://192.168.1.73:8554/ # don't forget / at the end

try:
	subprocess.call(stream_video,shell=True)
except:
	pass
print("Done")

Bonus : Afficher le stream vidéo de FFMPEG avec OpenCV

Une fois le flux vidéo établi entre les deux machines, il est possible d’utiliser OpenCV afin de lire et afficher les images provenant du stream UDP.

import cv2

def main(args):

	#cap = cv2.VideoCapture(0) #default camera
	cap = cv2.VideoCapture('udp://127.0.0.1:8554')
	#cap = cv2.VideoCapture('http://192.168.1.9:8554')
	#cap = cv2.VideoCapture('rtsp://192.168.1.9:8554/')

	while(True):
		ret, frame = cap.read()
		if ret: #necessary if packet is lost
			frame=cv2.resize(frame, (800, 600)) 
			cv2.imshow('Capturing',frame)
			
		if cv2.waitKey(1) & 0xFF == ord('q'): #click q to stop capturing
			break

	cap.release()
	cv2.destroyAllWindows()
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Bonus2 : Afficher l’heure sur la vidéo

Pour afficher l’heure sur la vidéo, nous allons utiliser le filtre drawtext de ffmpeg qui utilise certain paramètre de texte

"drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460"

Le filtre est appliqué avec le tag -vf. Voici la commande complète

ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460" -vcodec copy -f mpegts udp://192.168.1.9:8554?pkt_size=1316

En python

stream_cmd="""ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460" -vcodec copy -f mpegts udp://192.168.1.9:8554?pkt_size=1316"""

Pratique pour imiter une caméra CCTV ou pour comparer les temps provenant de différentes caméra

Applications

Sources

Quitter la version mobile