fix: bundle FFmpeg offline, fix NoneType write crash in windowed apps, fallback to system PATH
This commit is contained in:
@@ -70,6 +70,21 @@ def build():
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
print("WARNUNG: customtkinter nicht installiert. Bitte 'pip install -r requirements.txt' ausführen.")
|
print("WARNUNG: customtkinter nicht installiert. Bitte 'pip install -r requirements.txt' ausführen.")
|
||||||
|
|
||||||
|
# static_ffmpeg-Binaries einbinden (FFmpeg komplett offline bündeln)
|
||||||
|
try:
|
||||||
|
import static_ffmpeg
|
||||||
|
print("Lade FFmpeg-Binaries herunter (falls noch nicht vorhanden)...")
|
||||||
|
# Zwingt static_ffmpeg dazu, FFmpeg herunterzuladen, falls es noch nicht im venv/bin ist
|
||||||
|
static_ffmpeg.run.get_or_fetch_platform_executables_else_raise()
|
||||||
|
|
||||||
|
sf_path = Path(static_ffmpeg.__file__).parent
|
||||||
|
if system == "Windows":
|
||||||
|
args.extend(["--add-data", f"{sf_path};static_ffmpeg"])
|
||||||
|
else:
|
||||||
|
args.extend(["--add-data", f"{sf_path}:static_ffmpeg"])
|
||||||
|
except Exception as e:
|
||||||
|
print(f"WARNUNG: static_ffmpeg konnte nicht gebündelt werden: {e}")
|
||||||
|
|
||||||
# Hauptdatei
|
# Hauptdatei
|
||||||
args.append(str(project_dir / "main.py"))
|
args.append(str(project_dir / "main.py"))
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,36 @@ import static_ffmpeg
|
|||||||
from .metadata import apply_id3_tags
|
from .metadata import apply_id3_tags
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import io
|
||||||
|
import shutil
|
||||||
|
|
||||||
def _ensure_ffmpeg() -> tuple[str, str]:
|
def _ensure_ffmpeg() -> tuple[str, str]:
|
||||||
"""Stellt sicher, dass ffmpeg und ffprobe verfügbar sind.
|
"""Stellt sicher, dass ffmpeg und ffprobe verfügbar sind.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(ffmpeg_path, ffprobe_path)
|
(ffmpeg_path, ffprobe_path)
|
||||||
"""
|
"""
|
||||||
|
# 1. Behebe NoneType 'write' Fehler, wenn App im windowed-Modus gestartet wurde
|
||||||
|
if sys.stdout is None:
|
||||||
|
sys.stdout = io.StringIO()
|
||||||
|
if sys.stderr is None:
|
||||||
|
sys.stderr = io.StringIO()
|
||||||
|
|
||||||
|
# 2. Versuch 1: static_ffmpeg (jetzt direkt in der App gebündelt)
|
||||||
|
try:
|
||||||
ffmpeg_path, ffprobe_path = static_ffmpeg.run.get_or_fetch_platform_executables_else_raise()
|
ffmpeg_path, ffprobe_path = static_ffmpeg.run.get_or_fetch_platform_executables_else_raise()
|
||||||
return ffmpeg_path, ffprobe_path
|
return ffmpeg_path, ffprobe_path
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 3. Versuch 2: System-FFmpeg (z.B. über winget, apt, brew) als Fallback
|
||||||
|
sys_ffmpeg = shutil.which("ffmpeg")
|
||||||
|
sys_ffprobe = shutil.which("ffprobe")
|
||||||
|
if sys_ffmpeg and sys_ffprobe:
|
||||||
|
return sys_ffmpeg, sys_ffprobe
|
||||||
|
|
||||||
|
raise RuntimeError("FFmpeg konnte weder im Bundle noch im System gefunden werden.")
|
||||||
|
|
||||||
|
|
||||||
def get_duration(file_path: Path, ffprobe_path: str) -> float:
|
def get_duration(file_path: Path, ffprobe_path: str) -> float:
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ Startet die grafische Benutzeroberfläche.
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import platform
|
import platform
|
||||||
|
import io
|
||||||
|
|
||||||
|
# Behebe NoneType 'write' Fehler in windowed GUI-Modus (PyInstaller --windowed auf Windows/macOS)
|
||||||
|
if sys.stdout is None:
|
||||||
|
sys.stdout = io.StringIO()
|
||||||
|
if sys.stderr is None:
|
||||||
|
sys.stderr = io.StringIO()
|
||||||
|
|
||||||
# DPI-Awareness auf Windows setzen (vor dem GUI-Import)
|
# DPI-Awareness auf Windows setzen (vor dem GUI-Import)
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
|
|||||||
Reference in New Issue
Block a user