Ljudet fungerade. Då började jag störa mig på allt runt ljudet.
När strömmen i sig var stabil nog började jag lägga märke till det lyssnaren faktiskt ser: artist, låttitel, status och senare historik. Metadata låter som en liten detalj tills flera källor skriver den på olika sätt.
En källa kan skriva artist och titel i ett enda fält. En annan kan separera dem. En intern stationstext kan råka se ut som en låt. Ett stations-ID kan dyka upp som historik om jag bara sparar allt som förändras. Om samma titel rapporteras flera gånger kan en enkel historik tro att låten spelats flera gånger.
Jag började därför bygga ett eget lager som tolkar informationen innan den visas. Det var en tidig föregångare till dagens Relay 7 Now Playing API.
rå metadata
↓
normalisera text
↓
filtrera interna poster
↓
deduplicera
↓
publicera "nu spelas"
↓
lägg riktig låt i historikenDet här var också första gången jag på riktigt byggde något som inte behövdes för själva ljudet men som gjorde stationen mer begriplig. När den komponenten väl fanns blev det självklart att webben senare skulle kunna visa historik, omslag, showinfo och nästa låt utan att behöva förstå hela radiomotorn.
Metadata blev mitt första API-problem
Det var lockande att låta webben läsa rå streammetadata direkt. Jag gjorde sådana försök, men problemet blev snart att varje klient behövde förstå specialfallen. Jag ville inte ha samma regex i webben, mobilen och en framtida adminpanel.
Jag började därför tänka i ett canonical now-playing object. Det behöver inte spegla exakt hur upstream skriver metadata. Det ska spegla hur Relay Seven definierar “en aktuell låt”. När den tanken satt blev API-lagret ett naturligt hem för fler saker senare.
Historiken blev det första stället där “rådata” och “sanning för lyssnaren” skildes åt
När jag började visa historik märkte jag snabbt att rå metadata inte är samma sak som en publik händelselogg. Ett internt stations-ID kan vara relevant för driften men ointressant i historiken. Samma låt kan rapporteras flera gånger när metadata uppdateras. En tom artist eller titel ska inte skapa en post bara för att upstream skickade något.
Jag började lägga in små filter ett efter ett. Först ignorera tomma poster. Sedan ignorera kända interna etiketter. Sedan deduplicera samma artist/titel inom kort tid. Sedan hålla ett begränsat antal poster så sidan inte växer okontrollerat.
Det här blev så småningom en viktig designprincip för alla publika API:er: jag vill skicka domändata, inte implementationens rådata. Om Broadcast internt kallar något “voice_queue” behöver appen inte veta det. Om ett stations-ID spelas ska historiken kunna behandla det enligt publik policy utan att klienten känner till hur Broadcast klassificerar filer.
event = normalize(rawMetadata)
if event.is_internal:
skip()
if same_as_last_public_track(event):
skip()
history.prepend(event)
history = history.slice(0, limit)Det här gjorde senare flytten till flera klienter betydligt lättare.