Canlı ses + çalan parça meta verisi + senkron SRT transkript. Statik dosya + poll mimarisi: sunucuda kalıcı bağlantı yok, sadece CDN-dostu küçük dosyalar.
schemaVersion 1 · base: https://radyo.akil.cloudnow.json current.srt radyo.m3u8 openapi.json llms.txt player.html
Üç adet salt-okunur uç nokta; hepsi GET, Access-Control-Allow-Origin: * (CORS açık), kimlik doğrulama yok. Tümü Apache tarafından statik servis edilir → minimum sunucu yükü, kolay önbellekleme.
| Uç nokta | İçerik | Content-Type | Önbellek |
|---|---|---|---|
/radyo.m3u8 | Canlı ses (HLS, AAC, MPEG-TS segment) | application/vnd.apple.mpegurl | no-cache |
/now.json | Çalan parça meta verisi | application/json | no-cache |
/current.srt | Çalan parçanın SRT transkripti | text/plain; charset=utf-8 | parça başına değişir |
Segment dosyaları (seg_*.ts) max-age=10 ile önbelleklenir; oynatıcı bunları otomatik çözer.
/radyo.m3u8GET Kayan pencereli HLS playlist (AAC 48 kHz stereo, ~4 sn'lik MPEG-TS segmentleri, son 6 segment). Safari yerel oynatır; Chrome/Firefox için hls.js.
<audio id="a" controls></audio>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1/dist/hls.min.js"></script>
<script>
const a = document.getElementById('a');
const src = 'https://radyo.akil.cloud/radyo.m3u8';
if (a.canPlayType('application/vnd.apple.mpegurl')) a.src = src; // Safari
else if (window.Hls) { const h = new Hls(); h.loadSource(src); h.attachMedia(a); }
</script>
/now.jsonGET Çalan parçanın anlık durumu. ~2 sn'de bir güncellenir. İstemci 5–10 sn'de bir poll'lamalı; daha sık gerekmez (positionSec ile aradaki süre istemcide hesaplanır).
| Alan | Tip | Açıklama |
|---|---|---|
schemaVersion | number | Şema sürümü (şu an 1). |
serverTime | string (ISO-8601 UTC) | positionSec'in geçerli olduğu an. Drift düzeltmesi için referans. |
serverTimeLocal | string | İstanbul saati HH:MM:SS (insan için). |
isPlaying | boolean | Çalma durumu. false ise zaman alanları null olabilir. |
title | string | Parça başlığı (boş olabilir). |
startedAt | string|null | Parçanın başladığı an (ISO UTC). |
endsAt | string|null | Parçanın biteceği an (ISO UTC). |
endsAtLocal | string | Bitiş İstanbul saati HH:MM. |
durationSec | number|null | Parça toplam süresi (sn). |
positionSec | number | serverTime anındaki çalma pozisyonu (sn). SRT senkronu için anahtar. |
remainingSec | number|null | Kalan süre (sn). |
audio | object | { hls, codec, container, sampleRate, channels }. |
transcript | object | { available:boolean, srt:url, format:"srt" }. |
// /now.json
/current.srtGET Çalan parçanın tam SRT'si (parça değişince atomik güncellenir). transcript.available=false ise içerik boştur. Parça başına bir kez indir (başlık/startedAt değişince yenile), sonra istemcide positionSec ile cue seç.
HLS sesi ile SRT'yi hizalamak için sunucu saatine güvenmek gerekmez; positionSec yeterli:
// 1) now.json'u 5-10 sn'de bir cek; cektigin ani isaretle:
let basePos = data.positionSec, baseAt = Date.now();
let trackKey = data.title + '|' + data.startedAt; // parca degisimini boyle anla
// 2) parca degistiyse current.srt'yi YENIDEN indir ve parse et (parca basina 1 kez):
if (trackKey !== lastKey) { srtCues = parseSrt(await (await fetch('/current.srt')).text()); lastKey = trackKey; }
// 3) her karede gecerli pozisyonu hesapla ve cue sec:
const elapsed = basePos + (Date.now() - baseAt) / 1000; // sn
const cue = srtCues.find(c => elapsed >= c.startSec && elapsed < c.endSec);
SRT zamanları parça başından (0) itibarendir; elapsed de öyle → doğrudan karşılaştırılır. Drift, bir sonraki now.json poll'unda otomatik düzelir.
*), tarayıcıdan doğrudan fetch edilebilir.now.json ve .m3u8 no-cache; her zaman taze.now.json'u 5 sn'den sık çekmeyin.