395 lines
13 KiB
TeX
395 lines
13 KiB
TeX
%
|
||
% new 24 juillet 2014 - Mixart Myrys
|
||
%
|
||
\chapter{streaming}
|
||
\label{chap:streaming}
|
||
\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.
|
||
|
||
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}
|
||
|
||
%-------------------------------------------------------------
|
||
\section{icecast2}
|
||
\index{icecast2}
|
||
\label{icecast2}
|
||
|
||
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.
|
||
|
||
\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
|
||
Ices2\index{ices}, a program that sends audio data to Icecast servers
|
||
|
||
\end{quote}
|
||
|
||
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}.
|
||
|
||
Il peut envoyer depuis une entrée audio (alsa, jack, pulseaudio...)
|
||
ou une playlistde fichiers \texttt{.ogg}\index{ogg}.
|
||
|
||
|
||
|
||
\textsl{more to come...}
|
||
|
||
%-------------------------------------------------------------
|
||
|
||
% https://github.com/radiofrance/rf-liquidsoap
|
||
|
||
\section{liquidsoap}
|
||
\index{liquidsoap}
|
||
|
||
Mais nous allonc commencer par un outil puissant, bien que
|
||
délicat à comprendre au premier abord~:
|
||
\texttt{https://www.liquidsoap.info/}
|
||
|
||
\begin{quote}
|
||
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.
|
||
|
||
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.
|
||
|
||
\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}
|
||
|
||
\subsection{10.20.0.23}
|
||
|
||
Maintenant, voyons un exemple plus complet et plus réaliste,
|
||
largement inspiré d'un tutoriel de la documentation officielle,
|
||
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~:
|
||
|
||
\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
|
||
presque simple à comprendre, et un peu plus compliqué à mettre
|
||
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}
|
||
|
||
\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.
|
||
|
||
\lstinputlisting{code/takeover.liq}
|
||
|
||
\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}
|
||
|
||
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
|
||
|
||
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}.
|
||
|
||
%-------------------------------------------------------------
|
||
|
||
\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}
|
||
\index{vlc} \label{streamvlc}
|
||
|
||
VLC est le « cône de chantier » du multimédia.
|
||
|
||
%-------------------------------------------------------------
|
||
\subsection{butt}
|
||
\index{butt}
|
||
|
||
Du clickaconvi qui plante en X remote ;( mais sinon une
|
||
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.
|
||
|
||
%-------------------------------------------------------------
|
||
|
||
\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/} ?
|
||
|
||
Mais il faut avoir quelques connaissances en \textsc{modernophone}
|
||
pour arriver à tenter de comprendre pouquoi ça ne fonctionne pas,
|
||
alors que tout semble correct.
|
||
|
||
|
||
%====================================================================
|
||
\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,
|
||
est en train de se faire salement éjecter de son hangartistique.
|
||
À cette occasion, j'ai remonté \textit{à la rache} un Icecast,
|
||
et je l'ai voulu un peu surprenant pour le béotien, d'où l'uptime parlé.},
|
||
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.
|
||
|
||
Premier élément du pipeline, \texttt{espeak-ng} reçoit le texte
|
||
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.
|
||
|
||
%====================================================================
|
||
|
||
\section{Airtime} \index{Airtime}
|
||
|
||
Cette partie est écrite pendant l'installation de Airtime
|
||
dans \textsf{Radio-Parasite} en octobre 2021.
|
||
|
||
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}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
%====================================================================
|
||
|
||
\section{libshout}\index{libshout}\label{libshout}
|
||
|
||
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}
|
||
|
||
Mais il reste encore pas mal de chose importante à rajouter dans
|
||
ce logiciel : par exemple la partie encodage.
|
||
|
||
%====================================================================
|
||
|
||
%-------------------------------------------------------------
|
||
|