Files
auto-video-cut/ANFORDERUNGEN.md
Christoph K. 267070ad52 Initial commit: auto-video-cut project
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:51:01 +02:00

608 lines
26 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 |