diff --git a/stream/radio.liq b/stream/radio.liq index e5f2da0..96a51e7 100644 --- a/stream/radio.liq +++ b/stream/radio.liq @@ -1,6 +1,6 @@ #!/usr/bin/liquidsoap -# radieo — couche diffusion (jalon 2) +# radieo — couche diffusion. # La source principale est pilotée par le daemon d'ingestion via GET /next. # Le dossier /cache sert de secours quand le daemon n'a rien à proposer # (daemon indisponible, file momentanément vide…). Si tout est vide : silence. @@ -17,7 +17,7 @@ settings.harbor.bind_addrs := ["0.0.0.0"] ingest_url = "http://ingest:8080/next" # Callback appelé par request.dynamic pour obtenir le prochain morceau. -# Renvoie une requête à jouer, ou null() si rien n'est disponible (→ secours). +# Renvoie une requête à jouer, ou null si rien n'est disponible (→ secours). def next_track() = resp = http.get(ingest_url, timeout=5.0) body = string.trim(resp) @@ -32,16 +32,28 @@ end # prochain morceau ; retry_delay pour ne pas marteler le daemon en cas de vide. main = request.dynamic(next_track, prefetch=1, retry_delay=1.0) +# Filtre du secours : ne garder que les vrais fichiers audio et ignorer les +# fichiers cachés (.gitkeep, téléchargements .part en cours). Évite que le +# décodeur ne tente — et logue en erreur — des fichiers non-audio. +audio_ext = [".mp3", ".flac", ".ogg", ".opus", ".m4a", ".aac", ".wav"] +def audio_only(r) = + u = string.case(lower=true, request.uri(r)) + base = path.basename(u) + is_audio = list.exists(fun(e) -> string.contains(suffix=e, u), audio_ext) + is_audio and not string.contains(prefix=".", base) +end + # Secours : le cache local, joué en aléatoire, rechargé quand il change. -backup = playlist(mode="randomize", reload_mode="watch", "/cache") +backup = playlist( + mode="randomize", reload_mode="watch", check_next=audio_only, "/cache" +) # fallback préfère la source principale et bascule sur le cache si elle n'a # rien de prêt. track_sensitive=true : on ne coupe pas un morceau en cours. radio = fallback(track_sensitive=true, [main, backup]) # Transition douce entre les morceaux : fondu enchaîné de 3 s. La fin du -# morceau courant se fond dans le début du suivant. fade_in/fade_out donnent -# la durée des rampes, duration la zone de recouvrement. +# morceau courant se fond dans le début du suivant. radio = crossfade(duration=3.0, fade_in=3.0, fade_out=3.0, radio) # mksafe garantit un flux continu : silence plutôt que plantage si tout est vide.