Add prune_podcast_data.py: clean up podcast data Open Notebook leaves behind
Deleting an episode does not delete its data. DELETE /api/podcasts/episodes/{id}
resolves episode.audio_file and unlinks that one MP3 — the enclosing
data/podcasts/episodes/<uuid>/ directory, holding clips/ (one MP3 per dialogue
segment), outline.json and transcript.json, is never touched. Failed and
/retry-replaced runs leak a directory as well. Nothing reaps any of it: this
deployment had 15 directories on disk against 4 episodes in the database.
That is an upstream gap (roughly a shutil.rmtree of audio_path.parent.parent in
that handler), not something configurable here. Deliberately not patched by
bind-mounting a modified router — that would fork app logic into a deployment
repo and rot silently against pull_policy: always. Local cleanup instead.
scripts/prune_podcast_data.py reconciles the episode list from the API against
the directories on disk and removes:
- orphaned directories (no corresponding episode), and
- clips/ of completed episodes, since the clips are intermediate output once
the final MP3 exists.
Dry-run by default; --yes applies, --keep-clips restricts it to orphans.
Two guards, both tested: it aborts when any job is running/pending (a running
job has no audio_file yet, so its working directory is indistinguishable from an
orphan) and it skips directories touched within the last 60 minutes (--min-age).
It also refuses to act if the API is unreachable, rather than guessing.
Deletion runs inside the container (docker compose exec … rm -rf): the container
writes as root, so the host user cannot remove those directories — a plain
host-side rmtree fails with EPERM after the first directory.
Verified on this deployment: freed 13 MB (10 orphaned dirs + clips of 3 episodes,
49 MB -> 36 MB); all four surviving episodes still stream byte-identical MP3s
from /audio afterwards.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
03877588e1
commit
ba98ac4eb4
5 changed files with 268 additions and 1 deletions
|
|
@ -118,6 +118,36 @@ mehreren Sprechern) erzeugen — Text via Sprachmodell, Audio via TTS (hier: lok
|
|||
Alle Episode-/Sprecherprofile sind bereits auf lokale Modelle (`qwen3.5:27b` für Text,
|
||||
Chatterbox für Sprache) umgestellt — keine zusätzlichen Kosten.
|
||||
|
||||
### Episoden löschen räumt nur halb auf
|
||||
|
||||
**Der Mülleimer-Button löscht nicht alles.** Er entfernt die finale MP3 und den
|
||||
Datenbankeintrag — der Ordner der Episode bleibt aber liegen, samt Einzelclips:
|
||||
|
||||
```
|
||||
notebook_data/podcasts/episodes/<uuid>/
|
||||
├── clips/ ← 1 MP3 pro Dialogsegment BLEIBT LIEGEN
|
||||
├── outline.json BLEIBT LIEGEN
|
||||
├── transcript.json BLEIBT LIEGEN
|
||||
└── audio/<uuid>.mp3 ← nur diese wird gelöscht
|
||||
```
|
||||
|
||||
Das ist eine Lücke im Open-Notebook-Code selbst (der Löschpfad ruft `unlink()` nur auf die eine
|
||||
MP3-Datei auf), nicht an dieser Installation einstellbar. Ebenso hinterlässt jeder
|
||||
fehlgeschlagene oder per Retry wiederholte Lauf einen Ordner, der nie aufgeräumt wird.
|
||||
|
||||
Zum Aufräumen dient:
|
||||
|
||||
```bash
|
||||
./scripts/prune_podcast_data.py # zeigt nur an, was wegfiele (Trockenlauf)
|
||||
./scripts/prune_podcast_data.py --yes # löscht wirklich
|
||||
```
|
||||
|
||||
Es entfernt (a) Ordner ohne zugehörige Episode und (b) die `clips/` fertiger Episoden — die
|
||||
Einzelclips sind nach dem Zusammenbau reines Zwischenprodukt, die Episode bleibt vollständig
|
||||
abspielbar. Schutzmechanismen: bei einem laufenden Podcast-Job bricht es ab, und Ordner, die
|
||||
jünger als 60 Minuten sind, bleiben unangetastet (`--min-age`). Mit `--keep-clips` werden nur
|
||||
die verwaisten Ordner gelöscht.
|
||||
|
||||
---
|
||||
|
||||
## 5. Stimmklonung
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue