2020-09-27 17:15:15 +02:00
|
|
|
|
%
|
|
|
|
|
% new 24 juillet 2014 - Mixart Myrys
|
|
|
|
|
%
|
|
|
|
|
\chapter{streaming}
|
2020-11-13 01:35:31 +01:00
|
|
|
|
\label{chap:streaming}
|
2020-09-27 17:15:15 +02:00
|
|
|
|
\index{streaming}
|
|
|
|
|
|
|
|
|
|
Avertissement : pour le moment\footnote{En juillet 2014}, nous
|
|
|
|
|
n'allons nous pencher que sur la diffusion de flux audios, avec
|
|
|
|
|
des encodages libres comme \textsl{ogg} ou \textsl{speex}.
|
|
|
|
|
Tout simplement parce que le monde de la vidéo est un gigantesque
|
|
|
|
|
foutoir de codecs, de containers, de brevets logiciels et
|
|
|
|
|
d'incompatiblités diverses et variées.
|
|
|
|
|
|
2021-02-04 09:58:41 +01:00
|
|
|
|
Une notion importante à bien comprendre, c'est l'organisation
|
|
|
|
|
du flux des sons immatériels au travers des intertubes.
|
|
|
|
|
|
|
|
|
|
\textbf{insert picture here !}\index{XXX}
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
\section{icecast2}
|
|
|
|
|
\index{icecast2}
|
|
|
|
|
\label{icecast2}
|
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
Icecast est, semble-t-il, \textbf{le} serveur de streaming de référence.
|
|
|
|
|
Il se configure facilement avec des fichiers en XML\index{XML}.
|
|
|
|
|
Première approche d'une ergonomie différente, vous êtes avertis.
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
\begin{quote}
|
|
|
|
|
Icecast, the project, is a collection of programs and libraries for
|
|
|
|
|
streaming audio over the Internet. This includes:
|
|
|
|
|
Icecast, the program that streams audio data to listeners,
|
|
|
|
|
libshout, a library for communicating with Icecast servers and
|
2020-12-11 15:06:59 +01:00
|
|
|
|
Ices2\index{ices}, a program that sends audio data to Icecast servers
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
|
|
|
|
\end{quote}
|
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
Pour alimenter Icecast en son, il faut utiliser un
|
|
|
|
|
\textsl{source-client} approprié. Le modèle recommandé
|
|
|
|
|
est \textbf{ices2} qui est détaillé un peu plus loin,
|
|
|
|
|
à la page \pageref{ices2}.
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
Il peut envoyer depuis une entrée audio (alsa, jack, pulseaudio...)
|
|
|
|
|
ou une playlistde fichiers \texttt{.ogg}\index{ogg}.
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
|
|
|
|
|
\textsl{more to come...}
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
\section{liquidsoap}
|
|
|
|
|
\index{liquidsoap}
|
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
Mais nous allonc commencer par un outil puissant, bien que
|
|
|
|
|
délicat à comprendre au premier abord~:
|
2020-11-10 02:40:30 +01:00
|
|
|
|
\texttt{https://www.liquidsoap.info/}
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
\begin{quote}
|
2020-12-22 22:53:57 +01:00
|
|
|
|
Liquidsoap is an extensible and flexible audio stream generator,
|
|
|
|
|
mainly used for streaming to a shoutcast/icecast server.
|
|
|
|
|
It is also possible to output in a file, to speakers or as
|
|
|
|
|
raw PCM stream.
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
liquidsoap can
|
|
|
|
|
perform any audio processing, mixing streams together,
|
|
|
|
|
applying filters, generating sound procedurally,
|
|
|
|
|
there is no limit but your imagination.
|
|
|
|
|
Input files can be accessed through the network, using samba,
|
|
|
|
|
ftp or speech synthesis.
|
|
|
|
|
The system features lots of programming operators, including user
|
|
|
|
|
requests, time-based selection, sum...
|
|
|
|
|
\end{quote}
|
|
|
|
|
|
|
|
|
|
Un étonnant langage de script pour gérer tous ces octets musicaux
|
|
|
|
|
en les promenant un peu dans tous les sens, la possibilité
|
|
|
|
|
de commander Savonet avec un simple telnet\index{telnet}.
|
|
|
|
|
Vite, un exemple d'utilisation, vous créez un fichier texte avec
|
|
|
|
|
cez quelques lignes dedans et vous le sauvez sous le nom
|
|
|
|
|
\texttt{savon.liq} :
|
|
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
set("log.file.path","/tmp/savon.log")
|
|
|
|
|
set("log.stdout",true)
|
|
|
|
|
|
|
|
|
|
output.icecast (%vorbis,
|
|
|
|
|
host = "10.20.0.23",
|
|
|
|
|
port = 1984,
|
|
|
|
|
password = "hopla!",
|
|
|
|
|
mount = "savon.ogg",
|
|
|
|
|
single("loveme.ogg"))
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
|
|
Avec ce petit programme, nous pouvons envoyer en boucle un fichier
|
|
|
|
|
Ogg vers notre serveur.
|
|
|
|
|
Les deux premières lignes permettent de voir et d'enregistrer les
|
|
|
|
|
diverses actions.
|
|
|
|
|
Et la grosse instruction \texttt{output.icecast}
|
|
|
|
|
envoie la musique dans votre serveur
|
|
|
|
|
Icecast2 en passant les paramètres nécessaires.
|
|
|
|
|
|
2021-02-17 17:07:18 +01:00
|
|
|
|
\subsection{Logfile}
|
|
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
set("log.file.path", "/home/tth/Radio/log/takeover.log")
|
|
|
|
|
set("log.stdout", false)
|
|
|
|
|
set("log.level",3)
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
|
|
Alors, la grande question est : « quelle valeur pour le loglevel ? », et
|
|
|
|
|
la réponse n'est pas évidente à trouver dans la documentation, il y
|
|
|
|
|
a même un ticker ouvert\dots
|
|
|
|
|
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item{1 = critical}
|
|
|
|
|
\item{2 = important}
|
|
|
|
|
\item{3 = normal}
|
|
|
|
|
\item{4 = information}
|
|
|
|
|
\item{5 = debug}
|
|
|
|
|
\end{itemize}
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
\subsection{10.20.0.23}
|
|
|
|
|
|
|
|
|
|
Maintenant, voyons un exemple plus complet et plus réaliste,
|
|
|
|
|
largement inspiré d'un tutoriel de la documentation officielle,
|
2020-12-11 15:06:59 +01:00
|
|
|
|
et qui deviendra un de ces jours la base de la nouvelle%
|
|
|
|
|
\footnote{L'ancienne ayant été fermée pour des raisons
|
|
|
|
|
incompréhensibles.} radio de Myrys~:
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
set("log.file.path", "/tmp/savon.log")
|
|
|
|
|
set("log.stdout", false)
|
|
|
|
|
|
|
|
|
|
default = single("loveme.ogg")
|
|
|
|
|
openbsd = playlist(mode="random", "files/openbsd.pls")
|
|
|
|
|
others = playlist(mode="random", "files/others.pls")
|
|
|
|
|
jingles = playlist( "files/jingles.pls")
|
|
|
|
|
|
|
|
|
|
radio = fallback([ switch([({ 5h-11h }, openbsd),
|
|
|
|
|
({ 11h-5h }, others)]),
|
|
|
|
|
default])
|
|
|
|
|
radio = random(weights=[1,12],[ jingles, radio ])
|
|
|
|
|
|
|
|
|
|
output.icecast( %vorbis,
|
|
|
|
|
host = "localhost",
|
|
|
|
|
port = 1984,
|
|
|
|
|
password = "hopla!",
|
|
|
|
|
mount = "savon.ogg",
|
|
|
|
|
radio)
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
|
|
Ah bah oui, ça commence à être robuste, mais en fait c'est
|
2020-12-11 15:06:59 +01:00
|
|
|
|
presque simple à comprendre, et un peu plus compliqué à mettre
|
2020-09-27 17:15:15 +02:00
|
|
|
|
en œuvre.
|
|
|
|
|
|
|
|
|
|
On se retrouve vite face à un problème classique :
|
|
|
|
|
les différences de niveau sonore entre les divers morceaux.
|
|
|
|
|
Et comme on veut avancer sur d'autres choses, on rache un
|
|
|
|
|
petit bout de Bash avec de la poudre verte dedans :
|
|
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
#!/bin/bash/
|
|
|
|
|
echo "que faire ?"
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
|
|
Cette poudre verte pourrait bien être \texttt{vorbisgain(1)}\dots
|
|
|
|
|
|
|
|
|
|
\subsection{rotation des playlists}
|
|
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
|
pl2014 = playlist("2014")
|
|
|
|
|
pl2013 = playlist("2013")
|
|
|
|
|
...
|
|
|
|
|
jingles = playlist("jingles")
|
|
|
|
|
s = rotate([pl2014, pl2013, ..., jingles])
|
|
|
|
|
output.icecast(..., s)
|
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
\subsection{Take over the playlist}
|
|
|
|
|
|
|
|
|
|
XXX\index{XXX}
|
|
|
|
|
|
|
|
|
|
Il est également possible, avec liquidsoap, d'interrompre la
|
|
|
|
|
diffusion d'une playlist à partir d'une autre source
|
|
|
|
|
(fichier ou entrée audio), eventuellement externe.
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
2020-12-22 22:53:57 +01:00
|
|
|
|
\lstinputlisting{code/takeover.liq}
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
\subsection{trucs divers}
|
|
|
|
|
|
|
|
|
|
Que signifie ce message : \textbf{That source is fallible.} ?
|
|
|
|
|
Par exemple, que le fichier que vous aviez soigneusement
|
|
|
|
|
désigné comme \texttt{default} n'existe plus sur le disque.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Comment envoyer vers plusieurs icecasts ? Bah c'est très facile :
|
|
|
|
|
il suffit de mettre plusieurs "blocs" \texttt{output.icecast} à
|
|
|
|
|
la suite les uns des autres ;)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
%====================================================================
|
|
|
|
|
\section{Source clients}
|
|
|
|
|
\label{sourceclients}
|
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
Il existe une foultitude de clients source pour abreuver icecast2.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
\subsection{ices2} \index{ices2} \label{ices2}
|
|
|
|
|
|
|
|
|
|
Premier mystère : comment faire le rapprochement entre
|
|
|
|
|
la déclaration du périphérique d'entrée
|
|
|
|
|
(\texttt{<param name="device">hw:1,0</param>}) et
|
|
|
|
|
l'équivalent dans le monde Alsa ?
|
|
|
|
|
|
|
|
|
|
La commande \texttt{arecord -L} va nous donner quelques
|
|
|
|
|
informations sur les « points d'entrée » utilisables.
|
|
|
|
|
Liste dont nous extrayons (par la pure pensée logique)
|
|
|
|
|
ce fameux nom de device~: \texttt{ plughw:CARD=Snowball,DEV=0}
|
|
|
|
|
XXX\index{XXX} que nous pouvons mettre dans le XML.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\textbf{Attention} si votre source est monophonique, comme
|
|
|
|
|
le microphone USB \textsc{Snowball} utilisé dans cet exemple,
|
|
|
|
|
il NE faut PAS mettre \textsl{downmix} à 1\dots
|
|
|
|
|
|
2020-12-22 22:53:57 +01:00
|
|
|
|
Et si vous souhaitez dupliquer une entrée à un seul canal
|
|
|
|
|
(genre un micro usb) por obtenir une sortie stéréo, ça ne
|
|
|
|
|
semble pas possible fin 2020\index{2020}. Il serait temps
|
|
|
|
|
de songer à écrire un patch\index{patch}.
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
\subsection{Ezstream}
|
|
|
|
|
|
|
|
|
|
\begin{quote}
|
|
|
|
|
Ezstream is an audio and video streaming client which feeds any
|
|
|
|
|
icecast server with audio data and metadata from a standard input
|
|
|
|
|
without reencoding. It thus requires very little CPU resources. Some
|
|
|
|
|
playlists can be looped and composed with MP3, Ogg Vorbis or Ogg
|
|
|
|
|
Theora media files.
|
|
|
|
|
\end{quote}
|
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
\subsection{darkice}
|
|
|
|
|
\index{darkice}
|
|
|
|
|
|
|
|
|
|
\begin{quote}
|
|
|
|
|
DarkIce as a live audio streamer. It records audio from an audio
|
|
|
|
|
interface (e.g. sound card), encodes it and sends it to a streaming server.
|
|
|
|
|
\end{quote}
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
\subsection{VLC}
|
2021-10-15 23:22:38 +02:00
|
|
|
|
\index{vlc} \label{streamvlc}
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
2020-12-22 22:53:57 +01:00
|
|
|
|
VLC est le « cône de chantier » du multimédia.
|
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
\subsection{butt}
|
|
|
|
|
\index{butt}
|
|
|
|
|
|
|
|
|
|
Du clickaconvi qui plante en X remote ;( mais sinon une
|
2021-10-15 23:22:38 +02:00
|
|
|
|
interface graphique simple et facile d'emploi. Un bon
|
|
|
|
|
choix pour qui aime les choses simples où juste
|
|
|
|
|
brancher un microphone et causer dans le Ternet.
|
2020-12-22 22:53:57 +01:00
|
|
|
|
|
2020-12-11 15:06:59 +01:00
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
\subsection{idjc}
|
|
|
|
|
\index{idjc}
|
|
|
|
|
|
|
|
|
|
\begin{quote}
|
|
|
|
|
Internet DJ Console is an Internet radio application for making a
|
|
|
|
|
live radio show or podcast. Features include two main media players
|
|
|
|
|
with a crossfader, a jingle player, microphone signal processing
|
|
|
|
|
(compressor and noise gate)
|
|
|
|
|
\end{quote}
|
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
\subsection{Android} \index{Android}
|
|
|
|
|
|
|
|
|
|
Cool Mic \texttt{https://coolmic.net/} ?
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
2020-12-22 22:53:57 +01:00
|
|
|
|
Mais il faut avoir quelques connaissances en \textsc{modernophone}
|
|
|
|
|
pour arriver à tenter de comprendre pouquoi ça ne fonctionne pas,
|
|
|
|
|
alors que tout semble correct.
|
|
|
|
|
|
|
|
|
|
|
2021-02-04 09:58:41 +01:00
|
|
|
|
%====================================================================
|
|
|
|
|
\section{Gadgets}
|
|
|
|
|
|
|
|
|
|
On peut aussi imaginer des \textsl{client sources} plus ésotériques.
|
|
|
|
|
L'exemple classique étant l'utilisation de la synthèse vocale pour
|
|
|
|
|
faire une horloge parlante. Mais comme tout vieux linuxien, j'attache
|
|
|
|
|
un intérêt tout particulier à une valeur symbolique~:
|
|
|
|
|
l'uptime de ma machine.
|
|
|
|
|
En ces temps troublés\footnote{Début janvier 2021, le collectif
|
|
|
|
|
d'artistes Mixart-Myrys, dont je fais partie depuis dix ans,
|
2021-02-04 12:16:18 +01:00
|
|
|
|
est en train de se faire salement éjecter de son hangartistique.
|
2021-02-04 09:58:41 +01:00
|
|
|
|
À cette occasion, j'ai remonté \textit{à la rache} un Icecast,
|
2021-02-04 14:39:31 +01:00
|
|
|
|
et je l'ai voulu un peu surprenant pour le béotien, d'où l'uptime parlé.},
|
2021-02-04 09:58:41 +01:00
|
|
|
|
l'uptime, c'est important.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\lstinputlisting{code/say-uptime.sh}
|
|
|
|
|
|
|
|
|
|
L'option \texttt{-p} de la commande \texttt{uptime} permet d'obtenir
|
|
|
|
|
une sortie de cette forme : \textsf{up 1 day, 1 hour, 37 minutes}
|
|
|
|
|
qu'une micromagie \texttt{sed} change en une forme plus correcte
|
|
|
|
|
syntaxiquement, bien qu'anglo-saxonne.
|
|
|
|
|
|
|
|
|
|
La ligne suivante sert uniquement d'affichage de contrôle, et peut
|
|
|
|
|
être supprimée sans vergogne.
|
|
|
|
|
|
|
|
|
|
\label{say-uptime}
|
|
|
|
|
Les trois lignes suivantes vont effectivement généré le son qui sera
|
|
|
|
|
envoyé vers la radio\index{radio} de l'Internet.
|
|
|
|
|
|
2021-02-17 17:07:18 +01:00
|
|
|
|
Premier élément du pipeline, \texttt{espeak-ng} reçoit le texte
|
2021-02-04 09:58:41 +01:00
|
|
|
|
par son \textsl{stdin} et génère le flux de
|
|
|
|
|
parole sur son \textsl{stdout}, à partir des options
|
|
|
|
|
\texttt{-g 9 -s 150 -a 133}, réglant la voix synthétique.
|
|
|
|
|
Ensuite, il faut que les échantillons sonores soient au format
|
|
|
|
|
physique attendu par le diffuseur,
|
|
|
|
|
d'où la conversion en 2$x$16 bits. Et pour finir, il est
|
|
|
|
|
encodé/encapsulé dans du OggVorbis\index{ogg} que le
|
|
|
|
|
\textsl{yuser} final ne pourra peut-être pas écouter sur
|
|
|
|
|
son \textsf{iPhone}.
|
|
|
|
|
|
|
|
|
|
Quand à la dernière ligne \texttt{~/bin/sender} c'est un programme,
|
|
|
|
|
basé sur \texttt{libshout}, qui va gérer l'authentification et
|
|
|
|
|
le transfert des données vers un point d'entrée du serveur icecast.
|
|
|
|
|
|
|
|
|
|
Voilà, c'est tout pour le moment.
|
|
|
|
|
|
2020-09-27 17:15:15 +02:00
|
|
|
|
%====================================================================
|
2020-12-11 15:06:59 +01:00
|
|
|
|
|
2021-10-04 22:24:01 +02:00
|
|
|
|
\section{Airtime} \index{Airtime}
|
|
|
|
|
|
|
|
|
|
Cette partie est écrite pendant l'installation de Airtime
|
|
|
|
|
dans \textsf{Radio-Parasite} en octobre 2021.
|
|
|
|
|
|
2021-10-15 23:22:38 +02:00
|
|
|
|
Hélas, ça ne va pas être si simple que ça.
|
|
|
|
|
Le logiciel original a été abandonné depuis plusieurs années
|
|
|
|
|
(fin 2015 à la louche)
|
|
|
|
|
par son éditeur \textsf{Sourcefabric}.
|
|
|
|
|
Un remplaçant potentiel (un fork ?) existe~:
|
|
|
|
|
\textsl{LibreTime} qui semble identique.
|
|
|
|
|
|
|
|
|
|
\begin{quote}
|
|
|
|
|
LibreTime est un système d'automatisation de station de radio qui
|
|
|
|
|
prend en charge la diffusion Web.
|
|
|
|
|
Il est construit à partir de la communauté du système
|
|
|
|
|
d’automatisation de la station de radio Airtime de SourceFabric.
|
|
|
|
|
\end{quote}
|
|
|
|
|
|
|
|
|
|
\texttt{https://libretime.org/install}
|
|
|
|
|
|
|
|
|
|
\texttt{https://libretime.org/docs/host-configuration}
|
|
|
|
|
|
|
|
|
|
\texttt{https://progsoft.net/fr/software/libretime}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-10-04 22:24:01 +02:00
|
|
|
|
%====================================================================
|
2020-12-11 15:06:59 +01:00
|
|
|
|
|
2020-10-26 23:06:17 +01:00
|
|
|
|
\section{libshout}\index{libshout}\label{libshout}
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
2020-12-22 22:53:57 +01:00
|
|
|
|
Libshout c'est quoi ? Ah, chers amis de la radio en ligne,
|
|
|
|
|
c'est une porte
|
|
|
|
|
ouverte facilitant l'accès en direction du monde sonore extérieur,
|
|
|
|
|
comme le précise clairement sa documentation~:
|
|
|
|
|
|
|
|
|
|
\begin{quote}
|
|
|
|
|
Libshout is a library for communicating with and sending data to an
|
|
|
|
|
icecast server. It handles the socket connection, the timing of the
|
|
|
|
|
data, and prevents bad data from getting to the icecast server.
|
|
|
|
|
\end{quote}
|
|
|
|
|
|
|
|
|
|
\lstinputlisting[language=c]{code/microcast.c}
|
|
|
|
|
|
2021-10-04 22:24:01 +02:00
|
|
|
|
Mais il reste encore pas mal de chose importante à rajouter dans
|
|
|
|
|
ce logiciel : par exemple la partie encodage.
|
2020-10-26 23:06:17 +01:00
|
|
|
|
|
|
|
|
|
%====================================================================
|
2020-09-27 17:15:15 +02:00
|
|
|
|
|
|
|
|
|
%-------------------------------------------------------------
|
|
|
|
|
|