# YouTube Transcript RSS Feed - Geliştirme Planı

## Proje Özeti

YouTube video transkriptlerini otomatik olarak çıkarıp, tam metin içeren RSS feed'ine dönüştüren otomatik bir pipeline geliştirilmesi. Sistem, Python tabanlı transcript çıkarımı ve RSS feed oluşturma ile RSS-Bridge entegrasyonu seçeneklerini içerir.

---

## Faz 1: Proje Altyapısı ve Ortam Kurulumu

### 1.1. Teknoloji Stack Seçimi

**Ana Yaklaşım: Python Tabanlı (Önerilen)**
- **Transcript Çıkarımı**: `youtube-transcript-api`
- **RSS Oluşturma**: `python-feedgen`
- **Video Listesi**: RSS-Bridge (RSS feed parser)
- **Dil**: Python 3.8+

### 1.2. Geliştirme Ortamı Kurulumu

**Görevler:**
- [ ] Python 3.8+ kurulumu doğrulama
- [ ] Virtual environment oluşturma (`python -m venv venv`)
- [ ] Gerekli paketlerin kurulumu:
  ```bash
  pip install youtube-transcript-api
  pip install feedgen
  pip install python-dateutil
  pip install feedparser  # RSS-Bridge feed'lerini parse etmek için
  pip install requests   # HTTP istekleri için
  pip install aiolimiter  # Async rate limiting için
  pip install httpx      # Async HTTP client
  pip install spacy      # NLP ve Sentence Boundary Detection için
  ```
  **Not**: SQLite Python'da built-in (`sqlite3` modülü), ekstra kurulum gerekmez.
  **SpaCy Model**: `python -m spacy download en_core_web_sm` (veya `tr_core_news_sm` Türkçe için)
- [ ] Proje dizin yapısı oluşturma:
  ```
  yttranscriptrss/
  ├── src/
  │   ├── transcript_extractor.py
  │   ├── transcript_cleaner.py
  │   ├── rss_generator.py
  │   ├── video_fetcher.py
  │   └── database.py
  ├── config/
  │   └── config.yaml
  ├── data/
  │   └── videos.db
  ├── output/
  │   └── transcript_feed.xml
  ├── tests/
  ├── requirements.txt
  └── main.py
  ```

**Süre Tahmini**: 1-2 gün

---

## Faz 2: Transcript Çıkarımı ve Temizleme Modülü

### 2.1. Transcript Çıkarımı (`transcript_extractor.py`)

**Görevler:**
- [ ] `youtube-transcript-api` ile video ID'den transcript çıkarma
- [ ] Çoklu dil desteği (fallback mekanizması)
  - Örnek: `languages=['tr', 'en']` - önce Türkçe, yoksa İngilizce
- [ ] Hata yönetimi:
  - Transcript bulunamama durumları
  - API rate limiting
  - Geçersiz video ID'ler
- [ ] Raw transcript formatını anlama:
  ```python
  # Format: [{"text": "...", "start": 0.0, "duration": 2.5}, ...]
  ```

**Kritik Gereksinimler:**
- Headless browser kullanmama (API tabanlı yaklaşım)
- Otomatik ve manuel transkriptleri destekleme
- **Async Rate Limiting**: AIOLimiter ile eş zamanlı istek yönetimi
  - API limiti: 10 saniyede 5 istek
  - Async batching ile paralel işleme
- **Retry-After Header**: 429 hatalarında `Retry-After` header'ını kullanma
  - Dinamik bekleme süresi (statik delay yerine)
  - Exponential backoff mekanizması
- Timeout ve retry mekanizmaları

**Süre Tahmini**: 3-4 gün

### 2.2. Transcript Temizleme ve Dönüştürme (`transcript_cleaner.py`)

**Görevler:**
- [ ] **Veri Temizleme Pipeline**:
  - **Artifact Removal**: 
    - Zaman tabanlı işaretçileri kaldırma
    - Konuşma dışı etiketler: `[Music]`, `[Applause]`, vb.
    - Aşırı boşlukları temizleme
  - **Normalizasyon**:
    - Unicode karakter normalleştirme
    - Metin standardizasyonu
- [ ] **Sentence Boundary Detection (SBD) - SpaCy Entegrasyonu**:
  - **SpaCy Model Kullanımı**: `en_core_web_sm` veya `tr_core_news_sm`
  - Noktalama işaretlerinin ötesine geçme:
    - Doğal duraklama noktalarını tespit
    - Anlamsal sınırları belirleme
    - Konuşmacı değişikliklerini algılama
  - Fragment'ları birleştirme ve cümle sınırlarını tespit etme
  - Paragraf yapısı oluşturma (cümle sayısı veya anlamsal değişikliklere göre)
  - **Özelleştirme**: Özel içerik için kural tabanlı SBD uzantıları
- [ ] **HTML Wrapping**:
  - Temizlenmiş metni `<p>...</p>` tag'leri ile sarmalama
  - Paragraf yapısını koruma
  - Minimal HTML (sadece gerekli tag'ler)
- [ ] **XML Entity Escaping** (Kritik!):
  - **Zorunlu karakter dönüşümleri**:
    - `&` → `&amp;` (özellikle URL'lerde kritik!)
    - `<` → `&lt;`
    - `>` → `&gt;`
    - `"` → `&quot;`
    - `'` → `&apos;`
  - **CDATA kullanımı**: İsteğe bağlı ama entity escaping hala gerekli
  - URL'lerdeki ampersand'ların kaçışı özellikle önemli

**Algoritma Özeti:**
1. Artifact'ları kaldır ve normalize et
2. SpaCy ile fragment'ları birleştir ve cümle sınırlarını tespit et
3. Paragraflara böl (anlamsal veya cümle sayısına göre)
4. HTML tag'leri ekle (`<p>...</p>`)
5. XML entity escaping uygula (özellikle `&` karakterleri)

**Süre Tahmini**: 4-5 gün

---

## Faz 3: Video Metadata Çıkarımı ve Yönetimi

### 3.1. Video Metadata Fetcher (`video_fetcher.py`) - RSS-Bridge Entegrasyonu

**Görevler:**
- [ ] **RSS-Bridge Feed Parser**:
  - **Public RSS-Bridge instance kullanımı (Önerilen)**:
    - Base URL: `https://rss-bridge.org/bridge01/`
    - Ücretsiz ve hazır kullanılabilir
    - Rate limiting riski var ama başlangıç için yeterli
  - RSS-Bridge YouTube Bridge endpoint'ini kullanma
  - **Doğru URL formatı**:
    - Public (Channel ID): `https://rss-bridge.org/bridge01/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=CHANNEL_ID&format=Atom`
    - Public (Channel Handle): `https://rss-bridge.org/bridge01/?action=display&bridge=YoutubeBridge&context=By+username&u=USERNAME&format=Atom`
    - Self-hosted (opsiyonel): `http://localhost:3000/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=CHANNEL_ID&format=Atom`
  - **Önemli parametreler**:
    - `bridge=YoutubeBridge` (Youtube değil!)
    - `context=By+channel+id` veya `context=By+username`
    - `c=CHANNEL_ID` (channel ID için) veya `u=USERNAME` (handle için)
    - `format=Atom` veya `format=Rss` (feed için, Html değil)
    - `duration_min` ve `duration_max` (opsiyonel filtreleme)
- [ ] **Feed Parsing** (`feedparser` kullanarak):
  - RSS/Atom feed'ini parse etme
  - Video entry'lerini çıkarma
  - Metadata çıkarımı:
    - Video ID (YouTube URL'den parse)
    - Video başlığı (`entry.title`)
    - Yayın tarihi (`entry.published` - timezone-aware)
    - Video URL (`entry.link`)
    - Video açıklaması (`entry.summary` - opsiyonel)
    - Thumbnail URL (opsiyonel)
- [ ] **RSS-Bridge Avantajları**:
  - Native feed'den daha fazla video (10-15 yerine 100+)
  - Channel Handle (@username) desteği
  - Filtreleme seçenekleri (duration, vb.)
- [ ] **Hata Yönetimi**:
  - RSS-Bridge instance erişilemezse fallback (native RSS)
  - Rate limiting handling
  - Feed format validation
- [ ] **Channel ID Extraction (Handle'dan)**:
  - Channel handle (@username) verildiğinde Channel ID'yi bulma
  - Web scraping ile HTML source'dan Channel ID çıkarma
  - Regex pattern: `"externalId":"(UC[a-zA-Z0-9_-]{22})"` veya `"channelId":"(UC[a-zA-Z0-9_-]{22})"`
  - Channel ID formatı: `UC` ile başlar, 22 karakter
  - Fallback mekanizması: İlk pattern bulunamazsa alternatif pattern dene
  - Hata yönetimi: Request exception handling
- [ ] **Video ID Extraction**:
  - YouTube URL'den video ID çıkarma
  - Regex pattern: `youtube.com/watch?v=([a-zA-Z0-9_-]+)`
  - Short URL desteği: `youtu.be/([a-zA-Z0-9_-]+)`
- [ ] `yt-dlp` entegrasyonu (opsiyonel, gelişmiş metadata için)

**RSS-Bridge Kullanım Örneği:**
```python
import feedparser
from urllib.parse import urlencode

# Public RSS-Bridge base URL
RSS_BRIDGE_BASE = "https://rss-bridge.org/bridge01"

# Channel ID ile feed URL'i oluştur
params = {
    'action': 'display',
    'bridge': 'YoutubeBridge',
    'context': 'By channel id',
    'c': 'UC9h8BDcXwkhZtnqoQJ7PggA',  # Channel ID
    'format': 'Atom'  # veya 'Rss'
}
rss_bridge_url = f"{RSS_BRIDGE_BASE}/?{urlencode(params)}"

# Feed'i parse et
feed = feedparser.parse(rss_bridge_url)

# Video entry'lerini işle
for entry in feed.entries:
    video_id = extract_video_id(entry.link)
    video_title = entry.title
    published_date = entry.published_parsed  # timezone-aware
    video_url = entry.link
```

**Gerçek Örnek URL:**
```
https://rss-bridge.org/bridge01/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC9h8BDcXwkhZtnqoQJ7PggA&format=Atom
```

**Channel ID Bulma Fonksiyonu (Handle'dan):**
```python
import requests
import re

def get_channel_id_from_handle(handle_url):
    """
    Channel handle URL'inden Channel ID'yi web scraping ile bulur.
    Örnek: https://www.youtube.com/@tavakfi -> UC...
    """
    try:
        # HTML içeriğini çek
        response = requests.get(handle_url)
        response.raise_for_status()
        
        html_content = response.text
        
        # İlk pattern: "externalId":"UC..."
        match = re.search(r'"externalId":"(UC[a-zA-Z0-9_-]{22})"', html_content)
        if match:
            return match.group(1)
        
        # Alternatif pattern: "channelId":"UC..."
        match_alt = re.search(r'"channelId":"(UC[a-zA-Z0-9_-]{22})"', html_content)
        if match_alt:
            return match_alt.group(1)
        
        return None  # Channel ID bulunamadı
        
    except requests.exceptions.RequestException as e:
        raise Exception(f"Error fetching channel page: {e}")

# Kullanım örneği
handle_url = "https://www.youtube.com/@tavakfi"
channel_id = get_channel_id_from_handle(handle_url)
# Artık channel_id ile RSS-Bridge feed'ini çekebiliriz
```

**Süre Tahmini**: 3 gün

### 3.2. İşlenmiş Video Takibi (`database.py` - SQLite)

**Görevler:**
- [ ] SQLite veritabanı modülü oluşturma (`database.py`)
- [ ] Veritabanı şeması tasarımı:
  ```sql
  -- Channels tablosu (kanal takibi için)
  CREATE TABLE IF NOT EXISTS channels (
      channel_id TEXT PRIMARY KEY,  -- UC... formatında
      channel_name TEXT,
      channel_url TEXT,
      last_checked_utc TEXT,  -- ISO 8601 UTC format
      created_at_utc TEXT DEFAULT (datetime('now'))
  );
  
  CREATE INDEX IF NOT EXISTS idx_channels_last_checked ON channels(last_checked_utc);
  
  -- Videos tablosu (detaylı şema)
  CREATE TABLE IF NOT EXISTS videos (
      video_id TEXT PRIMARY KEY,  -- 11 karakterli YouTube video ID
      channel_id TEXT,  -- UC... formatında (FK)
      video_title TEXT,
      video_url TEXT,
      published_at_utc TEXT,  -- ISO 8601 UTC format (YYYY-MM-DDTHH:MM:SSZ)
      processed_at_utc TEXT,  -- ISO 8601 UTC format
      transcript_status INTEGER DEFAULT 0,  -- 0: Beklemede, 1: Çıkarıldı, 2: Başarısız
      transcript_language TEXT,
      transcript_raw TEXT,  -- Ham, bölümlenmemiş transcript
      transcript_clean TEXT,  -- SBD ile işlenmiş, RSS için hazır HTML
      last_updated_utc TEXT DEFAULT (datetime('now'))
  );
  
  -- Kritik index'ler (performans için)
  CREATE INDEX IF NOT EXISTS idx_videos_channel_id ON videos(channel_id);
  CREATE INDEX IF NOT EXISTS idx_videos_published_at_utc ON videos(published_at_utc);
  CREATE INDEX IF NOT EXISTS idx_videos_transcript_status ON videos(transcript_status);
  CREATE INDEX IF NOT EXISTS idx_videos_processed_at_utc ON videos(processed_at_utc);
  ```
  
  **Önemli Notlar**:
  - **Zaman Formatı**: UTC ISO 8601 (`YYYY-MM-DDTHH:MM:SSZ`) - SQLite'ın timezone desteği yok
  - **transcript_status**: INTEGER (0, 1, 2) - String değil, performans için
  - **Index Optimizasyonu**: `EXPLAIN QUERY PLAN` ile sorgu performansını doğrula
  - **DATE() fonksiyonu kullanma**: Index kullanımını engeller, direkt timestamp karşılaştırması yap
- [ ] Database helper fonksiyonları:
  - `init_database()` - Veritabanı ve tablo oluşturma
  - `is_video_processed(video_id)` - Duplicate kontrolü
  - `get_pending_videos()` - `transcript_status = 0` olan videoları getir
  - `add_video(video_data)` - Yeni video kaydı (status=0 olarak)
  - `update_video_transcript(video_id, raw, clean, status, language)` - Transcript güncelleme
  - `get_processed_videos(limit=None, channel_id=None)` - İşlenmiş videoları getir
  - `mark_video_failed(video_id, reason)` - Kalıcı hata işaretleme (status=2)
  - `is_transcript_cached(video_id, cache_days=3)` - Transcript cache kontrolü (3 günlük)
  - `get_cached_transcript(video_id)` - Cache'den transcript getirme
  - **Query Performance**: `EXPLAIN QUERY PLAN` ile index kullanımını doğrula
- [ ] **Transcript Cache Mekanizması**:
  - **3 Günlük Cache**: İşlenmiş transcript'ler 3 gün boyunca cache'de tutulur
  - **Cache Kontrolü**: Transcript çıkarımından önce cache kontrolü yapılır
  - **Avantajlar**:
    - YouTube IP blocking riskini azaltır
    - Performans artışı (tekrar isteklerde hızlı yanıt)
    - API rate limiting'i azaltır
    - Aynı videoların transcript'ini tekrar çekmez
  - **Cache Süresi**: `processed_at_utc` tarihine göre 3 gün kontrolü
  - **Otomatik Yenileme**: 3 gün sonra cache geçersiz olur, yeni transcript çekilir
- [ ] Yeni video tespiti algoritması:
  1. RSS-Bridge feed'den son videoları çek (max_items × 2, minimum 50 video)
  2. SQLite veritabanında `video_id` ile sorgula
  3. Sadece yeni videoları (veritabanında olmayan) işle
  4. **Cache Kontrolü**: İşlenmiş videolar için 3 günlük cache kontrolü yap
     - Eğer 3 gün içinde işlenmişse, transcript çıkarma (cache'den kullan)
     - 3 günden eskiyse, yeni transcript çek
  5. **max_items Parametresi**: Her API isteğinde işlenecek transcript sayısı
     - **Varsayılan**: 10 transcript
     - **Maksimum**: 100 transcript
     - **Kullanım**: `?max_items=50` query parametresi ile belirtilir
     - **Batch İşleme**: 20'şer batch'ler halinde işlenir (YouTube IP blocking önleme için)
     - **Veritabanı Kaydı**: Her batch işlendikten sonra hemen veritabanına kaydedilir
     - **RSS-Bridge Limit**: max_items × 2 kadar video çekilir (bazı videolar transcript'siz olabilir)
- [ ] Transaction yönetimi (ACID compliance)
- [ ] Connection pooling ve error handling

**Avantajlar:**
- Daha hızlı sorgulama (index'li)
- Transaction desteği
- İlişkisel veri yapısı
- Daha iyi veri bütünlüğü
- İstatistik sorguları kolaylaşır

**Süre Tahmini**: 2 gün

---

## Faz 4: RSS Feed Oluşturma

### 4.1. RSS Generator (`rss_generator.py`)

**Görevler:**
- [ ] `python-feedgen` ile FeedGenerator oluşturma
- [ ] **Content Namespace Extension** ekleme:
  ```xml
  <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  ```
- [ ] Channel metadata ayarlama:
  - `fg.id()` - Channel ID
  - `fg.title()` - Kanal başlığı
  - `fg.link()` - Kanal URL'i
  - `fg.language('tr')` - Dil
  - `fg.lastBuildDate()` - Son güncelleme tarihi
- [ ] Item oluşturma:
  - `fe.id(video_id)` - GUID (YouTube Video ID)
  - `fe.title(video_title)` - Video başlığı
  - `fe.link(href=video_url)` - Video linki
  - `fe.published(datetime_with_timezone)` - Yayın tarihi (timezone-aware)
  - `fe.description(summary)` - Kısa özet
  - `fe.content(content=cleaned_transcript_html)` - Tam transcript (`<content:encoded>`)

**Kritik Gereksinimler:**
- Timezone-aware tarih formatı (RFC 822 veya ISO 8601)
- Video ID'nin GUID olarak kullanılması (immutable)
- Full-text için `<content:encoded>` tag'i

**Süre Tahmini**: 2-3 gün

### 4.2. RSS Output ve Serialization

**Görevler:**
- [ ] XML dosyası oluşturma:
  ```python
  fg.rss_file('transcript_feed.xml', pretty=True, extensions=True)
  ```
- [ ] Pretty printing (okunabilirlik için)
- [ ] Extensions desteği (Content Namespace dahil)

**Süre Tahmini**: 1 gün

---

## Faz 5: Ana Pipeline ve Otomasyon

### 5.1. Main Pipeline (`main.py`)

**Görevler:**
- [ ] Tüm modüllerin entegrasyonu
- [ ] İş akışı:
  1. SQLite veritabanını başlat (`init_database()`)
  2. Configuration'dan channel bilgisini oku:
     - Eğer handle (@username) verildiyse, `get_channel_id_from_handle()` ile Channel ID'ye çevir
     - Channel ID zaten varsa direkt kullan
  3. RSS-Bridge feed'den yeni videoları tespit et (`video_fetcher.py`)
  4. SQLite veritabanında `video_id` ile duplicate kontrolü yap
  5. Yeni videolar için:
     a. Transcript çıkar
     b. Transcript'i temizle
     c. RSS feed'e ekle
     d. SQLite'a kaydet (video metadata + işlenme durumu)
  6. RSS feed'i güncelle (veritabanından tüm işlenmiş videoları çek)
  7. XML dosyasını kaydet
- [ ] Hata yönetimi ve logging
- [ ] Configuration dosyası yükleme
- [ ] Database transaction yönetimi (rollback on error)

**Süre Tahmini**: 2-3 gün

### 5.2. Configuration Management (`config.yaml`)

**Görevler:**
- [ ] Yapılandırma dosyası oluşturma:
  ```yaml
  channel:
    # Channel ID veya Handle (otomatik dönüştürülür)
    id: "UC9h8BDcXwkhZtnqoQJ7PggA"  # Channel ID (UC ile başlar)
    # veya handle kullanılabilir:
    # handle: "@tavakfi"  # Handle kullanılırsa otomatik olarak Channel ID'ye çevrilir
    # veya full URL:
    # handle_url: "https://www.youtube.com/@tavakfi"
    name: "Channel Name"
    url: "https://youtube.com/channel/..."
    language: "tr"
  
  rss_bridge:
    # Public RSS-Bridge instance (varsayılan - önerilen)
    base_url: "https://rss-bridge.org/bridge01"
    # Self-hosted instance (opsiyonel - rate limiting sorunları için)
    # base_url: "http://localhost:3000"
    bridge_name: "YoutubeBridge"  # Önemli: "YoutubeBridge" olmalı
    context: "By channel id"  # veya "By username"
    format: "Atom"  # veya "Rss" (feed için)
    max_items: 100  # RSS-Bridge'den çekilecek maksimum video sayısı
    use_fallback: true  # RSS-Bridge erişilemezse native RSS kullan
    # Opsiyonel filtreleme
    duration_min: null  # dakika cinsinden minimum süre
    duration_max: null  # dakika cinsinden maksimum süre
  
  transcript:
    languages: ["tr", "en"]
    enable_sbd: true
    paragraph_length: 3
  
  rss:
    title: "Channel Transcript Feed"
    description: "Full-text transcript RSS feed"
    output_file: "transcript_feed.xml"
  
  automation:
    check_interval_hours: 12
    max_items: 100
  ```

**Süre Tahmini**: 1 gün

---

## Faz 6: Test ve Validasyon

### 6.1. Unit Testler

**Görevler:**
- [ ] Transcript extractor testleri
- [ ] Transcript cleaner testleri (SBD, XML escaping)
- [ ] RSS generator testleri
- [ ] Video fetcher testleri:
  - RSS-Bridge feed parsing
  - Channel ID extraction (handle'dan):
    - Handle URL'den Channel ID çıkarma
    - Regex pattern matching testleri
    - Fallback pattern testleri
    - Hata durumları (geçersiz handle, network error)
  - Video ID extraction (URL'den)
  - Fallback mekanizması (RSS-Bridge erişilemezse)
  - Feed format validation (Atom/RSS)
- [ ] Database modülü testleri:
  - Veritabanı oluşturma
  - Video ekleme/sorgulama
  - Duplicate kontrolü
  - Transaction rollback testleri
  - Test veritabanı kullanımı (in-memory SQLite)

**Süre Tahmini**: 2-3 gün

### 6.2. RSS Feed Validasyonu

**Görevler:**
- [ ] W3C Feed Validation Service ile doğrulama
  - URL: https://validator.w3.org/feed/
- [ ] Validasyon checklist:
  - [ ] XML entity escaping doğru mu?
  - [ ] Zorunlu RSS 2.0 tag'leri mevcut mu? (`<title>`, `<link>`, `<description>`)
  - [ ] Content Namespace doğru tanımlanmış mı?
  - [ ] Timezone-aware tarih formatı doğru mu?
  - [ ] GUID'ler unique ve immutable mi?
- [ ] Farklı RSS reader'larda test (Feedly, Tiny Tiny RSS, vb.)

**Süre Tahmini**: 1-2 gün

---

## Faz 7: Deployment ve Hosting

### 7.1. Static Hosting Seçimi

**Seçenekler:**
1. **GitHub Pages** (Önerilen)
   - Ücretsiz
   - CI/CD entegrasyonu
   - Version control
2. **Static.app / StaticSave**
   - Ücretsiz tier mevcut
   - Dosya boyutu limitleri var

**Görevler:**
- [ ] GitHub repository oluşturma
- [ ] GitHub Actions workflow oluşturma (otomatik çalıştırma için)
- [ ] MIME type ayarları (`application/rss+xml`)
- [ ] Public URL oluşturma

**Süre Tahmini**: 1-2 gün

### 7.2. Otomasyon ve Scheduling

**Seçenekler:**
1. **GitHub Actions** (Önerilen)
   - Cron job: Her 12-24 saatte bir
   - Ücretsiz tier yeterli
2. **Cron Job** (VPS/Server)
   - Tam kontrol
   - Sunucu gereksinimi
3. **Cloud Functions** (AWS Lambda, Google Cloud Functions)
   - Serverless
   - Kullanım bazlı maliyet

**GitHub Actions Workflow Örneği (Optimize Edilmiş):**
```yaml
name: Update RSS Feed
on:
  schedule:
    - cron: '0 */12 * * *'  # Her 12 saatte bir
  workflow_dispatch:  # Manuel tetikleme

jobs:
  update-feed:
    runs-on: ubuntu-latest
    steps:
      # 1. Checkout (commit SHA ile sabitlenmiş - güvenlik)
      - uses: actions/checkout@8e5e7e5f366d5b8b75e3d67731b8b25a0a40a8a7  # v4 commit SHA
      
      # 2. Python setup
      - uses: actions/setup-python@0a5d62f8d0679a54b4c1a51b3c9c0e0e8e8e8e8e  # v5 commit SHA
        with:
          python-version: '3.10'
      
      # 3. Cache veritabanı (Git commit yerine - performans)
      - name: Cache database
        uses: actions/cache@v3
        with:
          path: data/videos.db
          key: ${{ runner.os }}-videos-db-${{ hashFiles('data/videos.db') }}
          restore-keys: |
            ${{ runner.os }}-videos-db-
      
      # 4. Install dependencies
      - run: pip install -r requirements.txt
      - run: python -m spacy download en_core_web_sm
      
      # 5. Run pipeline
      - run: python main.py
      
      # 6. Save database to cache
      - name: Save database to cache
        uses: actions/cache@v3
        with:
          path: data/videos.db
          key: ${{ runner.os }}-videos-db-${{ hashFiles('data/videos.db') }}
      
      # 7. Upload RSS feed as artifact
      - name: Upload RSS feed
        uses: actions/upload-artifact@v3
        with:
          name: transcript-feed
          path: output/transcript_feed.xml
          retention-days: 30
      
      # 8. Deploy to GitHub Pages (opsiyonel)
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./output
```

**Önemli Notlar**:
- **Cache Kullanımı**: Veritabanı için `actions/cache` kullan (Git commit yerine) - daha hızlı
- **Action Pinning**: Tüm action'lar commit SHA ile sabitlenmiş (güvenlik)
- **Artifact**: RSS feed'i artifact olarak sakla (GitHub Pages'e deploy edilebilir)
- **SpaCy Model**: CI/CD'de model indirme adımı eklendi

**Süre Tahmini**: 1-2 gün

---

## Faz 8: İleri Özellikler ve Optimizasyon

### 8.1. Performans Optimizasyonu

**Görevler:**
- [ ] Paralel transcript çıkarımı (çoklu video için)
- [ ] Caching mekanizması
- [ ] Rate limiting yönetimi
- [ ] Batch processing optimizasyonu

**Süre Tahmini**: 2-3 gün

### 8.2. Self-Hosted RSS-Bridge Deployment (Opsiyonel - Rate Limiting Sorunları İçin)

**Görevler:**
- [ ] **Ne zaman self-hosting gerekir?**
  - Public instance rate limiting'e maruz kalırsa
  - Yüksek hacimli kullanım gerekiyorsa
  - Özelleştirilmiş bridge'ler (YoutubeEmbedBridge) gerekiyorsa
- [ ] RSS-Bridge Docker deployment:
  ```bash
  docker create --name=rss-bridge --publish 3000:80 \
    --volume $(pwd)/rss-bridge-config:/config \
    rssbridge/rss-bridge
  docker start rss-bridge
  ```
- [ ] RSS-Bridge konfigürasyonu:
  - `config.ini.php` ayarları
  - `CACHE_TIMEOUT` ayarlama (TTL kontrolü)
  - Custom bridge'ler ekleme (YoutubeEmbedBridge)
- [ ] Self-hosting avantajları:
  - Rate limiting'den kaçınma (dedicated IP)
  - Daha fazla video çekebilme (100+)
  - Özelleştirilmiş bridge'ler
  - Gizlilik ve kontrol
- [ ] Production deployment:
  - Reverse proxy (Nginx) kurulumu
  - SSL sertifikası (Let's Encrypt)
  - Monitoring ve health checks
- [ ] YoutubeEmbedBridge entegrasyonu (ad-free playback):
  - `YoutubeEmbedBridge.php` dosyasını `/config/bridges/` klasörüne ekle
  - Container'ı restart et
  - Embed bridge'i test et

**Not**: Public RSS-Bridge (`https://rss-bridge.org/bridge01/`) varsayılan olarak kullanılır ve çoğu durumda yeterlidir. Self-hosting sadece rate limiting sorunları yaşandığında veya özel gereksinimler olduğunda önerilir.

**Süre Tahmini**: 2-3 gün (opsiyonel)

### 8.3. Monitoring ve Logging

**Görevler:**
- [ ] Detaylı logging sistemi
- [ ] Hata bildirimleri (email, webhook)
- [ ] Feed health monitoring
- [ ] İstatistikler (SQLite sorguları ile):
  - Toplam işlenen video sayısı
  - Başarı/başarısızlık oranları
  - Son işlenme tarihleri
  - Dil dağılımı
  - Günlük/haftalık istatistikler

**SQLite İstatistik Örnekleri:**
```sql
-- Toplam işlenen video sayısı
SELECT COUNT(*) FROM processed_videos;

-- Başarı oranı
SELECT 
  transcript_status,
  COUNT(*) as count,
  ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM processed_videos), 2) as percentage
FROM processed_videos
GROUP BY transcript_status;

-- Son 7 günde işlenen videolar
SELECT COUNT(*) FROM processed_videos 
WHERE processed_at >= datetime('now', '-7 days');
```

**Süre Tahmini**: 2 gün

---

## Toplam Süre Tahmini

| Faz | Süre |
|-----|------|
| Faz 1: Altyapı | 1-2 gün |
| Faz 2: Transcript Modülü | 7-9 gün |
| Faz 3: Video Metadata | 6 gün |
| Faz 4: RSS Generation | 3-4 gün |
| Faz 5: Pipeline | 3-4 gün |
| Faz 6: Test & Validasyon | 3-5 gün |
| Faz 7: Deployment | 2-4 gün |
| Faz 8: İleri Özellikler | 4-9 gün (opsiyonel) |
| **TOPLAM (Temel)** | **25-35 gün** |
| **TOPLAM (Tam)** | **29-44 gün** |

---

## Kritik Başarı Faktörleri

1. **API Stabilitesi**: `youtube-transcript-api` kullanımı (scraping değil)
2. **XML Compliance**: Content Namespace Extension ve entity escaping
3. **Timezone Handling**: Tüm tarihler timezone-aware olmalı
4. **Duplicate Prevention**: Video ID GUID olarak kullanılmalı
5. **Efficient Processing**: Sadece yeni videolar işlenmeli

---

## Riskler ve Mitigasyon

| Risk | Etki | Mitigasyon |
|------|------|------------|
| YouTube API değişikliği | Yüksek | `youtube-transcript-api` güncellemelerini takip et |
| Transcript bulunamama | Orta | Fallback diller, hata yönetimi |
| Rate limiting | Orta | Exponential backoff, request throttling |
| XML validation hataları | Yüksek | Comprehensive testing, W3C validation |
| Hosting maliyeti | Düşük | GitHub Pages (ücretsiz) kullan |

---

## Sonraki Adımlar

1. **Hemen Başla**: Faz 1 - Proje altyapısı kurulumu
2. **MVP Hedefi**: Faz 1-6 tamamlanarak çalışan bir sistem
3. **Production Ready**: Faz 7 deployment ile canlıya alma
4. **Optimizasyon**: Faz 8 ile gelişmiş özellikler

---

## Referanslar ve Kaynaklar

- `youtube-transcript-api`: https://github.com/jdepoix/youtube-transcript-api
- `python-feedgen`: https://github.com/lkiesow/python-feedgen
- RSS 2.0 Specification: https://www.rssboard.org/rss-specification
- Content Namespace: http://purl.org/rss/1.0/modules/content/
- W3C Feed Validator: https://validator.w3.org/feed/
- RSS-Bridge: https://github.com/RSS-Bridge/rss-bridge

