Files
Homelab--Bratonein-Kontroll…/Kapitel 13/Tutorial.md

18 KiB
Raw Blame History

🛠️ 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, 12 GB RAM, 10 GB Speicher reichen aus
  • Grundwissen: SSH-Verbindung, Nano-Editor, Basiskenntnisse in n8n

Vorbereitung

Wir beginnen mit einem frischen Debian12LXC 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 Metadaten
  • temp Zwischenspeicher für Analyse
  • logs Protokolle aller Abläufe

Damit ist das Fundament gelegt.


Abschnitt 2 ClipperLXC einrichten (Benutzer, Verzeichnisse, Pakete, Skripte)

In diesem Abschnitt richten wir den ClipperContainer so ein, dass SSHSchlüssel, Downloads und n8nAufrufe ohne Berechtigungsfehler funktionieren. Wir arbeiten jetzt im Terminal deines ClipperLXC als root.

Entscheidung & Begründung Benutzer mit Home & Bash
Der Benutzer clipper bekommt ein Homeverzeichnis (/home/clipper) und eine LoginShell. So können SSHSchlüssel sauber in ~clipper/.ssh landen und n8n später per SSH Befehle ausführen. Varianten ohne Home (SystemUser) führen bei ssh-copy-id zu 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: TwitchVOD/ClipDownloads (HLS)
  • jq: JSONHandling
  • python3/venv: spätere AnalyseTools
  • inotify-tools: DateisystemEvents (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/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.

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 PythonUmgebung 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)

AnalyseStub 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"

SchneidStub 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 SSHSchlüssel, Berechtigungen und Pfade konsistent. ssh-copy-id aus Abschnitt 3 funktioniert dadurch ohne Fehlermeldungen und n8n kann die Skripte stabil starten.

Abschnitt 2 Clipper-LXC einrichten (Basisdienste & Einstiegsskripte)

Damit der Benutzer clipper sauber funktioniert, legen wir ihn immer mit Home-Verzeichnis und Shell an. So können wir später SSH-Schlüssel ohne Fehler hinterlegen.

Benutzer und Verzeichnisse

Als root:

adduser --home /home/clipper --shell /bin/bash clipper

Vergib ein Passwort und bestätige die Abfragen. Danach richte das Konfigurationsverzeichnis ein:

mkdir -p /etc/clipper
chown root:clipper /etc/clipper
chmod 750 /etc/clipper

Pakete installieren

apt install -y ffmpeg jq python3 python3-venv curl unzip inotify-tools sudo
  • ffmpeg: Kern für Analyse/Schnitt
  • jq: JSON-Auswertung
  • python3/venv: Virtuelle Umgebung für Analyse
  • inotify-tools: Events
  • sudo: für Rechteeskalation

Konfiguration anlegen

nano /etc/clipper/clipper.env

Inhalt:

CLIPPER_IN=/srv/clipper/watch
CLIPPER_OUT=/srv/clipper/out
CLIPPER_TMP=/srv/clipper/temp
CLIPPER_LOG=/srv/clipper/logs/clipper.log

Rechte setzen:

chown root:clipper /etc/clipper/clipper.env
chmod 640 /etc/clipper/clipper.env

Python-Umgebung vorbereiten

su - clipper
python3 -m venv /srv/clipper/.venv
source /srv/clipper/.venv/bin/activate
pip install --upgrade pip
pip install numpy opencv-python-headless

Einstiegsskripte erstellen

Analyse-Stub:

nano /srv/clipper/bin/clipper-analyze
#!/usr/bin/env bash
set -euo pipefail
source /etc/clipper/clipper.env
IN="$1"
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:

nano /srv/clipper/bin/clipper-cut
#!/usr/bin/env bash
set -euo pipefail
source /etc/clipper/clipper.env
IN="$1"
RANGES_JSON="$2"
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:

chmod +x /srv/clipper/bin/clipper-*
chown -R clipper:clipper /srv/clipper/bin

Logs und Rotation

nano /etc/logrotate.d/clipper
/srv/clipper/logs/*.log {
  rotate 14
  daily
  missingok
  notifempty
  compress
  delaycompress
  copytruncate
}

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 n8nWeboberflä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)

Melde dich zuerst im Terminal deines n8nLXC an. Wir richten hier die Verbindung zum Clipper und zu Nextcloud ein.

SSHSchlüssel für Clipper erzeugen:

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
ssh-copy-id clipper@<CLIPPER-IP>
ssh clipper@<CLIPPER-IP> "echo OK"

Ersetze <CLIPPER-IP> durch die IP/den Hostnamen deines ClipperLXC (z.B. 10.0.0.42). Wenn OK erscheint, kann n8n ohne Passwort auf den Clipper zugreifen.

AppPasswort für Nextcloud:
Melde dich nun in der NextcloudWeboberfläche an. Gehe in dein Benutzerprofil → SicherheitAppPasswörter und erzeuge ein neues Passwort. Notiere dir Benutzername + AppPasswort. Diese nutzt n8n später für den Upload via WebDAV. Die Adresse sieht so aus:

https://<DEINE_NEXTCLOUD_DOMAIN>/remote.php/dav/files/<DEIN_NC_BENUTZER>/

Beispiel: https://cloud.example.com/remote.php/dav/files/streamer/

TwitchAPI Zugang:
Gehe in die Twitch Developer Console, lege eine App an und notiere Client ID und Client Secret. Danach öffne die n8nWeboberfläche in deinem Browser (http://<DEINE_N8N_DOMAIN>:5678), melde dich an und gehe links auf Credentials+ Add CredentialOAuth2 API.

  • Grant Type: Client Credentials
  • Access Token URL: https://id.twitch.tv/oauth2/token
  • Client ID / Secret eintragen
  • Speichern und testen.

Referenz: Twitch AuthDoku

Entscheidung & Begründung Warum ClientCredentials?
Für Get Users, Get Videos, Get Clips reicht ein AppToken. Der Flow ist stabil, ohne UserLogin/RefreshTokenPflege.


Schritt 2: TwitchUserID herausfinden (n8nWeboberfläche)

Die TwitchAPI benötigt deine numerische UserID, nicht den LoginNamen. Wir holen diese ID einmalig in n8n.

  1. Gehe in der n8nWeboberfläche auf Workflows+ New Workflow.
  2. Ziehe einen HTTP Request Node auf die Arbeitsfläche.
  3. 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>
  4. Klicke auf Execute Node.
  5. Im Ergebnis findest du im Feld data[0].id deine UserID (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. UserID
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 (n8nWeboberfläche)

Jetzt bauen wir den eigentlichen Workflow, der regelmäßig neue VODs prüft, herunterlädt und ablegt.

  1. CronTrigger 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.
  2. VODDaten abrufen:

    • Ziehe einen weiteren HTTP Request Node an den CronNode.
    • 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] stehen id, title, url, created_at, published_at.

    Referenz: Get Videos

  3. Clips abrufen (optional):

    • Ziehe einen weiteren HTTP Request Node an.
    • URL:
      https://api.twitch.tv/helix/clips?broadcaster_id=<DEINE_TWITCH_USER_ID>&started_at=<created_at>&ended_at=<published_at>
      
    • Ergebnis: Liste mit Clips, die im Zeitraum des VOD erstellt wurden.

    Referenz: Get Clips

  4. VOD herunterladen (Terminal im ClipperLXC):
    Jetzt wechselst du ins Terminal des ClipperLXC. Stelle sicher, dass yt-dlp installiert ist (apt install -y yt-dlp). n8n ruft per SSH folgenden Befehl auf:

    mkdir -p "/srv/clipper/inbox/{{ $json.data[0].id }}"
    yt-dlp -o "/srv/clipper/inbox/{{ $json.data[0].id }}/%(title)s.%(ext)s" {{ $json.data[0].url }}
    

    Damit entsteht ein Unterordner /srv/clipper/inbox/<VOD-ID>/ mit dem Video.

    Entscheidung & Begründung Warum lädt Clipper (und nicht n8n)?
    VODs kommen als HLSStreams (m3u8, segmentiert, signiert). Ein robuster Download braucht ytdlp/ffmpeg mit Retry/Resume und I/OPuffer. Das ist CPU/IOlastig und gehört auf die Werkbank (Clipper), nicht in die Steuerzentrale (n8n). So bleibt n8n stabil und reagiert weiter auf Webhooks.

  5. Clips herunterladen (Terminal im ClipperLXC, optional):
    Für jeden ClipURL ruft n8n per SSH yt-dlp auf:

    yt-dlp -o "/srv/clipper/inbox/<CLIP_ID>/%(title)s.%(ext)s" https://clips.twitch.tv/<CLIP_ID>
    
  6. Upload nach Nextcloud (n8nWeboberfläche):

    • Ziehe einen HTTP Request Node auf die Arbeitsfläche.
    • Methode: PUT
    • Auth: Basic Auth (Benutzername + AppPasswort aus Schritt 1)
    • 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.

  7. Analyse starten (Terminal im ClipperLXC):
    Zum Abschluss ruft n8n per SSH das Skript clipper-analyze auf:

    /srv/clipper/bin/clipper-analyze \
      "/srv/clipper/inbox/{{ $json.data[0].id }}/{{ $json.data[0].title }}.mp4" \
      "vod-{{ $json.data[0].id }}"
    

    Das Skript erzeugt im ClipperTempOrdner eine candidates.json. Mit dieser arbeiten wir in Abschnitt 4 weiter.


Alternative: TwitchCommunityNode (n8nWeboberfläche)

Wenn du statt HTTP Requests lieber einen fertigen TwitchNode nutzen willst, kannst du in selfhosted n8n einen CommunityNode installieren. Die Anleitung: n8n Community Nodes. Beachte: CommunityNodes sind DrittanbieterCode und können bei Updates Probleme machen. Für einen stabilen Dauerbetrieb empfehlen wir den APIWeg mit HTTP Request.


Kontrolle

Nach einem erfolgreichen Durchlauf prüfst du im Terminal des ClipperLXC:

su - clipper
ls -lh /srv/clipper/inbox/<VOD-ID>

tail -n 50 /srv/clipper/logs/clipper.log

Und in der NextcloudWeboberflä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 AnalyseLogik und die KIAuswertung.