From 5aef72f72bc9eacbf7146cc071374382899d34a6 Mon Sep 17 00:00:00 2001 From: Martin Porwoll Date: Sat, 14 Feb 2026 11:51:13 +0000 Subject: [PATCH] docs: add YouTube thumbnail download design document Co-Authored-By: Claude Opus 4.6 --- ...02-14-youtube-thumbnail-download-design.md | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 docs/plans/2026-02-14-youtube-thumbnail-download-design.md diff --git a/docs/plans/2026-02-14-youtube-thumbnail-download-design.md b/docs/plans/2026-02-14-youtube-thumbnail-download-design.md new file mode 100644 index 0000000..350051d --- /dev/null +++ b/docs/plans/2026-02-14-youtube-thumbnail-download-design.md @@ -0,0 +1,96 @@ +# YouTube Thumbnail Download — Design + +**Datum:** 14.02.2026 +**Status:** Approved + +## Ziel + +Automatischer Download von YouTube-Video-Thumbnails und Kanalbildern als Payload Media, damit diese offline verfügbar sind und von Payload's Sharp-Pipeline optimiert werden. + +## Scope + +- **Video-Thumbnails:** Auto-Download bei Sync + Bulk-Import für bestehende Einträge +- **Kanalbilder:** Profilbilder und Banner beim Channel-Sync +- **Nicht im Scope:** Kommentar-Autor-Avatare (bleiben als externe URLs) + +## Qualität + +- YouTube-Thumbnails: `hqdefault` (480x360) +- Payload generiert daraus automatisch alle responsive Sizes (thumbnail, small, medium, etc.) + +## Architektur: Inline beim Sync + +Download direkt im Sync-Flow integriert, kein separater Queue-Job. + +### 1. Kern-Utility: `downloadAndUploadImage()` + +**Datei:** `src/lib/utils/media-download.ts` + +```typescript +interface DownloadOptions { + url: string + filename: string + alt?: string + tenantId?: number +} + +async function downloadAndUploadImage( + payload: Payload, + options: DownloadOptions +): Promise +``` + +- Lädt Bild von URL herunter +- Erstellt Payload Media-Dokument (mit Tenant-Zuordnung) +- Sharp-Pipeline generiert alle 11 responsive Sizes automatisch +- Duplikat-Erkennung: Prüft ob Media mit gleichem Dateinamen + Tenant existiert +- Fehler → `null` (kein harter Fehler, Sync läuft weiter) + +### 2. Integration in YouTube-Sync + +**YouTubeContent** (beim Erstellen/Updaten): +- Wenn `thumbnail`-Feld leer → Download von `https://img.youtube.com/vi/{videoId}/hqdefault.jpg` +- Media-ID in `thumbnail`-Feld speichern +- Manuell hochgeladene Thumbnails werden nie überschrieben + +**YouTubeChannels** (beim Channel-Sync): +- Profilbild und Banner aus YouTube API herunterladen (falls Felder leer) +- In entsprechende Media-Felder speichern + +### 3. Bulk-Import Endpoint + +**Route:** `POST /api/youtube/thumbnails/bulk` +**Auth:** Super-Admin erforderlich + +- Findet alle `YouTubeContent`-Einträge ohne Thumbnail +- Downloadet sequentiell mit 500ms Delay (Rate-Limit-Schutz) +- Response: `{ processed, downloaded, skipped, errors }` +- Optional: `?dryRun=true` + +### 4. Fehlerbehandlung + +| Aspekt | Verhalten | +|--------|-----------| +| Rate-Limiting | 500ms Delay zwischen Downloads (Bulk) | +| Timeout | 10s pro Download | +| Retry | Kein Retry (YouTube CDN zuverlässig) | +| 404/Fehler | `null` zurückgeben, Sync fortsetzen | +| Duplikate | Existierendes Media zurückgeben | +| Manuelle Uploads | Nie überschreiben | +| Logging | Console.log (nicht AuditLogs) | + +## Betroffene Dateien + +### Neu +- `src/lib/utils/media-download.ts` — Kern-Utility +- `src/app/(payload)/api/youtube/thumbnails/bulk/route.ts` — Bulk-Endpoint + +### Modifiziert +- YouTube-Sync-Services — Thumbnail-Download nach Content-Erstellung +- YouTubeChannels-Sync — Kanalbild-Download nach Channel-Update + +## Nicht-Ziele + +- Keine Kommentar-Avatare herunterladen +- Kein Queue-basierter Download +- Keine automatische Aktualisierung bestehender Thumbnails