Kapitel 13/Tutorial.md aktualisiert
This commit is contained in:
@@ -451,82 +451,96 @@ In diesem Schritt erstellen wir den eigentlichen Workflow in **n8n**. Er sorgt d
|
|||||||
```
|
```
|
||||||
Nun befüllst du sie mit:
|
Nun befüllst du sie mit:
|
||||||
```bash
|
```bash
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
. /etc/clipper/clipper.env
|
. /etc/clipper/clipper.env
|
||||||
|
|
||||||
ID="${1:?need VOD id}"
|
ID="${1:?need VOD id}"
|
||||||
URL="${2:-https://www.twitch.tv/videos/${ID}}"
|
URL="${2:-https://www.twitch.tv/videos/${ID}}"
|
||||||
|
|
||||||
TMP="${CLIPPER_TMP}"
|
TMP="${CLIPPER_TMP}"
|
||||||
OUT_BASE="${CLIPPER_OUT}/${ID}"
|
OUT_BASE="${CLIPPER_OUT}/${ID}"
|
||||||
LOGDIR="${CLIPPER_LOG}/${ID}"
|
LOGDIR="${CLIPPER_LOG}/${ID}"
|
||||||
CONF="/home/clipper/.config/rclone/rclone.conf"
|
CONF="/home/clipper/.config/rclone/rclone.conf"
|
||||||
|
|
||||||
DST="${CLIPPER_NC_REMOTE}/VODs/${ID}/"
|
DST="${CLIPPER_NC_REMOTE}/VODs/${ID}/"
|
||||||
|
|
||||||
OUT="$TMP/${ID}.%(ext)s"
|
OUT="$TMP/${ID}.%(ext)s"
|
||||||
FILE="$TMP/${ID}.mp4"
|
FILE="$TMP/${ID}.mp4"
|
||||||
TEMP="$TMP/${ID}.temp.mp4"
|
TEMP="$TMP/${ID}.temp.mp4"
|
||||||
PART="$TMP/${ID}.mp4.part"
|
PART="$TMP/${ID}.mp4.part"
|
||||||
LOCK="$TMP/${ID}.lock"
|
LOCK="$TMP/${ID}.lock"
|
||||||
|
|
||||||
mkdir -p "$TMP" "$LOGDIR"
|
mkdir -p "$TMP" "$LOGDIR" "$OUT_BASE"
|
||||||
LOG="$LOGDIR/download.log"
|
LOG="$LOGDIR/download.log"
|
||||||
log(){ echo "[$(date '+%F %T')] $*"; }
|
log(){ echo "[$(date '+%F %T')] $*"; }
|
||||||
exec > >(tee -a "$LOG") 2>&1
|
exec > >(tee -a "$LOG") 2>&1
|
||||||
|
|
||||||
log "=== Start VOD $ID ==="
|
# ---- atomarer Lock (kein Race zwischen zwei Starts)
|
||||||
log "URL: $URL"
|
exec 9>"$LOCK"
|
||||||
log "DST: $DST"
|
if ! flock -n 9; then
|
||||||
|
log "LOCK: $ID wird bereits verarbeitet"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
trap 'flock -u 9; rm -f "$LOCK"' EXIT
|
||||||
|
|
||||||
if rclone lsf "$DST" --config "$CONF" >/dev/null 2>&1; then
|
log "=== Start VOD $ID ==="
|
||||||
log "SKIP: $ID bereits in Nextcloud"
|
log "URL: $URL"
|
||||||
exit 0
|
log "DST: $DST"
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -e "$LOCK" ]]; then
|
# ---- Prüfe, ob die ZIELDATEI bereits existiert (nicht nur der Ordner)
|
||||||
log "LOCK: $ID wird bereits verarbeitet"
|
if rclone lsf "$DST" --config "$CONF" | grep -qx "${ID}.mp4"; then
|
||||||
exit 0
|
log "SKIP: $ID.mp4 bereits in Nextcloud"
|
||||||
fi
|
exit 0
|
||||||
trap 'rm -f "$LOCK"' EXIT
|
fi
|
||||||
: > "$LOCK"
|
|
||||||
|
|
||||||
# Resume
|
# ---- Resume: unvollständigen Download sauber fortsetzen
|
||||||
if [[ -s "$TEMP" && ! -s "$FILE" ]]; then
|
if [[ -s "$TEMP" && ! -s "$FILE" ]]; then
|
||||||
log "RESUME: $TEMP -> $FILE"
|
log "RESUME: $TEMP -> $FILE"
|
||||||
mv -f "$TEMP" "$FILE"
|
mv -f "$TEMP" "$FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -s "$FILE" ]]; then
|
# ---- Gemeinsame rclone-Flags: Nextcloud-Chunking + robuste Timeouts
|
||||||
log "MOVE (resume): $FILE → $DST"
|
export RCLONE_WEBDAV_CHUNK_SIZE=100Mi # wirkt bei neueren rclone Versionen
|
||||||
rclone move "$FILE" "$DST" --config "$CONF" --create-empty-src-dirs -v
|
|
||||||
rm -f "$PART" "$TEMP" || true
|
|
||||||
log "CLEANUP: $TMP"
|
|
||||||
rm -rf "${TMP:?}/"*
|
|
||||||
log "=== Done VOD $ID (resume path) ==="
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Download + Remux
|
rclone move "$FILE" "$DST" \
|
||||||
yt-dlp -q --no-progress --retries 20 --fragment-retries 50 --retry-sleep 5 \
|
--config "$CONF" --create-empty-src-dirs \
|
||||||
--socket-timeout 30 --hls-prefer-ffmpeg --remux-video mp4 -o "$OUT" "$URL"
|
--transfers 1 --checkers 4 \
|
||||||
|
--retries 10 --low-level-retries 50 --retries-sleep 30s \
|
||||||
|
--timeout 1h --contimeout 1m --expect-continue-timeout 10m \
|
||||||
|
-v
|
||||||
|
|
||||||
[[ -s "$FILE" ]] || { [[ -s "$TEMP" ]] && mv -f "$TEMP" "$FILE"; }
|
# ---- Wenn Datei schon da: nur noch hochschieben
|
||||||
|
if [[ -s "$FILE" ]]; then
|
||||||
|
log "MOVE (resume): $FILE → $DST"
|
||||||
|
rclone move "$FILE" "$DST" "${RCLONE_FLAGS[@]}"
|
||||||
|
rm -f "$PART" "$TEMP" || true
|
||||||
|
log "CLEANUP: $TMP"
|
||||||
|
rm -rf "${TMP:?}/"*
|
||||||
|
log "=== Done VOD $ID (resume path) ==="
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -s "$FILE" ]]; then
|
# ---- Download + Remux
|
||||||
log "ERROR: Download fehlgeschlagen ($FILE fehlt/leer)"
|
yt-dlp -q --no-progress --retries 20 --fragment-retries 50 --retry-sleep 5 \
|
||||||
exit 2
|
--socket-timeout 30 --hls-prefer-ffmpeg --remux-video mp4 -o "$OUT" "$URL"
|
||||||
fi
|
|
||||||
|
|
||||||
log "MOVE: $FILE → $DST"
|
[[ -s "$FILE" ]] || { [[ -s "$TEMP" ]] && mv -f "$TEMP" "$FILE"; }
|
||||||
rclone move "$FILE" "$DST" --config "$CONF" --create-empty-src-dirs -v
|
|
||||||
rm -f "$PART" "$TEMP" || true
|
|
||||||
|
|
||||||
log "CLEANUP: $TMP"
|
if [[ ! -s "$FILE" ]]; then
|
||||||
rm -rf "${TMP:?}/"*
|
log "ERROR: Download fehlgeschlagen ($FILE fehlt/leer)"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
log "=== Done VOD $ID ==="
|
log "MOVE: $FILE → $DST"
|
||||||
|
rclone move "$FILE" "$DST" "${RCLONE_FLAGS[@]}"
|
||||||
|
rm -f "$PART" "$TEMP" || true
|
||||||
|
|
||||||
|
log "CLEANUP: $TMP"
|
||||||
|
rm -rf "${TMP:?}/"*
|
||||||
|
|
||||||
|
log "=== Done VOD $ID ==="
|
||||||
|
"
|
||||||
```
|
```
|
||||||
Mit diesem Skript laden wir die aktuellen VODs herunter, laden sie in die Nextcloud für die weitere Verabeitung und räumen wieder auf. Zusätzlich erzeugen wir logs in `<clipper-ordner>/logs/<ID>.log`.
|
Mit diesem Skript laden wir die aktuellen VODs herunter, laden sie in die Nextcloud für die weitere Verabeitung und räumen wieder auf. Zusätzlich erzeugen wir logs in `<clipper-ordner>/logs/<ID>.log`.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user