arthur.bebou

Le site arthur.bebou.netlib.re - retour accueil

git clone git://bebou.netlib.re/arthur.bebou
Log | Files | Refs |

index.sh (11362B)


      1 #! page
      2 title: Supervision sonore
      3 author: Arthur Pons
      4 description: De la supervision de serveur web \(ou autre\) avec du son
      5 publication: 2024-06-11
      6 
      7 sectionmd: main
      8 
      9 Je suis récemment tombé sur des projets similaires, je les liste ici :
     10 
     11   * Sonoriser les cookies : https://vimeo.com/502348796
     12   * Bip à chaque paquet envoyé à un tracker : https://berthub.eu/articles/posts/tracker-beeper/
     13 
     14 ## But et outillage
     15 
     16 Une fois n'est pas coutume, faisons quelque chose qui n'implique pas *que* du texte.
     17 Quelque chose d'un peu plus fun : de la supervision de serveurs web avec du son.
     18 Cette expérimentation n'a pas vocation à se substituer à ce que serait de la
     19 supervision plus sérieuse. Elle a pour but :
     20 
     21   * d'être un moyen ludique de garder un œil (ou une oreille huhu) sur
     22     l'activité des sites du serveur
     23   * de favoriser les interactions avec les utilisateur·ices
     24   * d'être un outil pédagogique autour du web
     25   * apprendre quelques trucs au sujet du son sur linux
     26 
     27 J'ai décidé dans cet article d'utiliser principalement
     28 [ffmpeg](https://ffmpeg.org/), souvent présenté comme le couteau suisse du son
     29 et de la vidéo. Cette décision est principalement motivée par le fait que je ne
     30 connais pas vraiment d'outil similaire et que celui-ci est fait pour être
     31 utilisé en ligne de commande, ce que j'apprécie. Cela dit ce ne veut pas pour
     32 autant dire que son utilisation est facile. ffmpeg est connu pour sa quantité
     33 d'options absolument gigantesque, ce qui est un atout en cela que la commande
     34 "sait tout faire", mais est un gros désavantage à sa prise en main, sa
     35 découvrabilité, son utilisation lors des phases exploratoires. Ce passage du
     36 site de l'outil :
     37 
     38 > Converting video and audio has never been so easy.
     39 
     40 >      $ ffmpeg -i input.mp4 output.avi
     41 
     42 Est vrai mais une fois sortie des cas d'usages les plus simples ça
     43 part vite en cacahuète. Comme beaucoup d'outils en ligne de commande passé une
     44 certaine quantité et complexité de paramétrage.
     45 
     46 Cet article ne sera pas un cours de ffmpeg. Pour tout avouer je n'y comprends
     47 pas grand chose et j'en suis malheureusement encore à l'étape *"copier/coller des
     48 trucs de stackoverflow et me plaindre de la documentation un peu nulle sans
     49 vraiment l'avoir lu ni vouloir investir le temps nécessaire à comprendre les
     50 principes fondamentaux"* de ma relation avec cet outil. Avant lui le shell,
     51 gnuplot, sed etc.
     52 
     53 ## Créer du son
     54 
     55 Avant de se demander comment lier les logs à du son, demandons nous comment en
     56 créer. Il y aurait mille façons de le faire, mille sources à utiliser et mille
     57 sons à créer. Nous allons ici utiliser ffmpeg mais tout le reste de l'article
     58 peu se dérouler avec n'importe quel fichier audio, il n'est pas nécessaire d'en
     59 générer un de zéro.
     60 
     61 Dans ffmpeg il existe un concept de
     62 "[device](https://ffmpeg.org/ffmpeg-devices.html)". Un device est... bah je sais
     63 pas bien. Ils semblent
     64 pouvoir être en entrée ou en sortie. En entrée un device semble être un élément
     65 configurable qui permet d'accéder à une source d'audio. Par exemple si vous êtes
     66 sur un linux, que vous utilisez
     67 [alsa](https://www.alsa-project.org/wiki/Main_Page) et que vous avez un micro
     68 sur votre ordinateur alors vous pouvez probablement y accéder via le device
     69 "alsa". Pour choisir un device il faut utiliser l'option `-f` de ffmpeg.
     70 
     71 Il se trouve qu'il existe un device nommé
     72 [lavfi](https://ffmpeg.org/ffmpeg-devices.html#lavfi) qui permet de générer une
     73 entrée "virtuelle". Il semble possible de faire pleins de choses avec mais sans
     74 bien comprendre comment cela fonctionne je me suis contenté de trouver ça sur
     75 les internet :
     76 
     77     $ ffplay -f lavfi -i "sine=frequency=440:duration=1"
     78 
     79 endsection
     80 
     81 <<. ./details "ffplay ?" | save_html main
     82 ffplay est un lecteur audio/vidéo qui utilise ffmpeg sous le capot. Cette
     83 commande a les mêmes arguments que si l'on avait voulu enregistrer l'audio
     84 généré dans un fichier avec ffmpeg plutôt que de directement le lire.
     85 .
     86 
     87 sectionmd: main
     88 
     89 Cette commande utilise de device `lavfi` et prend en argument des commandes
     90 comprises par lavfi qui ici génèrent une fréquence de 440Hz pendant une seconde.
     91 `sine` est un "filtre" documenté
     92 [ici](https://ffmpeg.org/ffmpeg-filters.html#Sine). Il est un peu
     93 particulier puisque contrairement à la plupart des filtres il n'a pas pour objet
     94 de modifier une source mais d'un créer une. Il n'a donc pas d'entrée.
     95 
     96 endsection
     97 
     98 <<. ./details "du bruit lovecraftien horrifique avec anoisesrc" | save_html main
     99 
    100 Au passage je joue avec d'autres filtres et du bruit marron avec un sample
    101 rate très bas donne un côté "bruit qui vient du tréfond des océans" assez
    102 flippant et lovecraftien. Essayez
    103 
    104      $ ffplay -f lavfi -i "anoisesrc=c=brown:r=1000:a=1"
    105 
    106 Le visuel généré par ffplay donne une dimension encore plus angoissante.  
    107 Le saviez vous ? [Lovecraft était très raciste et antisémite](https://fr.wikipedia.org/wiki/H._P._Lovecraft#Race,_ethnie_et_classe)
    108 
    109 .
    110 
    111 sectionmd: main
    112 
    113 Plutôt que de directement jouer le son nous pouvons utiliser ffmpeg pour le
    114 stocker dans un fichier (ogg par exemple) :
    115 
    116     ffmpeg -f lavfi -i "sine=frequency=440:duration=1" bip.ogg
    117 
    118 On peut rejouer le fichier avec ffplay ou tout autre lecteur :
    119 
    120     mpv bip.ogg
    121 
    122 Pour l'article crééons quatre sons différents, quatre bip de fréquences
    123 différentes :
    124 
    125     ffmpeg -f lavfi -i "sine=frequency=440:duration=1" bip.ogg
    126     ffmpeg -f lavfi -i "sine=frequency=640:duration=1" bip-640.ogg
    127     ffmpeg -f lavfi -i "sine=frequency=240:duration=1" bip-240.ogg
    128     ffmpeg -f lavfi -i "sine=frequency=540:duration=1" bip-540.ogg
    129 
    130 endsection
    131 
    132 <<. ./details "faire des bips à la fréquence aléatoire" | save_html main
    133 On peut générer un entier aléatoire entre N et M en faisant :
    134 
    135     $ seq N M | shuf | head -n1
    136 
    137 Par exemple :
    138 
    139     $ seq 200 1000 | shuf | head -n1
    140     529
    141 
    142 Si l'on veut générer quatre bip aléatoires on peut donc faire :
    143 
    144     seq 200 1000 |
    145         shuf |
    146         head -n4 |
    147         xargs -I {} -r ffmpeg -f lavfi -i "sine=frequency={}:duration=1" bip-{}.ogg
    148 
    149 qui exécutera :
    150 
    151     ffmpeg -f lavfi -i sine=frequency=479:duration=1 bip-479.ogg
    152     ffmpeg -f lavfi -i sine=frequency=812:duration=1 bip-812.ogg
    153     ffmpeg -f lavfi -i sine=frequency=281:duration=1 bip-281.ogg
    154     ffmpeg -f lavfi -i sine=frequency=624:duration=1 bip-624.ogg
    155 
    156 .
    157 
    158 sectionmd: main
    159 
    160 ## Déclencher du son au bon moment
    161 
    162 L'idée d'origine est de déclencher un son à chaque visite du site. On commence
    163 d'abord par récupérer les logs du serveur en local :
    164 
    165     $ ssh host "tail -f /chemin/vers/logs"
    166     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"
    167     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"
    168     213.16.110.236 - - [11/Jun/2024:16:05:20 +0200] "GET / HTTP/1.0" 200 1068 "-" "-"
    169     [...]
    170 
    171 On peut boucler dessus avec un `while` :
    172 
    173     ssh host "tail -f /chemin/vers/logs" |
    174     while read line;do
    175         [...]
    176     done
    177 
    178 endsection
    179 
    180 <<\. ./details "ssh, les commandes et les pipes" | save_html main
    181 
    182 Si vous êtes étonné·es de voir ssh utilisé de la sorte j'explique.  L'usage
    183 "habituel" d'ssh est de `ssh host` ce qui permet de récupérer un shell
    184 interactif sur la machine distant. En réalité on peut passer n'importe quelle
    185 commande en argument d'ssh. Celle-ci s'exécutera sur la machine distante.  Ici
    186 on récupère donc les logs du serveur à l'aide d'un `tail`.  Deuxième surprise
    187 éventuelle, le fait de piper le résultat de la commande ssh dans la suite de
    188 notre script. Ca peut paraître un peu magique (ou au contraire tout à fait
    189 logique selon les personnes) mais ssh "connecte" les entrées et sorties des
    190 commandes locales et distantes. Ainsi dans :
    191 
    192     $ seq 10 | ssh host "paste -s -d '+'" | bc -l
    193 
    194   * `seq 10` est exécuté sur la machine locale, sa sortie est branchée à
    195     l'entrée de la commande `ssh`
    196   * `ssh` est exécuté en local et lance `paste -s -d '+'` sur la machine
    197     distante. Au passage ssh branche son entrée (la sortie de `seq`) sur l'entrée
    198     de la commande `paste` sur la machine distante. ssh récupère également la
    199     sortie du paste sur la machine distante pour la transmettre au pipe sur la
    200     machine locale.
    201   * `bc -l` est exécuté en local, son entrée étant la sortie de la commande ssh
    202     qui est la sortie de la commande paste distante.
    203 
    204 Tout ça pour dire qu'ssh branche les pipes les un avec les autres pour qu'ils
    205 se comportent comme si la commande distante était exécutée en local.
    206 .
    207 
    208 sectionmd: main
    209 
    210 En se basant sur le contenu de la variable `$line` on devrait pouvoir détecter
    211 (à la va vite on fait simple) quel site est visité :
    212 
    213     ssh host "tail -f /chemin/vers/logs" |
    214     while read line;do
    215         site=$(echo "$line" | grep -oE '/(arthur|doublezip|zinzine)\.')
    216         case "$site" in
    217             (/arthur.)    [...] ;;
    218             (/doublezip.) [...] ;;
    219             (/zinzine.)   [...] ;;
    220             (*)           [...] ;;
    221         esac
    222     done
    223 
    224 Et jouer un son différent selon le site avec deux dixième de seconde entre
    225 chacun :
    226 
    227     ssh host "tail -f /chemin/vers/logs" |
    228     while read line;do
    229         site=$(echo "$line" | grep -oE '/(arthur|doublezip|zinzine)\.')
    230         case "$site" in
    231             (/arthur.)
    232                 ffplay -autoexit -nodisp -loglevel panic -i bip-281.ogg & ;;
    233             (/doublezip.)
    234                 ffplay -autoexit -nodisp -loglevel panic -i bip-624.ogg & ;;
    235             (/zinzine.)
    236                 ffplay -autoexit -nodisp -loglevel panic -i bip-812.ogg & ;;
    237             (*)
    238                 ffplay -autoexit -nodisp -loglevel panic -i bip-479.ogg & ;;
    239         esac
    240         sleep 0.2
    241     done
    242 
    243 On emballe tout ça dans un script et on le lance ! On peut ajuster le sleep pour
    244 accélérer ou ralentir la lecture. On peut également retirer les `&` des lignes
    245 ffplay pour que chaque son soit joué l'un après l'autre de manière strictement
    246 séquentiel. Si un très grand nombre de requêtes arrivent dans un petit laps de
    247 temps ça risque de prendre un long moment pour tout dépiler.
    248 
    249 ## Des idées
    250 
    251   * Streamer le son sur une radio. Parfois c'est live sur la radio
    252     [sup-sonore](http://bebou.netlib.re:1111/sup-sonore.ogg)
    253   * Demander à chaque personne qui rejoint le serveur un fichier audio d'une
    254     seconde pour que ce soit le son associé à leur site
    255   * L'explication de ce script en atelier CESAR démontre que pour une personne
    256     avec un niveau moyen en Unix c'est un projet assez pédagogique
    257   * On pourrait utiliser ce système pour créer des pièces sonores basées sur
    258     l'interaction avec un public lors d'un concert par exemple. On peut imaginer
    259     des interactions plus sobres (et accessibles, pleins de personnes n'ont pas
    260     de smartphone) que de sortir son smartphone et spammer un site
    261     mais plus facile à mettre en place sans matériel dédié je suis pas sûr.
    262   * On peut imaginer n'importe quel truc à la place de balancer du son. Des
    263     idées en vrac : générer ou dévoiler une image (merci
    264     [Miguel](https://mig-ap.com)), générer une mosaïque, que les sons soient des
    265     notes...
    266