Kapitel 13/Tutorial.md aktualisiert
This commit is contained in:
@@ -402,73 +402,134 @@ Referenz: [Get Users](https://dev.twitch.tv/docs/api/reference#get-users)
|
|||||||
|
|
||||||
Jetzt bauen wir den eigentlichen Workflow, der regelmäßig neue VODs prüft, herunterlädt und ablegt.
|
Jetzt bauen wir den eigentlichen Workflow, der regelmäßig neue VODs prüft, herunterlädt und ablegt.
|
||||||
|
|
||||||
1. **Cron‑Trigger anlegen:**
|
1. **Cron-Trigger anlegen:**
|
||||||
- Ziehe einen **Cron Node** auf die Arbeitsfläche.
|
|
||||||
- Stelle ihn auf „Every 10 minutes“.
|
* Ziehe einen **Cron Node** auf die Arbeitsfläche.
|
||||||
Damit prüft n8n alle 10 Minuten auf neue VODs.
|
* Stelle ihn auf „Every 10 minutes“.
|
||||||
|
Damit prüft n8n alle 10 Minuten auf neue VODs.
|
||||||
|
|
||||||
|
2. **VOD-Daten abrufen:**
|
||||||
|
|
||||||
|
* Ziehe einen weiteren **HTTP Request Node** an den Cron-Node.
|
||||||
|
* URL:
|
||||||
|
|
||||||
2. **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
|
https://api.twitch.tv/helix/videos?user_id=<DEINE_TWITCH_USER_ID>&type=archive&first=1
|
||||||
```
|
```
|
||||||
- Auth: OAuth2 Credential
|
* Auth: OAuth2 Credential
|
||||||
- Header: `Client-Id: <DEINE_CLIENT_ID>`
|
* Header: `Client-Id: <DEINE_CLIENT_ID>`
|
||||||
- Ergebnis: In `data[0]` stehen `id`, `title`, `url`, `created_at`, `published_at`.
|
* Ergebnis: In `data[0]` stehen `id`, `title`, `url`, `created_at`, `published_at`.
|
||||||
|
|
||||||
Referenz: [Get Videos](https://dev.twitch.tv/docs/api/reference#get-videos)
|
Referenz: [Get Videos](https://dev.twitch.tv/docs/api/reference#get-videos)
|
||||||
|
|
||||||
3. **Clips abrufen (optional):**
|
3. **IF „Neu?“ Node hinzufügen:**
|
||||||
- Ziehe einen weiteren **HTTP Request Node** an.
|
|
||||||
- URL:
|
* Bedingung (Expression):
|
||||||
|
|
||||||
```
|
```
|
||||||
https://api.twitch.tv/helix/clips?broadcaster_id=<DEINE_TWITCH_USER_ID>&started_at=<created_at>&ended_at=<published_at>
|
{{$json.data[0].id !== $workflow.staticData.global.last_vod_id}}
|
||||||
```
|
```
|
||||||
- Ergebnis: Liste mit Clips, die im Zeitraum des VOD erstellt wurden.
|
|
||||||
|
|
||||||
Referenz: [Get Clips](https://dev.twitch.tv/docs/api/reference#get-clips)
|
* 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.
|
||||||
|
|
||||||
|
4. **VOD herunterladen (SSH Execute Command im Clipper-LXC):**
|
||||||
|
|
||||||
|
* Node: **SSH Execute Command** (Credential: *Clipper*)
|
||||||
|
|
||||||
|
* Command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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-archive` verhindert doppelte Downloads. Retries sichern HLS-Streams ab. Alles passiert auf Clipper, aber **gesteuert durch n8n**.
|
||||||
|
|
||||||
|
5. **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):
|
||||||
|
|
||||||
4. **VOD herunterladen (Terminal im Clipper‑LXC):**
|
|
||||||
Jetzt wechselst du ins **Terminal des Clipper‑LXC**. Stelle sicher, dass `yt-dlp` installiert ist (`apt install -y yt-dlp`). n8n ruft per SSH folgenden Befehl auf:
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p "/srv/clipper/inbox/{{ $json.data[0].id }}"
|
CID="{{ $json.id }}"
|
||||||
yt-dlp -o "/srv/clipper/inbox/{{ $json.data[0].id }}/%(title)s.%(ext)s" {{ $json.data[0].url }}
|
CURL="{{ $json.url }}"
|
||||||
```
|
DIR="/srv/clipper/inbox/$CID"
|
||||||
Damit entsteht ein Unterordner `/srv/clipper/inbox/<VOD-ID>/` mit dem Video.
|
|
||||||
|
|
||||||
> **Entscheidung & Begründung – Warum lädt *Clipper* (und nicht *n8n*)?**
|
mkdir -p "$DIR"
|
||||||
> VODs kommen als **HLS‑Streams** (m3u8, segmentiert, signiert). Ein robuster Download braucht **yt‑dlp/ffmpeg** mit Retry/Resume und I/O‑Puffer. Das ist CPU/IO‑lastig 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 Clipper‑LXC, optional):**
|
yt-dlp \
|
||||||
Für jeden Clip‑URL ruft n8n per SSH `yt-dlp` auf:
|
--download-archive "/srv/clipper/logs/yt-dlp.archive" \
|
||||||
```bash
|
--no-part --restrict-filenames \
|
||||||
yt-dlp -o "/srv/clipper/inbox/<CLIP_ID>/%(title)s.%(ext)s" https://clips.twitch.tv/<CLIP_ID>
|
--retries 10 --fragment-retries 10 --retry-sleep 5 \
|
||||||
|
-o "$DIR/%(title)s-%(id)s.%(ext)s" \
|
||||||
|
"$CURL"
|
||||||
```
|
```
|
||||||
|
|
||||||
6. **Upload nach Nextcloud (n8n‑Weboberfläche):**
|
6. **Upload nach Nextcloud (n8n‑Weboberfläche):**
|
||||||
- Ziehe einen **HTTP Request Node** auf die Arbeitsfläche.
|
|
||||||
- Methode: **PUT**
|
* Node: **HTTP Request**
|
||||||
- Auth: **Basic Auth** (Benutzername + App‑Passwort aus Schritt 1)
|
|
||||||
- URL:
|
* 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>
|
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>/…`.
|
|
||||||
|
* Ergebnis: In Nextcloud liegt danach ein Ordner `Clips/<VOD-ID>/…`.
|
||||||
|
|
||||||
> **Entscheidung & Begründung – Warum Nextcloud?**
|
> **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.
|
> 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 Clipper‑LXC):**
|
7. **Analyse starten (SSH Execute Command):**
|
||||||
Zum Abschluss ruft n8n per SSH das Skript `clipper-analyze` auf:
|
|
||||||
```bash
|
* Command:
|
||||||
/srv/clipper/bin/clipper-analyze \
|
|
||||||
"/srv/clipper/inbox/{{ $json.data[0].id }}/{{ $json.data[0].title }}.mp4" \
|
```bash
|
||||||
"vod-{{ $json.data[0].id }}"
|
VIDDIR="/srv/clipper/inbox/{{ $json.data[0].id }}"
|
||||||
```
|
MAINFILE="$(find "$VIDDIR" -maxdepth 1 -type f -name '*.mp4' -o -name '*.mkv' | head -n1)"
|
||||||
Das Skript erzeugt im Clipper‑Temp‑Ordner eine `candidates.json`. Mit dieser arbeiten wir in Abschnitt 4 weiter.
|
/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.
|
||||||
|
|
||||||
|
8. **State aktualisieren (n8n‑Weboberfläche):**
|
||||||
|
|
||||||
|
* Node: **Function** oder **Set**
|
||||||
|
|
||||||
|
```js
|
||||||
|
$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)
|
### Alternative: Twitch‑Community‑Node (n8n‑Weboberfläche)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user