Supervision sonore

Retour accueil


Je suis récemment tombé sur des projets similaires, je les liste ici :

But et outillage

Une fois n’est pas coutume, faisons quelque chose qui n’implique pas que du texte. Quelque chose d’un peu plus fun : de la supervision de serveurs web avec du son. Cette expérimentation n’a pas vocation à se substituer à ce que serait de la supervision plus sérieuse. Elle a pour but :

J’ai décidé dans cet article d’utiliser principalement ffmpeg, souvent présenté comme le couteau suisse du son et de la vidéo. Cette décision est principalement motivée par le fait que je ne connais pas vraiment d’outil similaire et que celui-ci est fait pour être utilisé en ligne de commande, ce que j’apprécie. Cela dit ce ne veut pas pour autant dire que son utilisation est facile. ffmpeg est connu pour sa quantité d’options absolument gigantesque, ce qui est un atout en cela que la commande “sait tout faire”, mais est un gros désavantage à sa prise en main, sa découvrabilité, son utilisation lors des phases exploratoires. Ce passage du site de l’outil :

Converting video and audio has never been so easy.

 $ ffmpeg -i input.mp4 output.avi

Est vrai mais une fois sortie des cas d’usages les plus simples ça part vite en cacahuète. Comme beaucoup d’outils en ligne de commande passé une certaine quantité et complexité de paramétrage.

Cet article ne sera pas un cours de ffmpeg. Pour tout avouer je n’y comprends pas grand chose et j’en suis malheureusement encore à l’étape “copier/coller des trucs de stackoverflow et me plaindre de la documentation un peu nulle sans vraiment l’avoir lu ni vouloir investir le temps nécessaire à comprendre les principes fondamentaux” de ma relation avec cet outil. Avant lui le shell, gnuplot, sed etc.

Créer du son

Avant de se demander comment lier les logs à du son, demandons nous comment en créer. Il y aurait mille façons de le faire, mille sources à utiliser et mille sons à créer. Nous allons ici utiliser ffmpeg mais tout le reste de l’article peu se dérouler avec n’importe quel fichier audio, il n’est pas nécessaire d’en générer un de zéro.

Dans ffmpeg il existe un concept de “device”. Un device est… bah je sais pas bien. Ils semblent pouvoir être en entrée ou en sortie. En entrée un device semble être un élément configurable qui permet d’accéder à une source d’audio. Par exemple si vous êtes sur un linux, que vous utilisez alsa et que vous avez un micro sur votre ordinateur alors vous pouvez probablement y accéder via le device “alsa”. Pour choisir un device il faut utiliser l’option -f de ffmpeg.

Il se trouve qu’il existe un device nommé lavfi qui permet de générer une entrée “virtuelle”. Il semble possible de faire pleins de choses avec mais sans bien comprendre comment cela fonctionne je me suis contenté de trouver ça sur les internet :

$ ffplay -f lavfi -i "sine=frequency=440:duration=1"
ffplay ?

ffplay est un lecteur audio/vidéo qui utilise ffmpeg sous le capot. Cette commande a les mêmes arguments que si l’on avait voulu enregistrer l’audio généré dans un fichier avec ffmpeg plutôt que de directement le lire.

Cette commande utilise de device lavfi et prend en argument des commandes comprises par lavfi qui ici génèrent une fréquence de 440Hz pendant une seconde. sine est un “filtre” documenté ici. Il est un peu particulier puisque contrairement à la plupart des filtres il n’a pas pour objet de modifier une source mais d’un créer une. Il n’a donc pas d’entrée.

du bruit lovecraftien horrifique avec anoisesrc

Au passage je joue avec d’autres filtres et du bruit marron avec un sample rate très bas donne un côté “bruit qui vient du tréfond des océans” assez flippant et lovecraftien. Essayez

 $ ffplay -f lavfi -i "anoisesrc=c=brown:r=1000:a=1"

Le visuel généré par ffplay donne une dimension encore plus angoissante.
Le saviez vous ? Lovecraft était très raciste et antisémite

Plutôt que de directement jouer le son nous pouvons utiliser ffmpeg pour le stocker dans un fichier (ogg par exemple) :

ffmpeg -f lavfi -i "sine=frequency=440:duration=1" bip.ogg

On peut rejouer le fichier avec ffplay ou tout autre lecteur :

mpv bip.ogg

Pour l’article crééons quatre sons différents, quatre bip de fréquences différentes :

ffmpeg -f lavfi -i "sine=frequency=440:duration=1" bip.ogg
ffmpeg -f lavfi -i "sine=frequency=640:duration=1" bip-640.ogg
ffmpeg -f lavfi -i "sine=frequency=240:duration=1" bip-240.ogg
ffmpeg -f lavfi -i "sine=frequency=540:duration=1" bip-540.ogg
faire des bips à la fréquence aléatoire
$ seq N M | shuf | head -n1

Par exemple :

$ seq 200 1000 | shuf | head -n1
529

Si l’on veut générer quatre bip aléatoires on peut donc faire :

seq 200 1000 |
    shuf |
    head -n4 |
    xargs -I {} -r ffmpeg -f lavfi -i "sine=frequency={}:duration=1" bip-{}.ogg

qui exécutera :

ffmpeg -f lavfi -i sine=frequency=479:duration=1 bip-479.ogg
ffmpeg -f lavfi -i sine=frequency=812:duration=1 bip-812.ogg
ffmpeg -f lavfi -i sine=frequency=281:duration=1 bip-281.ogg
ffmpeg -f lavfi -i sine=frequency=624:duration=1 bip-624.ogg

Déclencher du son au bon moment

L’idée d’origine est de déclencher un son à chaque visite du site. On commence d’abord par récupérer les logs du serveur en local :

$ ssh host "tail -f /chemin/vers/logs"
130.79.96.42 - - [11/Jun/2024:15:48:23 +0200] "GET /style.css HTTP/1.1" 200 170 "http://zinzine.bebou.netlib.re/" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"
130.79.96.42 - - [11/Jun/2024:15:48:23 +0200] "GET /cssVarFilledCookies.css HTTP/1.1" 200 975 "http://zinzine.bebou.netlib.re/" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"
213.16.110.236 - - [11/Jun/2024:16:05:20 +0200] "GET / HTTP/1.0" 200 1068 "-" "-"
[...]

On peut boucler dessus avec un while :

ssh host "tail -f /chemin/vers/logs" |
while read line;do
    [...]
done
ssh, les commandes et les pipes

Si vous êtes étonné·es de voir ssh utilisé de la sorte j’explique. L’usage “habituel” d’ssh est de ssh host ce qui permet de récupérer un shell interactif sur la machine distant. En réalité on peut passer n’importe quelle commande en argument d’ssh. Celle-ci s’exécutera sur la machine distante. Ici on récupère donc les logs du serveur à l’aide d’un tail. Deuxième surprise éventuelle, le fait de piper le résultat de la commande ssh dans la suite de notre script. Ca peut paraître un peu magique (ou au contraire tout à fait logique selon les personnes) mais ssh “connecte” les entrées et sorties des commandes locales et distantes. Ainsi dans :

$ seq 10 | ssh host "paste -s -d '+'" | bc -l

Tout ça pour dire qu’ssh branche les pipes les un avec les autres pour qu’ils se comportent comme si la commande distante était exécutée en local.

En se basant sur le contenu de la variable $line on devrait pouvoir détecter (à la va vite on fait simple) quel site est visité :

ssh host "tail -f /chemin/vers/logs" |
while read line;do
    site=$(echo "$line" | grep -oE '/(arthur|doublezip|zinzine)\.')
    case "$site" in
        (/arthur.)    [...] ;;
        (/doublezip.) [...] ;;
        (/zinzine.)   [...] ;;
        (*)           [...] ;;
    esac
done

Et jouer un son différent selon le site avec deux dixième de seconde entre chacun :

ssh host "tail -f /chemin/vers/logs" |
while read line;do
    site=$(echo "$line" | grep -oE '/(arthur|doublezip|zinzine)\.')
    case "$site" in
        (/arthur.)
            ffplay -autoexit -nodisp -loglevel panic -i bip-281.ogg & ;;
        (/doublezip.)
            ffplay -autoexit -nodisp -loglevel panic -i bip-624.ogg & ;;
        (/zinzine.)
            ffplay -autoexit -nodisp -loglevel panic -i bip-812.ogg & ;;
        (*)
            ffplay -autoexit -nodisp -loglevel panic -i bip-479.ogg & ;;
    esac
    sleep 0.2
done

On emballe tout ça dans un script et on le lance ! On peut ajuster le sleep pour accélérer ou ralentir la lecture. On peut également retirer les & des lignes ffplay pour que chaque son soit joué l’un après l’autre de manière strictement séquentiel. Si un très grand nombre de requêtes arrivent dans un petit laps de temps ça risque de prendre un long moment pour tout dépiler.

Des idées