22 KiB
🛠️ Kapitel 13 – Clipper (Tutorial)
Einleitung
Clips sind der beste Weg, lange Streams in kurze, teilbare Highlights zu verwandeln. Unser Ziel in diesem Kapitel: Wir bauen ein System, das neue Videos automatisch erkennt, sinnvolle Stellen analysiert, passende Highlights schneidet und die Ergebnisse in Nextcloud ablegt – inklusive Titeln und Hashtags für jede Plattform. Der Clipper selbst übernimmt dabei die technische Verarbeitung, während n8n für Steuerung, Analyse und Benachrichtigungen sorgt. Das System bleibt dadurch 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, 1–2 GB RAM, 10 GB Speicher reichen aus
- Grundwissen: SSH-Verbindung, Nano-Editor, Basiskenntnisse in n8n
Vorbereitung
Wir beginnen mit einem frischen Debian‑12‑LXC in Proxmox, benennen ihn clipper und vergeben die im Abschnitt oben genannten Ressourcen. Danach bringen wir das System auf Stand und installieren die Grundwerkzeuge:
apt update && apt upgrade -y
apt install -y curl unzip ffmpeg inotify-tools
Eine korrekte Systemzeit ist entscheidend, da Schnittmarken später auf exakten Sekunden basieren. Prüfe die Zeit mit:
timedatectl status
Wenn hier UTC steht und du lieber „Europe/Berlin“ nutzen willst:
timedatectl list-timezones | grep Europe
timedatectl set-timezone Europe/Berlin
timedatectl status
Die Zeit wird sofort angepasst, Logs und Schnittzeiten passen damit zur lokalen Umgebung.
Zum Schluss legen wir die Arbeitsordner an:
mkdir -p /srv/clipper/{watch,out,temp,logs}
watch– Eingangsordner für neue Videos (egal ob von Twitch oder RTMP)out– fertige Clips und Metadatentemp– Zwischenspeicher für Analyselogs– Protokolle aller Abläufe
Damit ist das Fundament gelegt.
Abschnitt 2 – Clipper‑LXC einrichten (Benutzer, Verzeichnisse, Pakete, Skripte)
In diesem Abschnitt richten wir den Clipper‑Container so ein, dass SSH‑Schlüssel, Downloads und n8n‑Aufrufe ohne Berechtigungsfehler funktionieren. Wir arbeiten jetzt im Terminal deines Clipper‑LXC als root.
Entscheidung & Begründung – Benutzer mit Home & Bash
Der Benutzer clipper bekommt ein Homeverzeichnis (/home/clipper) und eine Login‑Shell. So können SSH‑Schlüssel sauber in~clipper/.sshlanden und n8n später per SSH Befehle ausführen. Varianten ohne Home (System‑User) führen beissh-copy-idzu Fehlern.
2.1 Benutzer und Verzeichnisse anlegen (Terminal, als root)
adduser --home /home/clipper --shell /bin/bash clipper
Vergib ein Passwort und bestätige die Abfragen. Danach legst du die Arbeitsordner an und überträgst den Besitz an clipper:
mkdir -p /srv/clipper/{inbox,watch,out,temp,logs,bin}
chown -R clipper:clipper /srv/clipper
chmod 750 /srv/clipper
(optional, aber hilfreich für ssh-copy-id später):
install -d -m 700 -o clipper -g clipper /home/clipper/.ssh
Falls du den Benutzer bereits ohne Home angelegt hast:
Richte ihn so nach:
mkdir -p /home/clipper/.ssh && chown -R clipper:clipper /home/clipper && chmod 700 /home/clipper/.ssh
2.2 Pakete installieren (Terminal, als root)
apt update && apt install -y yt-dlp jq python3 python3-venv curl unzip inotify-tools sudo
- ffmpeg: Analyse & Schnitt
- yt-dlp: Twitch‑VOD/Clip‑Downloads (HLS)
- jq: JSON‑Handling
- python3/venv: spätere Analyse‑Tools
- inotify-tools: Dateisystem‑Events (optional)
- sudo: für gezielte Rechteerhöhungen falls nötig
2.3 Zentrale Konfiguration (Terminal, als root)
Bevor wir die Umgebungsdatei anlegen, brauchen wir ein eigenes Konfigurationsverzeichnis. Das existiert standardmäßig nicht, daher legen wir es einmalig an:
mkdir -p /etc/clipper
chown root:clipper /etc/clipper
chmod 750 /etc/clipper
Entscheidung & Begründung – eigenes /etc/clipper
Konfiguration gehört nach/etc. Mit einem eigenen Ordner/etc/clipperbleibt alles übersichtlich getrennt.
Besitzer istroot, die Gruppeclipper. So kann der Clipper-User die Datei lesen, aber nicht verändern – genau die Balance zwischen Sicherheit und Funktion.
Entscheidung & Begründung – eigenes /etc/clipper Konfiguration gehört nach /etc. Mit einem eigenen Ordner /etc/clipper bleibt alles übersichtlich getrennt. Besitzer ist root, die Gruppe clipper. So kann der Clipper-User die Datei lesen, aber nicht verändern – genau die Balance zwischen Sicherheit und Funktion.
Lege eine Umgebungsdatei an, die beide Skripte laden:
nano /etc/clipper/clipper.env
Inhalt:
CLIPPER_INBOX=/srv/clipper/inbox
CLIPPER_IN=/srv/clipper/watch
CLIPPER_OUT=/srv/clipper/out
CLIPPER_TMP=/srv/clipper/temp
CLIPPER_LOG=/srv/clipper/logs/clipper.log
Dateirechte setzen, damit clipper sie lesen darf:
chown root:clipper /etc/clipper/clipper.env
chmod 640 /etc/clipper/clipper.env
2.4 Python‑Umgebung vorbereiten (Wechsel zu Benutzer clipper)
Wechsle jetzt zum Benutzer clipper:
su - clipper
Erzeuge und fülle eine virtuelle Umgebung für die spätere Analyse:
python3 -m venv /srv/clipper/.venv
source /srv/clipper/.venv/bin/activate
pip install --upgrade pip
pip install numpy opencv-python-headless
deactivate
Wechsle für die nächsten Schritte im Benutzer clipper weiter.
2.5 Einstiegsskripte erstellen (im Benutzer clipper)
Analyse‑Stub – prüft Eingaben, schreibt Logs, erzeugt leere Kandidatenliste:
nano /srv/clipper/bin/clipper-analyze
Inhalt:
#!/usr/bin/env bash
set -euo pipefail
ENV_FILE="/etc/clipper/clipper.env"; [ -r "$ENV_FILE" ] || { echo "ENV nicht lesbar: $ENV_FILE" >&2; exit 1; }; source "$ENV_FILE"
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"
OUT_JSON="$CLIPPER_TMP/$JOBID/candidates.json"
echo '[]' > "$OUT_JSON"
echo "$OUT_JSON"
Schneid‑Stub – protokolliert Schnittaufrufe, echte Logik folgt in Abschnitt 5:
nano /srv/clipper/bin/clipper-cut
Inhalt:
#!/usr/bin/env bash
set -euo pipefail
ENV_FILE="/etc/clipper/clipper.env"; [ -r "$ENV_FILE" ] || { echo "ENV nicht lesbar: $ENV_FILE" >&2; exit 1; }; source "$ENV_FILE"
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"
exit 0
Rechte setzen und Eigentümer korrigieren:
chmod +x /srv/clipper/bin/clipper-*
chown -R clipper:clipper /srv/clipper/bin
2.6 Logrotation (zurück zu root)
Beende die Session (exit) und kehre zu root zurück. Richte Logrotation ein:
nano /etc/logrotate.d/clipper
Inhalt:
/srv/clipper/logs/*.log {
rotate 14
daily
missingok
notifempty
compress
delaycompress
copytruncate
}
Schnelltest (optional):
Zurück im Benutzer clipper:
/srv/clipper/bin/clipper-analyze /srv/clipper/watch/demo.mp4 job-001
/srv/clipper/bin/clipper-cut /srv/clipper/watch/demo.mp4 /srv/clipper/temp/job-001/ranges.json job-001
tail -n 50 /srv/clipper/logs/clipper.log
Mit dieser Einrichtung sind SSH‑Schlüssel, Berechtigungen und Pfade konsistent. ssh-copy-id aus Abschnitt 3 funktioniert dadurch ohne Fehlermeldungen – und n8n kann die Skripte stabil starten.
Abschnitt 3 – n8n ↔ Twitch: VOD & Clips importieren, in Nextcloud ablegen, Clipper starten
In diesem Abschnitt verbinden wir n8n mit Twitch, Nextcloud und dem Clipper. Das Ziel: n8n erkennt automatisch neue VODs auf Twitch, lädt sie zusammen mit Clips herunter, legt sie in Nextcloud ab und startet dann die Analyse auf dem Clipper. Wir gehen Schritt für Schritt vor – immer mit klaren Hinweisen, ob wir uns gerade in der n8n‑Weboberfläche, im Terminal oder in Nextcloud befinden.
Entscheidung & Begründung – Rollenverteilung
n8n steuert (APIs, Logik, Benachrichtigungen). Clipper arbeitet (Download, Analyse, Schnitt). Nextcloud speichert (Archiv & Übergabe). So bleibt n8n schlank und ausfallsicher, während Clipper CPU/IO für Medienjobs bekommt.
Schritt 1: Zugriff zwischen den Containern vorbereiten (Terminal)
Optional: SSH Known-Hosts zurücksetzen (falls Clipper schon einmal erstellt wurde)
Wenn du den Clipper-LXC bereits früher erstellt und neu aufgesetzt hast, kann es zu einem SSH-Fehler kommen:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Das bedeutet, dass sich der Server-Hostkey geändert hat. SSH blockiert dann aus Sicherheitsgründen.
Lösung Schritt für Schritt (im n8n-LXC als root)
- Fingerprint auf dem Clipper prüfen
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
(SHA256-Wert merken und vergleichen)
- Alten Eintrag löschen
ssh-keygen -R "<CLIPPER-IP>"
Entscheidung & Begründung – Sicherheitsprinzip
SSH schützt vor Man-in-the-Middle-Angriffen, indem es Hostkeys prüft. Wenn ein Container neu erstellt wird, ist ein neuer Hostkey normal. Wir löschen den alten Eintrag bewusst, prüfen den neuen Fingerprint und akzeptieren ihn erst danach. So bleibt die Verbindung sicher und stabil.
Schritt 1.1: SSH-Schlüssel für n8n erzeugen (n8n-LXC, Terminal)
Damit n8n später Befehle im Clipper ausführen kann, benötigt es einen SSH-Schlüssel im kompatiblen Format.
# Schlüssel für n8n → Clipper erzeugen (RSA, PEM-Format)
ssh-keygen -t rsa -b 4096 -m PEM -f ~/.ssh/id_n8n_clipper -N ""
- -t rsa: RSA ist breiter kompatibel als ed25519.
- -m PEM: n8n benötigt diesen Formattyp, sonst kommt "Unsupported key format".
- -N "": kein Passwort (n8n kann keine Passphrase abfragen).
Schritt 1.2: Public Key auf dem Clipper hinterlegen
ssh-copy-id -i ~/.ssh/id_n8n_clipper.pub clipper@<CLIPPER-IP>
Test der Verbindung (ohne Passwort):
ssh -i ~/.ssh/id_n8n_clipper clipper@<CLIPPER-IP> "echo OK"
Entscheidung & Begründung – RSA statt ed25519 Ed25519 ist moderner, erzeugt aber oft OpenSSH-Private Keys, die n8n nicht korrekt verarbeiten kann. Das klassische PEM-Format mit RSA ist voll kompatibel mit n8n und vermeidet Fehler.
Schritt 1.3: SSH Credential in n8n eintragen
Ort: n8n Weboberfläche → Credentials → + Add → SSH
Felder:
- Name: z. B.
clipper-ssh - Host:
<CLIPPER-IP> - Port:
22 - Username:
clipper - Private Key: Inhalt von
~/.ssh/id_n8n_clipper(nicht.pub!) - Passphrase: leer lassen
Fehler & Lösung "Unsupported key format" → Der Private Key muss im PEM-Format vorliegen und mit
-----BEGIN RSA PRIVATE KEY-----beginnen und-----END RSA PRIVATE KEY-----enden. Nicht.pubeinfügen. Kein Passwort setzen. Keine Zeilen umbrechen oder manipulieren.
Damit ist der n8n-Zugriff auf den Clipper fertig eingerichtet – ohne spätere Konvertierungen, Fehlermeldungen oder Korrekturen.
Ersetze <CLIPPER-IP> durch die IP/den Hostnamen deines Clipper‑LXC (z. B. 10.0.0.42). Wenn OK erscheint, kann n8n ohne Passwort auf den Clipper zugreifen.
Zugangsdaten für Nextcloud‑WebDAV erstellen (Weboberfläche)
Ort in Nextcloud: Avatar (oben rechts) → Persönliche Einstellungen → Sicherheit → ganz nach unten zum Bereich App‑Passwörter.
Anleitung:
- Melde dich in der Nextcloud‑Weboberfläche an.
- Gehe zu Persönliche Einstellungen → Sicherheit.
- Ganz nach unten scrollen bis zum Abschnitt App‑Passwörter (unscheinbar platziert).
- Trage bei App‑Name z. B.
n8n Clipperein und klicke auf Neues App‑Passwort erstellen. - Kopiere das einmalig angezeigte App‑Passwort sofort und notiere zusätzlich deinen Benutzernamen. (Das Passwort wird später nicht erneut angezeigt.)
WebDAV‑URL für n8n/Uploads:
https://<DEINE_NEXTCLOUD_DOMAIN>/remote.php/dav/files/<DEIN_NC_BENUTZER>/
(Alternativ, je nach Setup: https://<DEINE_NEXTCLOUD_DOMAIN>/remote.php/webdav/)
Schnelltest (optional, auf deinem n8n‑LXC)
curl -u "<BENUTZER>:<APP_PASSWORT>" \
-X PROPFIND -H "Depth: 0" \
-s -o /dev/null -w "%{http_code}\n" \
"https://<DEINE_NEXTCLOUD_DOMAIN>/remote.php/dav/files/<DEIN_NC_BENUTZER>/"
# Erwartet: 207
Optional kannst du die ersten Zeilen der Antwort prüfen:
curl -u "<BENUTZER>:<APP_PASSWORT>" \
-X PROPFIND -H "Depth: 0" -s \
"https://<DEINE_NEXTCLOUD_DOMAIN>/remote.php/dav/files/<DEIN_NC_BENUTZER>/" \
| head -n 5
# Erwartet: XML mit <d:multistatus ...>
Fehler & Lösung (kurz):
- 401/403 → Benutzername oder App‑Passwort falsch.
- 404 → Pfad prüfen (richtiger Benutzerordner?).
- App‑Passwörter fehlen? Admin muss sie in den Nextcloud‑Einstellungen aktivieren.
Twitch‑API Zugang:
Twitch Developer Console – App anlegen
- Gehe auf Twitch Developer Console → Applications → Register Your Application.
- Felder ausfüllen:
- Name: frei wählbar (muss einzigartig sein).
- OAuth Redirect URL: z. B.
https://localhost/(Platzhalter; für Client-Credentials Flow nicht genutzt). - Category: passend wählen (z. B. Chatbot/Website Integration).
- App speichern → Manage öffnen.
- Client ID notieren, New Secret klicken und Client Secret sichern.
Twitch OAuth2 Credential in n8n (Client Credentials Flow)
Beim Anlegen in n8n → Credentials → + Add → OAuth2 API:
- Name: Twitch API
- Grant Type:
Client Credentials - Authorization URL:
https://id.twitch.tv/oauth2/authorize(Pflichtfeld, wird in diesem Flow nicht genutzt) - Access Token URL:
https://id.twitch.tv/oauth2/token - Client ID: (aus Twitch Developer Console)
- Client Secret: (aus Twitch Developer Console)
- Scope: (leer lassen)
- Authentication:
Body← wichtig, sonst Fehler - OAuth Redirect URL:
https://automation.bratonien.de/rest/oauth2-credential/callback(muss in Twitch-App eingetragen sein, auch wenn bei Client Credentials nicht genutzt)
Speichern.
Prüfen (kein „Test“-Button bei Client Credentials):
- Lege einen HTTP Request-Node an.
- Authentication: Predefined Credential Type → wähle dein
Twitch APICredential. - Headers:
Client-Id: <DEINE_CLIENT_ID> - URL:
https://api.twitch.tv/helix/users?login=bratonien_tv - Execute Node → kommt JSON mit
data[0].id, ist OAuth korrekt.
Nutzung in HTTP Request Nodes
- Authentication: Predefined Credential Type → wähle dein
Twitch APICredential - Headers:
Client-Id: <DEINE_CLIENT_ID>
n8n setzt automatisch Authorization: Bearer <token>.
Schnelltest in n8n
HTTP Request Node:
- Method:
GET - URL:
https://api.twitch.tv/helix/users?login=bratonien_tv - Header:
Client-Id: <DEINE_CLIENT_ID>
Ergebnis: JSON mit data[0].id, login, usw. – dann funktioniert OAuth2 korrekt.
Schritt 2: Twitch‑User‑ID herausfinden (n8n‑Weboberfläche)
Die Twitch‑API benötigt deine numerische User‑ID, nicht den Login‑Namen. Wir holen diese ID einmalig in n8n.
- Gehe in der n8n‑Weboberfläche auf Workflows → + New Workflow.
- Ziehe einen HTTP Request Node auf die Arbeitsfläche.
- Konfiguriere ihn so:
- Methode: GET
- URL:
https://api.twitch.tv/helix/users?login=<DEIN_LOGIN> - Authentifizierung: OAuth2 Credential (aus Schritt 1)
- Header:
Client-Id: <DEINE_CLIENT_ID>
- Klicke auf Execute Node.
- Im Ergebnis findest du im Feld
data[0].iddeine User‑ID (z. B.123456789). Diese Zahl ist entscheidend und ersetzt ab jetzt<DEINE_TWITCH_USER_ID>in allen weiteren Schritten.
Referenz: Get Users
Entscheidung & Begründung – Login vs. User‑ID
Der „Login“ ist nur ein Anzeigename. Die API filtert zuverlässig über die numerische ID – deshalb holen wir sie einmalig und verwenden sie konsequent.
Schritt 3: Workflow bauen (n8n‑Weboberfläche)
Jetzt bauen wir den eigentlichen Workflow, der regelmäßig neue VODs prüft, herunterlädt und ablegt.
-
Cron-Trigger anlegen:
- Ziehe einen Cron Node auf die Arbeitsfläche.
- Stelle ihn auf „Every 10 minutes“. Damit prüft n8n alle 10 Minuten auf neue VODs.
-
VOD-Daten abrufen:
-
Ziehe einen weiteren HTTP Request Node an den Cron-Node.
-
URL:
https://api.twitch.tv/helix/videos?user_id=<DEINE_TWITCH_USER_ID>&type=archive&first=1 -
Auth: OAuth2 Credential
-
Header:
Client-Id: <DEINE_CLIENT_ID> -
Ergebnis: In
data[0]stehenid,title,url,created_at,published_at.
Referenz: Get Videos
-
-
IF „Neu?“ Node hinzufügen:
-
Bedingung (Expression):
{{$json.data[0].id !== $workflow.staticData.global.last_vod_id}} -
true → weiter; false → Ende
Entscheidung & Begründung – State merken Nur wenn die ID sich ändert, ist ein neues VOD da. So entstehen keine leeren Ordner und keine unnötigen API- oder SSH-Aufrufe.
-
-
VOD herunterladen (SSH Execute Command im Clipper-LXC):
-
Node: SSH Execute Command (Credential: Clipper)
-
Command:
JOBID="{{ $json.data[0].id }}" URL="{{ $json.data[0].url }}" DIR="/srv/clipper/inbox/$JOBID" mkdir -p "$DIR" yt-dlp \ --download-archive "/srv/clipper/logs/yt-dlp.archive" \ --no-part --restrict-filenames \ --abort-on-unavailable-fragment \ --retries 10 --fragment-retries 10 --retry-sleep 5 \ -o "$DIR/%(title)s-%(id)s.%(ext)s" \ "$URL"
Entscheidung & Begründung – yt-dlp Archive
--download-archiveverhindert doppelte Downloads. Retries sichern HLS-Streams ab. Alles passiert auf Clipper, aber gesteuert durch n8n. -
-
Clips abrufen (optional):
-
Node: HTTP Request
-
URL:
https://api.twitch.tv/helix/clips?broadcaster_id=<DEINE_TWITCH_USER_ID>&started_at={{$json.data[0].created_at}}&ended_at={{$json.data[0].published_at}} -
Danach: Split in Batches → je Clip-URL an SSH Execute Command
Command (SSH):
CID="{{ $json.id }}" CURL="{{ $json.url }}" DIR="/srv/clipper/inbox/$CID" mkdir -p "$DIR" yt-dlp \ --download-archive "/srv/clipper/logs/yt-dlp.archive" \ --no-part --restrict-filenames \ --retries 10 --fragment-retries 10 --retry-sleep 5 \ -o "$DIR/%(title)s-%(id)s.%(ext)s" \ "$CURL" -
-
Upload nach Nextcloud (n8n‑Weboberfläche):
-
Node: HTTP Request
-
Methode: PUT
-
Auth: Basic Auth (Nextcloud App-Passwort)
-
URL:
https://<DEINE_NEXTCLOUD_DOMAIN>/remote.php/dav/files/<DEIN_NC_BENUTZER>/Clips/{{ $json.data[0].id }}/<Dateiname> -
Ergebnis: In Nextcloud liegt danach ein Ordner
Clips/<VOD-ID>/….
Entscheidung & Begründung – Warum Nextcloud? Zentrales, versionierbares Speicherziel mit Freigaben/Quotas/Backups. Clipper und andere Systeme können darauf zugreifen, ohne erneut von Twitch laden zu müssen.
-
-
Analyse starten (SSH Execute Command):
-
Command:
VIDDIR="/srv/clipper/inbox/{{ $json.data[0].id }}" MAINFILE="$(find "$VIDDIR" -maxdepth 1 -type f -name '*.mp4' -o -name '*.mkv' | head -n1)" /srv/clipper/bin/clipper-analyze "$MAINFILE" "vod-{{ $json.data[0].id }}"
Entscheidung & Begründung – Arbeitsteilung n8n stößt nur an, Clipper rechnet. So bleibt n8n leicht und ausfallsicher.
-
-
State aktualisieren (n8n‑Weboberfläche):
-
Node: Function oder Set
$workflow.staticData.global.last_vod_id = $json.data[0].id; return items;
Damit merkt sich der Workflow, welches VOD zuletzt verarbeitet wurde.
-
Alternative: Twitch‑Community‑Node (n8n‑Weboberfläche)
Wenn du statt HTTP Requests lieber einen fertigen Twitch‑Node nutzen willst, kannst du in self‑hosted n8n einen Community‑Node installieren. Die Anleitung: n8n Community Nodes. Beachte: Community‑Nodes sind Drittanbieter‑Code und können bei Updates Probleme machen. Für einen stabilen Dauerbetrieb empfehlen wir den API‑Weg mit HTTP Request.
Kontrolle
Nach einem erfolgreichen Durchlauf prüfst du im Terminal des Clipper‑LXC:
su - clipper
ls -lh /srv/clipper/inbox/<VOD-ID>
tail -n 50 /srv/clipper/logs/clipper.log
Und in der Nextcloud‑Weboberfläche solltest du den Ordner Clips/<VOD-ID> sehen. Damit ist die Pipeline geschlossen: Twitch liefert VODs, n8n steuert den Ablauf, Clipper verarbeitet, Nextcloud speichert. In Abschnitt 4 gehen wir in die Analyse‑Logik und die KI‑Auswertung.