ZW3B :-: API Client * Contents * Docs by LAB3W.ORJ

Translate this page

Name : BETA-TESTERS

Project name : ZW3B-API-BETA-TESTERS

Authorized. - 200 - Client API Name and Origin Wildcard OK

¿Comment? 'Ou' ¿Que faire?, OS GNU/Linux, Serveurs, Icecast VLC Streaming audio video and LiquidSOAP Savonet

Comment faire un flux #streaming accroché à #Icecast par #VLC - Streaming audio vidéo avec #LiquidSOAP Savonet.

Author : O.Romain.Jaillet-ramey

NdM 20230816 : Ébauche d'article pour se mettre en appétit..
NdM 20230817 : Ajout de mon script avec prise à distance de la Webradio.

IceCast2

On va configurer rapidement le serveur IceCast2.

Script avec 100 lignes

001root@media:~ # vim /etc/icecast/icecast.xml
002
003<icecast>
004    <!-- Location and admin are two arbitrary strings that are e.g. visible
005         on the server info page of the icecast web interface
006         (server_version.xsl). -->
007    <location>FR</location>
008    <admin>orj(at)lab3w(dot)fr</admin>
009
010    <limits>
011        <clients>100</clients>
012        <sources>10</sources>
013        <queue-size>524288</queue-size>
014        <client-timeout>30</client-timeout>
015        <header-timeout>15</header-timeout>
016        <source-timeout>10</source-timeout>
017        <!-- Same as burst-on-connect, but this allows for being more
018             specific on how much to burst. Most people won't need to
019             change from the default 64k. Applies to all mountpoints. -->
020        <burst-size>65535</burst-size>
021        <!--
022        <max-bandwidth>100M</max-bandwidth>
023        -->
024    </limits>
025
026    <authentication>
027        <!-- Sources log in with username 'source' -->
028        <source-password>mot_de_passe_des_sources</source-password>
029        <!-- Relays log in username 'relay' -->
030        <relay-password>mot_de_passe_des_relay</relay-password>
031
032        <!-- Admin logs in with the username given below -->
033        <admin-user>admin</admin-user>
034        <admin-password>mot_de_passe_admin</admin-password>
035    </authentication>
036
037
038    <!-- This is the hostname other people will use to connect to your server.
039    It affects mainly the urls generated by Icecast for playlists and yp
040    listings. -->
041    <hostname>flows.zw3b.fr</hostname>
042
043    <!-- Set the mountpoint for a shoutcast source to use, the default if not
044         specified is /stream but you can change it here if an alternative is
045         wanted or an extension is required
046    <shoutcast-mount>/live.nsv</shoutcast-mount>
047    -->
048
049    <!-- port to use when talking to YP etc -->
050    <!--<port>8000</port> -->
051
052    <!-- You may have multiple <listener> elements -->
053    <listen-socket>
054        <port>8000</port>
055        <!-- <bind-address>127.0.0.1</bind-address> -->
056        <!-- use <shoutcast-mount> in here to implicitly define port n+1 -->
057    </listen-socket>
058
059    <fileserve>1</fileserve>
060    
061    <paths>
062        <!-- basedir is only used if chroot is enabled -->
063        <basedir>/usr/share/icecast2</basedir>
064
065        <!-- Note that if <chroot> is turned on below, these paths must both
066             be relative to the new root, not the original root -->
067        <logdir>/var/log/icecast2</logdir>
068        <webroot>/usr/share/icecast2/web</webroot>
069        <adminroot>/usr/share/icecast2/admin</adminroot>
070        
071        <alias source="/" dest="/index.html"/>
072
073        <x-forwarded-for>127.0.0.1</x-forwarded-for>
074    </paths>
075
076    <logging>
077        <accesslog>access.log</accesslog>
078        <errorlog>error.log</errorlog>
079        <!-- <accesslog_ip>0<accesslog_ip> -->
080        <!-- <playlistlog>playlist.log</playlistlog> -->
081        <loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
082        <logsize>10000</logsize> <!-- Max size of a logfile -->
083        <!-- If logarchive is enabled (1), then when logsize is reached
084             the logfile will be moved to [error|access|playlist].log.DATESTAMP,
085             otherwise it will be moved to [error|access|playlist].log.old.
086             Default is non-archive mode (i.e. overwrite)
087        -->
088        <!-- <logarchive>1</logarchive> -->
089    </logging>
090    
091    <security>
092        <chroot>0</chroot>
093        <!--
094        <changeowner>
095            <user>nobody</user>
096            <group>nogroup</group>
097        </changeowner>
098        -->
099    </security>
100</icecast>
Retirer les numéros de lignes

On peut lancer le serveur icecast (depuis l'utilisateur "icecast" :

Script avec 1 ligne

001su - "icecast2" -c "/usr/bin/icecast2 -b -c /etc/icecast2/icecast.xml"
Retirer les numéros de lignes

Envoie d'un flux vidéo VLC sur Icecast

Exemple d'une requête VLC pour créer un /point de montage Icecast sur un serveur distant :

La requête ci-dessous récupére le périphérique /dev/video0 de l'ordinateur.
Et envoie le flux vidéo sur une autre machine (au Canada en l'occurrence, sur un container de ma serveur hébergé chez OVH) la machine "10.101.150.80 sur le port "8000" qui bien sûr passe par un VPN perso IPSec .

Script avec 3 lignes

001#!/bin/bash
002
003su - orj -c 'cvlc v4l2:// :v4l2-dev=/dev/video0 :v4l2-width=320 :v4l2-height=240 --video-title="LAB3W.WebCam" --live-caching=2000 --sout "#transcode{vcodec=theo,vb=150,scale=1,acodec=vorb,ab=64,channels=2,samplerate=22050}:std{access=shout,mux=ogg,dst=source:mot_de_passe_des_sources@10.101.150.80:8000/cam0}" --ttl 12 :no-sout-rtp-sap :no-sout-standard-sap :sout-all :sout-keep'
Retirer les numéros de lignes

Cela permet de créer un flux constant en (vrai) streaming. Ce n'est pas un WebCam avec des images toutes les minutes.

Liquid SOAP (de Savonet)

est un outil puissant pour créer des générateurs de flux audio et vidéo complexes, ciblant généralement les radios Internet #webradio et les #webtv . Il se compose d'un langage de script simple, qui a une notion de première classe de source (essentiellement un flux) et fournit des constructeurs de source élémentaires et des compositions de source à partir desquels vous pouvez créer le générateur de flux que vous souhaitez. Cette conception rend le savon liquide flexible et facilement extensible.


Je vous pose un exemple de scripting liq liquidsoap 1.1.1 (la version LiquidSoap 2.2.0 est disponible mais ce script ne fonctionne pas avec, il faut l'adapter).

Script avec 87 lignes

001root@media:/home/streaming # vim radio.liq
002
003#!/usr/bin/liquidsoap
004
005set("log.file",false)
006set("log.stdout",true)
007set("log.level",3)
008#set("harbor.icy",true)
009
010%include "library.liq"
011
012set("server.telnet",true)
013
014
015liste_hds = mksafe(playlist("/home/alibaba/music/house.techo.electro/house-dancer-session-mp3/"))
016src_hds = normalize(liste_hds)
017jingle_hds = single("say: House Dancer Session!")
018jingle_hds = amplify(1.0,jingle_hds)
019
020liste_jd = mksafe(playlist("/home/alibaba/music/house.techo.electro/jus-dance/"))
021src_jd = normalize(liste_jd)
022jingle_jd = single("say: Jus Dance!")
023jingle_jd = amplify(1.0,jingle_jd)
024
025
026
027src_hds = rotate(weights=[1,2], [jingle_hds,src_hds])
028src_jd = rotate(weights=[1,2], [jingle_jd,src_jd])
029
030src = rotate(weights=[1,1], [src_hds,src_jd])
031
032s = fallback([request.queue(), src])
033
034
035
036jingle = single("say: WELCOME !!!!")
037jingle = amplify(1.0,jingle)
038
039
040
041s = rotate(weights=[1,2], [jingle,s])
042
043s = map_metadata(add_replaygain,s)
044s = amplify(override="replay_gain",1.,s)
045s = my_crossfade(s)
046s = map_metadata(update_title,s)
047s = on_metadata(apply_metadata,s)
048
049# A special source
050special = request.queue(id="special")
051# Smooth_add the special source
052s = smooth_add(normal=s,special=special)
053
054
055s = my_safe(s)
056
057
058jingle1 = single("say:Et now KSS AT HOME")
059to_live1 = to_live(jingle1)
060
061
062s = skip_blank(max_blank=3.,s)
063
064output.icecast(
065  %vorbis,
066  host = "mdia.zw3b.fr", port = 8000, password = "mot_de_passe_des_sources",
067  name = "HouseDancerSession - JusDance", description = "By Orel1, Delastef & Fukiflex - John Sill & Blaise", genre = "Soundtracks Electro, Deep House, Groove, SoulFull, Funky", url = "http://www.housedancer.net/",
068  mount="listen.ogg",s)
069
070output.icecast(
071  %mp3(bitrate=128),
072  host = "mdia.zw3b.fr", port = 8000, password = "mot_de_passe_des_sources",
073  name = "HouseDancerSession - JusDance", description = "By Orel1, Delastef & Fukiflex - John Sill & Blaise", genre = "Soundtracks Electro, Deep House, Groove, SoulFull, Funky", url = "http://www.housedancer.net/",
074  mount="listen",s)
075  
076#output.icecast(
077#  %ogg(%flac),
078#  host = "mdia.zw3b.fr", port = 8000, password = "mot_de_passe_des_sources",
079#  name = "HouseDancerSession", description = "By Orel1, Delastef & Fukiflex - John Sill & Blaise", genre = "Soundtracks Electro, Deep House, Groove, SoulFull, Funky", url = "http://www.housedancer.net/",
080#  mount="listen-flac.ogg",s)
081
082#output.icecast(
083#  %aacplus(bitrate=32),
084#  host = "mdia.zw3b.fr", port = 8000, password = "mot_de_passe_des_sources",
085#  name = "HouseDancerSession - JusDance", description = "By Orel1, Delastef & Fukiflex - John Sill & Blaise", genre = "Soundtracks Electro, Deep House, Groove, SoulFull, Funky", url = "http://www.housedancer.net/",
086#  mount="listen.aac",s)
087
Retirer les numéros de lignes

Il faut faire attention, l'ordre dans le fichiers est "extrêmement" important.

Pour lancer le streaming encoder en 2 formats (%vorbis et %mp3 et d'autres -- il faut installer les codecs des "dépots multimedia de débian" par exemple pour le codec "flac" etc.).

Par exemple :

Script avec 1 ligne

001su - "streaming" -c "liquidsoap radio.liq"
Retirer les numéros de lignes


J'écris la suite prochainement..

Histoire que vous essayez, ce n'est pas forcement simple.

Je vous laisse lire la documentation Liquidsoap.

Je vous expliquerais et détaillerais les fonctions et ajouterais la mise en place de possible connection de "DJs" sur le flux "constant" de la Web Radio.

J'ai fais des test de streaming vidéo avec inscrutation "image dans image", logo, ticker, text etc.. cela doit mieux fonctionner avec la version 2.2.0 qu'avec la version 1.1.1.

je vous laisse découvrir 🙂




Romain, bonne soirée.




Pour la suite (le jeudi 17 août 2023), je vous ajoute, ci-dessous mon script qui fait tourner les flux sur https://radio.zw3b.fr

L'operationg System :

Script avec 10 lignes

001root@media:~ # cat /etc/os-release
002PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
003NAME="Debian GNU/Linux"
004VERSION_ID="9"
005VERSION="9 (stretch)"
006VERSION_CODENAME=stretch
007ID=debian
008HOME_URL="https://www.debian.org/"
009SUPPORT_URL="https://www.debian.org/support"
010BUG_REPORT_URL="https://bugs.debian.org/"
Retirer les numéros de lignes

La version de liquidsoap :

Script avec 5 lignes

001root@media:~ # liquidsoap --version
002Liquidsoap 1.1.1
003Copyright (c) 2003-2013 Savonet team
004Liquidsoap is open-source software, released under GNU General Public License.
005See <http://liquidsoap.fm> for more information.
Retirer les numéros de lignes

Et le script radio-live.liq

Script avec 458 lignes

001#!/usr/bin/liquidsoap
002
003##############--------- functions -------------------------------------------------------------
004# This function turns a fallible
005# source into an infallible source
006# by playing a static single when
007# the original song is not available
008def my_safe(s) =
009  # We assume that festival is installed and
010  # functional in liquidsoap
011  security = single("say:Hello, this is radio FOO! We are currently having some technical difficulties but we'll be back soon so stay tuned!")
012
013  # We return a fallback where the original
014  # source has priority over the security
015  # single. We set track_sensitive to false
016  # to return immediately to the original source
017  # when it becomes available again.
018  fallback(track_sensitive=false,[s,security])
019end
020# This function is called when
021# a new metadata block is passed in
022# the stream.
023def apply_metadata(m) =
024  title = m["title"]
025  artist = m["artist"]
026  print("Now playing:#{title} by#{artist}")
027end
028
029# Our custom request function
030def get_request() =
031  # Get the URI
032  uri = list.hd(get_process_lines("cat /tmp/request"))
033  # Create a request
034  request.create(uri)
035end
036
037# This function updates the title metadata with
038# the content of "/tmp/metadata"
039def update_title(m) =
040  # The title metadata
041  title = m["title"]
042  # Our addition
043  content = list.hd(get_process_lines("cat /home/streaming/metadata.title"))
044       #content = list.hd(get_process_lines("[ZW3B.FR]"))
045  # If title is empty
046  if title == "" then
047    [("title", content)]
048  # Otherwise
049  else
050    [("title","#{title} on#{content}")]
051  end
052end
053
054#------------------------------------------------------------------------------------------
055# This function updates the title metadata with
056# the content of "/tmp/metadata"
057def update_user_0(m) =
058  # The title metadata
059  title = m["title"]
060  # Our addition
061  content = list.hd(get_process_lines("cat /home/streaming/metadata.title"))
062  usr = list.hd(get_process_lines("cat /home/streaming/metadata.live.user"))
063#  usr = m["user"]
064
065  # If title is empty
066  if title == "" and usr == "" then
067    [("title", "#{content}")]
068#  elif title == "" and usr == "" then
069#    [("title", "Live DJ#{usr} on#{content}")]
070  # Otherwise
071  else
072    if usr == "" then
073            [("title","#{title} on#{content}")]
074    else
075        [("title","Live DJ#{usr}#{title} on#{content}")]
076    end
077  end
078end
079
080def update_user_1(m) =
081  # The title metadata
082  title = m["title"]
083  # Our addition
084  content = list.hd(get_process_lines("cat /home/streaming/metadata.title"))
085#  usr = list.hd(get_process_lines("cat /home/streaming/metadata.live.user"))
086#  usr = m["user"]
087  usr = "D Jay 1 !"
088  # If title is empty
089  if title == "" and usr == "" then
090    [("title", "#{content}")]
091#  elif title == "" and usr == "" then
092#    [("title", "Live DJ#{usr} on#{content}")]
093  # Otherwise
094  else
095    if usr == "" then
096            [("title","#{title} on#{content}")]
097    else
098        [("title","Live DJ#{usr}#{title} on#{content}")]
099    end
100  end
101end
102
103def update_user_2(m) =
104  # The title metadata
105  title = m["title"]
106  # Our addition
107  content = list.hd(get_process_lines("cat /home/streaming/metadata.title"))
108#  usr = list.hd(get_process_lines("cat /home/streaming/metadata.live.user"))
109#  usr = m["user"]
110  usr = "D Jay 2 Guest..."
111  # If title is empty
112  if title == "" and usr == "" then
113    [("title", "#{content}")]
114#  elif title == "" and usr == "" then
115#    [("title", "Live DJ#{usr} on#{content}")]
116  # Otherwise
117  else
118    if usr == "" then
119            [("title","#{title} on#{content}")]
120    else
121        [("title","Live#{usr}#{title} on#{content}")]
122    end
123  end
124end
125
126def update_user_3(m) =
127  # The title metadata
128  title = m["title"]
129  # Our addition
130  content = list.hd(get_process_lines("cat /home/streaming/metadata.title"))
131#  usr = list.hd(get_process_lines("cat /home/streaming/metadata.live.user"))
132#  usr = m["user"]
133  usr = "D Jay 3"
134  # If title is empty
135  if title == "" and usr == "" then
136    [("title", "#{content}")]
137#  elif title == "" and usr == "" then
138#    [("title", "Live DJ#{usr} on#{content}")]
139  # Otherwise
140  else
141    if usr == "" then
142            [("title","#{title} on#{content}")]
143    else
144        [("title","Live DJ#{usr}#{title} on#{content}")]
145    end
146  end
147end
148
149def update_user_4(m) =
150  # The title metadata
151  title = m["title"]
152  # Our addition
153  content = list.hd(get_process_lines("cat /home/streaming/metadata.title"))
154#  usr = list.hd(get_process_lines("cat /home/streaming/metadata.live.user"))
155#  usr = m["user"]
156  usr = "D Jay 4"
157  # If title is empty
158  if title == "" and usr == "" then
159    [("title", "#{content}")]
160#  elif title == "" and usr == "" then
161#    [("title", "Live DJ#{usr} on#{content}")]
162  # Otherwise
163  else
164    if usr == "" then
165            [("title","#{title} on#{content}")]
166    else
167        [("title","Live DJ#{usr}#{title} on#{content}")]
168    end
169  end
170end
171
172#------------------------------------------------------------------------------------------
173
174# This function takes a metadata,
175# check if it is of type "file"
176# and add the replay_gain metadata in
177# this case
178def add_replaygain(m) =
179  # Get the type
180  type = m["type"]
181  # The replaygain script is located there
182  script = "#{configure.libdir}/extract-replaygain"
183  # The filename is contained in this value
184  filename = m["filename"]
185
186  # If type = "song", proceed:
187  if type == "song" then
188    info = list.hd(get_process_lines("#{script}#{filename}"))
189    [("replay_gain",info)]
190  # Otherwise add nothing
191  else
192    []
193  end
194end
195
196# Notre crossfade personnalise
197# only crossfade betwee tracks
198def my_crossfade(s) =
199  # Notre fonction de transition
200  def f(_,_, old_m, new_m, old, new) =
201    # If none of old and new have "type" metadata
202    # with value "jingles", we crossfade the source:
203    if old_m["type"] != "jingle" and new_m["type"] != "jingle" then
204      add([fade.initial(new), fade.final(old)])
205    else
206      sequence([old,new])
207    end
208 end
209 # Now, we apply smart_cross with this function:
210 smart_cross(f,s)
211end
212
213# Define a transition that fades out the
214# old source, adds a single, and then
215# plays the new source
216def to_live(jingle, old, new) =
217  # Fade out old source
218  old = fade.final(old)
219  # Supperpose the jingle
220  s = add([jingle,old])
221  # Compose this in sequence with
222  # the new source
223  sequence([s,new])
224end
225
226# A transition when switching back to files:
227def to_file(old, new) =
228  # We skip the file
229  # currently in new
230  # in order to being with
231  # a fresh file
232  source.skip(new)
233  sequence([old,new])
234end
235
236# Our custom authentication
237# Note: the ICY protocol
238# does not have any username and for
239# icecast, it is "source" most of the time
240# thus, we discard it
241
242def harbor_auth(port,_,password) =
243  # Alice connects on port 9000 between 20h and 21h
244  # with password "rabbit"
245 #(port == 9000 and 20h-22h and password == "live-guest-mot_de_passe")
246        (port == 10000 and password == "mot_de_passe_DJ0")
247    or
248  # Bob connection on port 7000 between 18h and 20h
249  # with password "foo"
250 #(port == 7000 and 00h-23h and password == "live-admin-m2p")
251        
252        (port == 10001 and password == "mot_de_passe_DJ1")
253    or
254        (port == 10002 and password == "mot_de_passe_DJ2")
255    or
256        (port == 10003 and password == "mot_de_passe_DJ3")
257    or
258        (port == 10004 and password == "mot_de_passe_DJ4")
259
260end
261
262##############--------------------------------------------------------------------------------
263# CONFIG
264
265#set("log.file.path","/home/streaming/logs/liquisoap.log")
266set("log.file",false)
267set("log.stdout",true)
268#set("log.stdout", false)
269set("log.level",4)
270#set("harbor.icy",true)
271set("server.telnet",true)
272
273# Stream dentree
274set("harbor.icy",false)
275#set("harbor.bind_addr","127.0.0.1") # ip-du-serveur-de-diff
276set("harbor.bind_addr","0.0.0.0")
277#set("harbor.port",8005) # port-pas-de-ton-icecast
278
279set("harbor.username","guest")
280set("harbor.password","mot_de_passe_des_sources")
281
282#---------------------------------------------------------------------------------------------
283
284#radio           =       fallback(track_sensitive=false, [live,radio])
285
286#live_0          =       input.harbor("live")
287
288#live_0_dj      =       "Kss*"
289live_0_jingle   =       single("say: D Jay KSS !")
290to_live_0       =       to_live(live_0_jingle)
291
292live_1_jingle   =       single("say:D Jay 1 !")
293to_live_1       =       to_live(live_1_jingle)
294
295live_2_jingle   =       single("say:D Jay 2 Live !")
296to_live_2       =       to_live(live_2_jingle)
297
298live_3_jingle   =       single("say:D Jay 3 !")
299to_live_3       =       to_live(live_3_jingle)
300
301live_4_jingle   =       single("say:D Jay 4 !")
302to_live_4       =       to_live(live_4_jingle)
303
304#---------------------------------------------------------------------------------------------
305
306s2                      =       sine()
307
308security                =       single("say:Hello, this is radio FOO! We are currently having some technical difficulties but we'll be back soon so stay tuned!")
309#jingles                =       mksafe(playlist("/home/alibaba/music/jingles/"))
310
311playlist_house          =       mksafe(playlist("/home/alibaba/music/house.techo.electro/house-dancer-session-mp3/"))
312
313jingle_house            =       amplify(1.0, single("say: The Web Radio!"))
314
315#---------------------------------------------------------------------------------------------
316
317radio_house     =       rotate(weights=[1,2], [jingle_house, playlist_house])
318
319radio           =       fallback(track_sensitive=true,
320                                [radio, security])
321
322radio           =       map_metadata(add_replaygain, radio)
323radio           =       amplify(override="replay_gain",1., radio)
324radio           =       my_crossfade(radio)
325#radio          =       smart_cross(id="cross", active=true, conservative=false, duration=5., inhibit=3., minimum=3., width=1., radio)
326radio           =       map_metadata(update_title, radio)
327radio           =       on_metadata(apply_metadata, radio)
328
329radio           =       normalize(radio)
330
331# A special source
332special         =       request.queue(id="special")
333# Smooth_add the special source
334radio           =       smooth_add(normal=radio, special=special)
335
336# security
337radio           =       my_safe(radio)
338
339#radio           =      skip_blank(threshold=-28.,length=3.,radio)
340#radio          =       skip_blank(radio, length=10., threshold=-40.)
341radio           =       skip_blank(id="blanc", threshold=-35., max_blank=5., min_noise=0., track_sensitive=true, radio)
342
343#---------------------------------------------------------------------------------------------
344timed_promotions = switch (
345#track_sensitive = true,
346[
347#  ({  00h59m55s }, amplify(5., override="replay_gain", single("say: une heure!")) ),
348#  ({  01h59m55s }, amplify(5., override="replay_gain", single("say: deux heure!")) ),
349#  ({  02h59m55s }, amplify(5., override="replay_gain", single("say: trois heure!")) ),
350  ({  03h59m55s }, amplify(5., override="replay_gain", single("say: quatre heure! sur the web radio !")) ),
351#  ({  04h59m55s }, amplify(5., override="replay_gain", single("say: cinq heure!")) ),
352#  ({  05h59m55s }, amplify(5., override="replay_gain", single("say: six heure!")) ),
353#  ({  06h59m55s }, amplify(5., override="replay_gain", single("say: sept heure!")) ),
354  ({  07h59m55s }, amplify(5., override="replay_gain", single("say: huigt heure! sur the web radio !")) ),
355#  ({  08h59m55s }, amplify(5., override="replay_gain", single("say: neuf heure!")) ),
356#  ({  09h59m55s }, amplify(5., override="replay_gain", single("say: dix heure!")) ),
357#  ({  10h59m55s }, amplify(5., override="replay_gain", single("say: onze heure!")) ),
358  ({  11h59m55s }, amplify(5., override="replay_gain", single("say: midi! sur the web radio !")) ),
359#  ({  12h59m55s }, amplify(5., override="replay_gain", single("say: treize heure!")) ),
360#  ({  13h59m55s }, amplify(5., override="replay_gain", single("say: quatorze heure!")) ),
361#  ({  14h59m55s }, amplify(5., override="replay_gain", single("say: quinze heure!")) ),
362  ({  15h59m55s }, amplify(5., override="replay_gain", single("say: catre heure! sur the web radio !")) ),
363#  ({  16h59m55s }, amplify(5., override="replay_gain", single("say: dix sept heure!")) ),
364#  ({  17h59m55s }, amplify(5., override="replay_gain", single("say: dix huigt heure!")) ),
365#  ({  18h59m55s }, amplify(5., override="replay_gain", single("say: dix neuf heure!")) ),
366  ({  19h59m55s }, amplify(5., override="replay_gain", single("say: vingt heure! sur the web radio !")) ),
367#  ({  20h59m55s }, amplify(5., override="replay_gain", single("say: vingt et une heure!")) ),
368#  ({  21h59m55s }, amplify(5., override="replay_gain", single("say: vingt deux heure!")) ),
369#  ({  22h59m55s }, amplify(5., override="replay_gain", single("say: vingt trois heure!")) ),
370  ({  23h59m55s }, amplify(5., override="replay_gain", single("say: minuit! sur the web radio !")) )
371])
372
373radio = add([radio, timed_promotions])
374
375# Create an interactive boolean
376b = interactive.bool("button", true)
377
378radio = switch(track_sensitive=false,[(b, radio), ({true}, s2)])
379
380#---------------------------------------------------------------------------------------------
381# Authentication for live :
382
383live_auth_0     =       harbor_auth(10000)
384live_0          =       input.harbor(port=10000,auth=live_auth_0,"live")
385live_0          =       map_metadata(update_user_0, live_0)
386
387live_auth_1     =       harbor_auth(10001)
388live_1          =       input.harbor(port=10001,auth=live_auth_1,"live")
389live_1          =       map_metadata(update_user_1, live_1)
390
391live_auth_2     =       harbor_auth(10002)
392live_2          =       input.harbor(port=10002,auth=live_auth_2,"live")
393live_2          =       map_metadata(update_user_2, live_2)
394
395live_auth_3     =       harbor_auth(10003)
396live_3          =       input.harbor(port=10003,auth=live_auth_3,"live")
397live_3          =       map_metadata(update_user_3, live_3)
398
399live_auth_4     =       harbor_auth(10004)
400live_4          =       input.harbor(port=10004,auth=live_auth_4,"live")
401live_4          =       map_metadata(update_user_4, live_4)
402
403#--------------------------------------------
404# transitions live
405
406full            =       fallback(track_sensitive=false, transitions=[to_live_0, to_file], [live_0, radio])
407
408#------------------
409# Test de tous les live
410
411full            =        fallback(track_sensitive=false, transitions=[to_live_1, to_file], [live_1, full])
412full            =        fallback(track_sensitive=false, transitions=[to_live_2, to_file], [live_2, full])
413full            =        fallback(track_sensitive=false, transitions=[to_live_3, to_file], [live_3, full])
414full            =        fallback(track_sensitive=false, transitions=[to_live_4, to_file], [live_4, full])
415
416#---------------------------------------------------------------------------------------------
417# flux
418
419full            =       mksafe(full)
420
421# And the clock jingle
422#radio          =       add([radio, switch([({0m0s},clock)])])
423
424#----------------------------------------------------------------------------------------------
425# LiquidFlow : http://flows.liquidsoap.fm/
426
427full = register_flow(
428  radio="ZW3B.Radio : HouseDancerSession & JusDance",
429  website="http://radio.zw3b.fr/",
430  description="By LAB3W : Laboratoire Web et reseaux - Sounds : Orel1, Delastef & Fukiflex - John Sill & Blaise",
431  genre="Electro, Deep House, Groove, SoulFull, Funky, Rap",
432#  user="zw3b",
433#  password="mon_super_passwd_du_site",
434  streams=[("mp3/64k","http://flows.zw3b.net/radio"),("ogg/112k","http://flows.zw3b.net/radio.ogg")],
435  full)
436
437#----------------------------------------------------------------------------------------------
438# encodage de sortie
439
440output.icecast(
441        %mp3(bitrate=64),
442        id = "ZW3B-RADIO",
443        host = "127.0.0.1", port = 8000, password = "mot_de_passe_des_sources",
444        name = "ZW3B.Radio : HouseDancerSession & JusDance", url = "http://radio.zw3b.fr/",
445        description = "By LAB3W : Laboratoire Web et reseaux - Sounds : Orel1, Delastef & Fukiflex - John Sill & Blaise", genre = "Electro, Deep House, Groove, SoulFull, Funky, Rap",
446        mount = "radio", full)
447
448#---------------------------------------------------------------------------------------------
449
450output.icecast(
451        %vorbis(samplerate=44100),
452        id = "ZW3B-RADIO",
453#       fallible = true
454        host = "127.0.0.1", port = 8000, password = "mot_de_passe_des_sources",
455        name = "ZW3B.Radio : HouseDancerSession & JusDance", url = "http://radio.zw3b.fr/",
456        description = "By LAB3W : Laboratoire Web et reseaux - Sounds : Orel1, Delastef & Fukiflex - John Sill & Blaise", genre = "Electro, Deep House, Groove, SoulFull, Funky, Rap",
457        mount = "radio.ogg", full)
458
Retirer les numéros de lignes

Il y a 5 utilisateurs DJ qui peuvent intéragir sur la webradio à n'importe quel moment - En gros, le bordel. On peut définir des plages horaires.

Pour vous connectez il suffit de lancer une "table de mixage" type le logiciel Mixxx : Diffuser en live de la musique disponible sur Microsoft, Linux et Apple.



Bon mix !

Romain