Fix Windows: nascondi finestra cmd per ogni subprocess yt-dlp/ffmpeg
Aggiunto helper subprocess_flags() in core/paths.py che ritorna CREATE_NO_WINDOW su Windows. Applicato a tutte le subprocess.run/Popen in downloader, upgrader e recorder per evitare il flash di console nera ad ogni traccia scaricata. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
b47fdd1ab3
commit
8610f4d95c
5 files changed
+31
-9
No files matched your search
+1
-1
@@ -5,7 +5,7 @@ import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
VERSION = "v1.5.0"
|
||||
VERSION = "v1.5.1"
|
||||
|
||||
|
||||
APP_NAME = "MusicTools"
|
||||
|
||||
+7
-4
@@ -9,7 +9,7 @@ import threading
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
from core.paths import find_ytdlp, find_ffmpeg_dir
|
||||
from core.paths import find_ytdlp, find_ffmpeg_dir, subprocess_flags
|
||||
|
||||
|
||||
# Flag globale per interruzione
|
||||
@@ -102,7 +102,7 @@ def _search_youtube(query: str, cookies_path: Optional[str] = None) -> tuple[str
|
||||
if cookies_path and Path(cookies_path).exists():
|
||||
cmd.extend(["--cookies", cookies_path])
|
||||
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, **subprocess_flags())
|
||||
if result.returncode != 0:
|
||||
raise ValueError(f"Ricerca fallita: {result.stderr.strip()}")
|
||||
|
||||
@@ -204,6 +204,7 @@ def download_playlist(
|
||||
with _process_lock:
|
||||
_current_process = subprocess.Popen(
|
||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
|
||||
for line in _current_process.stdout:
|
||||
@@ -278,7 +279,7 @@ def download_direct_url(
|
||||
probe_cmd.extend(["--cookies", cookies_path])
|
||||
|
||||
try:
|
||||
result = subprocess.run(probe_cmd, capture_output=True, text=True, timeout=60)
|
||||
result = subprocess.run(probe_cmd, capture_output=True, text=True, timeout=60, **subprocess_flags())
|
||||
if result.returncode != 0:
|
||||
raise ValueError(result.stderr.strip())
|
||||
except Exception as e:
|
||||
@@ -356,6 +357,7 @@ def download_direct_url(
|
||||
with _process_lock:
|
||||
_current_process = subprocess.Popen(
|
||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
|
||||
for line in _current_process.stdout:
|
||||
@@ -443,7 +445,7 @@ def download_video(
|
||||
probe_cmd.extend(["--cookies", cookies_path])
|
||||
|
||||
try:
|
||||
result = subprocess.run(probe_cmd, capture_output=True, text=True, timeout=60)
|
||||
result = subprocess.run(probe_cmd, capture_output=True, text=True, timeout=60, **subprocess_flags())
|
||||
if result.returncode != 0:
|
||||
raise ValueError(result.stderr.strip())
|
||||
except Exception as e:
|
||||
@@ -522,6 +524,7 @@ def download_video(
|
||||
with _process_lock:
|
||||
_current_process = subprocess.Popen(
|
||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
|
||||
for line in _current_process.stdout:
|
||||
|
||||
@@ -48,6 +48,19 @@ def _exe(name: str) -> str:
|
||||
return name
|
||||
|
||||
|
||||
def subprocess_flags() -> dict:
|
||||
"""Kwargs per subprocess.run/Popen che nascondono la console su Windows.
|
||||
|
||||
Senza CREATE_NO_WINDOW, ogni subprocess (yt-dlp, ffmpeg, ffprobe) lanciato
|
||||
da un'app GUI PyInstaller apre una finestra cmd nera per la durata del
|
||||
processo. Su macOS/Linux il flag non esiste, quindi ritorniamo dict vuoto.
|
||||
"""
|
||||
if _IS_WINDOWS:
|
||||
# 0x08000000 == CREATE_NO_WINDOW
|
||||
return {"creationflags": 0x08000000}
|
||||
return {}
|
||||
|
||||
|
||||
def find_ytdlp() -> str:
|
||||
"""Trova il path di yt-dlp.
|
||||
|
||||
|
||||
+4
-1
@@ -15,7 +15,7 @@ import time
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
from core.paths import find_ffmpeg
|
||||
from core.paths import find_ffmpeg, subprocess_flags
|
||||
|
||||
|
||||
_IS_MAC = sys.platform == "darwin"
|
||||
@@ -79,6 +79,7 @@ def _list_macos(ffmpeg: str) -> list[dict]:
|
||||
[ffmpeg, "-hide_banner", "-f", "avfoundation",
|
||||
"-list_devices", "true", "-i", ""],
|
||||
capture_output=True, text=True, timeout=10,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
except Exception:
|
||||
return []
|
||||
@@ -116,6 +117,7 @@ def _list_windows(ffmpeg: str) -> list[dict]:
|
||||
[ffmpeg, "-hide_banner", "-f", "dshow",
|
||||
"-list_devices", "true", "-i", "dummy"],
|
||||
capture_output=True, text=True, timeout=10,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
except Exception:
|
||||
return []
|
||||
@@ -247,6 +249,7 @@ def start_recording(
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.PIPE,
|
||||
text=False,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
|
||||
drain_t = threading.Thread(target=_drain_stderr,
|
||||
|
||||
+6
-3
@@ -9,7 +9,7 @@ import threading
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
from core.paths import find_ytdlp, find_ffmpeg_dir, find_ffprobe
|
||||
from core.paths import find_ytdlp, find_ffmpeg_dir, find_ffprobe, subprocess_flags
|
||||
|
||||
AUDIO_EXTENSIONS = {".mp3", ".m4a", ".wav", ".flac"}
|
||||
|
||||
@@ -61,6 +61,7 @@ def get_bitrate(filepath: str | Path) -> int:
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
data = json.loads(result.stdout)
|
||||
bit_rate = int(data.get("format", {}).get("bit_rate", 0))
|
||||
@@ -94,7 +95,7 @@ def _search_youtube(query: str, cookies_path: Optional[str] = None) -> str:
|
||||
if cookies_path and Path(cookies_path).exists():
|
||||
cmd.extend(["--cookies", cookies_path])
|
||||
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30, **subprocess_flags())
|
||||
if result.returncode != 0:
|
||||
raise ValueError("Ricerca fallita")
|
||||
|
||||
@@ -128,7 +129,7 @@ def update_cover_only(
|
||||
if cookies_path and Path(cookies_path).exists():
|
||||
cmd.extend(["--cookies", cookies_path])
|
||||
|
||||
subprocess.run(cmd, capture_output=True, timeout=60)
|
||||
subprocess.run(cmd, capture_output=True, timeout=60, **subprocess_flags())
|
||||
|
||||
cover_files = list(temp_dir.glob("cover*.jpg"))
|
||||
if not cover_files:
|
||||
@@ -152,6 +153,7 @@ def update_cover_only(
|
||||
],
|
||||
capture_output=True,
|
||||
timeout=60,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
except Exception:
|
||||
_cleanup_temp(temp_dir)
|
||||
@@ -284,6 +286,7 @@ def upgrade_folder(
|
||||
with _process_lock:
|
||||
_current_process = subprocess.Popen(
|
||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
|
||||
**subprocess_flags(),
|
||||
)
|
||||
|
||||
for line in _current_process.stdout:
|
||||
|
||||
Reference in new issue
Block a user