Initial commit: auto-video-cut project

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christoph K.
2026-04-06 21:51:01 +02:00
commit 267070ad52
15 changed files with 2635 additions and 0 deletions

607
ANFORDERUNGEN.md Executable file
View 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 |