Compare commits

...
2 Commits
Author SHA1 Message Date
luciano 29b9753aa3 fix: mostra causa reale dietro "yt-dlp exit 1" (v1.11.3)
In download_playlist il codice legge stdout/stderr merged per parsare
il progress ma poi butta via tutte le righe. Se return_code != 0
l'utente vedeva solo "error: yt-dlp exit 1" senza sapere il perche'
(video bloccato? age-gate? 403? region-lock?).

Fix: buffer ring (10 righe non-progress) durante il download. Se
return_code != 0, estrae la riga con ERROR/error e la accoda al
messaggio -> "error: yt-dlp exit 1 — ERROR: [youtube] Video unavailable".
Massimo 220 char per non intasare il log.

Applicato solo al pattern download_playlist per ora (quello che usa il
utente sul batch Spotify). Direct URL e batch tags idem se emergono.
2026-08-28 10:08:52 +02:00
luciano c88e6d359c fix: switch build_* a yt-dlp nightly channel (v1.11.2)
Fix strutturale ricorrente errore "yt-dlp exit 1" nel download.
YouTube rompe API ogni 1-2 settimane; yt-dlp stable esce ogni ~4
settimane, quindi la build imbarcava binari gia' obsoleti al rilascio.

- build_macos.py + build_windows.py: URL switch da
  yt-dlp/yt-dlp/releases/latest → yt-dlp/yt-dlp-nightly-builds
- Sempre re-download (niente skip se bundle_bin/yt-dlp esiste) —
  garantisce binario 24-48h, non 3-4 settimane
2026-08-28 00:41:40 +02:00
4 changed files with 33 additions and 16 deletions

No files matched your search

+10 -8
View File
@@ -39,21 +39,23 @@ def log(msg):
# 1. Scarica yt-dlp standalone # 1. Scarica yt-dlp standalone
# ========================================================================= # =========================================================================
def download_ytdlp(): def download_ytdlp():
"""Scarica il binario standalone di yt-dlp per macOS.""" """Scarica il binario standalone di yt-dlp per macOS.
Usa il NIGHTLY channel invece dello stable perche' YouTube rompe le
API ogni 1-2 settimane e la stable resta indietro di 3-4 settimane
tipicamente. La nightly esce quasi ogni giorno con i fix.
Sempre re-download: garantisce che ogni build imbarca yt-dlp fresco.
"""
arch = platform.machine() # arm64 o x86_64 arch = platform.machine() # arm64 o x86_64
if arch == "arm64": if arch == "arm64":
url = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos" url = "https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest/download/yt-dlp_macos"
else: else:
url = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos_legacy" url = "https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest/download/yt-dlp_macos_legacy"
dest = BUNDLE_DIR / "yt-dlp" dest = BUNDLE_DIR / "yt-dlp"
if dest.exists():
log(f"yt-dlp gia presente: {dest}")
return dest
log(f"Scarico yt-dlp da {url} ...")
BUNDLE_DIR.mkdir(parents=True, exist_ok=True) BUNDLE_DIR.mkdir(parents=True, exist_ok=True)
log(f"Scarico yt-dlp nightly da {url} ...")
# Usa curl perche urllib di Python 3.8 ha problemi SSL su macOS # Usa curl perche urllib di Python 3.8 ha problemi SSL su macOS
subprocess.run( subprocess.run(
["curl", "-L", "-o", str(dest), url], ["curl", "-L", "-o", str(dest), url],
+4 -6
View File
@@ -29,7 +29,7 @@ BUILD_DIR = ROOT / "build"
DIST_DIR = ROOT / "dist" DIST_DIR = ROOT / "dist"
BUNDLE_DIR = ROOT / "bundle_bin" BUNDLE_DIR = ROOT / "bundle_bin"
YTDLP_URL = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe" YTDLP_URL = "https://github.com/yt-dlp/yt-dlp-nightly-builds/releases/latest/download/yt-dlp.exe"
FFMPEG_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip" FFMPEG_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip"
FPCALC_URL = ("https://github.com/acoustid/chromaprint/releases/download/" FPCALC_URL = ("https://github.com/acoustid/chromaprint/releases/download/"
"v1.5.1/chromaprint-fpcalc-1.5.1-windows-x86_64.zip") "v1.5.1/chromaprint-fpcalc-1.5.1-windows-x86_64.zip")
@@ -43,13 +43,11 @@ def log(msg):
# 1. Scarica yt-dlp.exe # 1. Scarica yt-dlp.exe
# ========================================================================= # =========================================================================
def download_ytdlp(): def download_ytdlp():
"""Scarica sempre il nightly fresco: la stable resta indietro di
3-4 settimane rispetto alle rotture API YouTube."""
dest = BUNDLE_DIR / "yt-dlp.exe" dest = BUNDLE_DIR / "yt-dlp.exe"
if dest.exists():
log(f"yt-dlp.exe gia presente: {dest}")
return dest
log(f"Scarico yt-dlp.exe ...")
BUNDLE_DIR.mkdir(parents=True, exist_ok=True) BUNDLE_DIR.mkdir(parents=True, exist_ok=True)
log(f"Scarico yt-dlp.exe nightly ...")
urllib.request.urlretrieve(YTDLP_URL, dest) urllib.request.urlretrieve(YTDLP_URL, dest)
log(f"yt-dlp.exe scaricato ({dest.stat().st_size // 1024 // 1024} MB)") log(f"yt-dlp.exe scaricato ({dest.stat().st_size // 1024 // 1024} MB)")
return dest return dest
+1 -1
View File
@@ -5,7 +5,7 @@ import os
import sys import sys
from pathlib import Path from pathlib import Path
VERSION = "v1.11.1" VERSION = "v1.11.3"
APP_NAME = "MusicTools" APP_NAME = "MusicTools"
+18 -1
View File
@@ -247,6 +247,7 @@ def download_playlist(
**subprocess_flags(), **subprocess_flags(),
) )
last_lines: list = [] # buffer per capire l'errore se exit != 0
for line in _current_process.stdout: for line in _current_process.stdout:
if is_stopped(): if is_stopped():
_current_process.terminate() _current_process.terminate()
@@ -254,6 +255,13 @@ def download_playlist(
progress_callback(i, total, query, "stopped", 0) progress_callback(i, total, query, "stopped", 0)
return return
# Tieni le ultime 10 righe non-progress per il report d'errore
stripped = line.strip()
if stripped and not re.match(r"^\[download\]\s+\d", stripped):
last_lines.append(stripped)
if len(last_lines) > 10:
last_lines.pop(0)
# Parse progress da output yt-dlp # Parse progress da output yt-dlp
pct_match = re.search(r"(\d+(?:\.\d+)?)%", line) pct_match = re.search(r"(\d+(?:\.\d+)?)%", line)
if pct_match and progress_callback: if pct_match and progress_callback:
@@ -278,8 +286,17 @@ def download_playlist(
if progress_callback: if progress_callback:
progress_callback(i, total, query, "done", 100) progress_callback(i, total, query, "done", 100)
else: else:
# Estrai la vera causa da last_lines: cerca la riga ERROR di yt-dlp
err_hint = ""
for l in reversed(last_lines):
if "ERROR" in l or "error" in l:
err_hint = l[:220]
break
if not err_hint and last_lines:
err_hint = last_lines[-1][:220]
detail = f" — {err_hint}" if err_hint else ""
if progress_callback: if progress_callback:
progress_callback(i, total, query, f"error: yt-dlp exit {return_code}", 0) progress_callback(i, total, query, f"error: yt-dlp exit {return_code}{detail}", 0)
except Exception as e: except Exception as e:
with _process_lock: with _process_lock: