Publié le 27 janvier 2016 - par

Un timelapse pas comme les autres…

timelapse_web4allL’an passé l’hébergeur associatif Web4all proposait à ses adhérents/clients de tester -gratuitement- des serveurs VPS (Virtual Private Server = Serveur virtuel privé), suivant le principe premier inscrit premier servi. J’ai eu la chance de décrocher un VPS hébergé par Web4all qui souhaite ainsi tester sa future offre.
Automatiser entièrement un timelapse fut le deuxième projet testé sur ce VPS. Le premier avait été le traitement des trames SigFox dont je vous avais parlé en septembre.

Pour tester plus avant les possibilités du serveur, je propose à mon collègue Jean-Pierre qui a imaginé un projet de timelapse sur les levers de soleil, d’utiliser le VPS pour réaliser les vidéos, au lieu de les assembler sur le Raspberry. Ça devrait accélérer le processus et mettre la vidéo à disposition plus rapidement.

SI le projet vous intéresse, je vous propose un article décrivant cette réalisation. Attention, ce n’est pas un tutoriel ! Le projet est en constante évolution et pas du tout figé. Il sert aussi de « bac à sable » pour tester des solutions qui sont ensuite utilisées sur d’autres développements, y compris professionnels…
Ne vous attendez donc pas à un descriptif de type « Next.. Next.. Next » ! Si vous vous lancez dans un projet identique, il faudra vous prendre par la main et mettre au point certaines parties du projet (RTFM)…

Toutes les critiques sont possibles, sur la méthode, sur le code… Mais bon, si ça ne vous plait pas, il faudra réaliser « votre » projet et le publier… 🙂

Toutes les vidéos ne sont pas disponibles… Quand il y a de la brume on ne voit pas grand chose… Et puis la taille du disque étant limitée, il faut bien faire des choix 🙂

Le synoptique du projet

installation_timelapseUne caméra est chargée de prendre des photos toutes les 20 secondes. Le moment de la prise de vue est calculé en Python en fonction des heures de lever du soleil à l’endroit de la prise de vue.

Le Raspberry Pi dépose les photos dans un dossier du serveur VPS hébergé chez Web4all en passant par une liaison Wi-Fi, une FreeBox et Internet.

Le VPS qui a reçu les informations des heures de prise de vue démarre la construction de la vidéo et la publie sur Internet avec une mise en page minimaliste (bin oui quoi, c’est du test 🙂 ).

Voilà vous savez comment le système est organisé. On regarde les détails ?

Le VPS de Web4all

C’est Benoit (Expert infrastructure de Web4all) qui a bien voulu me donner les renseignements sur les VPS en test chez l’hébergeur.

Le serveur de virtualisation utilisé aujourd’hui, dans le cadre d’une pré-béta VPS de type container est basé sur une machine virtuelle qui fonctionne sous VMware.

En effet, toute l’infrastructure Web4all est virtualisée et offre déjà des services sur des VPS infogérés de type Vmware pour des besoins précis mais ce n’est pas encore mis en avant sur leur site. Les clients qui connaissent web4all n’hésitent pas à demander s’il est possible de mettre en place telle et telle solution ou infra pour eux.

web4all_470x210

Web4all envisage également de mettre un service de VPS type containter en place. Un projet parmi d’autres qui est lancé actuellement en pré-bêta pour avoir une idée du fonctionnement de la technologie
Pour l’instant il n’y a pas de panneau de gestion, ce n’est pas encore dans le manager Web4all actuellement ni dans la prochaine version qui devrait voir le jour avant la fin de l’année.
Le but des VPS de type container est de permettre aux clients de mettre en place des solutions suivant leur besoin pour des services qui ne nécessitent pas un environnement redondé. Donc on parle ici de services non productifs ou des applications non critiques au niveau disponibilité .

A terme, si ce service est lancé , web4all offrira la possibilité de déployer des VPS applicatifs pré-configurés.

Les classiques OS de base seront disponible (Centos, Debian, Ubuntu) avec installation/réinstallation depuis le manager.

Pour l’instant la question qui reste en suspend c’est de savoir si la virtualisation se fera en interne sur un serveur physique dédié ou si elle est externalisée chez un prestataire pour diminuer les coûts.

Le VPS d’un point de vue technique

Au niveau de la virtualisation

– Type de virtualisation : container
– Technologie de virtualisation LXD  basée sur LXC qui existe depuis plusieurs années.

lxd_takeover

La particularité ici est au niveau du fonctionnement de LXD et des containers « sans privilèges »… Globalement, l’utilsateur est root dans le container, mais sur l’hyperviseur, les processus exécutés dans le container en tant que root le sont comme un utilisateur standard sur le système. Si quelqu’un parvenait à s’échapper du container, il ne serait pas « root » sur la machine mais utilisateur standard.

Au niveau Hyperviseur

– Machine virtuelle (VM) type Vmware qui repose sur l’infrastructure web4all.
– Disque : 200 Go (LVM)
– OS: Ubuntu 15.04 (vivid)

baie_virtuelle

Au niveau réseau

– Virtualisation du réseau avec Open Vswitch (http://openvswitch.org/)
– Gestion des flux avec Open Flow (géré par OVS)

Au niveau VPS

Pour la pré-béta

Shares CPU: 1024
– Ram: 1Go
– Disque: 10 Go (en LVM)
– Connexion 10 Mb/s
– OS: Ubuntu 15.05 (vivid)
– Déploiement et mise en place automatisée entièrement par l’équipe Web4all 🙂

Comment ça marche ?

architecture_600px

Cliquez pour agrandir

Préparation du Raspberry

Matériel :

  • Raspberry Pi Model B
  • Carte SD avec distribution Wheezy en mode texte
  • clé USB WiFi
  • Caméra compatible Raspberry Pi
  • Alimentation 5V/2A
timelapse_0

Le Raspberry Pi utilisé pour le timelapse, avec une caméra à monture CS. (photoJ-P)

Préparer le Raspberry Pi

Si vous voulez tester l’encodage de la vidéo sur le Raspberry Pi, installez mencoder :

sudo apt-get install mencoder

La prise de vue se fera avec raspistill comme dans le tutoriel publié dans Epinglé.

raspistill -o timelapse_%d.jpg -tl 12000 -t 14400000

mencoder -nosound -ovc lavc -lavcopts vcodec=mpeg4 -o test.avi -mf type=jpeg:fps=20 mf://@files.txt

Les options de raspistill  -tl pour indiquer un timelapse avec prise de vue toutes les 12 secondes (12000 mS) pendant 4 heures (14400000 mS).

La ligne de commande avec mencoder permet de réaliser la vidéo sur le Raspberry Pi (ne soyez pas trop pressé(e) !) en fonction d’un liste files.txt dans laquelle on a copié les noms des photos à assembler. Le fichier obtenu, test.avi est en mpeg4.

timelapse_01

Le Raspberry Pi est posé sur un rebord de fenêtre. Il est abrité mais reste 24h/24h à l’extérieur. (photo J-P)

Le serveur est accessible sur vps.goblink.fr et le partage samba s’appelle goblink. Le partage du serveur est monté dans un premier temps manuellement sur le Raspberry Pi dans le dossier /home/pi/vps.

timelapse_montage_sambaUne fois que c’est testé et que ça fonctionne, il faut monter le partage dans /etc/fstab, sinon au premier redémarrage… hop ! plus de partage 🙁

timelapse_montage_fstab.jpg(les identifiants ont été masqués… allez savoir pourquoi?)

timelapse_02

Le Mont-Blanc est dans l’axe de prise de vue. Les branches sont visibles sur certaines vidéos. (photo J-P)

Le principe de fonctionnement étant de créer une crontab en Python, il faut installer le module python-crontab sur le Raspberry Pi.

pip install pyhton-crontab

Pour prendre en compte l’heure d’été :

heuredete = time.localtime().tm_isdst

Script exécuté à 00h01

A minuit et une minute (bin… pourquoi pas ?) le script python shedtlapse.py est exécuté.

Fichier shedtlapse.py

from math import cos, acos, sin, asin, degrees, radians
import crontab
import datetime
import time
import pickle
from crontab import CronTab

# Source:
# http://pagesperso-orange.fr/jean-paul.cornec/heures_lc.htm
class sunriseClass:
    def __init__(self):
        self.theDay=0
        self.theDate=[]
        self.solarDeclination=0
        self.equationOfTime=0
        self.latitude=0
        self.longitude=0
        self.sunrise=0
        self.sunset=0
        self.meridian=0
        self.duration=0
        self.sunriseTime=0
        self.sunsetTime=0
        self.meridianTime=0
        self.durationTime=0

    def getDay(self,d,m,y):
        d=float(d)
        m=float(m)
        y=float(y)
        n1 = int( (m* 275.0)/9.0 )
        n2 = int( (m+9.0)/12.0 )
        k = 1.0 + int( (y-4.0*int(y/4.0)+2.0)/3.0 )
        n=n1-n2*k+d-30.0
        return int(n)

    def getEoT(self,j):
        j=float(j)
        m = 357.0+(0.9856*j) 
        c = (1.914*sin(radians(m))) + (0.02*sin(radians(2.0*m)))
        l = 280.0 + c + (0.9856*j)
        r=(-2.465*sin(radians(2.0*l))) + (0.053*sin(radians(4.0*l)))
        Equ=(c+r)*4.0
        return Equ/60.0

    def getDec(self,j):
        j=float(j)
        m = 357.0+(0.9856*j) 
        c = (1.914*sin(radians(m))) + (0.02*sin(radians(2.0*m)))
        l = 280.0 + c + (0.9856*j)
        sinDec= 0.3978*sin(radians(l))
        return degrees(asin(sinDec))

    def getHo(self,Dec,Lat,Lon):
        cosHo=( -0.01454-sin(radians(self.solarDeclination))*sin(radians(self.latitude)) ) / ( cos(radians(self.solarDeclination))*cos(radians(self.latitude)) )
        return (degrees(acos(cosHo))/15.0)

    def setNumericalDate(self,d,m,y):
        self.theDate=[d,m,y]
        self.theDay=self.getDay(d,m,y)
        self.solarDeclination=self.getDec(self.theDay)
        self.equationOfTime=self.getEoT(self.theDay)
        return None

    def setLocation(self,Lat,Lon):
        self.latitude=Lat
        self.longitude=Lon
        return None

    def getHM(self,nH):
        h=int(nH)
        m=int(((nH*60.0)%60)+0.5)
        return '%d:%02d' % (h,m)

    def calculateWithUTC(self,UTC):
        mLon=(self.longitude*4.0)/60.0
        Ho=self.getHo(self.solarDeclination,self.latitude,self.longitude)
        self.meridian=12.0+self.equationOfTime-mLon+UTC
        self.sunrise=self.meridian-Ho 
        self.sunset=self.meridian+Ho 
        self.duration=2.0*Ho
        self.meridianTime=self.getHM(self.meridian)
        self.sunriseTime=self.getHM(self.sunrise)
        self.sunsetTime=self.getHM(self.sunset)
        self.durationTime=self.getHM(self.duration)
        return None

thisDay=datetime.date.today()
mySunrise=sunriseClass()
mySunrise.setNumericalDate(thisDay.day,thisDay.month,thisDay.year)
#mySunrise.setLocation(34.052222,-118.243611) # Los Angeles, UTC -8
#mySunrise.setLocation(41.012222,28.975833) # Istanbul, UTC +2
#mySunrise.setLocation(48.856667,2.350833) # Paris, UTC +1
mySunrise.setLocation(46.711667,4.696667) # renseigner votre location 
mySunrise.calculateWithUTC(+(1+time.localtime().tm_isdst))

coucher = mySunrise.sunset 
lever = mySunrise.sunrise

#-------------calcul décalage de la capture avant le lever du soleil---------------
debcapture = lever - 0.75
fincapture = debcapture + 2

coucherheure = int(coucher)
coucherminute =int( (coucher-int(coucher))*60)
leverheure = int(lever)
leverminute = int( (lever-int(lever))*60)

debcapheure = int(debcapture)
debcapminute = int((debcapture-int(debcapture))*60)

fincapheure = int(fincapture)
fincapminute = int((fincapture-int(fincapture))*60)

heuredete = time.localtime().tm_isdst

#----------------déclaration objet timelapse----------

timelapse ={
        "fincapture" :  fincapture,   
        "debcapheure":  debcapheure,
        "debcapminute": debcapminute,
        "fincapheure":  fincapheure,
        "fincapminute": fincapminute,
        "leverheure":   leverheure,
        "leverminute":  leverminute,
        "coucherheure": coucherheure,
        "coucherminute":  coucherminute,
}

#------------------génération de la tache crontab---------------------------
tab = CronTab(user='pi')
tab.remove_all()
cmd = 'sudo  /home/pi/capture.sh'
cron_job = tab.new(cmd, comment='timelaps du jour')
cron_job.minute.on(debcapminute)
cron_job.hour.on(debcapheure)

tab.write()
print tab.render()

#------------------création d'un fichier avec objet timelapse de la date du jour sur le serveur dans le dossier meta--------------
#-------------enregistrement de l’objet dans un fichier en texte-----------------------------
filename="./vpstimelaps/meta/" + str(thisDay.year) +"-"+ str(thisDay.month)+"-" + str(thisDay.day) + ".txt"    
with  open(filename,"wb")   as fichier:
    mon_pickler = pickle.Pickler(fichier)
    mon_pickler.dump(timelapse)

Jean-Pierre a utilisé un superbe programme (on ne réinvente pas le fil à couper l’eau chaude 😉 ) de Jean-Paul CORNEC qui calcule avec précision les heures de lever et de coucher du soleil. Les essais ont montré que (contrairement à ce que nous pensions) quelques kilomètres de décalage en longitude ou en latitude sont sensibles sur ces horaires…

timelapse_03

Sur cette photo on voit bien l’objectif à monture CS qui équipe la caméra – https://www.framboise314.fr/une-nouvelle-gamme-de-cameras-chez-arducam/2/ (photo J-P)

Script pour réaliser une capture d’images pendant 2 heures

Ce script est lancé pour réaliser la capture d’images pendant 2 heures, à raison d’une image toutes les 20 secondes.

timelapse_script_capture_2h

La zone couverte par la photo

timelapse_zone_couverte_600px

Cliquez pour agrandir.

Chaque image est prise depuis un point situé au sud-ouest de Chalon sur Saône, en direction du sud-est. La zone couverte par la photo englobe le Mont-Blanc (situé à 192 Km). La montagne apparait lorsque le temps est clair. On voit également la chaîne des Alpes sur la gauche du sommet de l’Europe.

timelapse_04

Le côté serveur

Côté serveur, le script Python cronjpg2mp4.py est lui exécuté tous les jours à 2h01, lancé depuis la crontab.

Fichier /etc/crontab du serveur

timelapse_crontab_serverLe fichier cronjpg2mp4.py lit le fichier contenant l’objet timelapse de la date du jour que le Raspberry Pi a déposé sur le serveur à minuit.

Il utilise les informations qu’il contient pour générer la tâche chargée d’exécuter l’assemblage des images 5 minutes après la fin de la capture.

timelapse_cronjpg

Cinq minutes après la fin de la prise de vue, le VPS lance l’assemblage des images pour en faire un vidéo. Il extrait également une image correspondant au moment du lever du soleil, pour en faire la miniature qui sera affichée pour présenter la vidéo (sinon la vidéo se charge et ralentit fortement l’affichage…).

Quand la vidéo est terminée, elle est transférée avec la miniature qui lui correspond. Le serveur web est chargé de gérer l’affichage des vidéos, le défilement avant/arrière…

Et ça donne quoi ?

Le mieux est d’aller voir sur le serveur VPS : http://vps.goblink.fr

Sinon, voici un avant-goût des résultats obtenus :

Conclusion

Encore en phase de test, le système connait parfois une interruption de service, souvent due à la perte de connexion du Raspberry Pi en Wi-Fi.

Par rapport au Raspberry qui mettait de nombreuses minutes (15 à 20 mn) pour assembler les 360 photos, le VPS raccourcit le temps de fabrication de la vidéo à 1 à 2 minutes minutes.

De plus, il permet de publier les vidéos en ligne à destination des visiteurs.

D’après les retours de Web4all, le serveur VPS est un des plus actifs de ceux mis à disposition pour les tests. Ne soyez pas étonné(e) si l’affichage est lent ou la diffusion de la vidéo un peu hâchée, la bande passante est (volontairement) limitée pour ces machines de test gratuites…

Merci à Jean-Pierre d’avoir mis cette expérience à disposition de la communauté.

Sources

Simple time lapse video in Linux

Time-lapse avec Raspberry Pi et sa (Pi)caméra

 

 

 

À propos François MOCQ

Électronicien d'origine, devenu informaticien, et passionné de nouvelles technologies, formateur en maintenance informatique puis en Réseau et Télécommunications. Dès son arrivée sur le marché, le potentiel offert par Raspberry Pi m’a enthousiasmé j'ai rapidement créé un blog dédié à ce nano-ordinateur (www.framboise314.fr) pour partager cette passion. Auteur de plusieurs livres sur le Raspberry Pi publiés aux Editions ENI.

11 réflexions au sujet de « Un timelapse pas comme les autres… »

  1. xhark

    C’est beau, bravo !
    Petite remarque sur le montage CIFS, la plupart des FAI bloquent purement et simplement le partage de fichier (smb/cifs) à travers internet, comme Numericable. Le plus sage serait de le tunneliser en SSH avec sshfs. Tu peux aussi opter pour du scp, bref les alternatives ne manquent pas 🙂

    On peut en savoir plus sur la référence de la caméra, car à cela n’a pas l’air d’être une raspicam ?

    Répondre
  2. Ping : Un timelapse pas comme les autres… | Fra...

  3. gabriel

    J’avais réalisé un montage de ce type avec prise de vue à intervalle régulier durant plusieurs mois. La caméra était une caméra Raspberry avec lentille CS permettant d’adapter différents objectifs, achetée sur watterott.com pour 24E environ, mais qui ne semble plus être au catalogue actuellement. On en trouve sur Amazon mais plus cher.
    J’avais utilisé pour la sauvegarde une clé USB + un envoi en FTP.
    Pour le FTP, voici l’essentiel:

    Récupération du client:
    sudo apt-get install putty-tools

    Commande pour envoyer une photo via FTP:
    sudo pscp -pw MOT_DE_PASSE_FTP CHEMIN_IMAGE_LOCALE UTILISATEUR_FTP@URL_SERVEUR:CHEMIN_SERVEUR

    Le montage a parfaitement tenu pendant les 8 mois d’utilisation mais le rythme de prise de vue était assez espacé (toutes les 20-30min). Un rythme plus court aurait probablement eu raison de la clé USB.

    Répondre
  4. loic

    Bonjour,

    Je débute sur raspberry et je m’essaye au timelapse … En suivant vos conseils j’ai automatisé le mien via la crontab et l’utilisation du script py pour que mon timelapse démarre un peu avant le début du lever du jour . J’aimerais le complémenter en le faisant s’arrêter de la même manière chaque jour 30 mn avant le coucher du soleil. Il me semble que le script py ne calcule pas le coucher du soleil, je ne peux donc pas m’en inspirer pour rajouter une tache dans la crontab qui mettrait fin à l’exécution du script de déclenchement de la capture à partir de l’heure du coucher …

    Comment puis je adapter le script ?

    Merci d’avance pour votre aide et pour votre site qui m’est bien utile depuis mes débuts
    cordialement

    Répondre
    1. François MOCQ Auteur de l’article

      Bonjour Loïc
      le script calcule bien le coucher du soleil
      coucherheure = int(coucher)
      coucherminute =int( (coucher-int(coucher))*60)
      leverheure = int(lever)
      leverminute = int( (lever-int(lever))*60)
      debcapheure = int(debcapture)
      debcapminute = int((debcapture-int(debcapture))*60)
      fincapheure = int(fincapture)
      fincapminute = int((fincapture-int(fincapture))*60)
      heuredete = time.localtime().tm_isdst

      cordialement
      François

      Répondre
  5. Lazy

    Salut. J utilise le raspi pour piloter un nikon, envoyer les jpg via 4G en ftp sur mon serveur, stocker les Raw sur un HD local et passe tous les trois mois échanger le hd. Ça tourne plusieurs années sans souci. Python Et ligne de commandes pour le Timelapse, AT pour envoyer des commandes au raspi ou récupérer des infos sur son fonctionnement.

    Répondre

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Complétez ce captcha SVP *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.