Televizyon.app Arşiv API

Türk TV kanallarının 7/24 kaydedilen dökümlerinde arama yapın: bir kelimenin hangi kanalda, yayında saat kaçta geçtiğini milisaniye hassasiyetinde öğrenin, bir kanalın belirli bir aralıktaki dökümünü alın, bir konunun gün içindeki yoğunluğunu görün.

Temel adres https://televizyon.app/api/v1

Yayındaki tam saat

Her kelimenin yayında söylendiği an kaydedilir. Arama sonucu, eşleşen kelimenin saatini verir.

Türkçe'ye uygun arama

“muhalefet” araması muhalefetin, muhalefete… biçimlerini de bulur. Yanlış yazımlar için benzer arama vardır.

Hızlı ve sayfalı

Dizinli tam metin arama; imleçli sayfalama ile büyük aralıklarda da hızlı yanıt.

Kimlik doğrulama

Tüm uç noktalar bir API token'ı ister. Token'ı her istekte Authorization başlığında gönderin:

HTTP başlığı
Authorization: Bearer tv2t_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Token'lar tv2t_ ile başlar ve oluşturulduklarında yalnızca bir kez gösterilir. İptal edilen token anında geçersiz olur. Token'ı adres satırına (URL) koymayın; yalnızca başlıkta gönderin.

Token almak: sistem yöneticisi sunucuda docker compose exec web python -m app.admin token create "isim" komutuyla oluşturur; token list ile listeler, token revoke <id> ile iptal eder.

Zaman, sayfalama, sınırlar

Zaman biçimi

Tüm zamanlar ISO 8601'dir. Yanıtlar UTC döner (+00:00). Sorgularda saat dilimi belirtebilirsiniz; Türkiye saati için +03:00 kullanın. URL içinde + işareti %2B olarak yazılmalıdır:

Örnek
from=2026-10-09T09:00:00%2B03:00&to=2026-10-09T12:00:00%2B03:00

Sayfalama

Liste döndüren uç noktalar next_cursor verir. Sonraki sayfa için aynı isteği cursor=<next_cursor> ekleyerek tekrarlayın. next_cursor değeri null ise başka sonuç yoktur. İmleçli sayfalama, sayfa numarasıyla sayfalamadan farklı olarak, derin sayfalarda da yavaşlamaz.

İstek sınırı

Token başına saniyede 20 istek (anlık 60'a kadar). Aşılırsa 429 döner; kısa bir süre bekleyip tekrar deneyin.

Arama nasıl çalışır

  • Büyük-küçük harf ve noktalama önemsizdir. Türkçe harfler doğru işlenir (İ/i, I/ı).
  • 5 ve daha uzun kelimeler ekleri yakalar: istanbul → İstanbul'da, İstanbul'un, İstanbullu…
  • Daha kısa kelimeler tam eşleşir (kesmeli ekler dahil): rize → Rize, Rize'de; ama “rizeli” değil.
  • Birden çok kelime (mode=word): hepsi aynı segmentte geçmeli, sıra önemsiz.
  • Yakın (mode=near): kelimeler aynı kanalda 60 sn içinde geçmeli (farklı cümlelerde olabilir): başarı ödül.
  • Operatörler (word ve near): festival VEYA konser (ya da OR, |) biri yeter · konser -yağmur (ya da DEĞİL, NOT) geçmesin · "iyi haberler" tırnak içi yan yana. Yalnızca -kelime ile arama yapılamaz.
  • Konuşmacı: konuşan:ad başarı (ad: panelde tanıtılan kişi) yalnızca o kişinin kendi sesiyle söylediği cümleler (ses tanıma; kişiler yönetim panelinde tanıtılır, bkz. /speakers). Tek başına konuşan:ad kişinin son konuşmalarını listeler. Ad, kayıtlı adın bir parçası olabilir; boşluklu ad tırnakla: konuşan:"ad soyad". kişi: da olur.
  • Yan yana ifade (mode=phrase): kelimeler bu sırayla, art arda geçmeli: “merkez bankası”.
  • Benzer yazım (mode=fuzzy): konuşma tanıma bazen kelimeyi yanlış yazar (“kpss” → “kfss”). Bu mod benzer yazılışları da bulur; sonuçlar daha geniştir, gözden geçirerek kullanın.

Bir segment, genellikle 2–15 saniyelik bir konuşma cümlesidir; arama sonuçları segment segment döner.

Döküm

GET/transcriptsBir kanalın zaman aralığındaki dökümü, zaman sırasıyla
ParametreAçıklama
channelzorunluKanal kimliği (/channels).metin
from, toZaman aralığı. from verilmezse son 1 saat.tarih-saat
include_wordstrue ise her kelime yayındaki anıyla döner.mantıksal
limit1–1000. Varsayılan 200.tam sayı
cursorÖnceki yanıttaki next_cursor.metin
curl -H "Authorization: Bearer $TELEVIZYON_TOKEN" \
  "https://televizyon.app/api/v1/transcripts?channel=ce5c463456&from=2026-10-09T17:00:00%2B03:00&to=2026-10-09T18:00:00%2B03:00"
# Bir saatlik dökümün tamamı (sayfa sayfa)
params = {"channel": "ce5c463456", "from": "2026-10-09T17:00:00+03:00",
          "to": "2026-10-09T18:00:00+03:00", "limit": 1000}
segments = []
while True:
    page = requests.get("https://televizyon.app/api/v1/transcripts", params=params, headers=H).json()
    segments += page["results"]
    if not page["next_cursor"]:
        break
    params["cursor"] = page["next_cursor"]

include_words=true ile her segmentte ek olarak:

words
"words": [ { "w": "sandıkta", "at": "2026-10-09T09:32:48.535+00:00" },
           { "w": "da",       "at": "2026-10-09T09:32:49.955+00:00" }, … ]

Zaman çizelgesi

GET/timelineBir kelimenin dakika/saat/gün bazında kaç segmentte geçtiği, kanal kanal
ParametreAçıklama
qzorunluKelime(ler); arama kuralları ve operatörler /search ile aynı. Yalnızca konuşan:ad: kişinin saat saat kaç cümle konuştuğu.metin
modeword (varsayılan, aynı segmentte) · near (aynı kanalda 60 sn içinde)metin
bucketminute · hour (varsayılan) · day. Dakikada en fazla 2 günlük aralık.metin
channelKanal kimliği/kimlikleri (virgülle).metin
from, toVarsayılan: son 24 saat.tarih-saat
Yanıt · 200
{
  "bucket": "hour",
  "from": "2026-10-08T14:13:57+00:00", "to": "2026-10-09T14:13:57+00:00",
  "series": [
    { "channel": { "id": "d50469f334", "name": "CNBC-e" },       "at": "2026-10-09T14:00:00+00:00", "count": 4 },
    { "channel": { "id": "422fffa5f6", "name": "Ekoturk" },      "at": "2026-10-09T14:00:00+00:00", "count": 2 },
    { "channel": { "id": "ce5c463456", "name": "Bloomberg HT" }, "at": "2026-10-09T14:00:00+00:00", "count": 1 }
  ]
}

Tek segment

GET/segments/{id}Segment, kelime kelime zamanlarıyla

Arama sonucundaki id ile çağrılır; yanıt arama sonucu alanlarına ek olarak words içerir. Bulunamazsa 404.

Ses

GET/audioBir kanalın zaman aralığındaki konuşma sesi (en fazla 10 dk)

Yalnızca konuşma içeren bölümler saklanır (müzik ve sessizlik yok) ve 30 gün tutulur. Bir arama sonucundaki eşleşmenin at değerinin birkaç saniye öncesinden istemek, kelimenin söylendiği anı verir.

ParametreAçıklama
channelzorunluKanal kimliği.metin
from, tozorunluAralık; en fazla 600 sn.tarih-saat
formatogg (Opus, varsayılan) · m4a (AAC; Safari/iOS için).metin

Yanıt bir ses dosyasıdır. X-Clip-Start başlığı dosyanın ilk örneğinin yayın saatini verir; aralıkta kesinti varsa ses ilk kesintide biter. Ses yoksa 404.

curl
curl -H "Authorization: Bearer $TOKEN" -D - -o an.ogg \
  "https://televizyon.app/api/v1/audio?channel=c651476ffd&from=2026-10-09T21:30:00%2B03:00&to=2026-10-09T21:31:00%2B03:00"

Görüntü

GET/videoBir kanalın zaman aralığındaki görüntüsü (MP4, en fazla 10 dk)

Görüntü yalnızca görüntü arşivindeki kanallar için vardır; hangi kanalın hangi aralıkta görüntüsü olduğu /channels yanıtındaki video alanında, tek tek sonuçlar için video: true ile görülür. Görüntü dökümle sesten hizalanır: from/to döküm ve /audio ile aynı saattir.

ParametreAçıklama
channelzorunluKanal kimliği.metin
from, tozorunluAralık; en fazla 600 sn.tarih-saat

Yanıt 360p H.264/AAC bir MP4 dosyasıdır (10 dk ≈ 25–30 MB). Kesit istek anında üretilir (10 dk ≈ 30 sn); aynı anda en çok 2 kesit üretilir, diğerleri sırada bekler. X-Clip-Start başlığı ilk karenin yayın saatini verir; aralıkta görüntü kesintisi varsa kesit ilk kesintide biter. Görüntü yoksa 404.

curl
curl -H "Authorization: Bearer $TOKEN" -D - -o an.mp4 \
  "https://televizyon.app/api/v1/video?channel=c651476ffd&from=2026-10-09T21:30:00%2B03:00&to=2026-10-09T21:31:00%2B03:00"

Kanallar

GET/channelsTüm kanallar, yayın ve arşiv durumu
Yanıttaki bir kanal
{
  "id": "04908db814", "name": "24 TV", "logo": "https://i.imgur.com/8FO41es.png",
  "group": "News", "lang": "tr", "stream_status": "ok", "archived": true,
  "archive": { "state": "ok", "engine": "whisper", "lang": "tr", "lag_s": 11.6,
               "queue_s": 0.0, "last_text_at": "2026-10-09T14:13:48.841+00:00", "error": null }
}
AlanAçıklama
stream_statusYayın linki durumu: ok · down · checking.
archivedKanal 7/24 arşivleniyor mu. Arama yalnızca arşivlenen kanalların kayıtlarını kapsar.
archive.stateok çalışıyor · down yayın koptu, yeniden deneniyor · stopped arşivden çıkarıldı.
archive.lag_sYayında söylenen ile veritabanına düşen arasındaki süre (saniye).
archive.queue_sÇözülmeyi bekleyen ses (saniye). Sürekli büyüyorsa sunucu yetişemiyor demektir.
archive.last_text_atBu kanaldan en son metin yazılan an.
videoGörüntü arşivinin ilk ve son anı {"from", "to"} ya da görüntü yoksa null. Aralığın içinde kesinti olabilir; tek bir anın görüntüsü olup olmadığını sonuçlardaki video alanı söyler.

Konuşmacılar

GET/speakersSes tanımada tanıtılmış kişiler

Her cümlenin ses izi çıkarılır ve yönetim panelinde tanıtılan kişilerin örnekleriyle karşılaştırılır. Tanınan kişi sonuçlarda speaker alanında döner; aramada konuşan:ad ya da speaker= ile süzülür. Ses izlerinin kendisi API'den verilmez. Çok kısa (2 sn altı), müzikli ya da üst üste konuşmalı cümlelerde tanıma zayıflar; tercüme edilen konuşmalarda duyulan ses tercümanınkidir.

Yanıt · 200
[
  { "id": 1, "name": "Ad Soyad", "segments": 4210, "last_heard_at": "2026-10-14T11:29:12+00:00" }
]

Hata kodları

Hatalar {"detail": "açıklama"} biçiminde döner.

KodAnlamı
400Geçersiz parametre (ör. boş q, bozuk cursor, dakika aralığı 2 günü aşıyor).
401Token yok, geçersiz veya iptal edilmiş.
404Segment bulunamadı; istenen aralıkta ses ya da görüntü yok.
422Parametre türü yanlış (ör. tarih biçimi).
429İstek sınırı aşıldı (saniyede 20).

Veri hakkında

  • Gecikme: bir konuşma, yayında söylendikten genellikle 10–60 saniye sonra aranabilir hale gelir.
  • Saat doğruluğu: zamanlar yayının kendi saat bilgisinden alınır. Yayın sunucusunun saati yanlışsa canlı yayın ucuna göre düzeltilir; bu bilgiyi vermeyen birkaç yayında saat birkaç saniye sapabilir.
  • Dökümler otomatik konuşma tanımadır; özel isim ve kısaltmalarda yazım hataları olabilir. Kritik aramalarda mode=fuzzy ile birlikte deneyin.
  • Müzik, reklam ve sessizlik kaydedilmez; konuşma tanımanın bu anlarda uydurduğu kalıplar filtrelenir.
  • Kürtçe ve Zazaca kanallar ayrı bir modelle çevrilir (engine: "omni"); bu kanallarda kelime zamanları ±1–2 sn hassasiyettedir.

Uç noktaları tarayıcıdan denemek için Swagger arayüzü: sağ üstteki Authorize düğmesine token'ı girin.