Files
youtube-app/CLAUDE.md
2026-04-05 14:54:10 +02:00

4.8 KiB

YouTube App

Selbst-gehostete Anwendung: YouTube-Videos per Browser Extension erfassen, auf einem Server speichern und per Kotlin-App auf Android/Android TV streamen und herunterladen.

Dokumentation

  • systems.md — Technologie-Stack pro Komponente
  • commication.md — Kommunikationsflüsse zwischen den Systemen
  • features.md — Konkrete Features und Benutzerinteraktionen
  • architecture.md — Detaillierter Systemaufbau (Endpoints, Services, Models, Screens)
  • szenarios.md — Benutzer-Szenarien

Architektur

Drei Komponenten:

Browser Extension (browser_extension/)

  • Manifest V2, Firefox-kompatibel (browser.* API)
  • content.js — extrahiert Videodaten direkt aus dem YouTube-DOM:
    • ytd-rich-item-renderer (Homepage, Abos, Kanalseiten)
    • ytd-video-renderer (Suchergebnisse)
    • IntersectionObserver (threshold 50%) — nur sichtbare Cards erfassen
    • MutationObserver registriert neue Cards beim IntersectionObserver
    • yt-navigate-finish Event-Listener fuer SPA-Navigation
    • Deduplizierung ueber sentUrls Set, wird bei Navigation geleert
    • Batch-Versand: sammelt sichtbare Videos, sendet als Array
    • Selektoren ohne Klassen: nur Tags (h3, img) und Attribute (href, src)
  • background.js — empfaengt Batch vom Content Script, sendet POST an Server
  • Laden via about:debugging#/runtime/this-firefox → "Temporaeres Add-on laden" → manifest.json

Server (backend/)

  • Python, FastAPI, SQLAlchemy, SQLite (videos/youtubeapp.db)
  • yt-dlp + ffmpeg fuer Video-Download und Live-Streaming
  • Dockerisiert: docker compose up --build -d im backend/ Verzeichnis
  • Laeuft auf http://localhost:8000
  • Download-Service speichert Videos unter /videos/{id}.mp4
  • Streaming: heruntergeladene Videos von Datei, sonst Live-Stream via yt-dlp + ffmpeg (fragmentiertes MP4)
  • Dedup: beim Batch-Import wird bestehender Eintrag mit gleicher Video-ID geloescht und neu eingefuegt
  • Sortierung: nach ID absteigend (erstes Video im Batch bekommt hoechste ID)

App (app/)

  • Kotlin, Jetpack Compose, Android/Android TV
  • Gradle-Projekt, Modul frontend
  • Screens: AllVideos (Grid), Downloaded, VideoDetail, VideoPlayer
  • Retrofit fuer API-Calls, Coil fuer Thumbnails, ExoPlayer fuer Streaming
  • Navigation mit Bottom Bar, Dark Theme
  • Server-IP konfigurierbar in ApiClient.kt (aktuell 192.168.178.92)
  • Emulator: Android Studio → Device Manager → Pixel 6a, API 35

API Endpoints

  • POST /videos — Video-Batch von Extension empfangen (Liste von Videos, Dedup + Reverse-Insert)
  • GET /videos — alle Videos abrufen (sortiert nach ID absteigend)
  • GET /videos/downloaded — heruntergeladene Videos abrufen
  • POST /videos/{id}/download — Download auf Server triggern
  • GET /videos/{id}/stream — Video streamen (von Datei oder Live via yt-dlp/ffmpeg)
  • GET /videos/{id}/file — Video-Datei zum Download auf Client ausliefern

Projektstruktur

backend/
  main.py              — FastAPI App, CORS, Startup
  database.py          — SQLAlchemy Engine, Session, Base
  models.py            — Video Model (id, title, youtuber, thumbnail_url, youtube_url, file_path, created_at)
  schemas.py           — Pydantic Schemas (VideoCreate, VideoResponse)
  routes/videos.py     — Alle API-Routen
  services/
    video_service.py   — CRUD-Operationen, Dedup
    download_service.py — yt-dlp Download + Live-Streaming
  Dockerfile           — Python 3.12 + ffmpeg
  docker-compose.yml   — Service-Definition, Port 8000, Volume /videos
  .dockerignore        — videos/, __pycache__/
  .gitignore           — videos/, __pycache__/

browser_extension/
  manifest.json        — Manifest V2, Permissions fuer youtube.com + localhost
  content.js           — DOM-Extraktion + IntersectionObserver + Batch-Versand
  background.js        — Batch-POST an Server

app/
  .gitignore           — .gradle/, build/, .idea/, local.properties
  frontend/src/main/java/com/youtubeapp/
    MainActivity.kt    — Einstiegspunkt
    data/              — Video, ApiClient, VideoApi, VideoRepository
    ui/screens/        — AllVideos, Downloaded, VideoDetail, VideoPlayer
    ui/components/     — VideoCard
    ui/viewmodel/      — VideoViewModel
    ui/navigation/     — AppNavigation, Routes
    ui/theme/          — Theme (Dark)

Entscheidungen

  • Kein Jellyfin — erfuellt nicht die Anforderung, Videos vor dem Download aufzulisten
  • Kein PostgreSQL/MySQL — SQLite reicht fuer den Prototyp
  • Keine Benutzerprofile im Prototyp
  • Videos werden auf dem Server gespeichert, Client speichert nur bei explizitem Download
  • DOM-Extraktion statt ytInitialData-Parsing — funktioniert auch bei SPA-Navigation und Scrollen
  • IntersectionObserver statt blindem Scan — nur sichtbare Videos erfassen
  • Live-Streaming via yt-dlp/ffmpeg statt synchronem Download vor dem Streamen
  • Sprache der Dokumentation: Deutsch