Initial commit: auto-video-cut project
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
607
ANFORDERUNGEN.md
Executable file
607
ANFORDERUNGEN.md
Executable file
@@ -0,0 +1,607 @@
|
||||
# Anforderungen: auto-video-cut
|
||||
|
||||
Stand: 2026-03-20 (aktualisiert: KI-Features, Übergänge, Audio-Ducking)
|
||||
|
||||
---
|
||||
|
||||
## 1. Ziel
|
||||
|
||||
`auto-video-cut` ist ein vollständig automatisiertes Kommandozeilen-Tool für Videoschnitt, -zusammenführung und Musikunterlegung. Keine GUI, keine manuelle Timeline. Zielgruppe: technisch versierte Einzelnutzer mit wiederholenden Video-Workflows.
|
||||
|
||||
---
|
||||
|
||||
## 2. Systemvoraussetzungen
|
||||
|
||||
| Anforderung | Detail |
|
||||
|-------------|--------|
|
||||
| Python | >= 3.10 |
|
||||
| ffmpeg | Im PATH verfügbar (für alle Video-/Audio-Operationen) |
|
||||
| ffprobe | Im PATH verfügbar (für Metadaten-Abfragen) |
|
||||
| Betriebssystem | Plattformunabhängig (getestet unter Linux/WSL, macOS, Windows) |
|
||||
|
||||
---
|
||||
|
||||
## 3. Python-Abhängigkeiten
|
||||
|
||||
| Paket | Version | Verwendung |
|
||||
|-------|---------|------------|
|
||||
| `typer` | >= 0.12 | CLI-Framework |
|
||||
| `pyyaml` | >= 6.0 | YAML-Konfiguration und Sequenz-Dateien |
|
||||
| `scenedetect[opencv]` | >= 0.6 | Szenen-Erkennung via ContentDetector |
|
||||
| `ffmpeg-python` | >= 0.2 | ffmpeg-Binding (Hilfsfunktionen) |
|
||||
| `discord.py` | >= 2.3 | Discord-Bot für Fernsteuerung |
|
||||
| `rich` | >= 13.0 | Fortschrittsanzeige und Terminal-UI |
|
||||
|
||||
Optionale KI-Abhängigkeiten (`pip install -e ".[ai]"`):
|
||||
|
||||
| Paket | Version | Verwendung |
|
||||
|-------|---------|------------|
|
||||
| `faster-whisper` | >= 1.0 | Lokale Sprach-Transkription (Whisper) |
|
||||
| `anthropic` | >= 0.40 | LLM-Anbindung für Auto-Kapitel, Highlights, Beschreibungen |
|
||||
|
||||
Installation: `pip install -e .`
|
||||
CLI-Einstiegspunkt: `video-cut`
|
||||
|
||||
---
|
||||
|
||||
## 4. Funktionale Anforderungen
|
||||
|
||||
### 4.1 Stille-Erkennung und -Entfernung
|
||||
|
||||
- **F-01** Das Tool erkennt Stille-Abschnitte in einem Video via `ffmpeg silencedetect`.
|
||||
- **F-02** Erkannte Stille-Abschnitte werden aus dem Video herausgeschnitten; die verbleibenden Ton-Abschnitte werden nahtlos zusammengefügt.
|
||||
- **F-03** Konfigurierbare Parameter:
|
||||
- `threshold_db` — Schwelle in dB, ab der Stille erkannt wird (Standard: `-40`)
|
||||
- `min_duration` — Mindestdauer in Sekunden, ab der Stille als solche gilt (Standard: `0.5`)
|
||||
- **F-04** Stille-Erkennung ist pro Clip in der Sequenz-Datei einzeln aktivierbar (`remove_silence: true` / `trim_silence: true`).
|
||||
|
||||
### 4.2 Szenen-Erkennung
|
||||
|
||||
- **F-05** Das Tool erkennt Szenen-Grenzen via PySceneDetect (`ContentDetector`).
|
||||
- **F-06** Das Video wird an erkannten Szenen-Grenzen in einzelne Clips aufgeteilt und in einen Ausgabe-Ordner gespeichert.
|
||||
- **F-07** Konfigurierbare Parameter:
|
||||
- `threshold` — Empfindlichkeit der Szenen-Erkennung (Standard: `27.0`)
|
||||
|
||||
### 4.3 Clips zusammenführen
|
||||
|
||||
- **F-08** Mehrere Video-Clips werden via `ffmpeg concat` zu einem einzigen Video zusammengeführt.
|
||||
- **F-09** Vor dem Zusammenführen werden Clips optional auf ein einheitliches Format re-encodet (H.264, AAC, yuv420p, 25fps), um Kompatibilitätsprobleme zu vermeiden.
|
||||
- **F-10** Optional: Intro-Clip vor dem ersten und Outro-Clip nach dem letzten Inhalt einfügen.
|
||||
|
||||
### 4.4 Hintergrundmusik
|
||||
|
||||
- **F-11** Musik-Dateien werden aus einem konfigurierbaren Ordner (`resources/music/`) gelesen.
|
||||
- **F-12** Unterstützte Musikformate: `.mp3`, `.wav`, `.flac`, `.aac`, `.ogg`
|
||||
- **F-13** Auswahlmodus für Musik:
|
||||
- `random` — zufällig aus dem Ordner
|
||||
- `alphabetical` — erste Datei alphabetisch
|
||||
- `loop` — erste Datei alphabetisch (wird geloopt)
|
||||
- **F-14** Musik wird auf die Länge des Videos getrimmt (`-shortest`) oder geloopt (`-stream_loop -1`).
|
||||
- **F-15** Original-Audio und Hintergrundmusik werden gemischt via `ffmpeg amix` mit konfigurierbaren Lautstärken:
|
||||
- `volume_original` — Lautstärke des Original-Tons (Standard: `1.0`)
|
||||
- `volume_music` — Lautstärke der Hintergrundmusik (Standard: `0.3`)
|
||||
- **F-16** Hat das Video keinen Audio-Track, wird die Musik direkt als einziger Audio-Track eingefügt.
|
||||
- **F-17** In der Sequenz-Datei kann eine konkrete Musikdatei oder `"random"` angegeben werden; Lautstärken sind pro Sequenz überschreibbar.
|
||||
|
||||
### 4.5 Text-Einblendungen
|
||||
|
||||
- **F-18** Text wird als Standbild-Clip auf einem konfigurierbaren Hintergrund (Farbe oder schwarz) gerendert via `ffmpeg drawtext` + `lavfi color`.
|
||||
- **F-19** Text-Overlays können über laufende Video-Clips gelegt werden, mit optionaler Zeitbegrenzung (`enable='between(t,0,N)'`).
|
||||
- **F-20** Konfigurierbare Text-Optionen:
|
||||
- `content` — Text-Inhalt
|
||||
- `duration` — Anzeigedauer in Sekunden (für Standbild-Clips)
|
||||
- `font_size` — Schriftgröße (Standard: `72` für Clips, `48` für Overlays)
|
||||
- `font_color` — Schriftfarbe (Standard: `"white"`)
|
||||
- `background_color` — Hintergrundfarbe oder `"transparent"` (Standard: `"black"`)
|
||||
- `position` — `center` | `top` | `bottom` (Standard: `"center"`)
|
||||
- **F-21** Sonderzeichen im Text (`'`, `:`, `\`) werden für ffmpeg korrekt escapt.
|
||||
|
||||
### 4.6 Bilder als Clips
|
||||
|
||||
- **F-22** Einzelne Bilder (`.png`, `.jpg`, `.jpeg`) werden in Video-Clips konvertiert (`ffmpeg -loop 1`).
|
||||
- **F-23** Konfigurierbare Anzeigedauer in Sekunden.
|
||||
- **F-24** Bilder werden auf die Zielauflösung skaliert und bei abweichendem Seitenverhältnis mit schwarzen Balken aufgefüllt (letterbox).
|
||||
- **F-25** Standard-Auflösung: 1920×1080, 25fps.
|
||||
|
||||
### 4.7 Sequenz-Verarbeitung
|
||||
|
||||
- **F-26** Eine `sequence.yaml`-Datei definiert die Timeline des finalen Videos: Reihenfolge, Quellen und Verarbeitungsoptionen aller Elemente.
|
||||
- **F-27** Unterstützte Sequenz-Typen:
|
||||
|
||||
| Typ | Beschreibung |
|
||||
|-----|-------------|
|
||||
| `video` | Einzelne Videodatei |
|
||||
| `image` | Standbild für konfigurierbare Dauer |
|
||||
| `text` | Text auf Hintergrundfarbe als Clip |
|
||||
| `folder` | Alle Medien in einem Ordner, sortierbar |
|
||||
|
||||
- **F-28** Ordner-Einträge (`type: folder`) unterstützen Sortierung nach:
|
||||
- `alphabetical` — alphabetisch nach Dateiname
|
||||
- `date` — nach Änderungsdatum
|
||||
- **F-29** Datei-Pfade in der Sequenz werden aufgelöst: absolut → relativ → aus `resources/`-Unterordner.
|
||||
- **F-30** Musik-Konfiguration kann direkt in der `sequence.yaml` angegeben werden und überschreibt die globale `config.yaml`.
|
||||
|
||||
### 4.8 Batch-Verarbeitung
|
||||
|
||||
- **F-31** Alle Video-Dateien in einem Ordner werden sequenziell verarbeitet.
|
||||
- **F-32** Unterstützte Video-Formate: `.mp4`, `.mov`, `.avi`, `.mkv`
|
||||
- **F-33** Jede Verarbeitungs-Option (Stille entfernen, Szenen, Musik) ist einzeln für den Batch aktivierbar.
|
||||
- **F-34** Ausgabe-Dateien werden in den konfigurierten Output-Ordner gespeichert.
|
||||
|
||||
---
|
||||
|
||||
## 5. Ressourcen-Struktur
|
||||
|
||||
```
|
||||
resources/
|
||||
├── music/ ← .mp3, .wav, .flac, .aac, .ogg
|
||||
├── videos/ ← Intros, Outros, Übergänge (.mp4, .mov, .avi, .mkv)
|
||||
└── images/ ← Titelkarten, Folien (.png, .jpg, .jpeg)
|
||||
```
|
||||
|
||||
- **F-35** Der Ressourcen-Ordner ist über `resources.folder` in der Konfiguration frei wählbar.
|
||||
- **F-36** Das Tool gibt eine Warnung aus, wenn der Ressourcen-Ordner oder der Musik-Unterordner nicht existiert oder leer ist — kein harter Abbruch.
|
||||
|
||||
---
|
||||
|
||||
## 6. Konfiguration (`config.yaml`)
|
||||
|
||||
Alle Parameter haben Standardwerte; eine Konfigurationsdatei ist optional.
|
||||
|
||||
| Schlüssel | Typ | Standard | Beschreibung |
|
||||
|-----------|-----|---------|--------------|
|
||||
| `resources.folder` | string | `"./resources"` | Basis-Ordner für Ressourcen |
|
||||
| `music.mode` | string | `"random"` | Musik-Auswahlmodus |
|
||||
| `music.volume_original` | float | `1.0` | Lautstärke Original-Ton |
|
||||
| `music.volume_music` | float | `0.3` | Lautstärke Hintergrundmusik |
|
||||
| `videos.intro` | string | `null` | Dateiname des Intro-Clips |
|
||||
| `videos.outro` | string | `null` | Dateiname des Outro-Clips |
|
||||
| `videos.transitions` | bool | `false` | Übergangs-Clips einsetzen |
|
||||
| `images.title_card` | string | `null` | Dateiname der Titelkarte |
|
||||
| `images.duration` | int | `3` | Standard-Anzeigedauer für Bilder (s) |
|
||||
| `silence.threshold_db` | float | `-40` | Stille-Schwelle in dB |
|
||||
| `silence.min_duration` | float | `0.5` | Minimale Stille-Dauer in Sekunden |
|
||||
| `scenes.threshold` | float | `27.0` | Szenen-Erkennungs-Schwelle |
|
||||
| `output.format` | string | `"mp4"` | Ausgabeformat |
|
||||
| `output.folder` | string | `"./output"` | Ausgabe-Ordner |
|
||||
|
||||
- **F-37** Fehlende Schlüssel in der Konfigurationsdatei werden mit Standardwerten aufgefüllt (Deep-Merge).
|
||||
- **F-38** Beim Laden der Konfiguration werden Warnungen für ungültige Lautstärke-Werte ausgegeben.
|
||||
|
||||
---
|
||||
|
||||
## 7. CLI-Befehle
|
||||
|
||||
### `video-cut cut`
|
||||
|
||||
```
|
||||
video-cut cut --input VIDEO [--output DATEI] [--config CONFIG]
|
||||
[--remove-silence] [--scene-detect]
|
||||
```
|
||||
|
||||
| Option | Beschreibung |
|
||||
|--------|-------------|
|
||||
| `--input`, `-i` | Eingabe-Videodatei (Pflicht) |
|
||||
| `--output`, `-o` | Ausgabedatei (Standard: `<stem>_no_silence.mp4`) |
|
||||
| `--config`, `-c` | Konfigurationsdatei |
|
||||
| `--remove-silence` | Stille entfernen |
|
||||
| `--scene-detect` | Szenen erkennen und aufteilen |
|
||||
|
||||
### `video-cut merge`
|
||||
|
||||
```
|
||||
video-cut merge --inputs CLIP1 CLIP2 [...] --output DATEI
|
||||
[--intro CLIP] [--outro CLIP] [--no-normalize]
|
||||
```
|
||||
|
||||
| Option | Beschreibung |
|
||||
|--------|-------------|
|
||||
| `--inputs` | Eingabe-Clips (Pflicht, mehrfach) |
|
||||
| `--output`, `-o` | Ausgabedatei (Pflicht) |
|
||||
| `--intro` | Optionaler Intro-Clip |
|
||||
| `--outro` | Optionaler Outro-Clip |
|
||||
| `--no-normalize` | Re-Encoding überspringen |
|
||||
|
||||
### `video-cut music`
|
||||
|
||||
```
|
||||
video-cut music --input VIDEO [--output DATEI] [--config CONFIG]
|
||||
[--music-file DATEI] [--vol-orig 1.0] [--vol-music 0.3]
|
||||
```
|
||||
|
||||
| Option | Beschreibung |
|
||||
|--------|-------------|
|
||||
| `--input`, `-i` | Eingabe-Videodatei (Pflicht) |
|
||||
| `--output`, `-o` | Ausgabedatei (Standard: `<stem>_music.mp4`) |
|
||||
| `--config`, `-c` | Konfigurationsdatei |
|
||||
| `--music-file` | Direkte Musikdatei (überschreibt config) |
|
||||
| `--vol-orig` | Lautstärke Original (Standard: `1.0`) |
|
||||
| `--vol-music` | Lautstärke Musik (Standard: `0.3`) |
|
||||
|
||||
### `video-cut batch`
|
||||
|
||||
```
|
||||
video-cut batch --input ORDNER [--config CONFIG]
|
||||
[--remove-silence] [--scene-detect] [--music]
|
||||
```
|
||||
|
||||
| Option | Beschreibung |
|
||||
|--------|-------------|
|
||||
| `--input`, `-i` | Ordner mit Videos (Pflicht) |
|
||||
| `--config`, `-c` | Konfigurationsdatei |
|
||||
| `--remove-silence` | Stille aus allen Videos entfernen |
|
||||
| `--scene-detect` | Szenen in allen Videos erkennen |
|
||||
| `--music` | Musik zu allen Videos hinzufügen |
|
||||
|
||||
### `video-cut sequence`
|
||||
|
||||
```
|
||||
video-cut sequence --seq SEQUENZ.yaml [--config CONFIG]
|
||||
[--output DATEI] [--music/--no-music]
|
||||
```
|
||||
|
||||
| Option | Beschreibung |
|
||||
|--------|-------------|
|
||||
| `--seq`, `-s` | Sequenz-Datei (Pflicht) |
|
||||
| `--config`, `-c` | Konfigurationsdatei |
|
||||
| `--output`, `-o` | Ausgabedatei (Standard: `output/output.mp4`) |
|
||||
| `--music` / `--no-music` | Musik hinzufügen oder nicht (Standard: an) |
|
||||
|
||||
---
|
||||
|
||||
## 8. Discord-Integration (Fernsteuerung)
|
||||
|
||||
### 8.1 Überblick
|
||||
|
||||
Die Applikation soll über einen Discord-Bot ferngesteuert werden können. Der Bot läuft als Hintergrund-Prozess auf demselben Server wie `auto-video-cut` und empfängt Befehle über Discord-Slash-Commands. Ergebnisse und Fortschrittsmeldungen werden in den aufrufenden Discord-Kanal zurückgemeldet.
|
||||
|
||||
### 8.2 Architektur
|
||||
|
||||
```
|
||||
Discord-Nutzer
|
||||
│ Slash-Command (/cut, /music, ...)
|
||||
▼
|
||||
Discord API
|
||||
│ discord.py Bot (auto_video_cut/bot.py)
|
||||
▼
|
||||
CLI-Logik (cutter, merger, audio, sequencer, ...)
|
||||
│ Ergebnis / Fortschritt
|
||||
▼
|
||||
Discord API → Antwort im Kanal
|
||||
```
|
||||
|
||||
Der Bot ruft intern dieselben Python-Funktionen auf wie die CLI — kein separater Prozess, keine HTTP-API.
|
||||
|
||||
### 8.3 Konfiguration
|
||||
|
||||
Neue Schlüssel in `config.yaml`:
|
||||
|
||||
```yaml
|
||||
discord:
|
||||
token: "BOT_TOKEN" # Discord-Bot-Token (Pflicht)
|
||||
allowed_channel_ids: # Whitelist der erlaubten Kanal-IDs
|
||||
- 123456789012345678
|
||||
allowed_user_ids: # Whitelist der erlaubten Nutzer-IDs (optional)
|
||||
- 987654321098765432
|
||||
upload_results: true # Fertige Videos direkt in Discord hochladen (≤ 25 MB)
|
||||
notify_on_complete: true # Abschluss-Meldung immer senden
|
||||
```
|
||||
|
||||
- **F-39** Der Bot-Token wird aus der Konfigurationsdatei oder alternativ aus der Umgebungsvariable `VIDEO_CUT_DISCORD_TOKEN` gelesen.
|
||||
- **F-40** Befehle werden nur in explizit erlaubten Kanälen akzeptiert; alle anderen Anfragen werden still ignoriert.
|
||||
- **F-41** Optional: Whitelist auf bestimmte Discord-Nutzer-IDs einschränken.
|
||||
|
||||
### 8.4 Bot starten
|
||||
|
||||
```bash
|
||||
video-cut bot --config config.yaml
|
||||
```
|
||||
|
||||
Der Bot läuft als Langzeit-Prozess (Blocking Event Loop). Empfohlen: `systemd`-Service oder `screen`/`tmux`-Session.
|
||||
|
||||
### 8.5 Slash-Commands
|
||||
|
||||
Alle CLI-Befehle werden als Discord-Slash-Commands gespiegelt. Dateipfade beziehen sich immer auf den Server, auf dem der Bot läuft.
|
||||
|
||||
#### `/cut`
|
||||
|
||||
```
|
||||
/cut input:<Pfad> [remove_silence:true|false] [scene_detect:true|false] [config:<Pfad>]
|
||||
```
|
||||
|
||||
- Schneidet ein Video (Stille entfernen und/oder Szenen aufteilen)
|
||||
- Antwort: Fortschritts-Embed → Abschluss-Embed mit Ausgabepfad
|
||||
|
||||
#### `/merge`
|
||||
|
||||
```
|
||||
/merge inputs:<Pfad1,Pfad2,...> output:<Pfad> [intro:<Pfad>] [outro:<Pfad>]
|
||||
```
|
||||
|
||||
- Fügt mehrere Clips zusammen
|
||||
|
||||
#### `/music`
|
||||
|
||||
```
|
||||
/music input:<Pfad> [config:<Pfad>] [music_file:<Pfad>] [vol_orig:1.0] [vol_music:0.3]
|
||||
```
|
||||
|
||||
- Legt Hintergrundmusik unter ein Video
|
||||
|
||||
#### `/batch`
|
||||
|
||||
```
|
||||
/batch input:<Ordner> [config:<Pfad>] [remove_silence:true] [music:true]
|
||||
```
|
||||
|
||||
- Verarbeitet alle Videos in einem Ordner
|
||||
|
||||
#### `/sequence`
|
||||
|
||||
```
|
||||
/sequence seq:<Pfad> [config:<Pfad>] [output:<Pfad>] [music:true|false]
|
||||
```
|
||||
|
||||
- Rendert ein Video aus einer `sequence.yaml`
|
||||
|
||||
#### `/status`
|
||||
|
||||
```
|
||||
/status
|
||||
```
|
||||
|
||||
- Zeigt laufende Jobs, Warteschlange und System-Status (ffmpeg vorhanden, Ressourcen-Ordner erreichbar)
|
||||
|
||||
#### `/cancel`
|
||||
|
||||
```
|
||||
/cancel [job_id:<ID>]
|
||||
```
|
||||
|
||||
- Bricht den aktuellen oder einen bestimmten Job ab
|
||||
|
||||
### 8.6 Antwort-Format
|
||||
|
||||
- **F-42** Jeder Befehl wird mit einem Discord-Embed bestätigt: Job-ID, Eingabe-Parameter, Startzeitpunkt.
|
||||
- **F-43** Während der Verarbeitung werden Fortschritts-Updates als bearbeitete Embed-Nachricht gesendet (alle ~10 Sekunden oder bei Meilenstein: Stille erkannt, Clips zusammengeführt, Musik gemischt).
|
||||
- **F-44** Bei Abschluss: Embed mit Ausgabepfad, Dauer der Verarbeitung, Dateigröße.
|
||||
- **F-45** Ist die fertige Datei ≤ 25 MB und `upload_results: true`, wird sie direkt in Discord hochgeladen.
|
||||
- **F-46** Bei Fehlern: Embed mit Fehlermeldung und dem betroffenen Verarbeitungsschritt (roter Embed-Rand).
|
||||
|
||||
### 8.7 Job-Verwaltung
|
||||
|
||||
- **F-47** Jobs werden sequenziell in einer FIFO-Warteschlange abgearbeitet — kein paralleles Rendering, da ffmpeg die CPU auslastet.
|
||||
- **F-48** Jeder Job erhält eine eindeutige Job-ID (kurzer UUID-Präfix), die in allen Nachrichten angezeigt wird.
|
||||
- **F-49** Läuft bereits ein Job, wird der neue Job mit geschätzter Warteposition bestätigt (`"Job #3 in Warteschlange"`).
|
||||
- **F-50** `/cancel` bricht laufende ffmpeg-Subprozesse sauber ab (`process.terminate()`).
|
||||
|
||||
### 8.8 Sicherheit
|
||||
|
||||
- **F-51** Dateipfade aus Discord-Nachrichten werden auf erlaubte Basis-Verzeichnisse beschränkt (konfigurierbar: `allowed_paths`). Path-Traversal-Angriffe (`../`) werden abgewiesen.
|
||||
- **F-52** Shell-Injection ist ausgeschlossen, da alle ffmpeg-Aufrufe als Argument-Listen via `subprocess` erfolgen (kein `shell=True`).
|
||||
- **F-53** Der Bot-Token wird niemals in Logs oder Discord-Nachrichten ausgegeben.
|
||||
|
||||
### 8.9 Neue Projektdatei
|
||||
|
||||
```
|
||||
auto_video_cut/
|
||||
└── bot.py ← Discord-Bot (discord.py, Slash-Commands, Job-Queue)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Video-Übergänge und Effekte
|
||||
|
||||
### 9.1 Crossfade
|
||||
|
||||
- **F-54** Zwischen zwei Clips kann ein Crossfade (weicher Übergang) eingefügt werden via ffmpeg `xfade` Filter.
|
||||
- **F-55** Konfigurierbare Parameter pro Sequenz-Eintrag:
|
||||
- `transition` — Übergangstyp: `crossfade` | `dissolve` | `wipeleft` (Standard: keiner)
|
||||
- `transition_duration` — Dauer in Sekunden (Standard: `0.5`)
|
||||
- **F-56** Globale Fade-Optionen:
|
||||
- `fade_in` — Einblende-Dauer am Anfang des Gesamtvideos
|
||||
- `fade_out` — Ausblende-Dauer am Ende des Gesamtvideos
|
||||
|
||||
### 9.2 Audio-Ducking
|
||||
|
||||
- **F-57** Hintergrundmusik wird automatisch leiser wenn Original-Audio (Sprache) erkannt wird, via ffmpeg `sidechaincompress`.
|
||||
- **F-58** Konfigurierbare Ducking-Parameter:
|
||||
- `ducking` — aktivieren/deaktivieren (Standard: `false`)
|
||||
- `duck_threshold` — ab welcher Lautstärke die Musik abgesenkt wird (Standard: `0.02`)
|
||||
- `duck_ratio` — Stärke der Absenkung (Standard: `4.0`)
|
||||
- `duck_attack` — wie schnell die Musik leiser wird in Sekunden (Standard: `0.3`)
|
||||
- `duck_release` — wie schnell die Musik wieder lauter wird in Sekunden (Standard: `1.0`)
|
||||
|
||||
### 9.3 Fortschrittsanzeige
|
||||
|
||||
- **F-59** Alle ffmpeg-Operationen zeigen einen Echtzeit-Fortschrittsbalken mit Prozent und geschätzter Restzeit via `rich`.
|
||||
- **F-60** ffmpeg wird mit `-progress pipe:1` gestartet; `out_time_ms` wird geparst und gegen die Gesamt-Dauer gerechnet.
|
||||
|
||||
### 9.4 Preview und Dry-Run
|
||||
|
||||
- **F-61** `--preview` erzeugt eine niedrig aufgelöste Schnellversion (360p, ultrafast-Preset) im Temp-Ordner.
|
||||
- **F-62** `--dry-run` zeigt die geplante Verarbeitung ohne zu rendern: Clip-Liste, geschätzte Gesamtdauer, geschätzte Dateigröße.
|
||||
|
||||
---
|
||||
|
||||
## 10. KI-Features
|
||||
|
||||
### 10.1 Whisper-Transkription
|
||||
|
||||
- **F-63** Audio wird aus dem Video extrahiert (WAV, 16kHz Mono) und lokal mit `faster-whisper` transkribiert.
|
||||
- **F-64** Konfigurierbare Whisper-Parameter:
|
||||
- `whisper_model` — Modellgröße: `tiny` | `base` | `small` | `medium` | `large-v3` (Standard: `base`)
|
||||
- `whisper_language` — Sprache oder `null` für Auto-Erkennung (Standard: `null`)
|
||||
- `whisper_device` — Gerät: `auto` | `cpu` | `cuda` (Standard: `auto`)
|
||||
- **F-65** Das Transkript enthält Wort-Level-Timestamps (Start, Ende, Konfidenz pro Wort).
|
||||
- **F-66** KI-Features sind optional: fehlt `faster-whisper`, wird eine verständliche Fehlermeldung ausgegeben mit Installationshinweis.
|
||||
|
||||
### 10.2 Automatische Untertitel
|
||||
|
||||
- **F-67** Aus dem Whisper-Transkript wird eine `.srt`-Datei mit korrekten Timestamps erzeugt.
|
||||
- **F-68** Untertitel werden via ffmpeg `subtitles`-Filter ins Video eingebrannt.
|
||||
- **F-69** Konfigurierbare Stil-Optionen: Schriftgröße, Farbe, Umrissfarbe, Position.
|
||||
- **F-70** In der Sequenz-Datei pro Clip aktivierbar: `auto_subtitles: true`.
|
||||
- **F-71** Alternativ: bestehende `.srt`-Datei direkt einbrennen ohne Whisper.
|
||||
|
||||
### 10.3 Intelligentes Schneiden (Smart Cut)
|
||||
|
||||
- **F-72** Füllwort-Erkennung: Deutsche und englische Füllwörter ("äh", "ähm", "also", "halt", "uh", "um") werden im Transkript erkannt und als Schnitt-Kandidaten markiert.
|
||||
- **F-73** Fehlstart-Erkennung: Sätze die abbrechen und neu begonnen werden, werden erkannt (Heuristik: kurzes Segment + Pause + ähnlicher Neubeginn).
|
||||
- **F-74** Pausen-Kürzung: Pausen zwischen Segmenten werden auf eine konfigurierbare Maximaldauer gekürzt (Standard: `1.0s` → `0.3s`).
|
||||
- **F-75** `--analyze-only` zeigt eine Aufschlüsselung aller erkannten Schnitt-Kandidaten (Typ, Zeitposition, eingesparte Sekunden) ohne das Video zu schneiden.
|
||||
- **F-76** Jede Schnitt-Kategorie (Füllwörter, Fehlstarts, Pausen) ist einzeln aktivierbar/deaktivierbar.
|
||||
- **F-77** In der Sequenz-Datei pro Clip aktivierbar: `smart_cut: true`.
|
||||
|
||||
### 10.4 Auto-Kapitel
|
||||
|
||||
- **F-78** Das Whisper-Transkript wird an ein LLM (Claude oder lokales Modell via Ollama) gesendet, das inhaltliche Kapitel mit Titeln erzeugt.
|
||||
- **F-79** Unterstützte LLM-Provider:
|
||||
- `anthropic` — Claude API (API-Key aus Config oder `ANTHROPIC_API_KEY`)
|
||||
- `ollama` — lokales Modell (URL und Modellname konfigurierbar)
|
||||
- **F-80** Export-Formate für Kapitel:
|
||||
- YouTube-kompatibel (`0:00 Intro`, `0:45 Ankunft in Berlin`, ...)
|
||||
- Als `type: text`-Einträge für die Sequenz-Datei (Kapitelmarken einblenden)
|
||||
- **F-81** Maximale Kapitelanzahl konfigurierbar (Standard: `10`).
|
||||
|
||||
### 10.5 Highlight-Reel
|
||||
|
||||
- **F-82** Transkript + Szenen-Erkennung → LLM bewertet jede Szene nach inhaltlichem Interesse (Schlüsselaussagen, Emotionen, Themenwechsel).
|
||||
- **F-83** Die besten Szenen werden chronologisch ausgewählt und zu einem Highlight-Video zusammengeschnitten.
|
||||
- **F-84** Ziel-Dauer des Highlight-Reels ist konfigurierbar (Standard: `60s`).
|
||||
- **F-85** Zwischen Highlight-Szenen werden automatisch Crossfades eingefügt.
|
||||
|
||||
### 10.6 Natürlichsprachliche Sequenz-Erstellung
|
||||
|
||||
- **F-86** Eine natürlichsprachliche Beschreibung wird per LLM in eine vollständige `sequence.yaml` übersetzt.
|
||||
- **F-87** Das LLM erhält als Kontext: verfügbare Ressourcen (Musik, Intros, Bilder), Dateien im angegebenen Ordner, und das Schema der Sequenz-Datei.
|
||||
- **F-88** Die generierte Sequenz wird zur Bestätigung angezeigt, bevor optional direkt gerendert wird (`--execute`).
|
||||
|
||||
---
|
||||
|
||||
## 11. KI-Konfiguration
|
||||
|
||||
Neuer Block in `config.yaml`:
|
||||
|
||||
```yaml
|
||||
ai:
|
||||
whisper_model: "base"
|
||||
whisper_language: null
|
||||
whisper_device: "auto"
|
||||
llm_provider: "anthropic"
|
||||
llm_model: "claude-haiku-4-5-20251001"
|
||||
anthropic_api_key: null
|
||||
ollama_url: "http://localhost:11434"
|
||||
ollama_model: "llama3"
|
||||
```
|
||||
|
||||
- **F-89** Der Anthropic-API-Key wird aus der Config oder der Umgebungsvariable `ANTHROPIC_API_KEY` gelesen.
|
||||
- **F-90** Fehlt der API-Key, funktionieren alle Features außer Auto-Kapitel, Highlights und natürlichsprachliche Sequenzen.
|
||||
|
||||
---
|
||||
|
||||
## 12. Neue CLI-Befehle
|
||||
|
||||
### `video-cut smart-cut`
|
||||
|
||||
```
|
||||
video-cut smart-cut --input VIDEO [--output DATEI]
|
||||
[--keep-fillers] [--no-false-starts]
|
||||
[--max-pause 1.0] [--analyze-only]
|
||||
```
|
||||
|
||||
### `video-cut transcribe`
|
||||
|
||||
```
|
||||
video-cut transcribe --input VIDEO [--output DATEI.srt]
|
||||
[--model base] [--language de]
|
||||
```
|
||||
|
||||
### `video-cut subtitle`
|
||||
|
||||
```
|
||||
video-cut subtitle --input VIDEO [--output DATEI]
|
||||
[--srt DATEI.srt]
|
||||
```
|
||||
|
||||
### `video-cut chapters`
|
||||
|
||||
```
|
||||
video-cut chapters --input VIDEO [--output chapters.txt]
|
||||
[--format youtube|sequence]
|
||||
[--inject-titles]
|
||||
```
|
||||
|
||||
### `video-cut highlights`
|
||||
|
||||
```
|
||||
video-cut highlights --input VIDEO [--output highlights.mp4]
|
||||
[--duration 60]
|
||||
```
|
||||
|
||||
### `video-cut describe`
|
||||
|
||||
```
|
||||
video-cut describe "Beschreibung des gewünschten Videos"
|
||||
[--execute] [--output sequence.yaml]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. Nicht-funktionale Anforderungen
|
||||
|
||||
- **NF-01** Kein GUI — ausschließlich Kommandozeile.
|
||||
- **NF-02** Alle Video-Operationen laufen über `subprocess` + `ffmpeg`/`ffprobe`; kein proprietäres Video-Framework.
|
||||
- **NF-03** Temporäre Dateien werden in einem `tempfile.TemporaryDirectory()` erzeugt und nach Abschluss automatisch gelöscht.
|
||||
- **NF-04** Fehlermeldungen erscheinen auf `stderr`; Fortschritts-Ausgaben auf `stdout`.
|
||||
- **NF-05** Exit-Code `0` bei Erfolg, `1` bei Fehler.
|
||||
- **NF-06** Ausgabe-Ordner werden automatisch angelegt, wenn sie nicht existieren.
|
||||
- **NF-07** Standardauflösung für generierte Clips (Text, Bilder): 1920×1080 @ 25fps, H.264, AAC.
|
||||
- **NF-08** Das Paket ist via `pip install -e .` installierbar (PEP 517, `setuptools`).
|
||||
- **NF-09** Der Discord-Bot läuft als Langzeit-Prozess; er blockiert nicht den CLI-Betrieb — beide Modi sind unabhängig voneinander nutzbar.
|
||||
- **NF-10** Discord-Befehle und CLI-Befehle rufen dieselbe interne Logik auf — keine duplizierte Implementierung.
|
||||
- **NF-11** KI-Features (`faster-whisper`, `anthropic`) sind optionale Abhängigkeiten — das Tool funktioniert ohne sie.
|
||||
- **NF-12** Whisper läuft lokal, keine Daten werden an externe Server gesendet (außer bei LLM-Provider `anthropic`).
|
||||
|
||||
---
|
||||
|
||||
## 14. Bekannte Einschränkungen
|
||||
|
||||
- **E-01** `--no-normalize` beim `merge`-Befehl kann zu Kompatibilitätsproblemen führen, wenn die Clips unterschiedliche Codecs oder Framerates haben.
|
||||
- **E-02** `type: folder` in der Sequenz-Datei erkennt Dateitypen nur anhand der Dateiendung, nicht des tatsächlichen Inhalts.
|
||||
- **E-03** Text-Overlays setzen voraus, dass die Standard-Schriftart von ffmpeg (`default`) auf dem System verfügbar ist; für abweichende Fonts muss `fontfile` in der drawtext-Option ergänzt werden (aktuell nicht konfigurierbar).
|
||||
- **E-04** Szenen-Erkennung via `split_scenes` setzt PySceneDetect und OpenCV voraus; fehlt das Paket, wird eine klare Fehlermeldung ausgegeben.
|
||||
- **E-05** `music.mode: loop` wiederholt aktuell nur die erste alphabetische Datei, kein echter Playlist-Loop über mehrere Dateien.
|
||||
- **E-06** Discord-Uploads sind auf 25 MB begrenzt (Discord-Limit für reguläre Server). Größere Ausgabe-Videos können nur als Pfad-Referenz zurückgemeldet werden.
|
||||
- **E-07** Slash-Commands müssen einmalig bei Discord registriert werden (`bot.tree.sync()`); nach Deployment kann die Synchronisation einige Minuten dauern.
|
||||
- **E-08** Der Bot unterstützt nur einen Server gleichzeitig sinnvoll — `allowed_channel_ids` verhindert ungewollten Multi-Server-Betrieb.
|
||||
- **E-09** Whisper-Modelle `medium` und `large-v3` benötigen signifikant mehr RAM/VRAM; auf CPU-only-Systemen empfohlen: `tiny` oder `base`.
|
||||
- **E-10** Füllwort-Erkennung kann kontextabhängige Wörter falsch markieren (z.B. "also" als Satzanfang vs. Füllwort). `--analyze-only` ermöglicht Review vor dem Schnitt.
|
||||
- **E-11** Auto-Kapitel und Highlights benötigen einen LLM-API-Zugang (Anthropic oder Ollama). Ohne API-Key sind diese Features deaktiviert.
|
||||
- **E-12** ffmpeg `xfade` erfordert ffmpeg >= 4.3. Ältere Versionen fallen auf harten Schnitt zurück.
|
||||
|
||||
---
|
||||
|
||||
## 15. Verifikation
|
||||
|
||||
| Test | Erwartetes Ergebnis |
|
||||
|------|---------------------|
|
||||
| `pip install -e .` | `video-cut --help` zeigt alle Befehle |
|
||||
| `video-cut cut --input test.mp4 --remove-silence` | Stille-freie MP4 im gleichen Ordner |
|
||||
| `video-cut cut --input test.mp4 --scene-detect` | Ordner `test_scenes/` mit Szenen-Clips |
|
||||
| `video-cut music --input test.mp4 --config config.yaml` | MP4 mit Hintergrundmusik aus `resources/music/` |
|
||||
| `video-cut batch --input ./videos/ --config config.yaml --remove-silence` | Alle Videos in `output/` ohne Stille |
|
||||
| `video-cut sequence --seq sequence.yaml --config config.yaml` | Finales Video gemäß Timeline in `output/` |
|
||||
| `video-cut bot --config config.yaml` | Bot startet, registriert Slash-Commands, wartet auf Befehle |
|
||||
| Discord: `/cut input:/pfad/test.mp4 remove_silence:true` | Bot bestätigt Job, verarbeitet Video, meldet Ergebnis zurück |
|
||||
| Discord: `/status` | Embed mit aktuellem Job-Status und Warteschlange |
|
||||
| Discord: `/cancel` | Laufender ffmpeg-Prozess wird beendet, Bestätigung im Kanal |
|
||||
| `video-cut transcribe --input test.mp4` | SRT-Datei mit Timestamps im gleichen Ordner |
|
||||
| `video-cut subtitle --input test.mp4` | Video mit eingebrannten Untertiteln |
|
||||
| `video-cut smart-cut --input test.mp4 --analyze-only` | Aufschlüsselung: Füllwörter, Fehlstarts, Pausen |
|
||||
| `video-cut smart-cut --input test.mp4` | Video ohne Füllwörter und mit gekürzten Pausen |
|
||||
| `video-cut chapters --input test.mp4 --format youtube` | YouTube-Kapitel-Beschreibung auf stdout |
|
||||
| `video-cut highlights --input test.mp4 --duration 60` | 60-Sekunden-Highlight-Video |
|
||||
| `video-cut merge --inputs a.mp4 b.mp4 -o out.mp4 --crossfade 0.5` | Video mit Crossfade-Übergang |
|
||||
| `video-cut sequence --seq s.yaml --preview` | Schnelle 360p-Vorschau |
|
||||
| `video-cut sequence --seq s.yaml --dry-run` | Clip-Liste und Dauer-Schätzung ohne Rendering |
|
||||
Reference in New Issue
Block a user