Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- proxy.py +10 -1
- radio.html +5 -4
proxy.py
CHANGED
|
@@ -186,7 +186,7 @@ def call_speak(text: str, voice: str = arc.VOICE) -> Dict[str, Any]:
|
|
| 186 |
resp = _get_client().post(
|
| 187 |
_modal_url() + "/speak",
|
| 188 |
headers=_modal_headers(),
|
| 189 |
-
json={"text": text, "voice": voice},
|
| 190 |
)
|
| 191 |
resp.raise_for_status()
|
| 192 |
return resp.json()
|
|
@@ -221,6 +221,15 @@ def _clean_dj_text(text: Optional[str]) -> Optional[str]:
|
|
| 221 |
return t
|
| 222 |
|
| 223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
# ---------------------------------------------------------------------------
|
| 225 |
# Pre-cached "stall" lines: instant filler audio played the moment a caller stops
|
| 226 |
# talking, while the real reply generates underneath -- so the call never has
|
|
|
|
| 186 |
resp = _get_client().post(
|
| 187 |
_modal_url() + "/speak",
|
| 188 |
headers=_modal_headers(),
|
| 189 |
+
json={"text": _speakable(text), "voice": voice},
|
| 190 |
)
|
| 191 |
resp.raise_for_status()
|
| 192 |
return resp.json()
|
|
|
|
| 221 |
return t
|
| 222 |
|
| 223 |
|
| 224 |
+
# All-caps "NIGHTWAVE" makes the TTS spell it out letter-by-letter; normalize to
|
| 225 |
+
# title case for SPEECH only (captions/UI keep the branded original text).
|
| 226 |
+
_SPEAK_FIX = re.compile(r"\bNIGHT\s*WAVE\b", re.IGNORECASE)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
def _speakable(text: Optional[str]) -> str:
|
| 230 |
+
return _SPEAK_FIX.sub("Nightwave", text or "")
|
| 231 |
+
|
| 232 |
+
|
| 233 |
# ---------------------------------------------------------------------------
|
| 234 |
# Pre-cached "stall" lines: instant filler audio played the moment a caller stops
|
| 235 |
# talking, while the real reply generates underneath -- so the call never has
|
radio.html
CHANGED
|
@@ -1047,9 +1047,10 @@ function pickSong(){
|
|
| 1047 |
return s;
|
| 1048 |
}
|
| 1049 |
function showNowPlaying(track){
|
| 1050 |
-
if (!els.nowPlaying) return;
|
| 1051 |
els.nowPlaying.classList.add("playing");
|
| 1052 |
-
if (els.npText) els.npText.textContent =
|
|
|
|
| 1053 |
}
|
| 1054 |
function clearNowPlaying(label){
|
| 1055 |
if (!els.nowPlaying) return;
|
|
@@ -1110,6 +1111,7 @@ async function runShow(){
|
|
| 1110 |
if (!State.powered || State.recording) continue;
|
| 1111 |
const intro = brk.segs[brk.segs.length - 1];
|
| 1112 |
const lead = brk.segs.slice(0, -1);
|
|
|
|
| 1113 |
// 1) the DJ break, over the crackle/pad bed
|
| 1114 |
for (const s of lead){
|
| 1115 |
if (!State.powered || State.recording) break;
|
|
@@ -1119,7 +1121,6 @@ async function runShow(){
|
|
| 1119 |
if (!State.powered || State.recording) continue;
|
| 1120 |
// 2) the record + its intro together -> the DJ talks OVER the intro
|
| 1121 |
const track = brk.track;
|
| 1122 |
-
State.song = track; showNowPlaying(track);
|
| 1123 |
const player = renderSong(track);
|
| 1124 |
State.songPlayer = player;
|
| 1125 |
// 3) dead-air gating: buffer the NEXT break while this song plays
|
|
@@ -1129,7 +1130,7 @@ async function runShow(){
|
|
| 1129 |
await player.ended;
|
| 1130 |
State.songPlayer = null;
|
| 1131 |
if (!State.powered) break;
|
| 1132 |
-
|
| 1133 |
}
|
| 1134 |
} finally { State.showRunning = false; clearNowPlaying(); }
|
| 1135 |
}
|
|
|
|
| 1047 |
return s;
|
| 1048 |
}
|
| 1049 |
function showNowPlaying(track){
|
| 1050 |
+
if (!els.nowPlaying || !track) return;
|
| 1051 |
els.nowPlaying.classList.add("playing");
|
| 1052 |
+
if (els.npText) els.npText.textContent =
|
| 1053 |
+
"♪ " + (track.title || "NIGHTWAVE") + " — " + (track.artist || "the all-night desk");
|
| 1054 |
}
|
| 1055 |
function clearNowPlaying(label){
|
| 1056 |
if (!els.nowPlaying) return;
|
|
|
|
| 1111 |
if (!State.powered || State.recording) continue;
|
| 1112 |
const intro = brk.segs[brk.segs.length - 1];
|
| 1113 |
const lead = brk.segs.slice(0, -1);
|
| 1114 |
+
State.song = brk.track; showNowPlaying(brk.track); // plate shows the song for the whole break
|
| 1115 |
// 1) the DJ break, over the crackle/pad bed
|
| 1116 |
for (const s of lead){
|
| 1117 |
if (!State.powered || State.recording) break;
|
|
|
|
| 1121 |
if (!State.powered || State.recording) continue;
|
| 1122 |
// 2) the record + its intro together -> the DJ talks OVER the intro
|
| 1123 |
const track = brk.track;
|
|
|
|
| 1124 |
const player = renderSong(track);
|
| 1125 |
State.songPlayer = player;
|
| 1126 |
// 3) dead-air gating: buffer the NEXT break while this song plays
|
|
|
|
| 1130 |
await player.ended;
|
| 1131 |
State.songPlayer = null;
|
| 1132 |
if (!State.powered) break;
|
| 1133 |
+
// keep the plate on the song that just played until the next break sets the next one
|
| 1134 |
}
|
| 1135 |
} finally { State.showRunning = false; clearNowPlaying(); }
|
| 1136 |
}
|