radio/station.liq
2026-09-01 09:57:29 -07:00

103 lines
2.8 KiB
Text

#!/usr/bin/env liquidsoap
# ---------------------------------------------------------------
# station.liq - Liquidsoap configuration for radio automation
# Written for Liquidsoap 2.2.x. Run from /srv/radio so that the
# relative config.json path resolves correctly; media lives under
# the storage path read from that file. Directory playlists scan
# recursively for audio files automatically.
# ---------------------------------------------------------------
set("log.stdout", true)
set("log.level", 3)
# --- Step 1: path to config.json (relative to working directory) ---
let config_path = "config.json"
# --- Step 2: read and parse the whole file with explicit types --
let json.parse (cfg : {
storage: string,
icecast: {
host: string,
port: int,
mount: string,
username: string,
password: string
}
}) = file.contents(config_path)
# --- Step 3: pull out the values we need ------------------------
let storage = cfg.storage
let ic_host = cfg.icecast.host
let ic_port = cfg.icecast.port
let ic_mount = cfg.icecast.mount
let ic_username = cfg.icecast.username
let ic_password = cfg.icecast.password
set("log.file.path", "#{storage}/logs/liquidsoap.log")
# --- Background music library (directory scanned recursively) --
music_playlist =
playlist("#{storage}/music")
# --- Scheduled content: request queue fed by schedule.txt ------
sched_queue = request.queue(id="scheduler")
# --- Helper: check if a directory contains any audio files -----
def has_audio(dir) =
try
let entries = file.ls(dir)
let audio_count = list.length(
list.filter(fun(f) -> regexp("\\.(mp3|m4a)$").test(f), entries)
)
audio_count > 0
catch _ do
false
end
# --- Jingles / announcements (only active if they have content) ---
jingles_active = has_audio("#{storage}/jingles")
announcements_active = has_audio("#{storage}/announcements")
log("#[info] Jingles directory has audio: #{string(jingles_active)}")
log("#[info] Announcements directory has audio: #{string(announcements_active)}")
# --- Assemble the stream ---------------------------------------
primary = fallback(track_sensitive=false, [sched_queue, music_playlist])
content =
if jingles_active then
random(weights=[1, 8], [
mksafe(playlist("#{storage}/jingles")),
primary
])
else
primary
end
final_content =
if announcements_active then
fallback(track_sensitive=false, [
mksafe(playlist("#{storage}/announcements")),
content
])
else
content
end
radio = normalize(final_content)
# --- Output to Icecast -----------------------------------------
output.icecast(
%mp3(bitrate=128, samplerate=44100, stereo=true),
host=ic_host,
port=ic_port,
user=ic_username,
password=ic_password,
mount=ic_mount,
name="Radio Station",
description="Automated internet radio",
genre="Various",
public=true,
radio
)