Files
HMS MediaEngine Agent 696e8eb1b3 PORTABLE INSTALLATION: umgeht 16-GB-Pruefung von macOS Installer.app
URSACHE GEFUNDEN: macOS Installer.app verlangt 10-16 GB freien
Speicher als SYSTEMRESERVE - obwohl GStreamer nur 146 MB gross
ist. Diese Pruefung blockiert Installationen auf vollen Platten.

LOESUNG: HMS-Portable-Install.command
- Laedt GStreamer .pkg (146 MB) per curl
- Entpackt mit 'pkgutil --expand-full' OHNE Installer.app
  (keine 16-GB-Pruefung, kein sudo, nichts systemweit)
- Kopiert GStreamer.framework in runtime/ im Projektordner
- Loescht Download + Temp (gibt ~750 MB zurueck)
- Schreibt runtime/env.sh mit allen Umgebungsvariablen
- Braucht NUR ca. 800 MB WAHREND der Installation
- Danach: ca. 500-600 MB im Projektordner (portable, loeschbar)

Integration:
- run.py: laedt portable env automatisch VOR gi-Import
  (DYLD_LIBRARY_PATH, GST_PLUGIN_PATH, GI_TYPELIB_PATH,
  PYTHONPATH fuer gi-Bindings)
- App-Launcher: sourced runtime/env.sh falls vorhanden
- launcher_core.py: gleiche portable env-Logik
- Freien Speicher pruefen (nur 800 MB noetig, nicht 16 GB)

Drei Installationswege jetzt verfuegbar:
1. HMS-Portable-Install.command (wenig Speicher, nichts systemweit)
2. HMS-Mac-Install.command (Homebrew, mehr Komfort)
3. HMS-MediaEngine.app startet mit whichever verfuegbar ist
2026-09-11 23:33:19 +02:00

101 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Gemeinsame Launcher-Logik fuer Windows-Starter und macOS.
Unsichtbarer Ablauf: GStreamer vorhanden -> Engine im Hintergrund
starten, auf die Web-UI warten, Browser oeffnen.
Fehlt etwas -> grafischer Installer (installer_gui.py) oeffnen.
"""
from __future__ import annotations
import json
import subprocess
import sys
import time
import urllib.request
import webbrowser
from pathlib import Path
ROOT = Path(__file__).resolve().parent
IS_WIN = sys.platform == "win32"
# Portable GStreamer laden (macOS: HMS-Portable-Install.command)
_fw = ROOT / "runtime" / "GStreamer.framework" / "Versions" / "1.0"
if _fw.is_dir():
import os as _os
_lib = str(_fw / "lib")
_os.environ["DYLD_LIBRARY_PATH"] = _lib + ":" + _os.environ.get("DYLD_LIBRARY_PATH", "")
_gst = str(_fw / "lib" / "gstreamer-1.0")
_os.environ["GST_PLUGIN_PATH"] = _gst
_os.environ["GST_PLUGIN_SYSTEM_PATH_1_0"] = _gst
_os.environ["GI_TYPELIB_PATH"] = (str(_fw / "lib" / "girepository-1.0")
+ ":" + _os.environ.get("GI_TYPELIB_PATH", ""))
for _v in ("python3.12", "python3.13", "python3.11"):
_sp = _fw / "lib" / _v / "site-packages"
if (_sp / "gi").is_dir():
sys.path.insert(0, str(_sp))
break
def web_port() -> int:
try:
cfg = json.loads((ROOT / "config.json").read_text("utf-8"))
return int(cfg.get("web", {}).get("port", 8080))
except Exception: # noqa: BLE001
return 8080
def gst_ok() -> bool:
try:
import gi # noqa: F401
gi.require_version("Gst", "1.0")
from gi.repository import Gst
Gst.init(None)
return True
except Exception: # noqa: BLE001
return False
def _spawn(py: str, target: str, hidden: bool) -> None:
if IS_WIN and hidden:
subprocess.Popen(
[py, str(ROOT / target)], cwd=str(ROOT),
creationflags=0x08000000, # CREATE_NO_WINDOW
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
subprocess.Popen(
[py, str(ROOT / target)], cwd=str(ROOT),
stdout=open("/tmp/hms-mediaengine.log", "ab"),
stderr=subprocess.STDOUT, start_new_session=not IS_WIN)
def wait_health(port: int, timeout_s: float = 25.0) -> bool:
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
try:
with urllib.request.urlopen(
f"http://localhost:{port}/api/health",
timeout=1.5) as r:
if json.loads(r.read().decode()).get("status") == "ok":
return True
except Exception: # noqa: BLE001
time.sleep(0.4)
return False
def launch() -> int:
if gst_ok():
_spawn(sys.executable, "run.py", hidden=True)
port = web_port()
if wait_health(port):
webbrowser.open(f"http://localhost:{port}")
return 0
print("[Launcher] Engine antwortete nicht rechtzeitig "
"oeffne Installer.", file=sys.stderr)
_spawn(sys.executable, "installer_gui.py", hidden=False)
return 1
if __name__ == "__main__":
sys.exit(launch())