Define techno-ethnic taste lane and notify when generation is ready.

Bonobo, Jamaica dub, Sahara, Mongolia overtone, and Urdu colour in settings and DJ prompts. Generate runs in background with polling, ready toast, optional browser notification, and autoplay of the new track.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-07 16:27:07 +01:00
parent e15b5e9f98
commit 5f90945b97
9 changed files with 308 additions and 186 deletions
+94 -10
View File
@@ -299,7 +299,30 @@
line-height: 1.4;
}
.status.generating { color: var(--accent); }
.status.ready-flash { color: #6bcf8e; font-weight: 600; }
.status.error { color: #ff5c7a; }
.gen-ready-toast {
position: fixed;
top: 1rem;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
background: linear-gradient(135deg, #1e3a2f, #2a4a3a);
border: 1px solid #6bcf8e;
color: #e8fff0;
padding: 0.85rem 1.25rem;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
box-shadow: 0 8px 32px rgba(0,0,0,0.45);
animation: toast-in 0.35s ease;
max-width: 90vw;
text-align: center;
}
@keyframes toast-in {
from { opacity: 0; transform: translateX(-50%) translateY(-12px); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
.stack {
font-size: 0.7rem;
color: #555568;
@@ -626,6 +649,7 @@
</div>
<div class="status" id="status">Connecting…</div>
<div id="genReadyToast" class="gen-ready-toast" hidden></div>
<button type="button" class="booth-toggle" id="boothToggle">🎙 Vocal booth — record your layer (Chrome)</button>
@@ -674,7 +698,10 @@
const moodEl = document.getElementById('mood');
const djEl = document.getElementById('dj');
const statusEl = document.getElementById('status');
const genReadyToast = document.getElementById('genReadyToast');
const genBtn = document.getElementById('genBtn');
let pollStartedAt = null;
let lastNotifiedCompletedAt = null;
const skipBtn = document.getElementById('skipBtn');
const refreshBtn = document.getElementById('refreshBtn');
const chatLog = document.getElementById('chatLog');
@@ -978,8 +1005,11 @@
const costs = stats.costs || {};
statSpent.textContent = fmtUsd(today.estimated_usd);
statPerTrack.textContent = `~${fmtUsd(costs.per_track_estimate_usd)} / track`;
statGenerated.textContent = `${today.generated || 0} / ${today.max_per_day || 10}`;
statRemaining.textContent = `${today.remaining ?? 0} remaining`;
const unlimited = today.unlimited || today.max_per_day === 0;
statGenerated.textContent = unlimited
? `${today.generated || 0} (unlimited)`
: `${today.generated || 0} / ${today.max_per_day || 10}`;
statRemaining.textContent = unlimited ? '∞' : `${today.remaining ?? 0} remaining`;
statMaxBudget.textContent = fmtUsd(stats.projected_daily_max_usd);
if (stats.playback) {
radioSettings.playback = stats.playback;
@@ -1161,22 +1191,63 @@
}
let pollTimer = null;
let toastTimer = null;
function showReadyToast(title) {
genReadyToast.textContent = `Ready · ${title}`;
genReadyToast.hidden = false;
clearTimeout(toastTimer);
toastTimer = setTimeout(() => { genReadyToast.hidden = true; }, 8000);
}
function notifyTrackReady(track, gen) {
const title = track?.title || gen?.last_completed_title || 'New track';
statusEl.textContent = `Ready · playing ${title}`;
statusEl.classList.remove('generating', 'error');
statusEl.classList.add('ready-flash');
setTimeout(() => statusEl.classList.remove('ready-flash'), 5000);
showReadyToast(title);
addBubble('dj', `Fresh cut ready: ${title} — on air now.`);
if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
new Notification('Live Ozan Radio', { body: `Ready: ${title}`, tag: 'track-ready' });
}
lastNotifiedCompletedAt = gen?.last_completed_at || null;
}
function pollForNewTrack() {
let n = 0;
pollStartedAt = Date.now();
clearInterval(pollTimer);
pollTimer = setInterval(async () => {
n += 1;
const stats = await loadStats(true);
if (stats?.generation?.busy) return;
if (stats?.generation?.error) {
const gen = stats?.generation;
if (gen?.busy) return;
if (gen?.error) {
clearInterval(pollTimer);
statusEl.textContent = gen.error;
statusEl.classList.add('error');
addBubble('dj', `Couldn't finish that track: ${gen.error}`);
return;
}
const completedAt = gen?.last_completed_at;
const isNewCompletion = completedAt
&& completedAt !== lastNotifiedCompletedAt
&& (!pollStartedAt || new Date(completedAt).getTime() >= pollStartedAt - 2000);
await refreshNow();
const now = await fetch(`${API}/api/now`).then(r => r.json()).catch(() => null);
if (isNewCompletion && now?.track) {
applyTrack(now.track, 'generated');
notifyTrackReady(now.track, gen);
clearInterval(pollTimer);
return;
}
await refreshNow();
const now = await fetch(`${API}/api/now`).then(r => r.json()).catch(() => null);
if (now?.track?.track_id !== currentTrackId) clearInterval(pollTimer);
if (n > 60) clearInterval(pollTimer);
}, 3000);
if (n > 90) {
clearInterval(pollTimer);
statusEl.textContent = 'Generation taking longer than usual — still polling…';
}
}, 2000);
}
async function refreshNow() {
@@ -1197,22 +1268,35 @@
}
async function generate() {
if (typeof Notification !== 'undefined' && Notification.permission === 'default') {
Notification.requestPermission();
}
genBtn.disabled = true;
statusEl.textContent = 'DeepSeek is planning… Lyria is composing…';
statusEl.textContent = 'Starting… DeepSeek plans, then Lyria composes (~3090s)';
statusEl.classList.add('generating');
try {
const res = await fetch(`${API}/api/generate`, { method: 'POST' });
const data = await res.json();
if (data.status === 'busy') {
statusEl.textContent = data.message;
applyGenerationState(data.generation);
pollForNewTrack();
} else if (data.status === 'limit') {
statusEl.textContent = data.message || 'Daily limit reached';
statusEl.classList.remove('generating');
updateDashboard({ today: data.budget, costs: radioSettings.costs });
} else if (data.status === 'error') {
statusEl.textContent = data.message || 'Generation failed';
statusEl.classList.add('error');
applyGenerationState(data.generation || { error: data.message });
} else if (data.status === 'accepted' || data.generating) {
applyGenerationState(data.generation || { busy: true, phase: 'planning' });
pollForNewTrack();
} else if (data.status === 'ok') {
if (data.track) applyTrack(data.track, data.source || 'generated');
if (data.track) {
applyTrack(data.track, data.source || 'generated');
notifyTrackReady(data.track, data.generation);
}
await loadStats();
} else {
statusEl.textContent = 'Generation failed — check server logs';
Before
After
+38 -42
View File
@@ -1,71 +1,67 @@
{
"listener": "ozan",
"profile_note": "Modern electronica meets ethnic fusion — Jon Hopkins Singularity, Karsh Kale, Transglobal Underground. Not Turkish folk. Updated 2026-06-07.",
"profile_note": "Techno-ethnic station — Bonobo, Jon Hopkins, Jamaica dub, Sahel, Mongolia overtone vocals, Urdu colour. Beautiful cross-cultural blends. Not Turkish folk. Updated 2026-06-07.",
"station": "Live Ozan Radio",
"taste": {
"summary": "Modern electronica meets ethnic fusion — Jon Hopkins Singularity lush synth builds, Karsh Kale tabla breaks, Transglobal dervish-trance. Electronic production first, world percussion and organic colour woven in. Not Turkish folk.",
"summary": "Techno-ethnic — beautiful electronica meets world dub. Bonobo lush downtempo, Jon Hopkins Singularity builds, Jamaica spring-reverb dub, Sahara/Sahel warmth, Mongolian overtone throat textures, Urdu vocal colour, Karsh Kale tabla breaks. Many cultures woven into one gorgeous track — not one country alone.",
"genres": [
"techno-ethnic",
"ethnic dub",
"bonobo-style downtempo electronica",
"jamaican dub and reggae-dub",
"modern electronica",
"ambient techno meets world",
"ethnic fusion",
"dervish trance",
"tabla electronica",
"asian underground",
"sahel desert electronica",
"mongolian overtone electronica",
"urdu-world fusion",
"global dub",
"dubtronica",
"world electronica",
"cinematic electronic",
"trip-hop dub"
"trip-hop dub",
"tabla electronica",
"cinematic electronic"
],
"mood": [
"beautiful",
"hypnotic",
"trance-like pulse",
"warm",
"spacious",
"late-night",
"cinematic gothic",
"lush and melodic",
"meditative but danceable",
"euphoric electronic builds",
"immersive and cinematic",
"cross-cultural blend"
"euphoric builds",
"immersive",
"cross-cultural wonder"
],
"instruments": [
"lush synth pads and arpeggiated electronica (Singularity-style)",
"tabla and Indian percussion driving the groove",
"sitar and synth leads blended",
"organic hand percussion meets digital pulse",
"oud and kora as colour accents",
"sub bass and sidechain warmth",
"dub delay and spring reverb",
"wordless vocal textures",
"Gregorian-adjacent choral layers (Frostbite lane)",
"ceremonial ritual chants (Chac's Dub lane)",
"breakbeat or four-on-floor-lite hypnotic pulse",
"analog warmth and wide stereo immersion"
"lush Bonobo-style synths and melodic electronica",
"Jamaica dub — spring reverb, one-drop feel, sub bass culture",
"Sahel kora and desert percussion accents",
"Mongolian overtone throat singing as wordless texture layer",
"Urdu male vocal colour — poetic, not Bollywood pop",
"tabla and hand percussion meets digital pulse",
"dub delay and tape echo",
"Jon Hopkins arpeggiated builds",
"organic samples woven through electronic production"
],
"tempo_bpm": [90, 124],
"references": "Jon Hopkins Singularity — modern electronica with organic world percussion and euphoric synth builds; Karsh Kale Milan (tabla electronica); Transglobal Underground Dervish Trans; Thievery Corporation lounge; Shye Ben Tzur / Anoushka Shankar Indian fusion; Baaba Maal Sahel accent; Glass Beams psychedelic tint. Electronic production leads — world colour is woven in, not folk-first.",
"tempo_bpm": [88, 118],
"references": "Bonobo — lush melodic downtempo, beautiful ethnic electronica; Jon Hopkins Singularity; Jamaica dub (Kingston spring reverb, Mungo's Hi Fi); Baaba Maal / Sahara Sahel warmth; Karsh Kale Milan; Transglobal Dervish Trans; Thievery Corporation; Shye Ben Tzur Urdu-Indian fusion without pop. We are inventing techno-ethnic — electronic beauty first, world voices as colour.",
"avoid": [
"Turkish-specific tracks — Ney Vakti, Anatolian night, Ottoman court, bağlama/saz as the identity",
"Turkish language lead vocals or Turkish folk melody as the hook",
"Anadolu psych or Altın Gün-style as the main flavour",
"Indian pop or Rajasthani folk dub — dholak, kartal, sarangi Bollywood-adjacent feel",
"Japanese enka shamisen slow-burn under 88 BPM — Kurai Yoru too slow",
"Armenian duduk hymn dub — slow mournful sacred chant, Duduk Zomari too slow",
"single-country homages of any nation",
"lead vocals locked to one national folk tradition",
"West African highlife and palm-wine guitar",
"slow ney-and-bağlama meditation",
"Turkish folk — Ney Vakti, Anatolian, Ottoman, bağlama/saz as identity",
"Indian pop / Rajasthani folk dub",
"Japanese enka shamisen slow-burn",
"Armenian duduk hymn slow sacred chant",
"single-country homages",
"slow sluggish tracks under 88 BPM",
"West African highlife palm-wine guitar",
"big-room EDM drops",
"four-on-the-floor house",
"fuzz electric guitar on griot or lead vocal tracks",
"sluggish tempo under 88 BPM"
"fuzz electric guitar on vocal tracks"
]
},
"dj": {
"variety": true,
"default_length": "1-2 minutes",
"prefer_fusion_over_locale": true
"prefer_fusion_over_locale": true,
"station_mission": "techno-ethnic — Bonobo-beautiful blends across Jamaica, Sahara, Mongolia, Urdu, and beyond"
},
"playback": {
"shuffle": true,
+20 -17
View File
@@ -1,26 +1,29 @@
{
"updated": "2026-06-07",
"description": "Station genre taxonomy — tags on each track; categories are broader browse buckets.",
"description": "Techno-ethnic taxonomy — Bonobo-beautiful electronica meets world dub and cross-cultural vocals.",
"station_lane": "techno-ethnic",
"categories": {
"fusion-electronic": "Jon Hopkins / Karsh Kale — modern electronica meets world percussion",
"techno-ethnic": "Bonobo / Hopkins — lush electronic beauty meets world colour",
"jamaica-dub": "Kingston spring reverb, reggae-dub bass culture",
"sahara-sahel": "Desert warmth, kora, Sahel pulse",
"mongolia-overtone": "Throat singing as wordless ethereal layer",
"urdu-fusion": "Urdu poetic vocal colour in electronica",
"dub-space": "Dub delay, sub bass, spacious mixes",
"ceremonial-world": "Ritual chant, temple/ceremony energy — Chac's Dub lane",
"cinematic-gothic": "Cold ether, choral depth, Only Lovers Left Alive mood — Frostbite / Gregorian lane",
"desert-dub": "Sahel warmth, caravan pulse, desert blues texture",
"vocal-ethnic": "Wordless or blended ethnic vocals, not folk-pop"
"ceremonial-world": "Ritual chant energy — Chac's Dub",
"cinematic-gothic": "Gregorian ether — Frostbite Dub"
},
"genres": {
"modern-electronica": { "category": "fusion-electronic", "label": "Modern electronica meets world" },
"tabla-electronica": { "category": "fusion-electronic", "label": "Karsh Kale / Milan-style" },
"dervish-trance": { "category": "fusion-electronic", "label": "Transglobal hypnotic breaks" },
"ceremonial-dub": { "category": "ceremonial-world", "label": "Ceremonial chant + dub space" },
"mesoamerican-electronica": { "category": "ceremonial-world", "label": "Clay flute, ritual pulse" },
"gregorian-ether": { "category": "cinematic-gothic", "label": "Gregorian-adjacent choral depth" },
"nordic-dub": { "category": "cinematic-gothic", "label": "Icelandic ether + sub bass" },
"cinematic-gothic": { "category": "cinematic-gothic", "label": "Cold cinematic gothic dub" },
"desert-dub": { "category": "desert-dub", "label": "Desert dubtronica" },
"sahel-blues": { "category": "desert-dub", "label": "Sahel griot warmth" },
"gnawa-dub": { "category": "dub-space", "label": "Gnawa meets dubtronica" },
"techno-ethnic": { "category": "techno-ethnic", "label": "Core station lane — beautiful blended electronica" },
"bonobo-downtempo": { "category": "techno-ethnic", "label": "Lush melodic Bonobo-style electronica" },
"modern-electronica": { "category": "techno-ethnic", "label": "Jon Hopkins Singularity builds" },
"jamaican-dub": { "category": "jamaica-dub", "label": "Jamaica dub and reggae-dub space" },
"sahel-electronica": { "category": "sahara-sahel", "label": "Sahara / Sahel desert electronica" },
"mongolian-overtone": { "category": "mongolia-overtone", "label": "Overtone throat textures in mix" },
"urdu-electronica": { "category": "urdu-fusion", "label": "Urdu vocal colour, not Bollywood" },
"tabla-electronica": { "category": "techno-ethnic", "label": "Karsh Kale / Milan-style" },
"ceremonial-dub": { "category": "ceremonial-world", "label": "Ceremonial chant + dub" },
"gregorian-ether": { "category": "cinematic-gothic", "label": "Gregorian-adjacent choral dub" },
"desert-dub": { "category": "sahara-sahel", "label": "Desert dubtronica" },
"world-dub": { "category": "dub-space", "label": "Pan-ethnic dub lounge" }
}
}
+11 -9
View File
@@ -1,7 +1,7 @@
{
"updated": "2026-06-07",
"listener": "ozan",
"summary": "Batch purge 2026-06-07 — kept original 5 + Chac's Dub + Frostbite Dub only. Lane: Hopkins/Karsh Kale fusion, not slow country-specific gens.",
"summary": "Techno-ethnic station — Bonobo, Jamaica dub, Sahara, Mongolia overtone, Urdu, Hopkins. Seven keepers. Beautiful cross-cultural blends, not single-nation folk.",
"genre_taxonomy": "songs/genres.json",
"global_avoid": [
"fuzz electric guitar on griot/vocal tracks",
@@ -19,14 +19,16 @@
"Armenian duduk hymn dub — slow sacred chant, listener hated Duduk Zomari (same problems)"
],
"global_love": [
"Jon Hopkins Singularity — modern electronica meets organic world percussion",
"ceremonial dub — Chac's Dub temple-step energy",
"Gregorian-adjacent choral ether — Frostbite Dub (listener used to love Gregorian)",
"lush arpeggiated synths and euphoric cinematic builds",
"Karsh Kale / Milan-style tabla electronica",
"Transglobal Underground dervish-trance pulse",
"sub bass pulse and warm analog dub space",
"wordless vocal textures"
"Bonobo — lush beautiful melodic downtempo ethnic electronica",
"techno-ethnic blends — Jamaica dub + Sahara + Mongolia + Urdu in one track",
"Jamaica spring-reverb dub and reggae-dub bass culture",
"Sahara / Sahel desert warmth as electronic colour",
"Mongolian overtone throat singing as wordless ethereal layer",
"Urdu poetic male vocal colour — fusion not Bollywood pop",
"Jon Hopkins Singularity builds",
"ceremonial dub — Chac's Dub",
"Gregorian ether — Frostbite Dub",
"sub bass and warm dub space"
],
"gold_standard_id": "1c1d7b8a",
"tracks": [
+1 -1
View File
@@ -1,5 +1,5 @@
{
"index": 6,
"index": 0,
"count": 7,
"tracks": [
{
+54 -64
View File
@@ -1,94 +1,84 @@
"""Curated batch directionsJon Hopkins Singularity meets ethnic fusion, not Turkish folk."""
"""Techno-ethnic batchBonobo-beautiful blends: Jamaica, Sahara, Mongolia, Urdu, and more."""
VOCAL_BATCH: list[str] = [
(
"Jon Hopkins Singularity-style — lush arpeggiated synths, organic tabla and "
"hand percussion, euphoric build, sub bass pulse, wordless vocal textures, 118 BPM. "
"Modern electronica meets world colour."
"Bonobo-style techno-ethnic — lush melodic synths, soft breakbeat, "
"Jamaica dub spring reverb on percussion, 96 BPM. Beautiful and spacious."
),
(
"Karsh Kale-style tabla electronica — driving tabla breakbeat, sitar riff "
"with synth pad, sub bass, wordless male vocal textures, 100 BPM. Indian-world fusion."
"Jamaica meets Sahara dub — Kingston one-drop sub bass, kora accents, "
"wordless Sahel male chant, tape delay, Mungo's Hi Fi warmth, 92 BPM."
),
(
"Transglobal Underground dervish-trance — hypnotic ethnic breakbeat, oud and "
"synth swirl, wordless call-and-response vocals, dub delay, 96 BPM pulse."
"Mongolia overtone electronica — wordless throat-singing texture layer "
"over Bonobo lush synth pad, tabla pulse, sub bass, 94 BPM ethereal blend."
),
(
"Milan-style fusion dub — tabla and sitar over downtempo break, male wordless "
"vocal hums, bass pulse, spring reverb, Thievery Corporation lounge energy."
"Urdu-world Bonobo dub — male poetic Urdu vocal colour over downtempo "
"electronica, tabla, dub delay, NOT Bollywood pop, 90 BPM beautiful."
),
(
"Sahel meets Asian underground — kora and tabla together, deep sub bass, "
"wordless griot-style chants, hand percussion, 94 BPM. No Turkish instruments lead."
"Jon Hopkins meets Jamaica — arpeggiated synth build, reggae-dub bass, "
"spring reverb, hand percussion, euphoric forward pulse 110 BPM."
),
(
"Ethiopian-jazz world breaks — krar, breathy wordless vocals, piano, synth pad, "
"tabla accents, sub bass, 90 BPM. Pan-ethnic not national."
"Sahara Sahel techno-ethnic — desert kora and talking drum with electronic "
"kick, wordless griot chant, Bonobo melodic warmth, 95 BPM."
),
(
"Persian-Sahel lounge fusion — oud and tar with sitar colour, baritone wordless "
"vocal, tabla groove, hand drums, cinematic ether 92 BPM."
"Karsh Kale Milan energy — tabla breakbeat, sitar-synth hook, sub bass, "
"Urdu wordless alaap texture blended in, 100 BPM."
),
(
"Balkan-brass world breaks — female vocalise, muted trumpet, tabla and darbuka "
"blend, sub bass, 98 BPM dark danceable mix."
),
(
"Atlantic-Desert electronica — soft wordless vocals, fingerpicked warmth, "
"tabla pulse, oceanic reverb, sub bass fusion lounge 88 BPM."
),
(
"Sahel-Asian underground fusion — kora and tabla with synth arpeggio, "
"wordless male chants, sub bass 93 BPM. No Rajasthani folk or sarangi pop."
),
(
"Desert caravan dub — Bambara wordless chants, kora and oud, tabla breakbeat "
"from bar one, sub bass, NO bağlama or ney as lead, 95 BPM."
),
(
"Mediterranean dubtronica mix — bouzouki colour as accent only, tabla groove, "
"wordless vocals, sub bass, 92 BPM. Not country-specific."
),
(
"Kurdish-Sahel storytelling dub — tanbur drone as texture, tabla pulse, "
"wordless narrative vocal, synth pad, 91 BPM cross-cultural."
),
(
"Nordic-desert ether fusion — breathy female wordless vocals, piano, synth, "
"tabla accents, sub bass, cold cinematic dub 90 BPM."
),
(
"East-West break fusion — sitar hook with tabla breakbeat at 96 BPM, "
"synth arpeggio, wordless vocal hum. No shamisen or enka slow-burn."
),
(
"Indo-dub lounge — female wordless alaap, tabla and sitar, synth bass, "
"Karsh Kale energy, 97 BPM. Fusion not Bollywood-only."
),
(
"Synth-pad world breaks — tabla groove, wordless male chant, sub bass, "
"96 BPM forward pulse. No duduk hymn or slow sacred woodwind lead."
"Transglobal dervish-trance — hypnotic ethnic breakbeat, oud swirl, "
"wordless vocals, dub space, 98 BPM danceable."
),
(
"Chac's Dub successor — ceremonial world dub, clay flute ritual chants, "
"baritone chest voice, darbuka, sub bass, temple-step energy 85 BPM."
"baritone chest voice, darbuka, sub bass, Bonobo spacious mix 85 BPM."
),
(
"Frostbite / Gregorian-ether dub — choral wordless female vocals, piano, "
"sub bass, cinematic gothic cold warmth, sacred choral through dub filter 90 BPM."
"Frostbite Gregorian-ether — choral wordless vocals, piano, sub bass, "
"cinematic gothic through Bonobo-style electronic warmth 90 BPM."
),
(
"Emerald Rush energy — driving Jon Hopkins electronica, pulsing synth arpeggio, "
"organic percussion layer, immersive forward momentum, sub bass, 120 BPM. "
"Electronic-first with subtle world accents."
"Jamaica-Mongolia fusion — dub bass and spring reverb, overtone throat "
"texture as ethereal pad, organic hand drums, lush synth, 93 BPM."
),
(
"Atlas-Indian dub — oud and sitar blended, tabla driving, wordless chant, "
"darbuka accents, sub bass 96 BPM. Multi-region not Turkish."
"Urdu-Sahel Bonobo lounge — poetic male Urdu hum, kora sparkle, "
"downtempo electronica, dub echo, beautiful late-night 88 BPM."
),
(
"Afro-Asian highlife-dub fusion — wordless call-and-response vocals, clean "
"plucked strings, talking drum with tabla, ney as light accent only, 94 BPM."
"Ethiopian-jazz techno-ethnic — krar, breathy vocals, piano, Bonobo synth "
"pad, forward pulse 91 BPM."
),
(
"Persian-Sahel Bonobo blend — oud and tar with lush electronica, wordless "
"baritone, tabla groove, 94 BPM."
),
(
"Balkan-brass world breaks — female vocalise, muted trumpet, tabla, "
"sub bass, 98 BPM dark beautiful mix."
),
(
"Indo-dub Bonobo — female wordless alaap, tabla, sitar colour, "
"lush melodic synth, 97 BPM not pop."
),
(
"Ceremonial techno-ethnic — ritual wordless chants, clay flute, "
"Bonobo downtempo pulse, deep sub, 92 BPM."
),
(
"Emerald Rush energy — driving Hopkins electronica, Jamaica dub bass, "
"Sahel percussion layer, 118 BPM immersive."
),
(
"Atlas-Indian dub banger — oud and sitar with tabla, wordless chant, "
"Bonobo beauty, punchy sub 96 BPM."
),
(
"Pan-world Bonobo finale — Jamaica dub + Sahara kora + Mongolia overtone "
"texture + Urdu vocal colour + lush synths, 95 BPM gorgeous blend."
),
]
+7 -8
View File
@@ -45,14 +45,13 @@ Your job:
"melodic call-and-response". Avoid "vocal sample" / "griot sample" phrasing.
9. Read listener curation metadata — clone what they loved, hard-avoid what they disliked
(e.g. fuzz electric guitar on vocal tracks, long guitar-only intros before saz).
10. Positive references: Jon Hopkins Singularity (modern electronica meets organic
world — lush synth arpeggios, euphoric builds, immersive pulse); Karsh Kale (Milan);
Transglobal Underground (Dervish Trans). Electronic production leads, ethnic colour woven in. Also clone keepers by genre:
ceremonial-dub (Chac's Dub), gregorian-ether / cinematic-gothic (Frostbite Dub).
11. Listener likes ETHNIC FUSION MIXES but NOT TURKISH — no Ney Vakti, no Anatolian
folk, no Ottoman court, no bağlama/saz as the lead identity, no Turkish vocals.
Blend Sahel, Indian fusion, Middle Eastern accents, and dub. Vocals: wordless
textures only, not national folk traditions.
10. Station mission: TECHNO-ETHNIC — beautiful electronica meets world dub. Big
inspirations: Bonobo (lush melodic downtempo), Jon Hopkins Singularity, Jamaica
dub (spring reverb, bass culture), Sahara/Sahel warmth, Mongolian overtone throat
textures (wordless ethereal layer), Urdu poetic vocal colour. Blend many cultures
in one gorgeous track — Jamaica + Sahara + Mongolia + Urdu + synth beauty.
11. NOT Turkish folk, NOT slow country homages, NOT Indian pop. Clone keepers:
ceremonial-dub (Chac's Dub), gregorian-ether (Frostbite Dub). Forward tempo 88+ BPM.
Respond with JSON only:
{
+57 -6
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
import asyncio
import json
import random
from datetime import datetime, timezone
from pathlib import Path
from fastapi import BackgroundTasks, FastAPI, HTTPException
@@ -35,7 +36,15 @@ app.add_middleware(
_config: Config | None = None
_queue: RadioQueue | None = None
_generating = False
_generation_state: dict = {"busy": False, "phase": None, "error": None, "track_title": None}
_generation_state: dict = {
"busy": False,
"phase": None,
"error": None,
"track_title": None,
"last_completed_at": None,
"last_completed_title": None,
"last_completed_id": None,
}
_chat = ChatStore()
@@ -101,14 +110,29 @@ def _play_library_entry(q: RadioQueue, cfg: Config, entry: dict) -> dict:
return {"status": "ok", "source": "library", "track": np.__dict__ if np else None}
def _set_generation(*, busy: bool, phase: str | None = None, error: str | None = None, title: str | None = None) -> None:
def _set_generation(
*,
busy: bool,
phase: str | None = None,
error: str | None = None,
title: str | None = None,
completed_id: str | None = None,
) -> None:
global _generation_state
_generation_state = {
state = {
"busy": busy,
"phase": phase,
"error": error,
"track_title": title,
"last_completed_at": _generation_state.get("last_completed_at"),
"last_completed_title": _generation_state.get("last_completed_title"),
"last_completed_id": _generation_state.get("last_completed_id"),
}
if completed_id and title:
state["last_completed_at"] = datetime.now(timezone.utc).isoformat()
state["last_completed_title"] = title
state["last_completed_id"] = completed_id
_generation_state = state
async def _compose_track(request: str | None = None, *, check_limit: bool = True) -> dict:
@@ -138,12 +162,17 @@ async def _compose_track(request: str | None = None, *, check_limit: bool = True
_set_generation(busy=True, phase="composing", title=plan.title)
track = LyriaEngine(cfg).generate(plan)
q.add(track)
q.play_id(track.plan.id)
rs = load_radio_settings(lyria_model=cfg.lyria_model)
cost = cost_per_track(cfg.lyria_model, rs.costs.__dict__)
record_generation(cfg.output_dir, cost, track.plan.id, track.plan.title)
np = q.now_playing()
_, budget = _can_generate_today(cfg)
_set_generation(busy=False)
_set_generation(
busy=False,
title=track.plan.title,
completed_id=track.plan.id,
)
return {
"status": "ok",
"source": "generated",
@@ -262,8 +291,30 @@ async def patch_settings(body: SettingsPatch) -> dict:
@app.post("/api/generate")
async def generate_track() -> dict:
return await _compose_track()
async def generate_track(background: BackgroundTasks) -> dict:
"""Start generation in background — poll /api/stats for progress and ready state."""
cfg = _get_config()
if _generating:
return {
"status": "busy",
"message": "Already generating a track",
"generation": _generation_state,
}
ok, budget = _can_generate_today(cfg)
if not ok:
return {
"status": "limit",
"message": f"Daily limit reached ({budget['max_per_day']} new songs)",
"budget": budget,
}
background.add_task(_background_compose, None)
return {
"status": "accepted",
"generating": True,
"message": "Generating — planning then Lyria compose (~3090s)",
"budget": budget,
"generation": _generation_state,
}
@app.post("/api/shuffle/next")
+26 -29
View File
@@ -9,64 +9,61 @@
"Your Top Songs 2025"
],
"artists": [
"Bonobo",
"Jon Hopkins",
"Karsh Kale",
"Transglobal Underground",
"Baaba Maal",
"Thievery Corporation",
"Mungo's Hi Fi",
"islandman",
"Kaya Project",
"Blanco White",
"Shye Ben Tzur",
"Anoushka Shankar",
"Jon Hopkins",
"Glass Beams",
"Francis Bebey",
"Mungo's Hi Fi",
"Matthew Halsall"
],
"albums": [
{ "title": "Garip", "artist": "Altın Gün", "vibe": "Anadolu psych-folk, bağlama, fuzzy warmth" },
{ "title": "Migration", "artist": "Bonobo", "vibe": "lush melodic downtempo, beautiful ethnic electronica, organic samples" },
{ "title": "Singularity", "artist": "Jon Hopkins", "vibe": "modern electronica meets organic world, euphoric builds" },
{ "title": "Estuaire", "artist": "Ablaye Cissoko", "vibe": "kora, West African elegance, spacious" },
{ "title": "Mirage", "artist": "Glass Beams", "vibe": "psychedelic instrumental, Middle Eastern tint" },
{ "title": "African Electronic Music 1975-1982", "artist": "Francis Bebey", "vibe": "early African electronic, playful hypnotic" },
{ "title": "Singularity", "artist": "Jon Hopkins", "vibe": "modern electronica meets organic world — lush synth builds, immersive pulse, euphoric cinematic" }
{ "title": "African Electronic Music 1975-1982", "artist": "Francis Bebey", "vibe": "early African electronic, playful hypnotic" }
],
"preference": "Modern electronica meets ethnic fusion — Jon Hopkins Singularity, Karsh Kale, Dervish Trans. Turkish folk no.",
"preference": "Techno-ethnic — Bonobo-beautiful electronica meets Jamaica dub, Sahara, Mongolia overtone vocals, Urdu colour. Cross-cultural blends, not single-nation folk.",
"reference_tracks": [
{ "title": "Singularity", "artist": "Jon Hopkins", "vibe": "lush arpeggiated synths, organic percussion, euphoric builds, modern electronic meets world" },
{ "title": "Emerald Rush", "artist": "Jon Hopkins", "vibe": "driving hypnotic electronica, pulsing bass, immersive forward momentum" },
{ "title": "Kerala", "artist": "Bonobo", "vibe": "lush downtempo, beautiful world electronica" },
{ "title": "Singularity", "artist": "Jon Hopkins", "vibe": "lush synths, organic percussion, euphoric electronic meets world" },
{ "title": "Milan", "artist": "Karsh Kale", "vibe": "tabla electronica, sitar-synth fusion" },
{ "title": "Dervish Trans", "artist": "Transglobal Underground", "vibe": "dervish trance breaks, hypnotic ethnic pulse" },
{ "title": "Milan", "artist": "Karsh Kale", "vibe": "tabla electronica, sitar-synth fusion, driving world breakbeat" }
{ "title": "Boboyillo", "artist": "Baaba Maal", "vibe": "Sahara Sahel warmth, rolling desert pulse" }
],
"cultural_palette": [
"Jamaica — dub spring reverb, reggae-dub bass culture",
"Sahara / Sahel — desert warmth, kora, griot colour",
"Mongolia — overtone throat singing as ethereal wordless layer",
"Urdu — poetic male vocal colour in fusion (not Bollywood pop)",
"and more — always blended, always beautiful"
],
"genres": [
"techno-ethnic",
"bonobo-style downtempo",
"ethnic dub",
"jamaican dub",
"sahel electronica",
"modern electronica",
"ambient techno meets world",
"ethnic fusion",
"ethnic chill",
"dubtronica",
"world dub",
"trip-hop",
"global fusion jazz",
"afro-dub",
"cinematic electronic",
"psychedelic world"
"global fusion"
],
"tracks": [
{
"title": "Boboyillo",
"artists": ["Baaba Maal", "Rougi"],
"album": "Being",
"vibe": "Sahel warmth, rolling desert pulse, call-and-response, spiritual but danceable"
},
{
"title": "Olalla",
"artists": ["Blanco White"],
"vibe": "melancholic indie folk, Spanish ether, intimate late-night"
},
{
"title": "Daily Mix 01",
"artists": ["BALTHVS", "Pentagram", "Cem Karaca"],
"vibe": "Turkish rock and psych crossover"
"vibe": "Sahara Sahel warmth, rolling desert pulse, spiritual but danceable"
},
{
"title": "Daily Mix 03",
@@ -76,7 +73,7 @@
{
"title": "Daily Mix 04",
"artists": ["Shye Ben Tzur", "Anoushka Shankar"],
"vibe": "Indian classical fusion, devotional texture, world spiritual"
"vibe": "Urdu-Indian fusion, devotional texture, world spiritual — not pop"
}
]
}