FESTPLATTE: Kompakt-Installation (spart ca. 1-1,5 GB) + Cache-Aufräumen

Mac-Installer fragt jetzt nach dem Installationsumfang:
- VOLLSTÄNDIG: alle 21 Effekte, GStreamer belegt ca. 1,5-2,5 GB
- KOMPAKT: 15 Effekte, nur ca. 0,5-1 GB (verzichtet auf 6
  Effekte aus gst-plugins-bad/ugly: Blur/Schärfen, Solarize,
  Brennen, Dilate, Exclusion). Videowiedergabe (libav),
  Compositor und alle 15 restlichen Effekte voll nutzbar.
- Auswahl läuft über native macOS-Dialoge (osascript, 3 Buttons)
- Danach: Homebrew-Cache-Aufräumen anbieten (gibt 0,5-2 GB frei,
  Installation bleibt unverändert) - nativer Ja/Nein-Dialog,
  zusätzlich im GUI-Installer nach Mac-Installation
- GUI-Installer hat Variante als Combobox (wird an Worker durchgereicht)

Gesamt-Festplatte nach Installation (Kompakt): ca. 1-1,5 GB
statt ca. 2,5 GB. RAM unverändert ca. 42 MB Leerlauf (gemessen).

GUI-Smoke-Test: Variante vorhanden, Cleanup-Dialog existiert und
läuft mit gemockter Antwort durch, Fenster sauber beendet.
This commit is contained in:
HMS MediaEngine Agent
2026-09-11 23:29:01 +02:00
parent bc1da530de
commit 34b1cb8cec
2 changed files with 95 additions and 39 deletions
+41 -33
View File
@@ -1,38 +1,35 @@
#!/bin/bash #!/bin/bash
# HMS MediaEngine macOS-Installation per Doppelklick (Finder) # HMS MediaEngine macOS-Installation per Doppelklick (Finder)
# Ablauf: brew pruefen/installieren -> python3+tk pruefen -> # Ablauf: Homebrew pruefen -> Installationsumfang waehlen (Festplatte!)
# GUI-Installer starten (Passwort-Dialog kommt von macOS selbst). # -> installieren -> Cache-Aufraeumen anbieten -> GUI-Installer.
# Kein Tippen im Terminal noetig: Passwort-Eingabe laeuft ueber den # Alle Abfragen kommen als native macOS-Fenster (Buttons), das
# nativen macOS-Dialog (osascript administrator privileges). # Administrator-Passwort fragt macOS selbst ab - kein Terminal-Tippen.
cd "$(dirname "$0")" cd "$(dirname "$0")"
echo "==================================================" echo "=================================================="
echo " HMS MediaEngine Installation" echo " HMS MediaEngine Installation"
echo " (Dieses Fenster zeigt nur den Fortschritt an " echo " Fortschritt siehst du hier; alle Abfragen kommen als"
echo " alle Abfragen kommen als eigene macOS-Fenster)" echo " eigene macOS-Fenster mit Klick-Buttons."
echo "==================================================" echo "=================================================="
echo "" echo ""
# Dialog mit Buttons: gibt nur bei 'Weiter' true zurueck
eingabe() { eingabe() {
local antwort local antwort
antwort=$(osascript -e 'display alert "'$1'" message "'$2'" buttons {"Abbrechen","Weiter"} default button "Weiter" as informational' 2>/dev/null) antwort=$(osascript -e 'display alert "'$1'" message "'$2'" buttons {"Abbrechen","Weiter"} default button "Weiter" as informational' 2>/dev/null)
echo "$antwort" | grep -q "Weiter" echo "$antwort" | grep -q "Weiter"
} }
# --- Homebrew --- # --- 1) Homebrew ---
BREW="" BREW=""
for p in /opt/homebrew/bin/brew /usr/local/bin/brew; do for p in /opt/homebrew/bin/brew /usr/local/bin/brew; do
if [ -x "$p" ]; then BREW="$p"; break; fi if [ -x "$p" ]; then BREW="$p"; break; fi
done done
if [ -z "$BREW" ]; then if [ -z "$BREW" ]; then
if eingabe "Homebrew installieren?" "HMS MediaEngine benoetigt Homebrew (Paketmanager fuer macOS). Die Installation dauert einige Minuten danach geht es automatisch weiter. Das Passwort wird im naechsten Fenster von macOS abgefragt."; then if eingabe "Homebrew installieren?" "HMS MediaEngine benoetigt Homebrew (Paketmanager fuer macOS). Die Installation dauert einige Minuten. Dein Administrator-Passwort wird im naechsten Fenster von macOS abgefragt."; then
echo "" echo ">> Installiere Homebrew (macOS fragt nach deinem Passwort)..."
echo ">> Installiere Homebrew (macOS fragt nach deinem Administrator-Passwort)..." if ! osascript -e 'do shell script "NONINTERACTIVE=1 /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" with administrator privileges with prompt "Homebrew fuer HMS MediaEngine installieren"' >/dev/null 2>&1; then
osascript -e 'do shell script "NONINTERACTIVE=1 /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" with administrator privileges with prompt "Homebrew fuer HMS MediaEngine installieren"' >/dev/null 2>&1 osascript -e 'display alert "Homebrew-Installation fehlgeschlagen" message "Bitte erneut versuchen oder die Meldung an den Support schicken." as critical' >/dev/null 2>&1
if [ $? -ne 0 ]; then
osascript -e 'display alert "Homebrew-Installation fehlgeschlagen" message "Bitte das Fenster nochmal versuchen oder Meldung an den Support schicken." as critical' >/dev/null 2>&1
exit 1 exit 1
fi fi
BREW=/opt/homebrew/bin/brew BREW=/opt/homebrew/bin/brew
@@ -42,35 +39,46 @@ if [ -z "$BREW" ]; then
exit 1 exit 1
fi fi
fi fi
echo ">> Homebrew: $BREW"
echo ">> Homebrew gefunden: $BREW" # --- 2) Installationsumfang (Festplatte) waehlen ---
VARIANTE=$(osascript -e 'display alert "Welcher Installationsumfang?" message "Vollstaendig: alle 21 Effekte. GStreamer belegt dann ca. 1,5-2,5 GB." & linefeed & linefeed & "Kompakt: 15 Effekte, belegt nur ca. 0,5-1 GB. Verzichtet auf Blur/Schaerfen, Solarize, Brennen, Dilate und Exclusion." & linefeed & linefeed & "Beide Varianten spielen alle Videos und Bilder vollstaendig ab - der Unterschied liegt nur in 6 wenigen Effekten." buttons {"Abbrechen","Kompakt","Vollstaendig"} default button "Vollstaendig" as informational' 2>/dev/null)
case "$VARIANTE" in
*Kompakt*)
PKGS="python@3.12 python-tk gstreamer gst-plugins-base gst-plugins-good gst-libav pygobject"
echo ">> Gewaehlt: Kompakt (spart ca. 1-1,5 GB)"
;;
*Abbrechen*|"")
exit 1
;;
*)
PKGS="python@3.12 python-tk gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav pygobject"
echo ">> Gewaehlt: Vollstaendig (alle Effekte)"
;;
esac
# --- Python 3.12 + tkinter --- # --- 3) Installation ---
if ! "$BREW" list --versions python-tk >/dev/null 2>&1; then echo ""
if eingabe "Python-Komponenten installieren?" "python@3.12 mit tkinter (grafische Oberflaeche) wird installiert."; then echo ">> Installiere Komponenten per Homebrew (dauert einige Minuten)..."
echo "" if ! "$BREW" install $PKGS; then
echo ">> Installiere Python + tkinter..." osascript -e 'display alert "Problem bei der Installation" message "Homebrew meldete einen Fehler. Der grafische Installer prueft jetzt, was trotzdem angekommen ist." as warning' >/dev/null 2>&1
"$BREW" install python@3.12 python-tk
fi
fi fi
# --- GStreamer --- # --- 4) Homebrew-Cache aufräumen (optional, gibt 0,5-2 GB frei) ---
if ! "$BREW" list --versions gstreamer >/dev/null 2>&1; then if osascript -e 'display alert "Homebrew-Cache aufraeumen?" message "Loescht die heruntergeladenen Installationspakete und gibt etwa 0,5-2 GB Festplatte frei. Die Installation selbst bleibt unveraendert." buttons {"Nein","Ja"} default button "Ja" as informational' 2>/dev/null | grep -q "Ja"; then
if eingabe "GStreamer installieren?" "GStreamer mit allen Video-/Audio-Plugins wird installiert (ca. 5-10 Minuten, je nach Internet)."; then echo ">> Raeume Homebrew-Cache auf..."
echo "" "$BREW" cleanup --prune=all >/dev/null 2>&1
echo ">> Installiere GStreamer + Plugins..." echo ">> Cache freigegeben."
"$BREW" install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav pygobject
fi
fi fi
# --- GUI-Installer starten --- # --- 5) GUI-Installer starten (verifiziert und startet die App) ---
PY=/opt/homebrew/bin/python3 PY=/opt/homebrew/bin/python3
if [ ! -x "$PY" ]; then PY=/usr/local/bin/python3; fi [ -x "$PY" ] || PY=/usr/local/bin/python3
if [ ! -x "$PY" ]; then PY=python3; fi [ -x "$PY" ] || PY=python3
echo "" echo ""
echo ">> Starte grafischen Installer (Fenster oeffnet sich)..." echo ">> Starte grafischen Installer (Fenster oeffnet sich)..."
"$PY" installer_gui.py "$PY" installer_gui.py
echo "" echo ""
echo "Fertig. Ab jetzt genuegt: 'HMS MediaEngine.app' doppelklicken." echo "Fertig. Ab jetzt genuegt: HMS MediaEngine.app doppelklicken."
+54 -6
View File
@@ -34,11 +34,19 @@ IS_WIN = sys.platform == "win32"
GST_MSI = ("https://gstreamer.freedesktop.org/data/pkg/windows/" GST_MSI = ("https://gstreamer.freedesktop.org/data/pkg/windows/"
"1.28.4/msvc/gstreamer-1.0-msvc-x86_64-1.28.4.msi") "1.28.4/msvc/gstreamer-1.0-msvc-x86_64-1.28.4.msi")
PY_EXE = "https://www.python.org/ftp/python/3.13.2/python-3.13.2-amd64.exe" PY_EXE = "https://www.python.org/ftp/python/3.13.2/python-3.13.2-amd64.exe"
BREW_PKGS = [ BREW_PKGS_FULL = [
"python@3.12", "python-tk", "gstreamer", "gst-plugins-base", "python@3.12", "python-tk", "gstreamer", "gst-plugins-base",
"gst-plugins-good", "gst-plugins-bad", "gst-plugins-ugly", "gst-plugins-good", "gst-plugins-bad", "gst-plugins-ugly",
"gst-libav", "pygobject", "gst-libav", "pygobject",
] ]
# Kompakt: ohne gst-plugins-bad/ugly. Spart ca. 1-1,5 GB; Effekte
# sinken von 21 auf 15 (Blur/Schaerfen/Solarize/Burn/Dilate/Exclusion
# stecken in gst-plugins-bad). Videowiedergabe (libav), Compositor
# und 15 Effekte bleiben voll nutzbar.
BREW_PKGS_COMPACT = [
"python@3.12", "python-tk", "gstreamer", "gst-plugins-base",
"gst-plugins-good", "gst-libav", "pygobject",
]
def brew_path() -> str | None: def brew_path() -> str | None:
@@ -128,6 +136,19 @@ class InstallerApp:
tk.Label(self.root, textvariable=self.status_var, tk.Label(self.root, textvariable=self.status_var,
bg="#16181d", fg="#c8ccd4").pack(fill="x", padx=16) bg="#16181d", fg="#c8ccd4").pack(fill="x", padx=16)
var_row = tk.Frame(self.root, bg="#16181d")
var_row.pack(fill="x", padx=16, pady=(0, 2))
tk.Label(var_row, text="Installationsumfang:",
bg="#16181d", fg="#8a8f9a").pack(side="left")
self.variant = tk.StringVar(
value="Vollständig (alle 21 Effekte)")
ttk.Combobox(
var_row, textvariable=self.variant, state="readonly",
width=38, values=(
"Vollständig (alle 21 Effekte)",
"Kompakt (15 Effekte, spart ca. 1,5 GB)")
).pack(side="left", padx=8)
self.bar = ttk.Progressbar(self.root, mode="determinate", self.bar = ttk.Progressbar(self.root, mode="determinate",
length=640) length=640)
self.bar.pack(fill="x", padx=16, pady=8) self.bar.pack(fill="x", padx=16, pady=8)
@@ -212,16 +233,20 @@ class InstallerApp:
def start_install(self): def start_install(self):
self.install_btn.config(state="disabled") self.install_btn.config(state="disabled")
threading.Thread(target=self._install_worker, daemon=True).start() variant = self.variant.get() # tk-Variable im Hauptthread lesen
threading.Thread(target=self._install_worker, args=(variant,),
daemon=True).start()
def _install_worker(self): def _install_worker(self, variant: str):
try: try:
if IS_MAC: if IS_MAC:
self._install_mac() self._install_mac(variant)
elif IS_WIN: elif IS_WIN:
self._install_win() self._install_win()
self.on_log("") self.on_log("")
self.on_log("Installation abgeschlossen.") self.on_log("Installation abgeschlossen.")
if IS_MAC:
self.root.after(0, self._offer_cleanup)
self.on_log("Falls gerade etwas installiert wurde, das Python " self.on_log("Falls gerade etwas installiert wurde, das Python "
"betrifft: dieses Fenster einmal schließen und " "betrifft: dieses Fenster einmal schließen und "
"die App erneut starten.") "die App erneut starten.")
@@ -243,7 +268,7 @@ class InstallerApp:
raise RuntimeError(r.stderr.strip() or "osascript fehlgeschlagen") raise RuntimeError(r.stderr.strip() or "osascript fehlgeschlagen")
return r.stdout return r.stdout
def _install_mac(self): def _install_mac(self, variant: str):
self.on_status("macOS: Installation läuft (Passwort-Dialog folgt)…") self.on_status("macOS: Installation läuft (Passwort-Dialog folgt)…")
lines = ["set -e"] lines = ["set -e"]
brew = brew_path() brew = brew_path()
@@ -259,7 +284,10 @@ class InstallerApp:
'if [ -x /opt/homebrew/bin/brew ]; then ' 'if [ -x /opt/homebrew/bin/brew ]; then '
'BREW=/opt/homebrew/bin/brew; ' 'BREW=/opt/homebrew/bin/brew; '
'else BREW=/usr/local/bin/brew; fi') 'else BREW=/usr/local/bin/brew; fi')
lines.append('"$BREW" install ' + " ".join(BREW_PKGS)) pkgs = (BREW_PKGS_FULL if variant.startswith("Voll")
else BREW_PKGS_COMPACT)
self.on_log("Variante: " + variant)
lines.append('"$BREW" install ' + " ".join(pkgs))
script = "\n".join(lines) script = "\n".join(lines)
with tempfile.NamedTemporaryFile("w", suffix=".sh", with tempfile.NamedTemporaryFile("w", suffix=".sh",
delete=False) as f: delete=False) as f:
@@ -300,6 +328,26 @@ class InstallerApp:
"Fenster schließen und HMS-Start.vbs erneut " "Fenster schließen und HMS-Start.vbs erneut "
"doppelklicken.") "doppelklicken.")
def _offer_cleanup(self):
"""Homebrew-Cache aufräumen gibt ca. 0,5-2 GB frei."""
try:
if messagebox.askyesno(
"HMS MediaEngine",
"Homebrew-Cache jetzt aufräumen?\n\n"
"Löscht heruntergeladene Installationspakete und "
"gibt etwa 0,5-2 GB Festplatte frei.\n"
"Die Installation selbst bleibt unverändert.",
parent=self.root):
brew = brew_path() or "/opt/homebrew/bin/brew"
self.on_log("Räume Homebrew-Cache auf…")
r = subprocess.run([brew, "cleanup", "--prune=all"],
capture_output=True, timeout=600)
self.on_log(
"Cache aufgeräumt." if r.returncode == 0
else f"cleanup endete mit Code {r.returncode}")
except Exception as e: # noqa: BLE001
self.on_log(f"cleanup übersprungen: {e}")
# ---------- Start ---------- # ---------- Start ----------
def start_engine(self): def start_engine(self):