Poll hatası şu ana kadar sadece panele girip bakınca görülüyordu — proaktif
haberdar olma yolu yoktu. Şimdi bir kanal hata vermeye BAŞLADIĞINDA (her
60sn'de tekrar değil, sadece durum değişince) ve düzeldiğinde Telegram
bildirimi gidiyor. Ayarlar'dan kapatılabilir (notify_poll_error).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Channel.segmentTimeSec (nullable, null = global SEGMENT_TIME_SEC env
var'ı kullan) eklendi. Kanal detay sayfasından dakika cinsinden
girilebiliyor, StreamIngestJob'a taşınıp streamIngest.ts'te ffmpeg'in
-segment_time argümanına yansıyor. Sadece o kanal için bundan sonra
başlayacak yeni kayıt oturumlarını etkiler — halihazırda çalışan bir
ffmpeg process'inin segment süresi zaten sabitlenmiş durumda.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- lastPollErrors artık {message, at} tutuyor — panelde hangi hatanın ne
zaman oluştuğu görünmüyordu, eski/güncel ayrımı yapılamıyordu.
- "This live event will begin in N minutes" gibi zararsız mesajlar da
hata rozetine düşüyordu, "is not currently live" ile aynı gruba alındı.
- Yeni stt_enabled ayarı (Ayarlar sayfası): kapatılınca stt_scoring.py
OpenAI Whisper çağrısı yapmadan adayı PENDING_STT'de bırakıp çıkıyor —
konuşmasız/ambiyans yayınlarda (bkz. NASA testi) boşa API maliyeti
önleniyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Yayın durdurma, kanal duraklat/devam (tekli+toplu), şimdi kontrol et,
manuel URL ile zorla kayıt başlatma, canlı player+log önizleme, oturum
süre sayacı, başarısız/takılı render için tekrar dene ve iptal, poll
aralığı + ham segment TTL'yi panelden canlı değiştirme, cookie bayatlık
uyarısı, Telegram bildirim aç/kapa, ve kullanım/maliyet özeti (/stats).
api-daemon'ın yeni state-değiştiren endpoint'leri (stop/force-start/
render/cancel) INTERNAL_API_TOKEN ile korunuyor — bu daemon'ın portu
Coolify'de public'e açık olduğu için korumasız bırakmak güvenlik açığı
olurdu.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
yt-dlp bunu da non-zero exit code ile bildiriyor, bu yüzden panelde
her kontrolde (kanal gerçekten sadece canlı değilken bile) kırmızı
"hata" rozeti görünüyordu — yanıltıcıydı. "is not currently live"
mesajı artık gerçek bir hata olarak işlenmiyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Regex tabanlı HTML çıkarımı IP'den bağımsız olarak tutarsız çıktı:
YouTube bazen player verisini (videoDetails) sunucu tarafında hiç
göndermiyor. yt-dlp'nin kendi extractor'ı engellenmediği sürece her
zaman doğru çözüyor, o yüzden kontrol tekrar yt-dlp'ye taşındı — bu
sefer üç katmanı birlikte kullanarak: cookie (oturum), pot-provider
(PO-token) ve PROXY_URL (temiz residential/ISP IP — Coolify
sunucusunun kendi IP'si bir günlük yoğun testten sonra işaretlendi).
Oxylabs ISP Proxies ile doğrulandı (gerçek ISP: CenturyLink), datacenter
proxy'lerin aksine.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
videoDetails yok ama sayfa consent duvarına da takılmıyor (büyük,
tam HTML dönüyor) — YouTube oynatıcı verisini bilerek vermiyor gibi
görünüyor. playabilityStatus.status/.reason genelde tam olarak
nedenini açıklıyor (LOGIN_REQUIRED, UNPLAYABLE, ERROR vb.).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cookie header'ı eklemek beklenen sonucu vermedi — @ertemsener kanalı
gerçekten canlıydı ama sistem hâlâ "değil" diyordu. Kör tahminle
devam etmek yerine, her kontrolde (sonuç ne olursa olsun) final URL,
HTML uzunluğu, cookie gönderilip gönderilmediği, videoDetails bulunup
bulunmadığı ve consent formu varlığı GET /status'ta lastPollDebug
alanında görünür kılındı.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Coolify sunucusu AB'de; oturumsuz istek YouTube'un interaktif consent
sayfasına düşüyor (o sayfada videoDetails yok), bu da gerçekten canlı
bir kanalı "değil" gibi gösteriyordu (doğrulandı: @ertemsener canlıydı,
sistem "değil" dedi). yt-dlp için zaten sakladığımız oturum açık
cookie'leri aynı fetch'e Cookie header'ı olarak eklendi — giriş yapılmış
hesaplar consent duvarını hiç görmüyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proxy'ye gerek kalmadan bir çözüm: bugün boyunca düz HTTP fetch hiç
engellenmedi, sadece yt-dlp çağrıları bot-check/PO-token duvarına
takıldı. Önceki naive regex sorunuysa "videoId" alanının sayfada
onlarca kez (kanal video listesi, öneriler) geçmesiydi. Çözüm:
YouTube'un videoDetails objesi — sayfa gerçekten canlıysa tek ve
biricik olarak videoId/isLive/channelId'yi birlikte içeriyor (canlı
değilse obje hiç yok, doğrulandı). channelId çapraz kontrolüyle
birlikte hem doğru video hem yt-dlp'ye hiç dokunmadan (dolayısıyla
bot-check'e hiç maruz kalmadan) tespit yapılıyor. yt-dlp + cookie +
pot-provider artık sadece gerçek capture adımında kullanılıyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cookie'ler saatler içinde eskiyordu, her seferinde manuel Coolify env
güncellemesi + redeploy gerekiyordu. Artık DB'de (app_settings tablosu)
tutuluyor; /settings sayfasından yeni cookies.txt yapıştırılıp
kaydedilebiliyor, bir sonraki yt-dlp çağrısında redeploy gerekmeden
devreye giriyor. YTDLP_COOKIES_B64 env var mekanizması kaldırıldı.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Kullanıcı panelindeki kayıtların kendi yayınıyla alakasız olduğunu
bildirdi. Sebep: channel /live sayfası onlarca alakasız videoId
içeriyor (kanal video listesi, öneriler); düz regex sayfadaki İLK
videoId'yi alıyordu, bu da rastgele başka bir videoydu — isLive:true
kontrolü de aynı bağlamda değildi. yt-dlp'nin extractor'ı kanalın asıl
o anki canlı videosunu doğru çözüyor; -f (format) verilmediği için
PO-token duvarını da tetiklemiyor (format çözümleme sadece gerçek
capture adımında, -f ile, gerekiyor).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PO-token duvarı polling'de hiç gerekli değildi — sadece stream byte'ı
indirirken (capture) lazım. yt-dlp --simulate bile format çözümlemeye
çalıştığı için PO-token'a takılıyordu. Artık /channel/<id>/live
sayfasını düz fetch ile çekip ytInitialData içindeki isLive/videoId'yi
regex ile okuyoruz — bot-check/cookie/PO-token'a hiç maruz kalmıyor.
yt-dlp + cookie + pot-provider sadece gerçek capture adımında kalıyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cookie bot-check'i çözdü ama "The page needs to be reloaded" hatası
kalıcıydı — YouTube artık proof-of-origin token da istiyor. Coolify
stack'ine brainicism/bgutil-ytdlp-pot-provider sidecar servisi
(sc_pot_provider, port 4416) eklendi, api-daemon imajına Python
plugin'i kuruldu, her yt-dlp çağrısına
--extractor-args youtubepot-bgutilhttp:base_url=... eklendi.
ytdlpCookieArgs -> ytdlpAntiBotArgs olarak birleştirildi.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cookie tek başına bot-check'i çözüyordu ama android client ile
birlikte kullanılınca "No video formats found" hatası sürekli
tekrarladı — android client + cookie kombinasyonu tutarsız bir
manifest döndürüyor gibi. android client'sız, sadece cookie +
varsayılan web client + bestvideo+bestaudio/best format seçiciyle
aynı video id lokal olarak sorunsuz çözüldü.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cookie bot-check'i çözdü ama yeni bir hata çıktı: "No video formats
found" / "Requested format is not available". AyrisTech'in canlı
yayını dikey (1080x1920) ve HLS formatları video-only/audio-only
ayrı geliyor — tek parça "best" format hiç yok. Hem live-check hem
capture çağrısını "bestvideo+bestaudio/best" seçicisine çevirdik;
lokal olarak doğrulandı (yt-dlp video id'yi doğru döndürüyor).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
android player_client YouTube'un "Sign in to confirm you're not a bot"
duvarını aşmadı — Coolify sunucusunun IP'si datacenter olarak
işaretlenmiş. Kimlik doğrulanmış bir tarayıcı oturumunun cookies.txt'i
YTDLP_COOKIES_B64 env değişkeni (Coolify'da ayarlandı, repo'da yok)
üzerinden container'a taşınıp /tmp'e yazılıyor ve her yt-dlp
çağrısına --cookies olarak veriliyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AyrisTech kanalı gerçekten canlıydı ama Coolify sunucusunun IP'si
YouTube'un "Sign in to confirm you're not a bot" duvarına takıldı
(bu ortamdan aynı komut sorunsuz çalıştı — IP itibarına bağlı).
Hem live-check hem capture çağrısına --extractor-args
"youtube:player_client=android" eklendi; bu client genelde aynı
PO-token doğrulamasına tabi değil.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
yt-dlp hem "kanal canlı değil" hem de gerçek bir hata (ağ engeli,
bot tespiti, extractor kırılması) durumunda non-zero exit code
veriyor; ikisi ayırt edilemiyordu. Son hata mesajı artık kanal
başına saklanıp GET /status içinde lastPollError alanında dönüyor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
yt-dlp headless capture (15dk segmentleme), ses peak + chat velocity sinyal
tespiti, OpenAI Whisper STT (kelime zaman damgalı), BullMQ/Redis/Postgres
altyapısı ve kanal durumu + transkript kütüphanesi gösteren Next.js panel.
LLM virality skorlama, render/crop/altyazı ve multi-platform dağıtım bu
fazın kapsamı dışında.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>