stream: compute now-playing duration/position off the HTTP thread
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
The /nowplaying handler called source.duration/source.elapsed on the live crossfaded source. Since it is polled every second by the web player, those cross-thread source queries contended with the crossfade's own clock during a transition and wedged the streaming clock — a few seconds of audio then a frozen buffer looping on air, only ever with a listener connected. Capture duration and the track start time in a synchronous on_metadata callback (which runs in the clock thread, where touching the source is safe) and have /nowplaying read those refs instead — position is just the wall-clock time since the track started. No handler touches the source outside its clock anymore, so the 3 s crossfade is safe again. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
a1f7fc29b3
commit
b5f83ef6c8
2 changed files with 22 additions and 2 deletions
|
|
@ -217,6 +217,23 @@ radio.on_metadata(
|
|||
end
|
||||
)
|
||||
|
||||
# Durée et instant de départ du morceau courant, pour la règle de scrobble du
|
||||
# player (« démarré au début et écouté à ~90 % »). CAPTURÉS ICI, DANS LE THREAD
|
||||
# D'HORLOGE via un on_metadata SYNCHRONE : interroger source.duration/
|
||||
# source.elapsed depuis un handler HTTP (thread harbor) entrait en contention
|
||||
# avec l'horloge du crossfade pendant une transition et figeait l'antenne. On ne
|
||||
# touche donc plus la source hors de son horloge : /nowplaying (web.liq) se
|
||||
# contente de lire ces refs — position = temps écoulé depuis cur_started.
|
||||
cur_duration = ref(0.)
|
||||
cur_started = ref(time())
|
||||
radio.on_metadata(
|
||||
synchronous=true,
|
||||
fun(_) -> begin
|
||||
cur_duration := source.duration(radio)
|
||||
cur_started := time()
|
||||
end
|
||||
)
|
||||
|
||||
# --- Sortie : flux MP3 sur http://<hote>:8000/radio.mp3 ---
|
||||
output.harbor(
|
||||
%mp3(bitrate=192),
|
||||
|
|
|
|||
|
|
@ -95,11 +95,14 @@ harbor.http.register(
|
|||
# /scrobble pour prouver qu'il parle bien du titre à l'antenne.
|
||||
# `duration`/`position` (secondes, arrondies) permettent au player de décider
|
||||
# d'un scrobble « écouté à 90 %, démarré au début ». duration=0 si inconnue.
|
||||
# Ces valeurs sont pré-calculées dans le thread d'horloge (voir cur_duration/
|
||||
# cur_started dans radio.liq) : on ne doit JAMAIS appeler source.duration/
|
||||
# source.elapsed ici, ça figerait l'antenne pendant un crossfade.
|
||||
resp.json({
|
||||
title=m["title"], artist=m["artist"], url=m["url"], origin=m["origin"],
|
||||
file=path.basename(m["filename"]),
|
||||
duration=int_of_float(source.duration(radio)),
|
||||
position=int_of_float(source.elapsed(radio))
|
||||
duration=int_of_float(cur_duration()),
|
||||
position=int_of_float(time() - cur_started())
|
||||
})
|
||||
end
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue