Hello,
J’ai fait un timelaps d’un chantier en février 2021, à l’aide du plugin-camera et de Jeedom :
Un simple scenario demande au plugin de prendre une capture toutes les minutes (de 4h à 23h).
Puis un autre scénario lance un script bash tous les jours à 23h30 pour construire la vidéo horodatée du jour (plugin script /var/www/html/plugins/script/data/timelapse_chantier.sh &> /dev/null
).
Voici le script /var/www/html/plugins/script/data/timelapse_chantier.sh
(qui lance le script plus bas) :
Il prend des images individuelles et les transforment en vidéo :
- force l’écriture toutes les sorties dans un fichier de log,
- déplace toutes les images de la camera (eqId
585
) dans le répertoire du jour, - le répertoire est passé en paramètre du second script pour construire les sous-titres (horodatage),
- toutes les images sont concaténées avec ffmpeg (25 image par seconde => ~46s de video),
- une archive est créée avec toutes les photos et les sous-titres (peuvent être supprimés),
- reste à récupérer ou juste lire la vidéo depuis Jeedom.
#!/bin/sh
exec 1> /var/www/html/log/ffmpeg_timelapse 2>&1
echo -n "### BEGIN at " ; date '+%Y/%m/%d %X'
CHDATE=Chantier_$(date '+%Y-%m-%d')
cd /var/www/html/plugins/camera/data/records/585
[ -n "$(ls -A ${CHDATE}_*.jpg 2> /dev/null)" ] || exit 0
echo "### Starting"
mkdir ${CHDATE}
mv ${CHDATE}_*.jpg ${CHDATE}/
echo "### Generating subs"
/var/www/html/plugins/script/data/mdate2srt.py ${CHDATE} > ${CHDATE}.srt
echo -n "### Creating Timelapse at " ; date '+%Y/%m/%d %X'
nice -n 10 ffmpeg -nostdin -y -hide_banner -framerate 25 -pattern_type glob -i "${CHDATE}/*.jpg" -s:v 1024x768 -c:v libx264 -crf 17 -pix_fmt yuv420p -vf subtitles=${CHDATE}.srt ${CHDATE}.mp4
echo "### Tarring"
tar --remove-files -zcf ${CHDATE}.tgz ${CHDATE}/
echo -n "### DONE at " ; date '+%Y/%m/%d %X'
Le second script Python /var/www/html/plugins/script/data/mdate2srt.py
, s’occupe de la génération des sous titres pour l’horodatage :
- récupères tous les noms de fichier et la date de création de chaque fichier,
- construit (affiche sur la sortie standard) les sous-titres en anticipant le temps de chaque image,
- le format du sous-titre est
YYYY-mm-dd HH:MM
, je n’avais pas jugé utile de mettre les secondes.
#!/usr/bin/python3
import glob, os, sys, datetime, time
def sec2ts(h):
# seconds to 'nn:nn:nn,nnn' format
s = h % 60
ms = (s - int(s)) * 1000
s = int(s)
h -= s
h /= 60
m = h % 60
h -= m
h /= 60
return "%02d:%02d:%02d,%03d"%(h, m, s, ms)
def main():
dirpath = sys.argv[1] if len(sys.argv) == 2 else r'.'
files = list(filter(os.path.isfile, glob.glob(dirpath + "/*")))
entries = ((os.path.getmtime(f), f) for f in files)
# 1
# 00:00:01,000 --> 00:00:01,999
# TEST 1
fps=25
framed=1/fps
frame = 0
frameid = 1
# sep='#'
sep="\r\n"
# for (mdate, path) in entries:
for mdate, path in sorted(entries):
# print(datetime.datetime.fromtimestamp(mdate).strftime("%Y-%m-%d %H:%M"), os.path.basename(path))
line = str(frameid)+sep
frameid += 1
line += sec2ts(frame)
frame += framed
line += " --> "+sec2ts(frame)+sep
line += datetime.datetime.fromtimestamp(mdate).strftime("%Y-%m-%d %H:%M")+sep
print(line+"\r")
if __name__ == "__main__":
# execute only if run as a script
main()
Y’a probablement des choses à adapter et peut-être besoin d’ajouter des transferts de fichiers entre machines, mais c’est probablement une bonne base de travail
Pour le transfert vers ton NAS, tu peux utiliser SAMBA, NFS, ou (le plus simple) SCP
Pour SCP :
- Crée un partage sur ton NAS pour tes vidéos/photos,
- Crée un utilisateur qui n’a le droit d’accéder qu’à ce dossier,
- Vérifie avec WinSCP que tu as bien le droit avec cet utilisateur de transférer un fichier dans le dossier et que tu peux bien le lire avec ton utilisateur habituel sur le NAS,
- Dans le script Bash plus haut, rajoute à la fin quelque chose du style :
scp <user>@<IP NAS>:/var/www/html/plugins/camera/data/records/585/${CHDATE}.* /volume1/partage/
Ou il faut adapter , et les chemins. (Pour éviter les problèmes de certificat, tu peux ajouter
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
entre scp
et <user>
).
Hope it helps,
Bad