Publié par 7 commentaires

Streaming RaspberryPi avec Node.js et ffmpeg via websocket

Mise à jour: 08.2016
– ajout notes RaspberryPi 3
– amélioration de la mise en forme de l’article
– publication d’une App iOS client

Version originale: 04.2015


Sommaire

  • Le but
  • La solution retenue
  • Schéma de fonctionnement
  • Les plus
  • Vidéo du résultat final
  • Client iOS eRaspiStream
  • Configuration du RaspberryPi
    1. Mise à jour
    2. Installer Node.js
    3. Valider Node.js
    4. Compiler h264
    5. Compiler ffmpeg
    6. Le point
    7. JSMPEG
    8. WebSocket
    9. FFMPEG
    10. UV4L
    11. Rassemblement du puzzle
    12. Comment regarder?
  • A venir prochainement
  • Autres liens non cités

J’ai fais beaucoup de recherche sur le moyen de streamer la caméra du RaspberryPi avec une latence vraiment très faible. Différentes solutions sont attirantes, comme MJPEG-Streamer, ou GStreamer, mais au final pour cette utilisation je met en avant cette solution car j’ai obtenu les meilleurs résultats.

Le but 
Une vraie caméra IP en « temps réel » ou presque, visible en html, en utilisant un RaspberryPi.
(Ce qui est le cas au final, avec moins de 0.2s de latence!)

La solution retenue:

  • Raspberry Pi model B v1 ou v2 ou v3
  • PiCam (peut aussi fonctionner avec d’autres types de webcam)
  • ffmpeg
  • UV4L
  • Node.js
  • Websocket
  • Nginx

Voici comment est-ce que tout ceci fonctionne, un petit schéma vaut mieux que des mots:

eRaspiStream linux part

Les plus:

Une vidéo du résultat final:

 

Client iOS eRaspiStream:
J’ai développé une petite app pour iOS, « eRaspiStream », qui permet de visualiser et ajouter plusieurs caméra.

Update 29.06.2015
L’application n’est toujours pas validée par Apple, mais une version 1.2 est en préparation, le tout en swift2.

Update 15.08.2016
L’application iOS est validée! Vous pouvez la télécharger gratuitement ici:
https://appsto.re/ch/99sX6.i


Configuration du RaspberryPi
C’est parti pour la configuration, heu, armes-toi de patience, certaines parties sont…longuettes, vive la compilation…
(Ceci n’est plus le cas avec la 3ème révision de la framboise. En 1h tout est configuré!)

  1. Mise à jour du RaspberryPi, revoir les notes
  2. Installer Node.js dernière version pour arm:
    sudo apt-get install nodejs npm node-semver

    Vérification, on affiche les versions des deux outils qui nous intéressent:

    node -v
    npm -v

    devrait vous afficher respectivement quelque chose comme v0.12.1 et 2.5.1 et nous indique que node est bien installé

  3. Optionnel: valider Node.js
    Un tout petit script qui se comporte comme un serveur web.
    Je ne décortiquerai pas ici le scripts, d’autres l’ont fait avant moi.Copier ce qui suit dans un fichier monpremiernode.js, que l’on édite avec vi, nano, etc

    # monpremiernode.js
    # 20150504 - eddy martignier
    # serveur web qui écoute le port 8080
    var http = require('http');
    var server = http.createServer(function(req, res) {
      res.writeHead(200);
      res.end('Mon premier script node.js fonctionne');
    });
    server.listen(8080);

    Depuis un navigateur, entrez l’adresse de votre framboise suivi de :8080, exemple:

    http://192.168.1.34:8080

    doit afficher:

    mon premier script node.js fonctionne.
  4. Compiler h264
    On démarre les différentes compilations.x264

    cd /usr/src
    git clone git://git.videolan.org/x264
    cd x264
    ./configure --host=arm-unknown-linux-gnueabi --enable-static --disable-opencl
    make
    sudo make install
  5. Compiler ffmpeg
    qui met plus ou moins long à compiler suivant votre configuration:
    – RaspberryPi 1, 4h10
    Oui oui, je l’ai fait! C’est long, 4h10 de compilation, à regarder des lignes défiler :p
    – RaspberryPi 2, 1h02
    C’est plus acceptable.
    – RaspberryPi 3, 17 min!
    On à un vainqueur!

    cd /usr/src
    git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
    cd ffmpeg
    sudo ./configure --arch=armel --target-os=linux --enable-gpl --enable-libx264 --enable-nonfree
    make
    (NOTE: Si vous utilisez une version 2 ou 3 du RaspberryPi, vous pouvez utiliser "make -j4" pour tirer avantages du multi-processeur)
    sudo make install
  6. Le point:
    OK, on fait le point vite fait. On à node.js, et ffmpeg fonctionnel.
    Il va falloir s’occuper maintenant de la partie serveur, je vais pas non plus m’allonger sur le sujet, d’autres s’en sont occupés largement.
    Voici la solution que j’ai adopté, en tombant sur cet article que je t’invites grandement à lire!

    http://phoboslab.org/log/2013/09/html5-live-video-streaming-via-websockets

    C’est l’article qui m’a permis de tout rassembler.

    Voici donc la suite:

  7. JSMPEGest une suite de scripts javascript juste top pour ce qu’on veut faire.
    Tu peux la télécharger ici:

    https://github.com/phoboslab/jsmpeg

    – copie le fichier « stream-server.js » sur ton raspberry, par exemple dans /Scripts/streamtest/ (par scp ou what else, samba, ssh, etc… 😉 )
    – copie « jsmpg.js » et « stream-example.html » dans un dossier « raspistream » sur ton bureau ou ailleurs, tant que tu le retrouves.

  8. WebSocket pour node.js
    Sur le raspberry, aller dans /Scripts/streamtest/ (là ou tu à copié « stream-server.js »)

    npm install ws

    Lancer le serveur de stream:

    node stream-server.js un-mot-de-passe
  9. FFMPEG pour capturer et encoder notre RaspiCam
    Toujours sur notre raspberry, on va lancer la commande ffmpeg qui s’occupera de la capture et encodage de notre PiCam.

    ffmpeg -s 320x240 -f video4linux2 -i /dev/video0 -f mpeg1video -b 800k -r 30 http://localhost:8082/un-mot-de-passe/320/240/

    Et là… c’est le drame… on ne trouve pas de device dans /dev/video0… grrrrr, encore quelques recherches et! Yes, solution!

  10. UV4L 
    http://www.raspberrypi.org/forums/viewtopic.php?f=43&t=74949
    cet article m’apporta la solution sous forme de lien suivants:
    http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14On installe!

    curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -

    Ajouter cette ligne à /etc/apt/sources.list

    deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main
    NOTE: Si vous utilisez raspbian jessie, remplacez wheezy par jessie main!

    On peut relancer apt-get update pour lister la nouvelle source:

    sudo apt-get update
    sudo apt-get install uv4l uv4l-raspicam
    sudo apt-get install uv4l-raspicam-extras

    Normalement, » ls /dev/video0 » devrait être présent.

    On peut prendre une photo via la PiCam pour valider:

    dd if=/dev/video0 of=snapshot.jpeg bs=11M count=1
  • On à toute les pièces, on rassemble le puzzle:
    Le serveur node.js tourne et attends les connections de la caméra (via ffmpeg) mais aussi du client.
    C’est la petite limitation, il faut que le client (le navigateur donc) supporte le protocole WebSocket.
    Mais bon, petite limitation, car Safari, Firefox et Chrome sont compatible.
    Il est temps de lancer la commande ffmpeg qui va capturer notre PiCam et envoyer le flux à notre script node.js:

    ffmpeg -s 320x240 -f video4linux2 -i /dev/video0 -f mpeg1video -b 800k -r 30 http://localhost:8082/un-mot-de-passe/320/240/

    Le serveur node.js doit indiquer « Stream Connected: »

  • Et on regarde comment alors?
    Au point 8, tu as dû copier des fichiers dans un dossier « raspistream » sur ton bureau ou documents…
    Edite le fichier html, et modifie l’adresse du serveur ws:// avec l’adresse ip de ton raspberry.
    Ouvre ensuite le fichier HTML dans un des naviguateurs compatible.
    Le serveur node.js va indiquer « New WebSocket Connection« 

On peut aussi dédier la tâche serveur sur une autre machine, il suffit ensuite de jouer avec la config des différentes ip 🙂

Voilà, pour la suite, je te laisse faire, les possibilités sont grandes, have fun! 😉

Have fun!

A venir prochainement:

  • scripts automatisé pour lancer node.js, ffmpeg, un serveur web nginx qui distribue le client html « jsmpeg »
    (il est prêt, il me reste à le commenter avant de vous le transmettre)

D’autres ressources non-citées: