241 lines
8.4 KiB
Markdown
241 lines
8.4 KiB
Markdown
# 🛠️ Kapitel 13 – Clipper (Tutorial)
|
||
|
||
---
|
||
|
||
## Einleitung
|
||
Clips sind der beste Weg, lange Streams in kurze, teilbare Highlights zu verwandeln.
|
||
Das Ziel dieses Kapitels: Wir bauen ein System, das neue Videos automatisch erkennt, sinnvolle Stellen analysiert, passende Highlights schneidet und die Ergebnisse in Nextcloud ablegt – komplett mit Titeln und Hashtags für jede Plattform.
|
||
Der Clipper selbst übernimmt dabei nur die technische Verarbeitung. Alles rund um Steuerung, Analyse und Benachrichtigungen läuft über **n8n** – so bleibt das System flexibel, ressourcenschonend und jederzeit erweiterbar.
|
||
|
||
---
|
||
|
||
## Voraussetzungen
|
||
- **Proxmox LXC** mit Debian 12 (Bookworm)
|
||
- **Nextcloud** (Pflicht, Zielort für Clips & Metadaten)
|
||
- **n8n-Instanz** (Automatisierung, Steuerung Clipper, Analyse, Metadaten-Erzeugung)
|
||
- **Twitch-Entwickler-Account** inkl. API-Key (für VOD- und Clip-Zugriff)
|
||
- **Optional**: RTMP-Server, falls VODs lokal aufgezeichnet werden
|
||
- **Ressourcen für den LXC**: 1 vCPU, 512 MB RAM, 10 GB Speicher reichen aus
|
||
- **Grundwissen**: SSH-Verbindung, Nano-Editor, Basiskenntnisse in n8n
|
||
|
||
---
|
||
|
||
## Vorbereitung
|
||
Bevor wir Clipper installieren, richten wir den Container sauber ein:
|
||
|
||
1. **LXC erstellen**
|
||
- Debian 12, Name `clipper`
|
||
- Ressourcen wie oben (1 vCPU, 512 MB RAM, 10 GB Speicher)
|
||
|
||
2. **System aktualisieren und Basis-Tools installieren**
|
||
```bash
|
||
apt update && apt upgrade -y
|
||
apt install -y curl nano unzip ffmpeg inotify-tools
|
||
```
|
||
|
||
3. **Zeitsynchronisation prüfen**
|
||
```bash
|
||
timedatectl status
|
||
```
|
||
Eine saubere Zeitbasis ist entscheidend, da Clips später anhand exakter Sekundenmarken geschnitten werden.
|
||
|
||
Wenn der Container standardmäßig auf UTC läuft, kann man die Zeitzone so ändern:
|
||
```bash
|
||
timedatectl list-timezones | grep Europe
|
||
timedatectl set-timezone Europe/Berlin
|
||
timedatectl status
|
||
```
|
||
|
||
Damit springt die Systemzeit sofort auf Europe/Berlin, und alle Logs sowie Schnittzeiten passen zur lokalen Zeit.
|
||
|
||
4. **Ordnerstruktur vorbereiten**
|
||
```bash
|
||
mkdir -p /srv/clipper/{watch,out,temp,logs}
|
||
```
|
||
- `watch` → Eingangsordner für neue Videos (über Nextcloud oder Twitch-Import)
|
||
- `out` → fertige Clips + Metadaten
|
||
- `temp` → Zwischenablagen für Analyse
|
||
- `logs` → Protokolle aller Abläufe
|
||
|
||
Damit ist das Fundament gelegt: Der LXC ist vorbereitet, das System auf Stand, und die Ordnerstruktur für Clipper ist vorhanden.
|
||
|
||
---
|
||
|
||
## Hinweis zu späteren Schritten (Analyse & Schneiden)
|
||
Im weiteren Verlauf des Tutorials berücksichtigen wir:
|
||
- **Facecam-Erkennung**: Falls eine Facecam im Stream vorhanden ist, wird sie automatisch erkannt und als Overlay (z. B. Kreis, Rechteck oder wechselnde Form) in den Clip eingeblendet.
|
||
- **Format-Anpassung**: Clips können zusätzlich ins **Hochformat (9:16)** umgewandelt werden, damit sie ohne Nachbearbeitung für TikTok, Instagram Reels oder YouTube Shorts nutzbar sind.
|
||
- **Varianten**: Optional werden sowohl Querformat (16:9) als auch Hochformat exportiert, um alle Plattformen optimal zu bedienen.
|
||
- **Untertitel-Steuerung**: In n8n gibt es ein Auswahlfeld mit drei Modi:
|
||
1. **Aus** – keine Untertitel.
|
||
2. **SRT** – es wird eine `.srt` erzeugt und neben dem Clip abgelegt.
|
||
3. **Generiert nach Preset** – STT erzeugt Text + Timing, und n8n rendert sie mit einem Style-Preset direkt ins Video. Presets können zentral (z. B. Nextcloud `/presets/subtitles.json`) gepflegt werden.
|
||
|
||
**Pipeline-Auswirkung:**
|
||
- Modus **SRT** → `.srt` speichern, Clip bleibt „clean“.
|
||
- Modus **Preset** → `.srt` + gerenderte Untertitel im Video; optional `.srt` zusätzlich.
|
||
|
||
---
|
||
|
||
## Einrichten des Clipper-LXC
|
||
Nun richten wir Clipper selbst im vorbereiteten Container ein: Installation von ffmpeg, grundlegende Services und Basis-Konfiguration. (Details folgen in diesem Abschnitt.)
|
||
|
||
Ziel: Der LXC enthält alles Nötige, damit n8n ihn bei Bedarf starten kann und klare Einstiegspunkte zum **Analysieren** und **Schneiden** vorhanden sind. Die eigentliche Logik füllen wir später (Abschnitt 4/5) – jetzt legen wir nur das **saubere Gerüst** an.
|
||
|
||
### Service‑Benutzer & Verzeichnisse
|
||
```bash
|
||
# Systemnutzer ohne Login
|
||
useradd --system --create-home --shell /usr/sbin/nologin clipper
|
||
mkdir -p /srv/clipper/{watch,out,temp,logs,bin}
|
||
chown -R clipper:clipper /srv/clipper
|
||
|
||
# Ort für Konfiguration/Secrets
|
||
mkdir -p /etc/clipper
|
||
chmod 750 /etc/clipper
|
||
```
|
||
|
||
### Pakete installieren
|
||
```bash
|
||
apt update && apt install -y ffmpeg jq python3 python3-venv curl unzip inotify-tools
|
||
```
|
||
|
||
> **Warum diese Pakete?**
|
||
> **ffmpeg** für Analyse/Schnitt, **jq** für JSON‑Handling, **python3/venv** für optionale Analyse‑Hilfen (z. B. Szenen/Facedetect in Abschnitt 4), **inotify-tools** für eventuelle lokale Hooks.
|
||
|
||
### Konfiguration (env)
|
||
```bash
|
||
nano /etc/clipper/clipper.env
|
||
```
|
||
Inhalt (minimal, erweiterbar in späteren Abschnitten):
|
||
```
|
||
CLIPPER_IN=/srv/clipper/watch
|
||
CLIPPER_OUT=/srv/clipper/out
|
||
CLIPPER_TMP=/srv/clipper/temp
|
||
CLIPPER_LOG=/srv/clipper/logs/clipper.log
|
||
# Standard-Exportformate; Details folgen in Abschnitt 5/6
|
||
EXPORT_VARIANTS="16x9,9x16"
|
||
```
|
||
Rechte setzen:
|
||
```bash
|
||
chown root:clipper /etc/clipper/clipper.env
|
||
chmod 640 /etc/clipper/clipper.env
|
||
```
|
||
|
||
### Python‑Umgebung vorbereiten (für Analyse‑Tools, Abschnitt 4)
|
||
```bash
|
||
# Virtuelle Umgebung im Home des clipper-Users erstellen
|
||
runuser -u clipper -- python3 -m venv /srv/clipper/.venv
|
||
runuser -u clipper -- /srv/clipper/.venv/bin/pip install --upgrade pip
|
||
# Pakete für spätere Analyse (Details in Abschnitt 4)
|
||
runuser -u clipper -- /srv/clipper/.venv/bin/pip install numpy opencv-python-headless
|
||
```
|
||
> Wir installieren nur Basis‑Bausteine. STT/KI o. Ä. binden wir erst in Abschnitt 4 an.
|
||
|
||
### Entrypoints (noch „stubs“)
|
||
Wir erstellen zwei **CLI‑Einstiegspunkte**, die n8n aufruft. Sie tun jetzt noch nichts Schweres – nur Validierung & Logging. Die echte Logik folgt in Abschnitt 4/5.
|
||
|
||
**Analyse‑Stub**
|
||
```bash
|
||
nano /srv/clipper/bin/clipper-analyze
|
||
```
|
||
Inhalt:
|
||
```bash
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
source /etc/clipper/clipper.env
|
||
IN="$1" # absolute Datei
|
||
JOBID="${2:-manual}"
|
||
mkdir -p "$CLIPPER_TMP/$JOBID"
|
||
echo "$(date '+%F %T') [ANALYZE] job=$JOBID file=$IN" | tee -a "$CLIPPER_LOG"
|
||
# Platzhalter: Wir erzeugen vorerst nur eine leere Kandidatenliste
|
||
OUT_JSON="$CLIPPER_TMP/$JOBID/candidates.json"
|
||
echo '[]' > "$OUT_JSON"
|
||
echo "$OUT_JSON"
|
||
```
|
||
|
||
**Schneid‑Stub**
|
||
```bash
|
||
nano /srv/clipper/bin/clipper-cut
|
||
```
|
||
Inhalt:
|
||
```bash
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
source /etc/clipper/clipper.env
|
||
IN="$1" # absolute Datei
|
||
RANGES_JSON="$2" # Zeitbereiche (kommt später aus Abschnitt 4)
|
||
JOBID="${3:-manual}"
|
||
mkdir -p "$CLIPPER_OUT/$JOBID"
|
||
echo "$(date '+%F %T') [CUT] job=$JOBID file=$IN ranges=$RANGES_JSON" | tee -a "$CLIPPER_LOG"
|
||
# Platzhalter: noch kein Schnitt; wir protokollieren nur
|
||
exit 0
|
||
```
|
||
|
||
Ausführbar machen:
|
||
```bash
|
||
chmod +x /srv/clipper/bin/clipper-*
|
||
chown -R clipper:clipper /srv/clipper/bin
|
||
```
|
||
|
||
### Systemd‑Dienst (on‑demand)
|
||
Wir wollen Clipper „auf Zuruf“ starten/stoppen. Für einfache Integrationen setzt n8n **SSH/Command** ab. Optional ergänzen wir später einen Webhook.
|
||
|
||
```bash
|
||
nano /etc/systemd/system/clipper.target
|
||
```
|
||
Inhalt:
|
||
```ini
|
||
[Unit]
|
||
Description=Clipper Target (on-demand services)
|
||
```
|
||
|
||
```bash
|
||
nano /etc/systemd/system/clipper@.service
|
||
```
|
||
Inhalt:
|
||
```ini
|
||
[Unit]
|
||
Description=Clipper Job %i
|
||
After=network.target
|
||
Wants=clipper.target
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
User=clipper
|
||
Group=clipper
|
||
EnvironmentFile=/etc/clipper/clipper.env
|
||
ExecStart=/srv/clipper/bin/%i
|
||
StandardOutput=append:/srv/clipper/logs/systemd-%i.log
|
||
StandardError=append:/srv/clipper/logs/systemd-%i.log
|
||
|
||
[Install]
|
||
WantedBy=clipper.target
|
||
```
|
||
|
||
Aktualisieren & testen:
|
||
```bash
|
||
systemctl daemon-reload
|
||
# Beispiel: Analyse-Stub einmalig ausführen
|
||
systemctl start "clipper@clipper-analyze"
|
||
```
|
||
> In Abschnitt 3/4 ruft n8n die EntryPoints mit Parametern auf (Dateipfad, JOBID usw.).
|
||
|
||
### Log‑Rotation
|
||
```bash
|
||
nano /etc/logrotate.d/clipper
|
||
```
|
||
Inhalt:
|
||
```
|
||
/srv/clipper/logs/*.log {
|
||
rotate 14
|
||
daily
|
||
missingok
|
||
notifempty
|
||
compress
|
||
delaycompress
|
||
copytruncate
|
||
}
|
||
```
|
||
|
||
Damit ist der **Clipper‑LXC** vorbereitet: Benutzer, Verzeichnisse, Pakete, Konfiguration und Systemd‑Skelett sind vorhanden. In den nächsten Abschnitten hängen wir **Twitch/n8n** an, füllen die **Analyse‑Logik** (inkl. Facecam/Hochformat/Untertitel‑Option) und implementieren das **Schneiden** samt sauberer Ablage in Nextcloud.
|