174 lines
5.4 KiB
Plaintext
174 lines
5.4 KiB
Plaintext
#!/usr/bin/liquidsoap
|
|
|
|
# Asteroid Radio - Docker streaming script
|
|
# Streams music library continuously to Icecast2 running in Docker
|
|
|
|
# Allow running as root in Docker
|
|
set("init.allow_root", true)
|
|
|
|
# Set log level (4 = warning, suppresses info messages including telnet noise)
|
|
log.level.set(4)
|
|
|
|
# Audio buffering settings to prevent choppiness
|
|
settings.frame.audio.samplerate.set(44100)
|
|
settings.frame.audio.channels.set(2)
|
|
# Use "fast" resampler instead of "best" to reduce CPU load on 96kHz files
|
|
settings.audio.converter.samplerate.libsamplerate.quality.set("fast")
|
|
|
|
# Prefer native decoders over FFmpeg for better performance
|
|
settings.decoder.priorities.flac := 10
|
|
settings.decoder.priorities.mad := 10
|
|
settings.decoder.priorities.ffmpeg := 1
|
|
|
|
# Enable telnet server for remote control
|
|
settings.server.telnet.set(true)
|
|
settings.server.telnet.port.set(1234)
|
|
settings.server.telnet.bind_addr.set("0.0.0.0")
|
|
|
|
# =============================================================================
|
|
# CURATED STREAM (Low Orbit) - Sequential playlist
|
|
# =============================================================================
|
|
|
|
# Create playlist source from generated M3U file
|
|
# This file is managed by Asteroid's stream control system
|
|
# Falls back to directory scan if playlist file doesn't exist
|
|
radio = playlist(
|
|
mode="normal", # Normal mode: play sequentially without initial randomization
|
|
reload=300, # Check for playlist updates every 5 minutes
|
|
reload_mode="watch", # Watch file for changes (more efficient than polling)
|
|
"/app/stream-queue.m3u"
|
|
)
|
|
|
|
# Fallback to directory scan if playlist file is empty/missing
|
|
radio_fallback = playlist.safe(
|
|
mode="randomize",
|
|
reload=3600,
|
|
"/app/music/"
|
|
)
|
|
|
|
# Use main playlist, fall back to directory scan
|
|
radio = fallback(track_sensitive=false, [radio, radio_fallback])
|
|
|
|
# Simple crossfade for smooth transitions
|
|
radio = crossfade(
|
|
duration=3.0, # 3 second crossfade
|
|
fade_in=2.0, # 2 second fade in
|
|
fade_out=2.0, # 2 second fade out
|
|
radio
|
|
)
|
|
|
|
# Add buffer after crossfade to handle high sample rate files (96kHz -> 44.1kHz resampling)
|
|
radio = buffer(buffer=5.0, max=10.0, radio)
|
|
|
|
# Create a fallback with emergency content
|
|
emergency = sine(440.0)
|
|
emergency = amplify(0.1, emergency)
|
|
|
|
# Make source safe with fallback
|
|
radio = fallback(track_sensitive=false, [radio, emergency])
|
|
|
|
# Add metadata
|
|
radio = map_metadata(fun(m) ->
|
|
[("title", m["title"] ?? "Unknown Track"),
|
|
("artist", m["artist"] ?? "Unknown Artist"),
|
|
("album", m["album"] ?? "Unknown Album")], radio)
|
|
|
|
# Output to Icecast2 (using container hostname)
|
|
output.icecast(
|
|
%mp3(bitrate=128),
|
|
host="icecast", # Docker service name
|
|
port=8000,
|
|
password="H1tn31EhsyLrfRmo",
|
|
mount="asteroid.mp3",
|
|
name="Asteroid Radio",
|
|
description="Music for Hackers - Streaming from the Asteroid",
|
|
genre="Electronic/Alternative",
|
|
url="http://localhost:8080/asteroid/",
|
|
public=true,
|
|
radio
|
|
)
|
|
|
|
# AAC High Quality Stream (96kbps - better quality than 128kbps MP3)
|
|
output.icecast(
|
|
%fdkaac(bitrate=96),
|
|
host="icecast",
|
|
port=8000,
|
|
password="H1tn31EhsyLrfRmo",
|
|
mount="asteroid.aac",
|
|
name="Asteroid Radio (AAC)",
|
|
description="Music for Hackers - High efficiency AAC stream",
|
|
genre="Electronic/Alternative",
|
|
url="http://localhost:8080/asteroid/",
|
|
public=true,
|
|
radio
|
|
)
|
|
|
|
# Low Quality MP3 Stream (for compatibility)
|
|
output.icecast(
|
|
%mp3(bitrate=64),
|
|
host="icecast",
|
|
port=8000,
|
|
password="H1tn31EhsyLrfRmo",
|
|
mount="asteroid-low.mp3",
|
|
name="Asteroid Radio (Low Quality)",
|
|
description="Music for Hackers - Low bandwidth stream",
|
|
genre="Electronic/Alternative",
|
|
url="http://localhost:8080/asteroid/",
|
|
public=true,
|
|
radio
|
|
)
|
|
|
|
# =============================================================================
|
|
# SHUFFLE STREAM (Deep Space) - Random from full library
|
|
# =============================================================================
|
|
|
|
# Create shuffle source from full music library
|
|
shuffle_radio = playlist(
|
|
mode="randomize", # Random mode: shuffle tracks
|
|
reload=3600, # Reload playlist hourly
|
|
"/app/music/"
|
|
)
|
|
|
|
# Apply crossfade for smooth transitions
|
|
shuffle_radio = crossfade(
|
|
duration=3.0,
|
|
fade_in=2.0,
|
|
fade_out=2.0,
|
|
shuffle_radio
|
|
)
|
|
|
|
# Add buffer to handle high sample rate files
|
|
shuffle_radio = buffer(buffer=5.0, max=10.0, shuffle_radio)
|
|
|
|
# Make source safe with emergency fallback
|
|
shuffle_radio = fallback(track_sensitive=false, [shuffle_radio, emergency])
|
|
|
|
# Add metadata
|
|
shuffle_radio = map_metadata(fun(m) ->
|
|
[("title", m["title"] ?? "Unknown Track"),
|
|
("artist", m["artist"] ?? "Unknown Artist"),
|
|
("album", m["album"] ?? "Unknown Album")], shuffle_radio)
|
|
|
|
# Shuffle Stream - Medium Quality MP3 (96kbps)
|
|
output.icecast(
|
|
%mp3(bitrate=96),
|
|
host="icecast",
|
|
port=8000,
|
|
password="H1tn31EhsyLrfRmo",
|
|
mount="asteroid-shuffle.mp3",
|
|
name="Asteroid Radio (Shuffle)",
|
|
description="Music for Hackers - Random shuffle from the library",
|
|
genre="Electronic/Alternative",
|
|
url="http://localhost:8080/asteroid/",
|
|
public=true,
|
|
shuffle_radio
|
|
)
|
|
|
|
print("🎵 Asteroid Radio Docker streaming started!")
|
|
print("High Quality MP3: http://localhost:8000/asteroid.mp3")
|
|
print("High Quality AAC: http://localhost:8000/asteroid.aac")
|
|
print("Low Quality MP3: http://localhost:8000/asteroid-low.mp3")
|
|
print("Shuffle Stream: http://localhost:8000/asteroid-shuffle.mp3")
|
|
print("Icecast Admin: http://localhost:8000/admin/")
|
|
print("Telnet control: telnet localhost 1234")
|