Le module Raspberry Pi Camera (et la version sans filtre IR, le module NoIR) sont de petits circuits (2,5cm x 2,5cm) dotés d’un capteur photo de 2592 x 1944 pixels capable d’enregistrer en 1080p à 30 images par secondes (ou 60 fps en 720p). Ce module se branche directement sur le port CSI du Pi prévu à cet effet.
La version NoIR permet de voir les infra-rouge, ce qui autorisera une vision nocturne si on le couple à un projecteur infra-rouge comme expliqué à fin de cet article : Système de vidéo-surveillance abordable avec des Raspberry Pi
Que ce soit pour un système de vidéo surveillance ou pour le pilotage d’un robot à distance, il faut pouvoir récupérer le flux vidéo et le diffuser à travers le réseau (streaming). Nous allons voir dans cet article 5 méthodes pour diffuser le flux vidéo d’un module Raspberry Pi Camera, plus ou moins efficacement.
Introduction et matériel utilisé
Le module Raspberry Pi Camera étant branché directement sur un Raspberry Pi, si vous voulez pouvoir voir les images capturées depuis un autre endroit qu’un écran branché sur ce même Pi, vous allez devoir envoyer ces images à travers le réseau. De nombreuses utilisations sont possibles :
- la caméra de surveillance que l’on souhaite observer depuis son smartphone quand on part en vacance
- le robot que l’on souhaite piloter à distance depuis un ordinateur de contrôle
- filmer et diffuser des images en direct à travers internet
- etc…
Petit bémol sur la notion de « streaming » vidéo : En principe, lorsqu’on parle de streaming vidéo, il s’agit bien d’un flux vidéo diffusé en direct. Comme nous allons le voir plus loin dans cet article, cette méthode consomme énormément de ressources (notamment en terme de bande passante), et dans de nombreux cas, il sera plus judicieux de diffuser une « suite d’images » à intervalles réguliers.
Le matériel
Pour l’ensemble des méthodes exposées dans cet article, nous utiliserons le matériel et le montage suivant :
Le Raspberry Pi A+ est vraiment idéal pour ce genre projet. Découvrez pourquoi en lisant cet article : Raspberry Pi A+ : Le meilleur de tous
On installe une Raspbian, tout ce qu’il y a de plus standard, on se connecte à son réseau WiFi et on active le module caméra grâce à l’outil raspi-config.
Voyons maintenant comment diffuser les images sur le réseau.
Méthode 1 : Netcat et Mplayer
C’est la méthode la plus simple et la plus directe. Il s’agit simplement de rediriger le flux capturé par la commande raspivid dans netcat, puis de récupérer ce flux et l’injecter en entrée dans le lecteur vidéo Mplayer. L’inconvénient de cette méthode est que le flux vidéo n’est visible que depuis un seul PC distant.
Depuis un PC sous Linux exécutez dans un premier temps la commande suivante (après avoir installé mplayer si besoin) :
nc -l -p 5001 | /usr/bin/mplayer -fps 10 -cache 1024 -
Cette commande ordonne à nc (netcat) d’écouter sur le port 5001 et redirige ce qui arrive dans le lecteur vidéo Mplayer en prévoyant un cache de 1024 Ko pour 10 images par secondes.
Puis, sur le Pi, il suffit d’exécuter raspivid et de rediriger la sortie vers l’adresse IP de notre PC client en utilisant netcat :
raspivid -t 0 -w 1280 -h 720 -o - | nc adresse_ip_du_pc_client 5001
On indique ainsi à raspivid de capturer des images en 1280×720 pixels et de les envoyer à netcat.
Simple et efficace, une fenêtre Mplayer s’ouvre automatiquement sur le PC client avec les images en direct. On notera toutefois une forte latence qui peut varier de 3 à 15 secondes en fonction de la qualité et du nombre d’images transmisses et de la qualité du lien WiFi.
Note : Un test réalisé sur un Raspberry Pi B, branché en Ethernet, permet de réduire la latence à environ une seconde.
Si vous souhaitez enregistrer le flux vidéo dans un fichier sur le PC client, il suffit de modifier la première commande de cette manière :
nc -l -p 5001 | /usr/bin/mplayer -fps 10 -cache 1024 -demuxer h264es -dumpstream -dumpfile ./Bureau/ma_video.h264 -
Méthode 2 : streaming VLC
Cette méthode, relativement simple à mettre en place, souffre d’une très forte latence. Toutefois, et contrairement à la première méthode, le flux vidéo est visible depuis plusieurs postes clients.
Sur le Pi, il suffit d’installer VLC :
apt-get install vlc
Puis de rediriger la sortie de la commande raspivid (comme dans la méthode 1) vers VLC en exécutant la commande suivante :
raspivid -t 0 -n --width 1280 --height 720 -o - | cvlc stream:///dev/stdin --sout '#standard{access=http,mux=ts,dst=:8090}' :demux=h264
Coté PC client, il suffit de lire le flux vidéo avec VLC grâce à la commande :
cvlc http://adresse_ip_du_pi:8090
Pour enregistrer le flux vidéo dans un fichier, utilisez la commande suivante :
cvlc http://adresse_ip_du_pi:8090 --sout file/ts:./Bureau/ma_video.h264
Cette méthode est à privilégier si vous souhaitez diffuser votre flux vidéo à plusieurs personnes sur internet par exemple, et que la latence n’est pas un problème.
Méthode 3 : streaming de Pi à Pi avec OMXplayer
Les méthodes 1 et 2 permettent de diffuser le flux vidéo à destination d’un ordinateur distant. Si vous souhaitez capturer un flux vidéo depuis un Pi pour l’observer depuis un autre Pi branché à un écran, il convient d’utiliser le lecteur OMXplayer.
Cette méthode est un peu plus complexe à mettre en oeuvre mais permet plus de souplesse quant à l’usage que l’on souhaite en faire. Depuis le Pi équipé du module caméra, nous allons procéder exactement comme pour la méthode 1, en redirigeant la sortie de la commande raspivid dans netcat. Puis, sur le Pi branché à l’écran de visionnage, nous allons dans un premier temps récupérer le flux netcat pour l’enregistrer dans un fichier et le lire, dans un deuxième temps, avec OMXplayer.
Sur le Pi de visionnage, créez d’abord un fichier de type fifo :
mkfifo /dev/shm/video.fifo
Deux points très important à comprendre dans cette commande :
- /dev/shm : ce point montage fonctionne comme un disque dur mais aucune donnée ne sera stockée sur le disque dur en lui même ; tout sera géré en mémoire vive. C’est parfait pour y placer un fichier vidéo tampon.
- fichier de type .fifo : les fichiers de type fifo fonctionnent comme les fichiers standards, mais se comportent comme des « pipes », ce qui permet au système d’y stocker des données sans passer par le système de fichier. Encore une fois, parfait pour y placer un fichier vidéo tampon
![🙂](../themes/icons/grey.gif)
Le fichier tampon étant prêt, il faut maintenant le remplir. Côté Pi de visionnage, mettez netcat en écoute en redirigeant la sortie vers le fichier tampon :
nc -l -p 5001 > /dev/shm/video.fifo
Puis côté Pi caméra, envoyez le flux vidéo à travers netcat comme dans la méthode 1 :
raspivid -t 0 -w 960 -h 540 -o - | nc adresse_ip_du_pi_visionnage 5001
De retour sur le Pi de visionnage, il suffit de dire à OMXplayer de lire le fichier tampon :
omxplayer /dev/shm/video.fifo
Cette méthode n’offre pas une latence exemplaire, mais permet de transmettre un flux vidéo de Pi à Pi. Idéal par exemple pour créer un portier vidéo, avec un Pi qui film et un Pi qui affiche la vidéo, les deux Pi étant reliés par WiFi ![🙂](../themes/icons/grey.gif)
Méthode 4 : mjpg-streamer
A partir de là, on sort du streaming vidéo pur et dur puisqu’il s’agit, avec le mjpeg, de transmettre et d’afficher une suite de photos les unes après les autres. Le résultat est beaucoup moins fluide puisqu’on ne pourra espérer afficher que 5 à 10 images par seconde maximum (contre 10 à 30 images par secondes pour les méthodes précédentes), mais nous pourrons exploiter les images beaucoup plus simplement en les affichant dans une page web, ou sur un écran comme le PiHomeDashScreen par exemple. Si vous disposez d’un NAS Synology, ou d’un système sachant gérer des caméras IPs, vous pourrez également exploiter la caméra du Pi grâce à cette méthode.
Voici le lien vers la page SourceForge de mjpg-streamer : http://sourceforge.net/projects/mjpg-streamer/
Dans un premier temps, installez les dépendances de mjpg-streamer ainsi que subversion :
apt-get install subversion libv4l-dev
libjpeg8-dev
imagemagick
mjpg-streamer aura besoin d’un fichier videodev.sh pour fonctionner correctement :
ln -s /usr/include/linux/videodev2.h /usr/include/linux/videodev.h
Téléchargez ensuite la dernière version de mjpg-streamer grâce à subversion, puis installez le en utilisant les commandes suivantes :
svn co https://svn.code.sf.net/p/mjpg-streamer/code/
cd code/mjpg-streamer
make USE_LIBV4L2=true clean all
make DESTDIR=/usr install
Une fois installé, créez un répertoire temporaire et lancez raspistill en mode timelapse pour capturer 2 images par secondes :
mkdir /tmp/stream
raspistill --nopreview -w 640 -h 480 -q 5 -o /tmp/stream/pic.jpg -tl 500 -t 9999999
Enfin, lancez mjpg-streamer grâce à cette commande :
LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i "input_file.so -f /tmp/stream -n pic.jpg" -o "output_http.so -w ./www"
Par défaut, mjpg-streamer lancera un serveur web sur le port 8080/TCP auquel vous pouvez accéder avec un navigateur en utilisant l’adresse : http://adresse_du_pi:8080
Vous devriez voir l’interface de démonstration de mjpg-streamer :
![capture_mjpg-streamer](../themes/icons/grey.gif)
Les deux options les plus intéressantes sont JavaScript et Stream. Ces deux méthodes vous permettrons de récupérer les images pour les afficher dans une page web, ou sur le PiHomeDashScreen comme vous pouvez le voir dans la photo si dessous :
![capture_homedashscreen_pi_camera](../themes/icons/grey.gif)
Pour réaliser cela, j’ai simplement placé le code suivant dans le fichier index.php du PiHomeDashScreen (consulter les articles de ce projet pour en savoir plus).
<div id="webcam"><img src="http://adresse_ip_du_pi:8080/?action=snapshot" /></div>
<script type="text/javascript">
var imageNr = 0;
var finished = new Array();
var paused = false;
function createImageLayer() {
var img = new Image();
img.style.position = "absolute";
img.style.zIndex = -1;
img.onload = imageOnload;
img.onclick = imageOnclick;
img.src = "http://adresse_ip_du_pi:8080/?action=snapshot&n=" + (++imageNr);
var webcam = document.getElementById("webcam");
webcam.insertBefore(img, webcam.firstChild);
}
function imageOnload() {
this.style.zIndex = imageNr; // Image finished, bring to front!
while (1 < finished.length) {
var del = finished.shift(); // Delete old image(s) from document
del.parentNode.removeChild(del);
}
finished.push(this);
if (!paused) createImageLayer();
}
</script>
C’est de loin la méthode que je recommande car elle permet de diffuser les images à plusieurs clients en même temps tout en conservant une latence acceptable pour peu que l’on se contente d’une image de qualité moyenne.
Méthode 5 : Serveur Web
Cette méthode consiste à capturer des images à intervalles régulier avec la commande raspistill, puis à les diffuser grâce à un serveur web Apache. C’est la méthode que j’ai utilisé pour réaliser ce Système de vidéo-surveillance abordable avec des Raspberry Pi.
![video_surveillance_monitorin_safe](../themes/icons/grey.gif)
Cette méthode est très proche, fonctionnellement, de mjpg-streamer. Je songe d’ailleurs à refondre mon système de vidéo surveillance en utilisant mjpg-streamer.
Je vous invite à lire cet article pour en savoir plus sur cette méthode « artisanale »
: Système de vidéo-surveillance abordable avec des Raspberry Pi
Conclusion
Les méthodes de streaming vidéo pur (méthode 1 à 3) permettent un affichage fluide en sacrifiant la réactivité, ce qui rend cette option inutilisable pour le pilotage d’un robot par exemple.
Les méthodes utilisant une suite d’images sur le principe du mjpeg (méthode 4 et 5) permettent une plus grande souplesse dans l’exploitation des images et offrent globalement une meilleure latence (car moins d’images à traiter et à faire transiter par le réseau). Personnellement, j’utilise la méthode 4 avec mjpg-streamer pour la quasi totalité de mes projets actuels. C’est une méthode très polyvalente, simple à mettre en place et peu gourmande en ressource pour le Pi.
Quelque soit la méthode utilisée, le vrai problème reste la bande passante. Que ce soit en 3G, en Wifi ou même en Ethernet, la vitesse du réseau sera limitante pour la transmission d’images.
Vous trouverez sur le net beaucoup d’articles qui expliquent comment mettre en oeuvre le logiciel Motion sur un Raspberry Pi. Je conseille cette approche uniquement si vous souhaitez faire de la détection de mouvement car Motion est fait pour cela à la base. Même si Motion utilise le même principe du mjpeg que dans les méthodes 4 et 5, il est très gourmand en ressources pour un Pi et offrira moins de souplesse que mjpg-streamer.
Reste une méthode que je n’ai pas encore essayé à ce jour mais qui semble être intéressante car « prête à l’emploi » pour un Pi : http://elinux.org/RPi-Cam-Web-Interface.
Je vous invite à partager vos expériences sur ce sujet, notamment pour savoir si vous connaissez des méthodes qui offrent une latence très faible.
Article intéressant sur le sujet :
L’article Raspberry Pi Camera – 5 façons de faire du streaming est apparu en premier sur MagdiBlog.