Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DfhCF3fAgZyDN9BUsEyNFd
172 lines
8.8 KiB
Markdown
172 lines
8.8 KiB
Markdown
# yt-dlf — Handoff
|
||
|
||
> Übergabedokument für die Fortsetzung in einer Claude-Code-Session.
|
||
> Stand: 2026-08-30 — App läuft produktiv auf Gisela unter
|
||
> http://172.30.1.11:3300 (nur internes Netz), Downloads nach
|
||
> `/home/stwaidele/YouTube/<Titel>/`. Zuletzt: Fortschrittsanzeige
|
||
> gefixt (eine sich aktualisierende Zeile statt Zeilen-Kaskade),
|
||
> serverseitig live verifiziert.
|
||
> Dauerhafte Fakten stehen in `README.md`/`INSTALL.md`; hier steht nur, was
|
||
> **nicht** aus Code und Git-Historie ersichtlich ist.
|
||
|
||
**🔜 NÄCHSTE SESSION:** Kein konkreter inhaltlicher Auftrag hinterlegt.
|
||
Beim nächsten echten Download beiläufig prüfen, ob die Fortschrittszeile
|
||
im Browser wirklich in-place aktualisiert (Client-Teil des Fixes vom
|
||
30.08. ist implementiert, aber noch nicht im Browser beobachtet).
|
||
Arbeitskopie auf Gisela: `/home/stwaidele/Claude/yt-dlf` (am 29.08. von
|
||
`yt-dlp` umbenannt; systemd-Unit-Pfade angepasst, venv läuft weiter —
|
||
pip darin nur noch als `.venv/bin/python -m pip` aufrufen, der
|
||
`.venv/bin/pip`-Shebang zeigt auf den alten Pfad).
|
||
|
||
## Offene Punkte
|
||
|
||
- [ ] `users.txt` auf Gisela anlegen, falls Login gewünscht
|
||
(`python3 scripts/add_user.py <name> <pw>`, danach
|
||
`systemctl --user restart yt-dlf`); ohne Login zeigen `ads-*.html`
|
||
Platzhalter-Werbung.
|
||
- [x] Leeres Repo `stwaidele/yt-dlp` auf Gitea existierte neben `yt-dlf` —
|
||
von Stefan gelöscht (erledigt 29.08.); `yt-dlf` ist das einzige Repo,
|
||
und auch das lokale Verzeichnis heißt inzwischen `yt-dlf`.
|
||
- [ ] Mac-Instanz: ob die App auf dem Mac weiterlaufen soll, ist offen;
|
||
die dortigen gitignorten Dateien (`users.txt`, `ads-*.html`-Anpassungen)
|
||
wurden nicht nach Gisela übernommen.
|
||
- [x] Deploy-Status klären (erledigt 29.08. — läuft jetzt auf Gisela,
|
||
siehe Session-Block)
|
||
|
||
## Stolperfallen
|
||
|
||
- **Port 3000 ist auf Gisela belegt** (Open-WebUI bindet
|
||
`172.30.1.11:3000`) — yt-dlf läuft deshalb auf **3300**. Bei
|
||
Port-Änderungen zuerst `ss -tlnp` prüfen.
|
||
- **Git-Konten-Mix (nur Mac)** — auf dem Mac zeigt `origin` direkt auf
|
||
`git@gitea.101010.cloud:stwaidele/yt-dlf.git` mit dem alten generischen
|
||
`claude`-Key; dort Claude-Commits per Author-Override und Push über den
|
||
Modell-Alias. Auf **Gisela** ist das gelöst: Clone über
|
||
`git@gitea-fable-5:stwaidele/yt-dlf.git`, Repo-Config steht auf
|
||
`Claude Fable 5` / `fable-5@waidele.info`.
|
||
- **Rollende Auto-Captions** — YouTube-Auto-Untertitel wiederholen in jedem
|
||
Cue die letzte Zeile des Vorgänger-Cues; kurze Fortsetzungen (einzelne
|
||
Wörter) tragen dabei **keine** Inline-Timing-Tags. Ein Filter rein über
|
||
Timing-Tags reicht deshalb nicht — der Parser verwirft stattdessen
|
||
führende Wiederholungszeilen (`src/lib/subtitle.js`,
|
||
`scripts/subtitle_to_markdown.py`, beide identisch halten!).
|
||
|
||
## Session 2026-08-30 — Fortschrittsanzeige gefixt (Claude Fable 5)
|
||
|
||
Stefans Befund (mit Screenshots vom iPhone): jede yt-dlp-Progress-Zeile
|
||
erzeugte ein neues Log-Element — hunderte fast identische Kästen.
|
||
Ursache: yt-dlp überschreibt seine Fortschrittszeile per `\r` in-place,
|
||
die App schickte aber jedes Update als eigenes `log`-Event. Fix:
|
||
Server taggt Fortschrittszeilen als Event-Typ `progress`
|
||
(`/^\[download\]\s+[~\d]/` — bewusst breiter als nur `%`, weil
|
||
Downloads unbekannter Größe prozentlose Zeilen wie
|
||
`[download] 440.00B at Unknown B/s` ausgeben; ffmpeg-Zeilen
|
||
`frame=`/`size=` ebenso), Client ersetzt bei `progress` die vorige
|
||
Zeile, wenn diese auch `progress` war. Serverseitig live verifiziert
|
||
(SSE-Stream per curl, „Me at the zoo"); Client-Ersetzung implementiert,
|
||
im Browser noch nicht beobachtet. Nebeneffekt des Tests: die am 29.08.
|
||
versehentlich mit Whisper überschriebene
|
||
`~/YouTube/Me at the zoo/Me at the zoo.en.vtt` ist wieder die echte
|
||
YouTube-Caption. Stefans Debug-Screenshots (`IMG_70*.PNG` im
|
||
Projekt-Root) bleiben bewusst untracked.
|
||
|
||
## Session 2026-08-29 — Verzeichnis-Umbenennung & Memory-Umzug (Claude Fable 5)
|
||
|
||
Lokales Verzeichnis auf Gisela von `yt-dlp` nach `yt-dlf` umbenannt
|
||
(Dienst gestoppt → `mv` → Unit-Pfade angepasst → neu gestartet, HTTP 200
|
||
verifiziert). Claude-Auto-Memory auf den neuen Projekt-Schlüssel
|
||
`~/.claude/projects/-home-stwaidele-Claude-yt-dlf/memory/` kopiert.
|
||
Beim anschließenden Aufräumen wurde versehentlich der **komplette** alte
|
||
Projektordner `…/-home-stwaidele-Claude-yt-dlp/` gelöscht statt nur
|
||
`memory/` — damit sind die Claude-Code-Sitzungsprotokolle der Sessions
|
||
vom 29.08. weg (kein `--resume` mehr möglich); inhaltlich kein Verlust,
|
||
alles steht in diesem Handoff und in den Commits. Von Stefan abgenickt
|
||
(29.08.).
|
||
|
||
## Session 2026-08-29 — Whisper-Fallback für Videos ohne Untertitel (Claude Fable 5)
|
||
|
||
Auftrag: Plattformen ohne Untertitel (Instagram & Co.) sollen trotzdem
|
||
Transkripte liefern. Umsetzung: `scripts/transcribe.py` (faster-whisper,
|
||
`large-v3-turbo`, CUDA mit CPU-Fallback) + Hook in
|
||
`src/routes/api/download/+server.js` — springt nur an, wenn der Download
|
||
keine `.vtt`/`.srt` hinterlässt; die VTT läuft danach durch die normale
|
||
MD-Konvertierung. venv liegt in `.venv/` (gitignored, Python 3.13,
|
||
**nicht** das Linuxbrew-Python 3.14 — dafür gab es keine
|
||
ctranslate2-Wheels). cuDNN/cuBLAS kommen aus pip und werden im Script per
|
||
`ctypes.CDLL(RTLD_GLOBAL)` vorgeladen, damit kein `LD_LIBRARY_PATH` in
|
||
der systemd-Unit nötig ist. Modell-Cache: `~/.cache/huggingface` (~1,6 GB,
|
||
bereits geladen). Live verifiziert: archive.org „Duck and Cover"
|
||
(E2E über die API, Fallback sprang an, Transkript einwandfrei) und
|
||
Direktlauf auf GPU (`cuda`, Spracherkennung en p=1.00). Testerkenntnis:
|
||
**Vimeo verlangt inzwischen Login** und taugt nicht mehr als
|
||
Test-Plattform; archive.org funktioniert. Zusätzlich an einem echten
|
||
Instagram-Video verifiziert (`~/YouTube/Video by sugarkane2003/`, ~3 min,
|
||
Deutsch automatisch erkannt, Transkript inhaltlich einwandfrei — typische
|
||
Whisper-Schwächen nur bei Namen/Anglizismen wie „Wheel" statt „Reel");
|
||
lief als Direktaufruf der beiden Fallback-Schritte, weil der Download vor
|
||
dem Feature lag und die Original-URL nicht gespeichert ist. Nebenwirkung
|
||
des GPU-Direkttests:
|
||
`~/YouTube/Me at the zoo/Me at the zoo.en.vtt` ist jetzt die
|
||
Whisper-Version statt der YouTube-Caption (im echten Betrieb kein Thema,
|
||
Fallback läuft nur ohne vorhandene Untertitel).
|
||
|
||
## Session 2026-08-29 — Deploy auf Gisela (Claude Fable 5)
|
||
|
||
Auftrag: yt-dlf auf Gisela betreiben, Weboberfläche nur im
|
||
WireGuard-/internen Netz, Downloads unter `/home/stwaidele/YouTube/`.
|
||
Umsetzung: Build im Repo-Checkout (`npm install && npm run build`),
|
||
systemd-**User**-Unit `~/.config/systemd/user/yt-dlf.service`
|
||
(enabled, Linger war bereits aktiv → Autostart ohne Login). Die Unit
|
||
setzt `HOST=172.30.1.11`, `PORT=3300`, `DOWNLOAD_DIR`, `YTDLP_PATH`
|
||
(yt-dlp kommt aus Linuxbrew, nicht auf dem systemd-PATH). Gisela hat
|
||
**kein eigenes wg-Interface** — sie hängt direkt im internen Netz
|
||
`172.30.1.0/24`, in das die WireGuard-Peers geroutet werden; „nur
|
||
WG-Netz" heißt hier also: exakt an die LAN-IP binden (localhost,
|
||
Docker-Bridges und IPv6 nachweislich nicht erreichbar). Live
|
||
verifiziert: Testdownload „Me at the zoo" über die API komplett
|
||
durchgelaufen, Dateien inkl. deduplizierter MDs unter
|
||
`~/YouTube/Me at the zoo/`. Nebenbei: `package-lock.json` durch npm
|
||
auf Gisela normalisiert (nur `libc`-Felder entfernt, kein
|
||
Versions-Update).
|
||
|
||
## Session 2026-08-29 — Untertitel-Dedup-Fix & Push nach Gitea (Claude Fable 5)
|
||
|
||
Stefans Befund: MD-Dateien aus VTT-Untertiteln enthielten jeden Satz ~3×.
|
||
Ursache waren die rollenden YouTube-Auto-Captions (Uploader-Untertitel waren
|
||
nie betroffen — sie sind die bessere Quelle und werden von yt-dlp bereits
|
||
bevorzugt geladen). Fix in beiden Parsern (JS + Python-CLI), dazu überspringt
|
||
`src/routes/api/download/+server.js` jetzt inhaltsgleiche MD-Dateien
|
||
(z.B. `en.md` ≡ `en-orig.md`). Erster Ansatz (nur getaggte Zeilen behalten)
|
||
scheiterte am Randfall ungetaggter Einzelwort-Fortsetzungen → siehe
|
||
Stolperfalle. Live verifiziert an realen Dateien unter `~/YouTube/*/`;
|
||
alle 16 Bestands-MDs dort und in `~/Downloads/*/` mit dem CLI regeneriert.
|
||
Repo erstmals seit Mai gepusht (main `6df26c1..a7d7d1c` über
|
||
`gitea-fable-5`-Alias); Stefan verlagert die Weiterentwicklung auf Gisela.
|
||
|
||
## Session 2026-08-29 — Handoff angelegt (Claude Fable 5)
|
||
|
||
Projekt hatte noch keine `Handoff.md`; per `/handoff init` aus README,
|
||
INSTALL.md und Git-Historie erstellt. Kein Projekt-`CLAUDE.md` vorhanden.
|
||
Beide bisherigen Commits (16.05.) stammen von Stefan; seither keine
|
||
Änderungen im Working Tree.
|
||
|
||
## Typische Handgriffe
|
||
|
||
Dev-Server, Deployment und User-Verwaltung sind vollständig in `README.md`
|
||
und `INSTALL.md` dokumentiert — dort nachschlagen, hier nicht duplizieren.
|
||
|
||
Betrieb auf Gisela (systemd-User-Dienst, läuft als `stwaidele`):
|
||
|
||
```bash
|
||
systemctl --user status|restart|stop yt-dlf
|
||
journalctl --user -u yt-dlf -f
|
||
# Nach Code-Änderungen:
|
||
npm run build && systemctl --user restart yt-dlf
|
||
```
|
||
|
||
## Verwandte Handoffs
|
||
|
||
_keine_
|
||
|
||
<!-- Ältere Sessions: git log -p Handoff.md -->
|