Geonark TikTok Canlı Yayın Kayıt ve Yönetim Sistemi
Kesintisiz çalışmak için tasarlanmış, kendi kendini toparlayan bir kayıt altyapısının uçtan uca rehberi. Tek bir Debian sunucusu üzerinde Python ile sürülen süreçler, canlı yayınları yakalar, parçalar halinde diske yazar ve buluta taşır.
Genel Bakış
Sistem üç temel görevi sürekli olarak yürütür: izlenecek hesapları gözlemler, canlıya geçen yayınları gecikmesiz yakalar ve kaydı güvenli bir şekilde uzun süreli depolamaya taşır. Bütün bileşenler tek bir Debian sunucusunda, birbirinden bağımsız çalışan süreçler olarak koşar; herhangi biri çökerse diğerlerini etkilemeden yeniden başlar.
Tasarım hedefi tek bir cümleyle özetlenebilir: hiçbir yayını kaçırmamak. Bu yüzden her aşama, hata durumunda en kötü senaryoyu veri kaybı değil, kısa bir gecikme olacak şekilde kurgulanmıştır. Aşağıdaki bölümler bu garantiyi sağlayan kuralları ayrıntılandırır.
Mimari
Altyapı dört katmandan oluşur. Her katman bağımsızdır ve aralarındaki iletişim yalnızca SQLite veritabanı ve dosya sistemi üzerinden gerçekleşir. Bu sayede bir katman güncellenirken diğerleri çalışmaya devam eder.
- İzleyici (watcher): Python ile yazılmış, hedef hesapların durumunu düzenli aralıklarla yoklayan süreç. Bir hesap canlıya geçtiğinde kayıt görevini sıraya ekler.
- Kayıt motoru: FFmpeg sürecini başlatıp yöneten, yayın akışını parçalar halinde diske yazan katman.
- Depolama: Diske yazılan parçalar; durum bilgisi ise WAL modunda çalışan bir SQLite veritabanında tutulur.
- Taşıma: Tamamlanan kayıtları
rcloneile uzak depoya yükleyen, başarılı yüklemeden sonra yerel kopyayı temizleyen süreç.
Veri akışı
Aşağıdaki şema, bir yayının yakalanmasından arşivlenmesine kadar izlediği yolu özetler:
TikTok yayını
│
▼
[izleyici] ──► hesap canlıda mı? ──(hayır)──► bekle
│ (evet)
▼
[kayıt motoru] ──► ffmpeg ──► parça-001.mp4
parça-002.mp4 ...
│
▼
[sqlite/WAL] ◄── durum: KAYIT_EDILIYOR
│
▼ (yayın bitti)
[rclone] ──► uzak:arsiv/<hesap>/<tarih>/ ──► yerel temizlikSunucu kurulumu
Sistem temiz bir Debian kurulumu üzerinde çalışır. Gerekli paketler tek komutla yüklenir:
sudo apt update
sudo apt install -y python3 python3-venv python3-pip ffmpeg rclone sqlite3
# İzole bir Python ortamı oluştur
python3 -m venv /opt/geonark/venv
source /opt/geonark/venv/bin/activate
pip install -r requirements.txtSüreçler systemd birimleri olarak tanımlanır; böylece sunucu yeniden başladığında ya da bir süreç çöktüğünde otomatik olarak ayağa kalkarlar.
[Unit]
Description=Geonark izleyici
After=network-online.target
[Service]
Type=simple
User=geonark
WorkingDirectory=/opt/geonark
ExecStart=/opt/geonark/venv/bin/python -m geonark.watcher
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.targetİzleme Kuralları
İzleyici, hedef hesapları sabit bir döngüde yoklar. Amaç, yayın başladıktan sonra mümkün olan en kısa sürede kayda geçmektir; ancak aynı anda hedef sunucuyu gereksiz isteklerle yormamaktır.
- 1.Her hesap için yoklama aralığı varsayılan 20 saniyedir. Bu değer hesap bazında ayarlanabilir.
- 2.Bir hesabın canlıya geçtiği tespit edildiğinde, aynı hesap için yeni bir kayıt görevi açılmadan önce
aktif_kayittablosu kontrol edilir; mükerrer kayıt engellenir. - 3.Yoklama hatası (zaman aşımı, ağ kopması) durumunda izleyici hesabı listeden çıkarmaz; üstel geri çekilme (backoff) ile yeniden dener.
- 4.Ardışık beş hatadan sonra hesap
askidadurumuna alınır ve operatöre Telegram üzerinden bildirim gönderilir.
Yoklama mantığı
def izle(hesap: Hesap) -> None:
while not durdur.is_set():
try:
durum = yayin_durumu(hesap.kullanici_adi)
if durum.canli and not aktif_kayit_var(hesap.id):
kuyruga_ekle(hesap, durum.akis_url)
hesap.hata_sayisi = 0
except IzlemeHatasi:
hesap.hata_sayisi += 1
if hesap.hata_sayisi >= 5:
hesabi_askiya_al(hesap)
bildir(f"{hesap.kullanici_adi} askıya alındı")
finally:
durdur.wait(geri_cekilme(hesap.hata_sayisi, taban=20))FFmpeg Kuralları
Kayıt motorunun kalbi FFmpeg'dir. Yayın akışı yeniden kodlanmadan (-c copy) diske yazılır; böylece hem işlemci yükü düşük tutulur hem de orijinal kalite korunur. En kritik kural, akışı sabit süreli parçalara bölmektir.
- Parçalama: Kayıt, her biri 10 dakikalık parçalara bölünür. Bir parça diske tamamen yazıldığında bağımsız olarak yüklenebilir hale gelir.
- Yeniden kodlama yok: Akış olduğu gibi kopyalanır, bu da uzun yayınlarda dahi sunucuyu yormaz.
- Bozuk paket toleransı: Ağ kaynaklı bozuk paketler kaydı durdurmaz; FFmpeg bunları atlayarak devam eder.
- Otomatik kapanış: Yayın bittiğinde akış sonlanır, FFmpeg temiz şekilde çıkış yapar ve son parça kapatılır.
Referans komut
ffmpeg -hide_banner -loglevel warning \
-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5 \
-i "$AKIS_URL" \
-c copy \
-f segment -segment_time 600 -reset_timestamps 1 \
-segment_format mp4 \
"/veri/kayit/$HESAP/$TARIH/parca-%03d.mp4"Bayrakların anlamı
- -reconnect 1
- Bağlantı koparsa FFmpeg otomatik olarak yeniden bağlanır.
- -reconnect_delay_max 5
- Yeniden bağlanma denemeleri arasında en fazla 5 saniye bekler.
- -c copy
- Akışı yeniden kodlamadan kopyalar; CPU kullanımı minimumdur.
- -segment_time 600
- Her parçayı 600 saniye (10 dakika) uzunluğunda keser.
- -reset_timestamps 1
- Her parçanın zaman damgasını sıfırlar; parçalar bağımsız oynatılabilir.
Veritabanı
Tüm durum bilgisi tek bir SQLite dosyasında tutulur. SQLite'ın WAL (Write-Ahead Logging) modu, okuma ve yazmaların birbirini kilitlemeden eşzamanlı yürümesini sağlar; bu, birden çok sürecin aynı veritabanına dokunduğu bu sistemde zorunludur.
WAL modunu açma
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA busy_timeout = 5000;
PRAGMA foreign_keys = ON;journal_mode = WAL okuyucuların yazıcıyı, yazıcının da okuyucuları bloke etmemesini sağlar. busy_timeout ise kısa süreli kilit çakışmalarında sürecin hata vermek yerine beklemesini garanti eder.
Şema
CREATE TABLE IF NOT EXISTS hesaplar (
id INTEGER PRIMARY KEY,
kullanici_adi TEXT NOT NULL UNIQUE,
durum TEXT NOT NULL DEFAULT 'aktif', -- aktif | askida
yoklama_sn INTEGER NOT NULL DEFAULT 20,
hata_sayisi INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS kayitlar (
id INTEGER PRIMARY KEY,
hesap_id INTEGER NOT NULL REFERENCES hesaplar(id),
baslangic TEXT NOT NULL, -- ISO 8601
bitis TEXT,
durum TEXT NOT NULL, -- KAYIT_EDILIYOR | TAMAMLANDI | YUKLENDI
parca_dizin TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_kayit_durum ON kayitlar(durum);Durum geçişleri
- KAYIT_EDILIYOR
- FFmpeg aktif olarak parça yazıyor. Yükleme yapılmaz.
- TAMAMLANDI
- Yayın bitti, tüm parçalar diskte. Yükleme kuyruğuna hazır.
- YUKLENDI
- Parçalar uzak depoya taşındı; yerel kopya temizlenebilir.
Bulut Gönderimi
Tamamlanan kayıtlar rclone ile uzak depoya taşınır. Taşıma süreci, veritabanında TAMAMLANDI durumundaki kayıtları bulur, parçalarını yükler ve başarı doğrulandıktan sonra yerel alanı boşaltır.
- 1.Süreç,
kayitlartablosundandurum = 'TAMAMLANDI'olan satırları çeker. - 2.İlgili dizini
rclone copyile uzak depoya yükler; kontrol toplamı (checksum) doğrulaması açıktır. - 3.Yükleme doğrulandığında kayıt
YUKLENDIolarak işaretlenir ve yerel parçalar silinerek disk boşaltılır. - 4.Yükleme başarısız olursa kayıt
TAMAMLANDIdurumunda kalır; bir sonraki turda yeniden denenir. Yerel veri asla erkenden silinmez.
rclone yapılandırması
Uzak hedef bir kez yapılandırılır. Aşağıdaki örnek S3 uyumlu bir nesne deposunu hedefler; SFTP, WebDAV ya da başka bir arka uç da kullanılabilir.
rclone config create arsiv s3 \
provider=Other \
access_key_id=$ANAHTAR \
secret_access_key=$GIZLI \
endpoint=$UC_NOKTASI
# Tamamlanan bir kaydı yükle
rclone copy \
"/veri/kayit/$HESAP/$TARIH" \
"arsiv:geonark/$HESAP/$TARIH" \
--checksum --transfers 4 --retries 5Telegram Botları
Operatör sistemi Telegram üzerinden izler ve yönetir. İki bot vardır: biri olayları bildirir, diğeri komut kabul eder. Her ikisi de aynı SQLite veritabanına bağlıdır.
Bildirim botu
Önemli olaylarda operatöre anlık mesaj gönderir: kayıt başladı, kayıt tamamlandı, yükleme bitti, hesap askıya alındı ya da disk doluyor.
def bildir(metin: str) -> None:
requests.post(
f"https://api.telegram.org/bot{TOKEN}/sendMessage",
json={"chat_id": OPERATOR_ID, "text": metin},
timeout=10,
)Komut botu
Operatör sahaya gitmeden hesapları yönetebilir. Her komut doğrudan veritabanına işlenir; izleyici bir sonraki döngüde değişikliği görür.
- /ekle <kullanici>
- İzleme listesine yeni bir hesap ekler.
- /cikar <kullanici>
- Bir hesabı izleme listesinden çıkarır.
- /durum
- Aktif kayıtları, bekleyen yüklemeleri ve disk doluluğunu listeler.
- /devam <kullanici>
- Askıya alınmış bir hesabı yeniden aktifleştirir.