From aea26493db8b82394ce7d19f49b3c919bb1e1714 Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Sun, 26 Jul 2026 12:58:23 +0200 Subject: [PATCH] feat(installer): der Windows-Installer holt die Freigabe jetzt selbst von Rippy DER BLOCKER aus dem SAVEPOINT v3.16 ist zu. Beide Installer (Kommandozeile und GUI) fragen GET /worker-setup/pfad-map, pruefen mit Test-Path, ob DIESER PC die Freigabe wirklich erreicht, und schreiben `set RIPPY_PATH_MAP=...` in start-tray.bat und start-worker.bat. Der Commander muss dafuer nichts ueber Container-Pfade wissen - das Feld bleibt leer, der Installer holt den Wert. Von Hand geht es trotzdem (Knopf "Von Rippy holen" bzw. -PfadMap), falls dieser PC die Freigabe anders erreicht. Ist nichts erreichbar, steht das als Klartext im Log samt dem haeufigsten Grund (fehlende Zugangsdaten - Freigabe einmal im Explorer oeffnen). Die Installation laeuft weiter: ein Worker, der sich meldet und ehrlich scheitert, ist besser als einer, der nicht existiert. Ein LEERES RIPPY_PATH_MAP wird bewusst nicht gesetzt - pfad_lokal() liest das als "kein Mapping", und die Fehlermeldung im Worker unterscheidet genau diese beiden Faelle. GUI: neues Feld samt Knopf, Fenster 560->648 px. Layout headless gerendert und angesehen (nichts ueberlappt, Umlaute korrekt), beide Dateien mit echtem PowerShell 5.1 auf Parser-Fehler geprueft, UTF-8-BOM erhalten. .exe neu gebaut. install.ps1 hatte durch ein Werkzeug LF statt CRLF bekommen - zurueckgedreht. remote-transcode-worker.yml richtiggestellt: Dort stand "mount -t nfs :/srv/rippy" - das geht NICHT, auf der Rippy-Maschine laeuft kein NFS- und kein Samba-Server, sie ist selbst nur Client der NAS. Der Weg, der funktioniert: dieselbe Freigabe einhaengen, die auch Rippy nutzt. Co-Authored-By: Claude Opus 5 --- deploy/remote-transcode-worker.yml | 48 +++++-- deploy/worker-windows/RippyWorkerSetup.exe | Bin 60416 -> 66048 bytes deploy/worker-windows/install-gui.ps1 | 150 +++++++++++++++++++-- deploy/worker-windows/install.ps1 | 64 +++++++-- 4 files changed, 229 insertions(+), 33 deletions(-) diff --git a/deploy/remote-transcode-worker.yml b/deploy/remote-transcode-worker.yml index 74ec4b0..090c19e 100644 --- a/deploy/remote-transcode-worker.yml +++ b/deploy/remote-transcode-worker.yml @@ -1,17 +1,36 @@ -# Optionaler Remote-Transcode-Worker — für eine GPU-Maschine im Netz. -# (EXPERIMENTELL, 23.07.2026: VAAPI/NVENC-Presets folgen; aktuell nutzt der -# Worker dieselben HandBrake-CPU-Presets, bringt also v.a. stärkere CPUs.) +# Optionaler Remote-Transcode-Worker — für eine GPU-Maschine im Netz (Linux). +# Für Windows gibt es den nativen Weg: RippyWorkerSetup.exe (Einstellungen → Worker). +# +# ══ DAS ENTSCHEIDENDE: der Worker muss die Dateien SEHEN ══════════════════════ +# Rippy schickt ihm Pfade wie /app/media/rippy//title_t00.mkv — Pfade +# INNERHALB des Rippy-Containers. Dieser Container muss dieselben Daten unter +# GENAU DEMSELBEN Pfad haben, sonst nimmt er die Aufgabe an und lehnt sie +# Millisekunden später ab („Keine Roh-MKVs gefunden" — genau so passiert am +# 26.07.2026, Job 95afdc89). +# +# Richtigstellung 26.07.2026: Hier stand vorher „mount -t nfs +# :/srv/rippy /mnt/rippy". Das geht NICHT — auf der Rippy-Maschine +# läuft kein NFS- und kein Samba-Server, sie ist selbst nur Client der NAS. +# Der Weg, der funktioniert: DIESELBE Freigabe einhängen, die auch Rippy nutzt. # # Auf der GPU-Maschine: # 1. Dieses Repo klonen (oder nur dieses File + Zugriff aufs Registry-Image) -# 2. Rohdaten-Freigabe der Rippy-Maschine mounten, z. B.: -# mount -t nfs :/srv/rippy /mnt/rippy -# (die Rippy-VM muss /srv/rippy + das temp-Volume exportieren) -# 3. RIPPY_HOST unten setzen und starten: -# docker compose -f deploy/remote-transcode-worker.yml up -d --build +# 2. Die Freigabe einhängen, die Rippy als Arbeitsverzeichnis UND Ablage +# benutzt (Einstellungen → Ripping). Heißt sie in Rippy „rippy", liegt +# sie dort unter /app/media/rippy — also z. B.: +# mount -t cifs //NAS/rippy /mnt/rippy-freigabe -o guest,iocharset=utf8 +# 3. Unten RIPPY_HOST setzen, den Freigabe-Pfad im volumes-Block anpassen +# und starten: +# RIPPY_HOST=192.168.178.162 docker compose \ +# -f deploy/remote-transcode-worker.yml up -d --build +# +# Passt der Pfad im Container nicht (weil die Freigabe woanders hängt), gibt es +# als Ausweg RIPPY_PATH_MAP — dieselbe Übersetzung, die der Windows-Worker +# nutzt, Format: /app/media/rippy=/mnt/anderer-pfad (Paare per „;"). +# Den fertigen Wert nennt GET /worker-setup/pfad-map. # # Der Worker meldet seine Encoder-Fähigkeiten automatisch — er taucht danach -# unter Einstellungen → Verarbeitung auf. Er bedient NUR die transcode-Queue; +# unter Einstellungen → Worker auf. Er bedient NUR die transcode-Queue; # gerippt wird weiterhin dort, wo das Laufwerk hängt. services: @@ -30,10 +49,15 @@ services: - WORKER_NAME=${WORKER_NAME:-transcode-worker} # Serien-Episoden-Matching fragt die Rippy-API nach Laufzeiten - API_URL=http://${RIPPY_HOST}:8000 + # Nur nötig, wenn die Freigabe hier NICHT unter demselben Pfad liegt wie + # in Rippy. Fertigen Wert holen: curl http://${RIPPY_HOST}/api/worker-setup/pfad-map + - RIPPY_PATH_MAP=${RIPPY_PATH_MAP:-} volumes: - # Freigabe der Rippy-Maschine (siehe Kopf-Kommentar) - - /mnt/rippy/media:/app/media - - /mnt/rippy/temp:/app/temp + # LINKS der Pfad auf DIESER Maschine, RECHTS der Pfad, den Rippy nennt. + # Rechts muss stehen, was in Rippy als Speicherziel heißt: ein Ziel + # namens „rippy" ist dort /app/media/rippy. Prüfen mit + # curl http:///api/worker-setup/pfad-map + - /mnt/rippy-freigabe:/app/media/rippy devices: # GPU für Hardware-Encoding (AMD/Intel: /dev/dri; NVIDIA: nvidia-runtime) - /dev/dri:/dev/dri diff --git a/deploy/worker-windows/RippyWorkerSetup.exe b/deploy/worker-windows/RippyWorkerSetup.exe index 47a92484aab79d8073dc692b09671de1d05a88fc..1be880a24d704d1c0bcdd6f5bfa50c9d8fa41ad3 100644 GIT binary patch delta 4577 zcmai2TWl298J=Bp2?iW+!7enI!+I0e;9YxdV-}}07;Li+*lcWrF@(Zd@7dj9=dzhO zgTcsJQdMfz2UI$bZKXc+q3T6dv~Bv*N>Qq)4{4I#l;#bR_8~%5+q|?7mC}CaoSF5m zsoIsTnK^UjzkdJs|1-qABtP} z|H%JZq<0%OY0u#5&;IL?gYDR2ls zAFa(YzPiGkN^;6!dWq&4DSFHy1)Y&OyIi20StKzxoy#p<&y6o+ug{F<`gXSW;*U&> z&l6^Gce%{;0^|L}&Wq<f)b}$ z(X$Ft=Jaay4uNoexx$HFHc75X3yiG5vH@DH4w$T<(*Z|p8~FT9 zJO2fe6vEW5>Dk%Ix$OA))1<&$B`bNxwm8)-=C~d7k>zW+LIgakM5tFJ47W)b z2_enZS(%4k<<5|T?Qml0%VqBN<7k@lCK>mNGIrD=!V!a&EiRrV>C6x@T`8$b8AnWL zK1C*Qob~uBb85u34TBUA8!46Cf5gyZHuFI@25@jk?2~nYe#AQa_MQnAe#LARe zB`(!hn5ESB!+VFEv+Qb-lx;(rl-k)IH}b{|t&)>u*8l0mkr|w)7T9f$h1ipLFm)(~ zJ?n6gqJsQL3;M=l4XJ*5a&YHRCIgfNdi>wy4*M6f9c|F#(`@=_9B~)-`E4%N#!vS8 z_g`w?5?l%a!-G;lumSJsWYg6fJ~}xxttn?DxIWE?6g|K zKA91LysGodpBGiW78#(b5RzI?kJ5+`cMcCXAV9G(79%StzyMDbVR}o^ib75lzj zf8%=dGfB(lq_F|HuYx4SgAFy|?qH#I)#VQMT-*52&UTn0GC1j=MS}Us#PsC+Y(JPmt;qyhnII`ZY9Ai5mchyogph&r#4K zPC?_4eHI;rH>Wixi)cNu>yE1M#X%Wtf`ZxO99z|5(RP?fOd?*T)FIH9h?_MPB9e5g z1{go~e5@}3hXRC5gxoJeYf=sYv6C?o(q%MO-SSu%QSm^0Rc8j&20B8iCu5+@zN_hL z$`Y|t2wq_BKAy}`UM9)&sDFnV@nRvW5JAEd*fN0A^Vs{`cfSj-ewnRjfV2qF%Ad*WM zBUzTGW~VD&iCQIB&QD_vnAGHufCQV=ASmL=+f@U(aGLZ7LTy$o3aS&Fet6t6nNeVB z7;~!vgv_xH6Ka(ydOfx-ci*pXb!!$@vPHhcj?4(Cp|K z4^cJD0n7nv5q|OORpry#LYm03!IdQk;c;u2t5#)4k=)rVr)Atk&jf|80PuO;1rM1` z^QPn|$)Jp!Htb~#uT2KUgQ}8MBu5t6rBe$SWfOgu*EPx-*;s#mLNTtFwhQ@?y z;8JsEAaO@@g>{eorMufVOYZdTyL-EX(JLHMLMeXFT6eACn($2a@)mDG&EgnMdI@TuZdFVn>`8z>!&=gAqcfOu08EweeH2PcfifH|z>E5`6@0O=4nhA~UKdp=SslL^hfQsn#h1EA28H zFP#?phg%EYN@0veJ(Wq47cZ)4x|D&&SdyEiXKniuPDSKiwkIbQ$fD_`p9fU~LbLgD%u za9Jhce`WEA|A)m+{})SVcdg=;98tm`Au&n(zfA1+M=tO6U%Ap#Gyhi&D{orb))O_n z9@Kzrf)4>Lb==fZT8pbI7%EX+sH>o)*ZS(+_s&M@H(veWnO!?heCt<#{P+9ke)Rso zBESFZ_g}9+^VZ8xb$%Rt&=4OrJ{9NW!J)1;eCF_f@XoSN9>3vty!)qgJfiLE5?jRwe`ISU1=Emx=_a5%w26;QMvMXKR{rGQ@2ZLMx16}2U$N&HU delta 483 zcmZo@VQIL*JfXwOLnbwg0SX>4Ffnp7ax*ZT0Sd@L1kb$&(h49pBM>`4*h~xzEFd8u zfYA&N6EErURRC27gT)ycUPw<=6lPIiWZ;>s_}FA}B%?almD4~u1t2~%xrU544#ygEt%L9pYj(H8a@!-QtE2lcmAti{3emOhzV??R_nn3=B3``t~tRjt}3> zYy^~(jbLZwG&0iU@_*usJ4jE+eyvh1upmQQIMmZ82vUH(R6%2u)6@ z)|)I``)RX4T_NLSfjY^}OY66>GMa6UX>H=$oIcf&k&$8Z@@Z?G1tcYImN4B-aoZjt zmvB{Plho#vTQMB`3!okXd1~KlhRNq2NpizH2^5 - +# Pfade INNERHALB des Rippy-Containers. Ohne Uebersetzung auf eine Freigabe +# sieht dieser PC dort nichts, nimmt die Aufgabe an und lehnt sie 182 ms +# spaeter ab. Der Nutzer soll das nicht verstehen muessen: Rippy hat die +# Freigabe selbst eingehaengt und kennt sie, der Knopf holt sie. +$lblMap = New-Object System.Windows.Forms.Label +$lblMap.Text = "Netzwerk-Freigabe mit den Rohdaten (holt Rippy selbst):" +$lblMap.Location = New-Object System.Drawing.Point(24, 288) +$lblMap.Size = New-Object System.Drawing.Size(500, 18) +$lblMap.ForeColor = $cGedaempft +$form.Controls.Add($lblMap) + +$txtMap = New-Object System.Windows.Forms.TextBox +$txtMap.Location = New-Object System.Drawing.Point(24, 308) +$txtMap.Size = New-Object System.Drawing.Size(374, 26) +$txtMap.Font = New-Object System.Drawing.Font("Consolas", 9) +$txtMap.BackColor = $cFeld +$txtMap.ForeColor = $cText +$txtMap.BorderStyle = "FixedSingle" +$form.Controls.Add($txtMap) + +$btnMap = New-Object System.Windows.Forms.Button +$btnMap.Text = "Von Rippy holen" +$btnMap.Location = New-Object System.Drawing.Point(408, 307) +$btnMap.Size = New-Object System.Drawing.Size(116, 28) +$btnMap.FlatStyle = "Flat" +$btnMap.BackColor = $cFeld +$btnMap.ForeColor = $cText +$btnMap.FlatAppearance.BorderColor = $cGedaempft +$form.Controls.Add($btnMap) + +$lblMapHilfe = New-Object System.Windows.Forms.Label +$lblMapHilfe.Text = "Leer lassen und installieren - der Installer holt und prüft den Wert selbst." +$lblMapHilfe.Location = New-Object System.Drawing.Point(24, 338) +$lblMapHilfe.Size = New-Object System.Drawing.Size(500, 18) +$lblMapHilfe.ForeColor = $cGedaempft +$form.Controls.Add($lblMapHilfe) + # Autostart $chkAuto = New-Object System.Windows.Forms.CheckBox $chkAuto.Text = "Beim Anmelden automatisch starten (Tray-Symbol)" -$chkAuto.Location = New-Object System.Drawing.Point(24, 290) +$chkAuto.Location = New-Object System.Drawing.Point(24, 364) $chkAuto.Size = New-Object System.Drawing.Size(400, 22) $chkAuto.Checked = $true $chkAuto.ForeColor = $cText @@ -191,8 +232,8 @@ $form.Controls.Add($chkAuto) # Log-Bereich $log = New-Object System.Windows.Forms.TextBox -$log.Location = New-Object System.Drawing.Point(24, 322) -$log.Size = New-Object System.Drawing.Size(500, 150) +$log.Location = New-Object System.Drawing.Point(24, 396) +$log.Size = New-Object System.Drawing.Size(500, 174) $log.Multiline = $true $log.ReadOnly = $true $log.ScrollBars = "Vertical" @@ -205,7 +246,7 @@ $form.Controls.Add($log) # Knöpfe $btnInstall = New-Object System.Windows.Forms.Button $btnInstall.Text = "Installieren" -$btnInstall.Location = New-Object System.Drawing.Point(24, 486) +$btnInstall.Location = New-Object System.Drawing.Point(24, 584) $btnInstall.Size = New-Object System.Drawing.Size(150, 40) $btnInstall.BackColor = $cAmber $btnInstall.ForeColor = $cBg @@ -215,7 +256,7 @@ $form.Controls.Add($btnInstall) $btnStart = New-Object System.Windows.Forms.Button $btnStart.Text = "Worker starten" -$btnStart.Location = New-Object System.Drawing.Point(190, 486) +$btnStart.Location = New-Object System.Drawing.Point(190, 584) $btnStart.Size = New-Object System.Drawing.Size(150, 40) $btnStart.BackColor = $cEmerald $btnStart.ForeColor = [System.Drawing.Color]::White @@ -229,6 +270,46 @@ function Log($text) { [System.Windows.Forms.Application]::DoEvents() } +# --- RIPPY_PATH_MAP: holen und wirklich pruefen ----------------------------- +# Rippy leitet den Wert aus seinen eigenen eingehaengten Freigaben ab +# (GET /worker-setup/pfad-map) - hier wird nichts geraten. Der Rueckgabewert +# ist der fertige Wert fuer die .bat-Dateien, oder "" wenn Rippy keine +# Freigabe hat (dann kann dieser Worker nichts komprimieren, und das muss +# im Log stehen statt still zu passieren). +function Hole-PfadMap($rippyHost) { + try { + $antwort = Invoke-RestMethod "http://$rippyHost/api/worker-setup/pfad-map" -TimeoutSec 15 + } catch { + Log "HINWEIS: Rippy nach der Freigabe zu fragen schlug fehl ($($_.Exception.Message))." + return "" + } + if ($antwort.hinweis) { Log $antwort.hinweis } + if (-not $antwort.mapping) { return "" } + return [string]$antwort.mapping +} + +# Erreicht DIESER PC die Freigaben wirklich? Ohne diese Probe merkt der Nutzer +# den Fehler erst, wenn ein Job Stunden spaeter scheitert. +function Pruefe-PfadMap($mapping) { + $alleDa = $true + foreach ($paar in ($mapping -split ";")) { + if ($paar -notmatch "=") { continue } + $ziel = ($paar -split "=", 2)[1] + if (Test-Path -LiteralPath $ziel -ErrorAction SilentlyContinue) { + Log " OK: $ziel ist von hier erreichbar." + } else { + $alleDa = $false + Log " NICHT erreichbar: $ziel" + } + } + if (-not $alleDa) { + Log " Meist fehlen nur die Zugangsdaten: die Freigabe einmal im Explorer" + Log " oeffnen und 'Anmeldedaten speichern' anhaken, dann erreicht der" + Log " Worker sie auch. Die Installation laeuft trotzdem durch." + } + return $alleDa +} + # --- Installations-Logik --------------------------------------------------- function Do-Install { $rHost = $txtHost.Text.Trim() @@ -322,11 +403,40 @@ function Do-Install { } Log "HandBrake bereit." - # 5. Start-Skripte + Deinstaller erzeugen - $trayBat = "@echo off`r`ncd /d `"%~dp0`"`r`nset REDIS_URL=redis://${rHost}:6379/0`r`nset DATABASE_URL=postgresql://rippy:rippy@${rHost}:5432/rippy`r`nset API_URL=http://${rHost}:8000`r`nset WORKER_NAME=$wName`r`nset RIPPY_TRAY_HOST=$rHost`r`nset PATH=%~dp0;%PATH%`r`nstart `"`" venv\Scripts\pythonw.exe tray.py" + # 5. Netzwerk-Freigabe klaeren, BEVOR die Start-Skripte geschrieben werden. + # Ohne RIPPY_PATH_MAP kann dieser Worker grundsaetzlich nicht + # komprimieren - das war bis zum 26.07.2026 der stille Blocker. + $mapping = $txtMap.Text.Trim() + if ($mapping) { + Log "Freigabe (von Hand eingetragen): $mapping" + } else { + Log "Frage Rippy, ueber welche Freigabe die Rohdaten erreichbar sind ..." + $mapping = Hole-PfadMap $rHost + if ($mapping) { + $txtMap.Text = $mapping + Log "Freigabe von Rippy: $mapping" + } + } + if ($mapping) { + Log "Pruefe Erreichbarkeit ..." + [void](Pruefe-PfadMap $mapping) + } else { + Log "ACHTUNG: Ohne Freigabe kann dieser Worker NICHTS komprimieren." + Log " Der Worker wird trotzdem installiert und meldet sich in" + Log " Rippy - Jobs schlagen aber mit einer Klartext-Meldung fehl." + } + + # 6. Start-Skripte + Deinstaller erzeugen + # RIPPY_PATH_MAP nur setzen, wenn es einen Wert gibt - eine leere + # Zuweisung in einer .bat ist harmlos, aber ein gesetztes leeres + # RIPPY_PATH_MAP liest pfad_lokal() als "kein Mapping", und die + # Fehlermeldung im Worker unterscheidet genau diese beiden Faelle. + $mapZeile = if ($mapping) { "set RIPPY_PATH_MAP=$mapping`r`n" } else { "" } + + $trayBat = "@echo off`r`ncd /d `"%~dp0`"`r`nset REDIS_URL=redis://${rHost}:6379/0`r`nset DATABASE_URL=postgresql://rippy:rippy@${rHost}:5432/rippy`r`nset API_URL=http://${rHost}:8000`r`nset WORKER_NAME=$wName`r`nset RIPPY_TRAY_HOST=$rHost`r`n${mapZeile}set PATH=%~dp0;%PATH%`r`nstart `"`" venv\Scripts\pythonw.exe tray.py" Set-Content -Path "start-tray.bat" -Value $trayBat -Encoding ASCII - $workBat = "@echo off`r`ncd /d `"%~dp0`"`r`nset REDIS_URL=redis://${rHost}:6379/0`r`nset DATABASE_URL=postgresql://rippy:rippy@${rHost}:5432/rippy`r`nset API_URL=http://${rHost}:8000`r`nset WORKER_NAME=$wName`r`nset PATH=%~dp0;%PATH%`r`nvenv\Scripts\celery.exe -A celery_app worker --loglevel=info -Q transcode --pool=solo -n ${wName}@%%h" + $workBat = "@echo off`r`ncd /d `"%~dp0`"`r`nset REDIS_URL=redis://${rHost}:6379/0`r`nset DATABASE_URL=postgresql://rippy:rippy@${rHost}:5432/rippy`r`nset API_URL=http://${rHost}:8000`r`nset WORKER_NAME=$wName`r`n${mapZeile}set PATH=%~dp0;%PATH%`r`nvenv\Scripts\celery.exe -A celery_app worker --loglevel=info -Q transcode --pool=solo -n ${wName}@%%h" Set-Content -Path "start-worker.bat" -Value $workBat -Encoding ASCII $uninstall = @" @@ -349,7 +459,7 @@ Remove-Item -Recurse -Force `$PSScriptRoot "@ Set-Content -Path "uninstall.ps1" -Value $uninstall -Encoding ASCII - # 6. Autostart über den Autostart-ORDNER, nicht über schtasks. + # 7. Autostart über den Autostart-ORDNER, nicht über schtasks. # # Befund 25.07.2026 (auf dem Commander-PC aufgetreten): schtasks /create # mit /tn "RippyWorker" legt die Aufgabe im WURZELORDNER der @@ -416,6 +526,20 @@ Remove-Item -Recurse -Force `$PSScriptRoot } } +$btnMap.Add_Click({ + $rHost = $txtHost.Text.Trim() + if (-not $rHost) { + [System.Windows.Forms.MessageBox]::Show( + "Bitte zuerst oben die LAN-IP der Rippy-Maschine eintragen.", "Fehlt") + return + } + $m = Hole-PfadMap $rHost + if ($m) { + $txtMap.Text = $m + Log "Freigabe von Rippy: $m" + [void](Pruefe-PfadMap $m) + } +}) $btnInstall.Add_Click({ Do-Install }) $btnStart.Add_Click({ Start-Process -FilePath (Join-Path $InstallDir "start-tray.bat") -WindowStyle Hidden diff --git a/deploy/worker-windows/install.ps1 b/deploy/worker-windows/install.ps1 index 69cc3d8..3565c5e 100644 --- a/deploy/worker-windows/install.ps1 +++ b/deploy/worker-windows/install.ps1 @@ -5,7 +5,9 @@ # 2. Lädt den Worker-Code direkt von deiner Rippy-Instanz (/api/worker-setup/paket) # 3. Lädt HandBrakeCLI (gepinnte Version, offizielles GitHub-Release), # falls nicht schon im PATH oder im Ordner vorhanden -# 4. Erzeugt start-worker.bat - Doppelklick startet den Worker +# 4. Fragt Rippy, über welche Netzwerk-Freigabe die Rohdaten erreichbar sind, +# und prüft, ob DIESER PC sie wirklich sieht (RIPPY_PATH_MAP) +# 5. Erzeugt start-worker.bat - Doppelklick startet den Worker # # Der Worker bedient NUR die Kompressions-Queue (transcode) - gerippt wird # weiterhin auf der Rippy-Hauptmaschine (dort hängt das Laufwerk). @@ -13,12 +15,18 @@ # Aufruf (PowerShell): # .\install.ps1 -RippyHost 192.168.178.162 [-WorkerName mein-pc] [-Autostart] # -# -Autostart registriert eine Aufgabe "RippyWorker" (Start bei Anmeldung). +# -Autostart legt eine Verknüpfung im Autostart-Ordner an (Start bei Anmeldung). param( [Parameter(Mandatory = $true)] [string]$RippyHost, [string]$WorkerName = $env:COMPUTERNAME.ToLower(), [switch]$Autostart, + # Übersetzung der Rippy-Container-Pfade auf Freigaben, die DIESER PC sieht. + # Leer lassen: dann holt der Installer den Wert von Rippy selbst + # (GET /worker-setup/pfad-map, abgeleitet aus dessen eigenen Mounts). + # Von Hand nur, wenn dieser PC die Freigabe anders erreicht, z. B. + # -PfadMap "/app/media/rippy=Z:\" + [string]$PfadMap = "", # Zielverzeichnis. Standard ist "Programme", wie bei jedem anderen Programm # (Commander-Wunsch 25.07.2026). Dorthin schreiben braucht Adminrechte - # PowerShell also "Als Administrator" starten, oder hier einen Ordner im @@ -108,7 +116,47 @@ if (-not (Test-Path ".\HandBrakeCLI.exe") -and -not $hb) { } Write-Host "HandBrakeCLI bereit." -# 5. Start-Skript erzeugen +# 5. Netzwerk-Freigabe klären (RIPPY_PATH_MAP) - der stille Blocker bis 26.07.2026 +# +# Rippy schickt dem Worker Pfade wie /app/media/rippy/. Das sind Pfade +# INNERHALB des Rippy-Containers; dieser PC sieht sie nur, wenn sie auf eine +# Netzwerk-Freigabe übersetzt werden. Ohne das nimmt der Worker die Aufgabe an +# und lehnt sie Millisekunden später ab ("Keine Roh-MKVs gefunden") - gemessen +# am Job 95afdc89. Geraten wird nichts: Rippy hat die Freigabe selbst +# eingehängt und kennt ihre Quelle. +if (-not $PfadMap) { + Write-Host "Frage Rippy, über welche Freigabe die Rohdaten erreichbar sind ..." + try { + $antwort = Invoke-RestMethod "http://$RippyHost/api/worker-setup/pfad-map" -TimeoutSec 15 + if ($antwort.hinweis) { Write-Host $antwort.hinweis -ForegroundColor Yellow } + if ($antwort.mapping) { $PfadMap = [string]$antwort.mapping } + } catch { + Write-Host "HINWEIS: Abfrage fehlgeschlagen ($($_.Exception.Message))." -ForegroundColor Yellow + } +} +if ($PfadMap) { + Write-Host "Freigabe: $PfadMap" + foreach ($paar in ($PfadMap -split ";")) { + if ($paar -notmatch "=") { continue } + $zielPfad = ($paar -split "=", 2)[1] + if (Test-Path -LiteralPath $zielPfad -ErrorAction SilentlyContinue) { + Write-Host " OK: $zielPfad ist von hier erreichbar." -ForegroundColor Green + } else { + Write-Host " NICHT erreichbar: $zielPfad" -ForegroundColor Yellow + Write-Host " Meist fehlen nur die Zugangsdaten: die Freigabe einmal im" -ForegroundColor Yellow + Write-Host " Explorer öffnen und 'Anmeldedaten speichern' anhaken." -ForegroundColor Yellow + } + } +} else { + Write-Host "ACHTUNG: Ohne Freigabe kann dieser Worker NICHTS komprimieren." -ForegroundColor Yellow + Write-Host " Er wird trotzdem installiert; Jobs schlagen dann mit einer" -ForegroundColor Yellow + Write-Host " Klartext-Meldung fehl statt still zu hängen." -ForegroundColor Yellow +} +# Leeres RIPPY_PATH_MAP nicht setzen: pfad_lokal() liest es als "kein Mapping", +# und die Fehlermeldung im Worker unterscheidet genau diese beiden Fälle. +$mapZeile = if ($PfadMap) { "set RIPPY_PATH_MAP=$PfadMap`r`n" } else { "" } + +# 6. Start-Skript erzeugen $bat = @" @echo off rem Rippy Windows-Transcode-Worker - verbindet sich mit $RippyHost @@ -117,12 +165,12 @@ set REDIS_URL=redis://${RippyHost}:6379/0 set DATABASE_URL=postgresql://rippy:rippy@${RippyHost}:5432/rippy set API_URL=http://${RippyHost}:8000 set WORKER_NAME=$WorkerName -set PATH=%~dp0;%PATH% +${mapZeile}set PATH=%~dp0;%PATH% venv\Scripts\celery.exe -A celery_app worker --loglevel=info -Q transcode --pool=solo -n ${WorkerName}@%%h "@ Set-Content -Path "start-worker.bat" -Value $bat -Encoding ASCII -# 6. Tray-Start (empfohlen): Symbol neben der Uhr, kein Konsolenfenster +# 7. Tray-Start (empfohlen): Symbol neben der Uhr, kein Konsolenfenster $trayBat = @" @echo off rem Rippy-Worker mit Tray-Symbol - verbindet sich mit $RippyHost @@ -132,13 +180,13 @@ set DATABASE_URL=postgresql://rippy:rippy@${RippyHost}:5432/rippy set API_URL=http://${RippyHost}:8000 set WORKER_NAME=$WorkerName set RIPPY_TRAY_HOST=$RippyHost -set PATH=%~dp0;%PATH% +${mapZeile}set PATH=%~dp0;%PATH% start "" venv\Scripts\pythonw.exe tray.py "@ Set-Content -Path "start-tray.bat" -Value $trayBat -Encoding ASCII Write-Host "start-worker.bat + start-tray.bat erzeugt." -# 7. Deinstaller - MUSS-Kriterium: rückstandsfrei entfernbar +# 8. Deinstaller - MUSS-Kriterium: rückstandsfrei entfernbar $uninstall = @" # Rippy-Worker DEINSTALLIEREN: stoppt Prozesse, entfernt Autostart, # meldet den Worker in Rippy ab und löscht diesen Ordner komplett. @@ -169,7 +217,7 @@ Write-Host "Rippy-Worker deinstalliert." -ForegroundColor Green Set-Content -Path "uninstall.ps1" -Value $uninstall -Encoding ASCII Write-Host "uninstall.ps1 erzeugt." -# 8. Optional: Autostart bei Anmeldung (mit Tray) +# 9. Optional: Autostart bei Anmeldung (mit Tray) # # Über den Autostart-ORDNER, nicht über schtasks: Eine Aufgabe im # Wurzelordner der Aufgabenplanung anzulegen verlangt Administratorrechte, und