Liquidsoap
Website | http://liquidsoap.info/ |
---|---|
License | GPL |
OS | GNU/Linux, OS X, Windows |
Media | Streaming media |
Format | OGG, MP3 |
Interface | Custom programming language |
Wikipedia | http://en.wikipedia.org/wiki/Draft:Liquidsoap |
Thumbnail |
Cookbook
From: https://www.liquidsoap.info/doc-1.4.2/cookbook.html
The recipes show how to build a source with a particular feature. You can try short snippets by wrapping the code in an out(..) operator and passing it directly to liquidsoap:
liquidsoap -v 'out(recipe)'
For longer recipes, you might want to create a short script:
#!/usr/bin/liquidsoap -v
set("log.file.path","/tmp/<script>_YOURNAME.log")
set("log.stdout",true)
recipe = single("/my/default.ogg")
out(recipe)
Now a version that sends to an icecast server... (NB: YOU NEED A passwords.liq file with the appropriate passwords...
# %include "passwords.liq"
ICECAST_SERVER_HOST="echo.lurk.org"
ICECAST_SERVER_PORT=9999
ICECAST_SERVER_PASSWORD="hackme"
#!/usr/bin/liquidsoap -v
set("log.file.path","/tmp/<script>_YOURNAME.log")
set("log.stdout",true)
%include "passwords.liq"
recipe = single("/my/default.ogg")
output.icecast(%vorbis,
host = ICECAST_SERVER_HOST, port = ICECAST_SERVER_PORT,
password = ICECAST_SERVER_PASSWORD, mount = "prototyping.ogg",
mksafe(recipe))
See the quickstart guide for more information on how to run Liquidsoap, on what is this out(..) operator, etc.
Hello world (singie file output)
Bash command to output a single file...
liquidsoap -v 'out(single("/my/default.ogg"))'
Live override
A good example is given in the "complete case" of a program that uses the fallback function to allow a live program to cut-in and interrupt an otherwise automated program.
#!/usr/bin/liquidsoap -v
set("log.file.path","/tmp/<script>.log")
set("log.stdout",true)
%include "passwords.liq"
# Add the ability to relay live shows
liveorstatic =
fallback(track_sensitive=false,
[input.http("http://echo.lurk.org:999/prototyping_live.ogg"),
single("brownnoise.mp3")])
# out(liveorstatic)
output.icecast(%vorbis,
host = ICECAST_SERVER_HOST, port = ICECAST_SERVER_PORT,
password = ICECAST_SERVER_PASSWORD, mount = "prototyping.ogg",
mksafe(liveorstatic))
Sound processing
liquidsoap can be used to process / filter sound either in a streaming pipeline, or used "offline" to directly produce an audio output (file).
See https://www.liquidsoap.info/doc-1.4.2/reference.html#source-sound-processing
Links / Projects / Radio streams that use liquidsoap
- Data Radio. Here a script created a day and night playlist, with a "fallback" to allow a live stream to interrupt.
playlist
playlist source
mode (of type string, which defaults to "randomize"): Play the files in the playlist either in the order (“normal” mode), or shuffle the playlist each time it is loaded, and play it in this order for a whole round (“randomize” mode), or pick a random file in the playlist each time (“random” mode).
say_metadata
say_metadata filter
outputs
Basic outputs of interest:
- out which is the shortcut for output.preferred: play to the soundcard directly (if possible)
- output.file: play to a file
- output.icecast Send audio to an icecast server
examples
liquidsoap 'out(noise())'
liquidsoap 'out(playlist("playlist.pls"))'
liquidsoap 'output.prefered(mksafe(playlist("playlist.pls")))'
liquidsoap 'output.file(%mp3,"output.mp3",mksafe(playlist("playlist.pls")))'
with playlist.pls:
brown.ogg
Observations:
- WAV files don't seem to work, but ogg + mp3 seem OK! (or was this the stereo problem)
- explicit output modules (like output.file) seem to require the use of mksafe (out doesn't need this).
Doesn't work with mono source material -- default seems to be stereo...
[decoder:3] Unable to decode "./speech0001.mp3" as {audio=2;video=0;midi=0}! 2020/05/11 17:42:04 [decoder.mad:3] File "./speech0003.mp3" has an incompatible number of channels.
WAV file "speech0001.wav" has content type {audio=1;video=0;midi=0} but {audio=2;video=0;midi=0} was expected.
How would you output a mono audio stream?
Presentation
Recently presented at Fosdem2020 also on vimeo
Documentation conventions
The docs have cryptic syntax, for instance the say_metadata filter is described with the signature:
(source(?A), ?pattern : string) -> source(?A)
Which means you can call this function like:
say_metadata(mysource)
or
say_metadata(mysource, pattern="")