From 5121ae2cf213877d6e4acb52915cf744214ecc32 Mon Sep 17 00:00:00 2001 From: RelaxJonh <92573950+RelaxJonh@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:15:30 +0700 Subject: [PATCH] fix: add creationflags to plugins subprocess calls (Windows console flash) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three plugin adapters have non-interactive subprocess calls (ffprobe, ffmpeg, ImageMagick convert) missing CREATE_NO_WINDOW on Windows: - plugins/platforms/matrix/adapter.py — ffprobe duration + ffmpeg PCM extraction + ffmpeg Ogg/Opus transcode (3 calls) - plugins/platforms/discord/adapter.py — ffprobe duration probe (1 call) - plugins/platforms/simplex/adapter.py — ImageMagick convert for format conversion + thumbnail generation (2 calls) Without CREATE_NO_WINDOW (0x08000000), each subprocess spawns a visible console window (cmd.exe / conhost.exe) that flashes on Windows. Uses the existing windows_hide_flags() helper from hermes_cli._subprocess_compat (local imports, same pattern as PR #65660). --- plugins/platforms/discord/adapter.py | 3 +++ plugins/platforms/matrix/adapter.py | 7 +++++++ plugins/platforms/simplex/adapter.py | 3 +++ 3 files changed, 13 insertions(+) diff --git a/plugins/platforms/discord/adapter.py b/plugins/platforms/discord/adapter.py index 5fab2307c30a..8602cff51e2f 100644 --- a/plugins/platforms/discord/adapter.py +++ b/plugins/platforms/discord/adapter.py @@ -3814,6 +3814,8 @@ def _playback_timeout_limit(self) -> int: def _probe_audio_duration_seconds(self, audio_path: str) -> Optional[float]: """Best-effort audio duration probe used to size playback timeouts.""" + from hermes_cli._subprocess_compat import windows_hide_flags + try: import importlib mutagen = importlib.import_module("mutagen") @@ -3838,6 +3840,7 @@ def _probe_audio_duration_seconds(self, audio_path: str) -> Optional[float]: text=True, timeout=5, stdin=subprocess.DEVNULL, + creationflags=windows_hide_flags(), ) if proc.returncode == 0: raw = (proc.stdout or "").strip() diff --git a/plugins/platforms/matrix/adapter.py b/plugins/platforms/matrix/adapter.py index 8ed47897e0fe..7f3d6763e787 100644 --- a/plugins/platforms/matrix/adapter.py +++ b/plugins/platforms/matrix/adapter.py @@ -151,6 +151,8 @@ def _matrix_voice_metadata_for_file(path: Path) -> Dict[str, Any]: extraction is deliberately best-effort: media delivery must still work on systems without ffprobe/ffmpeg. """ + from hermes_cli._subprocess_compat import windows_hide_flags + metadata: Dict[str, Any] = {} ffprobe = shutil.which("ffprobe") @@ -171,6 +173,7 @@ def _matrix_voice_metadata_for_file(path: Path) -> Dict[str, Any]: text=True, timeout=10, stdin=subprocess.DEVNULL, + creationflags=windows_hide_flags(), ) if result.returncode == 0: duration = float((result.stdout or "").strip() or 0) @@ -200,6 +203,7 @@ def _matrix_voice_metadata_for_file(path: Path) -> Dict[str, Any]: capture_output=True, timeout=15, stdin=subprocess.DEVNULL, + creationflags=windows_hide_flags(), ) if result.returncode == 0 and result.stdout: samples = array.array("h") @@ -228,6 +232,8 @@ def _matrix_transcode_voice_to_ogg(path: str) -> Optional[str]: original file, matching the adapter's previous behaviour. Runs blocking subprocess work; call via ``asyncio.to_thread`` from async code. """ + from hermes_cli._subprocess_compat import windows_hide_flags + ffmpeg = shutil.which("ffmpeg") if not ffmpeg: return None @@ -261,6 +267,7 @@ def _matrix_transcode_voice_to_ogg(path: str) -> Optional[str]: capture_output=True, timeout=30, stdin=subprocess.DEVNULL, + creationflags=windows_hide_flags(), ) if result.returncode == 0 and os.path.getsize(ogg_path) > 0: return ogg_path diff --git a/plugins/platforms/simplex/adapter.py b/plugins/platforms/simplex/adapter.py index ae4c6be34b64..08c651af428f 100644 --- a/plugins/platforms/simplex/adapter.py +++ b/plugins/platforms/simplex/adapter.py @@ -869,6 +869,7 @@ def _prepare_image(file_path: str) -> tuple[str, str]: """ import subprocess import tempfile + from hermes_cli._subprocess_compat import windows_hide_flags p = Path(file_path) png_path = file_path @@ -900,6 +901,7 @@ def _prepare_image(file_path: str) -> tuple[str, str]: check=True, capture_output=True, timeout=30, + creationflags=windows_hide_flags(), ) with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: tmp_path = tmp.name @@ -916,6 +918,7 @@ def _prepare_image(file_path: str) -> tuple[str, str]: check=True, capture_output=True, timeout=30, + creationflags=windows_hide_flags(), ) with open(tmp_path, "rb") as f: thumb_uri = (