Last active
July 13, 2023 14:52
-
-
Save GeekBrony/47d2212ed6408be816a2 to your computer and use it in GitHub Desktop.
Liquidsoap Radio System
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
########################################################################################### | |
# Liquidsoap Radio System - built by GeekBrony, based from Liquidsoap. # | |
########################################################################################### | |
# Primary Features: | |
# - AutoDJ that crossfades between songs and has a 1/10 chance of landing on a Station ID/Jingle/Ad. | |
# - AutoDJ also selects tracks from "High Priority", "Low Priority" and "New Songs" playlists randomly. | |
# - Live Shows (that automatically dump to a directory) | |
# - Mic to speak over the stream. | |
# - Requests via Telnet/Web Interface, which have a 80-90% chance of queuing up when a song ends. | |
# - Outputs in 96kbps, 128kbps, and 320kbps MP3 with ID3v2 tags. | |
# | |
# Planned Changes: | |
# - Fix Live Show Dumping creating a file upon start, which is unnecessary. | |
# - Queuing Playlists | |
# - Add alternate streams with only the playlist running, for people who just want music. | |
# | |
################################# | |
# <BEGIN CONFIGURATION SECTION> # | |
################################# | |
# Please edit to your needs, or else you will get errors upon startup # | |
# Music | |
# 'musicdir' and 'jingledir' can be a local directory/playlist OR a playlist (pls/m3u) file on the internet. | |
musicdir = "/store/music/" | |
jingledir = "/store/ident/" | |
# Music Selection Mode | |
# random : Every playlist reload, shuffle. | |
# randomize : Every song, shuffle. | |
# normal : Sequential order. | |
pls_mode = "random" | |
# The variable 'securityuri' has to be a local file otherwise you will get an error saying 'That source is fallible!' | |
securityuri = "/var/www/bdn/httpdocs/maintenance/elevator.mp3" | |
# Playlists | |
# Hits | |
#hits_list = "/srv/pls/current_hits.m3u" | |
# Music Selection Mode | |
# random : Every playlist reload, shuffle. | |
# randomize : Every song, shuffle. | |
# normal : Sequential order. | |
#hits_mode = "random" | |
# New Songs | |
new_song_list = "/store/new_music/" | |
# Music Selection Mode | |
# random : Every playlist reload, shuffle. | |
# randomize : Every song, shuffle. | |
# normal : Sequential order. | |
new_mode = "random" | |
# Mellow Mondays | |
mellow_list = "/srv/pls/mellow_mondays.m3u" | |
# Music Selection Mode | |
# random : Every playlist reload, shuffle. | |
# randomize : Every song, shuffle. | |
# normal : Sequential order. | |
mellow_mode = "random" | |
# High Priority Songs | |
hp_list = "/var/www/bdn/httpdocs/api/voting/high_priority.pls" | |
hp_mode = "randomize" | |
# Low Priority Songs | |
lp_list = "/store/low_priority/" | |
lp_mode = "randomize" | |
# Live Stream | |
# Live Mount URL | |
livem = "http://localhost:8000/stream-live" | |
# Buffer | |
live_buffer = 5. | |
live_buffer_max = 15. | |
# Microphone (Speak over music) | |
# Microphone Mount URL | |
micm = "http://localhost:8000/stream-mic" | |
# Buffer | |
mic_buffer = 2. | |
mic_buffer_max = 10. | |
# Volume | |
background_volume = 0.15 | |
# Logging | |
log_to_stdout = true | |
log_to_file = true | |
logpath = "/home/server/liquidsoapconfig/log.log" | |
loglevel = 3 | |
# Telnet | |
enable_telnet = true | |
telnetbindaddr = "127.0.0.1" | |
telnetport = 2345 | |
# Live Dumping | |
# To disable live dumping, comment out lines 335-340 with '#' | |
# Make sure the directory exists and/or has permission to make one. | |
# %Y = year, %m = month, %d = day, %H = hour, %M = minute, %S = seconds | |
#dump_mp3_file = "/var/www/brony.co/htdocs/rdmp/LIVE_%Y-%m-%d_%H-%M-%S.mp3" | |
# Liquidsoap will add this string after request metadata | |
# Example: "Artist - Title (Remix) [RQ]" | |
# request_m = "[RQ]" | |
# NOT IN USE | |
# Last.fm Scrobbling | |
lfm_enable = true | |
lfmuser = "" | |
lfmpass = "" | |
# Icecast Information: | |
hostname = "127.0.0.1" | |
iceport = 8000 | |
passw = "[REDACTED]" | |
# Stream Name | |
icename = "Radio" | |
# Stream Genre | |
icegenre = "Pony" | |
# Description | |
icedesc = "Best Variety Pony Hits + Live Shows" | |
# Website URL | |
iceurl = "localhost" | |
############################### | |
# <END CONFIGURATION SECTION> # | |
############################### | |
#- DO NOT EDIT AFTER THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING -# | |
# For requests, add variable 'request_m' after the metadata | |
def append_title_request(m) = | |
# Grab the current title | |
title = m["title"] | |
# Return a new title metadata, which is disabled (for now). | |
[("title","#{title}")] | |
end | |
def crossfade(s) | |
#duration is automatically overwritten by metadata fields passed in | |
#with audio | |
s = fade.in(type="sin", duration=4., s) | |
s = fade.out(type="sin", duration=5., s) | |
fader = fun (a,b) -> add(normalize=false,[b,a]) | |
cross(fader,s) | |
end | |
def smooth_add(~delay=0.5,~p=0.2,~normal,~special) | |
d = delay | |
fade.final = fade.final(duration=d*2.) | |
fade.initial = fade.initial(duration=d*2.) | |
q = 1. - p | |
c = amplify | |
fallback(track_sensitive=false, | |
[special,normal], | |
transitions=[ | |
fun(normal,special)-> | |
add(normalize=false, | |
[c(p,normal), | |
c(q,fade.final(type="sin",normal)), | |
sequence([blank(duration=d),c(q,special)])]), | |
fun(special,normal)-> | |
add(normalize=false, | |
[c(p,normal), | |
c(q,fade.initial(type="sin",normal))]) | |
]) | |
end | |
# Add a skip function to a source | |
# when it does not have one | |
# by default | |
def add_skip_command(~command,s) | |
# Register the command: | |
server.register( | |
usage="skip", | |
description="Skip the current song in source.", | |
command, | |
fun(_) -> begin source.skip(s) "Done!" end | |
) | |
end | |
# Enable logging on Standard Output and set logging level. | |
set("log.stdout",log_to_stdout) | |
set("log.level",loglevel) | |
# Enable logging to file. See variable: logpath | |
set("log.file",log_to_file) | |
set("log.file.path",logpath) | |
# Allow requests from Telnet (Liquidsoap Requester) | |
set("server.telnet",enable_telnet) | |
set("server.telnet.bind_addr",telnetbindaddr) | |
set("server.telnet.port",telnetport) | |
set("harbor.bind_addr","0.0.0.0") | |
def lastfm.scrobble(~user,~password,m) = | |
if lfm_enable then | |
audioscrobbler.submit(user=user,password=password,m) | |
audioscrobbler.nowplaying(user=user,password=password,m) | |
end | |
# Only enable this if you really understand what everything does in these three PHP files | |
# Which at the moment, only GeekBrony knows what it does. | |
meta_database = true | |
if meta_database then | |
str = base64.encode(json_of(compact=true, m)) | |
system("php /var/www/bdn/httpdocs/api/countPlayed.php \"#{str}\"") | |
system("php /var/www/bdn/httpdocs/api/extra_info.php \"#{str}\"") | |
system("php /var/www/bdn/httpdocs/api/album_art.php \"#{str}\"") | |
end | |
end | |
myplaylist = playlist(id="playlist",length=3600.0,default_duration=1800.0,timeout=10.0, | |
mode=pls_mode,reload=480,reload_mode="seconds",mime_type="audio/x-mpegurl",musicdir) | |
#hits = playlist(id="playlist",length=3600.0,default_duration=1800.0,timeout=10.0, | |
# mode=hits_mode,reload=480,reload_mode="seconds",mime_type="audio/x-mpegurl",hits_list) | |
new = playlist(id="playlist",length=3600.0,default_duration=1800.0,timeout=10.0, | |
mode=new_mode,reload=480,reload_mode="seconds",mime_type="audio/x-mpegurl",new_song_list) | |
mellow = playlist(id="playlist",length=3600.0,default_duration=1800.0,timeout=10.0, | |
mode=mellow_mode,reload=480,reload_mode="seconds",mime_type="audio/x-mpegurl",mellow_list) | |
hp = playlist(id="playlist",length=3600.0,default_duration=1800.0,timeout=10.0, | |
mode=hp_mode,reload=480,reload_mode="seconds",mime_type="audio/x-mpegurl",hp_list) | |
lp = playlist(id="playlist",length=3600.0,default_duration=1800.0,timeout=10.0, | |
mode=lp_mode,reload=480,reload_mode="seconds",mime_type="audio/x-mpegurl",lp_list) | |
# myplaylist = smart_crossfade(myplaylist) | |
# Request Queue from Telnet (Liquidsoap Requester) | |
requests = audio_to_stereo(request.queue(id="requests")) | |
requests = map_metadata(append_title_request, requests) | |
jingles = nrj(playlist(jingledir)) | |
liveshow = nrj(audio_to_stereo(input.http(buffer=live_buffer,max=live_buffer_max,livem))) | |
microphone = nrj(audio_to_stereo(input.http(buffer=mic_buffer,max=mic_buffer_max,micm))) | |
# Start building the feed with music | |
# Randomize the source choices | |
radio = random(id="randomizer", weights=[7000, 2399, 400, 1, 200], [requests, myplaylist, hp, lp, new]) | |
radio=fallback(track_sensitive=true,[switch([ | |
#Monday = 1w# | |
({ (1w) and 8h-12h }, mellow), | |
#({ (5w) and 14h-18h }, ), | |
]), radio]) | |
# Add fallbacks and jingles | |
security = nrj(single(securityuri)) | |
radio = rotate(weights = [5, 1],[radio, jingles]) | |
radio = fallback(id="switcher",track_sensitive = false, [liveshow, radio, security]) #myplaylist | |
#radio = fallback(track_sensitive = false,[liveshow, radio]) | |
# Add a skip command for use via telnet | |
add_skip_command(command="skip", radio) | |
# Add an announcement queue. | |
announce = audio_to_stereo(request.queue(id="announce")) | |
# Talk over stream using microphone mount. | |
radio = smooth_add(delay=0.8, p=background_volume, normal=radio, special=microphone) | |
# Make quick announcements on the fly with this. | |
radio = smooth_add(delay=0.8, p=background_volume, normal=radio, special=announce) | |
radio = on_metadata(lastfm.scrobble(user=lfmuser,password=lfmpass), radio) | |
radio = mksafe(radio) | |
# Setup the output streams, and autodump to a webserver: | |
output.icecast(%mp3(samplerate=44100,stereo=true,id3v2=true,bitrate=128),id="ToVorbis",name=icename, | |
host=hostname,port=iceport,password=passw,mount="stream-128.mp3",genre=icegenre,icy_metadata="true", | |
description="#{icedesc} (Normal)",url=iceurl,public=true,radio) | |
output.icecast(%mp3(samplerate=48000,stereo=true,id3v2=true,bitrate=320),id="ToVorbis",name=icename, | |
host=hostname,port=iceport,password=passw,mount="stream-320.mp3",genre=icegenre,icy_metadata="true", | |
description="#{icedesc} (Ultra Quality)",url=iceurl,public=true,radio) | |
output.icecast(%mp3(samplerate=32000,stereo=false,id3v2=true,bitrate=96),id="ToVorbis",name=icename, | |
host=hostname,port=iceport,password=passw,mount="stream-96.mp3",genre=icegenre,icy_metadata="true", | |
description="#{icedesc} (Mobile)",url=iceurl,public=true,mean(radio)) | |
# radio = on_shutdown(fun(_) -> fade.final(type="sin", duration=3., radio)) | |
# Fail attempt at fading out on shutdown, will try to fix later. | |
#output.file( | |
# %mp3(bitrate=192),fallible=true, | |
# on_start={log("Starting live dump.")}, | |
# reopen_on_metadata=false,"#{dump_mp3_file}", | |
# on_close=fun(_) -> (log("Stopped live dump.")), | |
#liveshow) | |
# END OF SCRIPT # |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment