Files
musicdownload/upgrade_quality.sh
luzadevandClaude Opus 4.7 8c06a26ddb Initial commit: MusicDownload con UI pywebview
- Frontend HTML/CSS/JS in webui/ (stile Spotify-like, hero gradient, modal blur)
- API bridge JS<->Python in api/bridge.py
- Core invariato: downloader yt-dlp, upgrader, spotify client, config
- Build scripts macOS (WebKit) e Windows (EdgeChromium)
- .gitignore esclude credenziali (config.json, cookies.txt) e artefatti build

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 12:48:58 +02:00

429 lines
14 KiB
Bash
Executable File

#!/bin/bash
# ============================================
# Upgrade Quality - Cerca versioni HQ dei brani
# Sovrascrive i file originali
# Con progress bar e ripresa automatica
# ============================================
# Requisiti: yt-dlp, ffmpeg, ffprobe
# Installazione: brew install yt-dlp ffmpeg
# Percorso script (per trovare cookies.txt nella stessa cartella)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COOKIE_FILE="$SCRIPT_DIR/cookies.txt"
# Colori
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
BLUE='\033[0;34m'
NC='\033[0m'
BOLD='\033[1m'
# Soglia qualita (kbps) - sopra questa aggiorna solo copertina
HQ_THRESHOLD=310
# ============================================
# Funzione progress bar
# ============================================
progress_bar() {
local current=$1
local total=$2
local width=30
local percent=$((current * 100 / total))
local filled=$((current * width / total))
local empty=$((width - filled))
printf "\r ["
printf "%${filled}s" | tr ' ' '#'
printf "%${empty}s" | tr ' ' '-'
printf "] %3d%% (%d/%d)" "$percent" "$current" "$total"
}
# ============================================
# Funzione per aggiornare solo la copertina
# ============================================
update_cover_only() {
local FILE="$1"
local VIDEO_URL="$2"
local TEMP_DIR="$3"
local FILENAME="$4"
# Scarica thumbnail
yt-dlp \
--skip-download \
--write-thumbnail \
--convert-thumbnails jpg \
--no-warnings \
$COOKIE_OPTS \
--output "$TEMP_DIR/cover" \
"$VIDEO_URL" 2>/dev/null
local COVER_FILE=$(ls "$TEMP_DIR"/cover*.jpg 2>/dev/null | head -n 1)
if [ -n "$COVER_FILE" ] && [ -f "$COVER_FILE" ]; then
# Applica copertina con ffmpeg
local TEMP_OUTPUT="$TEMP_DIR/temp_output.mp3"
ffmpeg -y -i "$FILE" -i "$COVER_FILE" \
-map 0:a -map 1:0 \
-c:a copy \
-id3v2_version 3 \
-metadata:s:v title="Album cover" \
-metadata:s:v comment="Cover (front)" \
"$TEMP_OUTPUT" 2>/dev/null
if [ -f "$TEMP_OUTPUT" ]; then
mv "$TEMP_OUTPUT" "$FILE"
rm -f "$COVER_FILE"
return 0
fi
fi
rm -f "$TEMP_DIR"/cover*.jpg 2>/dev/null
return 1
}
# ============================================
# Funzione per processare una singola cartella
# ============================================
process_folder() {
local SOURCE_DIR="$1"
local LOGFILE="$SOURCE_DIR/upgrade.log"
local DONE_FILE="$SOURCE_DIR/.upgraded_tracks"
local TEMP_DIR="$SOURCE_DIR/.temp_download"
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} Cartella: ${YELLOW}$(basename "$SOURCE_DIR")${NC}"
echo -e "${CYAN}========================================${NC}"
# Crea file done se non esiste
touch "$DONE_FILE"
# Conta file totali e da processare
local ALL_FILES=$(find "$SOURCE_DIR" -maxdepth 1 -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.wav" -o -iname "*.flac" \) | wc -l | tr -d ' ')
if [ "$ALL_FILES" -eq 0 ]; then
echo -e " ${YELLOW}Nessun file audio, salto${NC}"
return
fi
# Conta quanti sono gia stati convertiti
local ALREADY_DONE=0
while IFS= read -r FILE; do
local BASENAME=$(basename "$FILE")
local FILENAME="${BASENAME%.*}"
if grep -qxF "$FILENAME" "$DONE_FILE" 2>/dev/null; then
((ALREADY_DONE++))
fi
done < <(find "$SOURCE_DIR" -maxdepth 1 -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.wav" -o -iname "*.flac" \))
local TO_PROCESS=$((ALL_FILES - ALREADY_DONE))
if [ "$TO_PROCESS" -eq 0 ]; then
echo -e " ${GREEN}Tutti i $ALL_FILES brani sono gia stati convertiti${NC}"
return
fi
if [ "$ALREADY_DONE" -gt 0 ]; then
echo -e " Totale: $ALL_FILES file | ${GREEN}Gia convertiti: $ALREADY_DONE${NC} | Da fare: $TO_PROCESS"
else
echo " Trovati $ALL_FILES file audio da processare"
fi
# Crea directory temporanea
mkdir -p "$TEMP_DIR"
local INDEX=0
local SUCCESS=0
local FAILED=0
local SKIPPED=0
# Processa ogni file audio
while IFS= read -r FILE; do
((INDEX++))
# Estrai nome file senza estensione
local BASENAME=$(basename "$FILE")
local FILENAME="${BASENAME%.*}"
# Controlla se gia convertito
if grep -qxF "$FILENAME" "$DONE_FILE" 2>/dev/null; then
((SKIPPED++))
continue
fi
# Analizza qualita attuale
local CURRENT_BITRATE=$(ffprobe -v quiet -print_format json -show_format "$FILE" 2>/dev/null | grep -o '"bit_rate": "[^"]*"' | grep -o '[0-9]*')
local CURRENT_KBPS=$((CURRENT_BITRATE / 1000))
# Mostra stato
echo ""
local DONE_COUNT=$((SKIPPED + SUCCESS + FAILED))
echo -e " ${YELLOW}[$((DONE_COUNT + 1))/$ALL_FILES]${NC} $FILENAME"
echo -e " ${GRAY}Qualita attuale: ${CURRENT_KBPS}kbps${NC}"
# Cerca su YouTube
echo -ne " ${GRAY}Cercando su YouTube...${NC}"
local VIDEO_INFO=$(yt-dlp "ytsearch1:$FILENAME" \
--get-id --get-title \
--no-warnings 2>/dev/null)
if [ -z "$VIDEO_INFO" ]; then
echo -e "\r ${RED}Non trovato su YouTube ${NC}"
echo "FALLITO: $FILENAME - Non trovato" >> "$LOGFILE"
# Segna come fatto comunque per non riprovare
echo "$FILENAME" >> "$DONE_FILE"
((FAILED++))
continue
fi
local VIDEO_TITLE=$(echo "$VIDEO_INFO" | head -n 1)
local VIDEO_ID=$(echo "$VIDEO_INFO" | tail -n 1)
local VIDEO_URL="https://www.youtube.com/watch?v=$VIDEO_ID"
echo -e "\r ${GRAY}Trovato: ${VIDEO_TITLE:0:50}...${NC} "
# Se qualita gia alta, aggiorna solo copertina
if [ "$CURRENT_KBPS" -ge "$HQ_THRESHOLD" ]; then
echo -ne " ${BLUE}Qualita gia alta, aggiorno solo copertina...${NC}"
if update_cover_only "$FILE" "$VIDEO_URL" "$TEMP_DIR" "$FILENAME"; then
echo -e "\r ${GREEN}Copertina aggiornata (audio ${CURRENT_KBPS}kbps mantenuto) ${NC}"
echo "COVER: $FILENAME - Copertina aggiornata (${CURRENT_KBPS}kbps)" >> "$LOGFILE"
else
echo -e "\r ${YELLOW}Copertina non disponibile (audio ${CURRENT_KBPS}kbps ok) ${NC}"
echo "SKIP: $FILENAME - Gia HQ ${CURRENT_KBPS}kbps" >> "$LOGFILE"
fi
echo "$FILENAME" >> "$DONE_FILE"
((SUCCESS++))
# Pulisci temp
rm -f "$TEMP_DIR"/*.jpg 2>/dev/null
rm -f "$TEMP_DIR"/*.webp 2>/dev/null
continue
fi
# Scarica con progress
echo -ne " ${CYAN}Scaricando...${NC} "
yt-dlp \
--extract-audio \
--audio-format mp3 \
--audio-quality 0 \
--embed-thumbnail \
--add-metadata \
--no-warnings \
--progress \
--newline \
$COOKIE_OPTS \
--output "$TEMP_DIR/%(title)s.%(ext)s" \
"$VIDEO_URL" 2>&1 | while IFS= read -r line; do
# Estrai percentuale dal output di yt-dlp
if [[ "$line" =~ ([0-9]+\.[0-9]+)% ]]; then
pct="${BASH_REMATCH[1]}"
pct_int=${pct%.*}
bar_width=20
filled=$((pct_int * bar_width / 100))
empty=$((bar_width - filled))
printf "\r ${CYAN}Scaricando${NC} ["
printf "%${filled}s" | tr ' ' '#'
printf "%${empty}s" | tr ' ' '-'
printf "] %3d%%" "$pct_int"
fi
done
if [ $? -eq 0 ] || [ -n "$(ls -A "$TEMP_DIR" 2>/dev/null)" ]; then
# Trova il file appena scaricato
local NEWEST_FILE=$(ls -t "$TEMP_DIR"/*.mp3 2>/dev/null | head -n 1)
if [ -n "$NEWEST_FILE" ] && [ -f "$NEWEST_FILE" ]; then
local NEW_BITRATE=$(ffprobe -v quiet -print_format json -show_format "$NEWEST_FILE" 2>/dev/null | grep -o '"bit_rate": "[^"]*"' | grep -o '[0-9]*')
local NEW_KBPS=$((NEW_BITRATE / 1000))
# Elimina file originale e sposta quello nuovo
rm -f "$FILE"
mv "$NEWEST_FILE" "$SOURCE_DIR/$FILENAME.mp3"
# Segna come completato
echo "$FILENAME" >> "$DONE_FILE"
local DIFF=$((NEW_KBPS - CURRENT_KBPS))
if [ "$DIFF" -gt 0 ]; then
echo -e "\r ${GREEN}Completato: ${NEW_KBPS}kbps (+${DIFF}kbps) ${NC}"
else
echo -e "\r ${GREEN}Completato: ${NEW_KBPS}kbps ${NC}"
fi
echo "OK: $FILENAME - ${CURRENT_KBPS}kbps -> ${NEW_KBPS}kbps" >> "$LOGFILE"
((SUCCESS++))
else
echo -e "\r ${RED}Errore: file non trovato dopo download ${NC}"
echo "$FILENAME" >> "$DONE_FILE"
((FAILED++))
fi
else
echo -e "\r ${RED}Errore durante il download ${NC}"
echo "ERRORE: $FILENAME - Download fallito" >> "$LOGFILE"
echo "$FILENAME" >> "$DONE_FILE"
((FAILED++))
fi
# Pulisci temp
rm -f "$TEMP_DIR"/*.mp3 2>/dev/null
rm -f "$TEMP_DIR"/*.webm 2>/dev/null
rm -f "$TEMP_DIR"/*.m4a 2>/dev/null
done < <(find "$SOURCE_DIR" -maxdepth 1 -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.wav" -o -iname "*.flac" \))
# Rimuovi directory temporanea
rmdir "$TEMP_DIR" 2>/dev/null
# Sommario cartella
echo ""
echo -e " ${GRAY}---${NC}"
echo -e " Convertiti: ${GREEN}$SUCCESS${NC} | Falliti: ${RED}$FAILED${NC} | Saltati: ${GRAY}$SKIPPED${NC}"
}
# ============================================
# MAIN
# ============================================
echo ""
echo "========================================"
echo " UPGRADE QUALITY AUDIO"
echo "========================================"
# Verifica cookies YouTube Premium
if [ -f "$COOKIE_FILE" ]; then
echo -e "Cookies: ${GREEN}YouTube Premium attivo${NC}"
COOKIE_OPTS="--cookies $COOKIE_FILE"
else
echo -e "Cookies: ${YELLOW}Non trovati (qualita standard)${NC}"
COOKIE_OPTS=""
fi
# Gestione parametri
if [ "$1" = "-r" ] || [ "$1" = "--recursive" ]; then
# Modalita ricorsiva: processa tutte le sottocartelle
if [ -z "$2" ]; then
echo -e "${CYAN}Inserisci la cartella principale:${NC}"
read -r BASE_DIR
else
BASE_DIR="$2"
fi
if [ ! -d "$BASE_DIR" ]; then
echo -e "${RED}Errore: Directory '$BASE_DIR' non trovata${NC}"
exit 1
fi
# Trova tutte le sottocartelle con file audio
echo ""
echo "Scansione cartelle in: $BASE_DIR"
FOLDERS=$(find "$BASE_DIR" -type d | while read -r dir; do
count=$(find "$dir" -maxdepth 1 -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.wav" -o -iname "*.flac" \) 2>/dev/null | wc -l | tr -d ' ')
if [ "$count" -gt 0 ]; then
echo "$dir"
fi
done)
if [ -z "$FOLDERS" ]; then
echo -e "${RED}Nessuna cartella con file audio trovata${NC}"
exit 1
fi
FOLDER_COUNT=$(echo "$FOLDERS" | wc -l | tr -d ' ')
echo ""
echo "Trovate $FOLDER_COUNT cartelle con file audio:"
echo "$FOLDERS" | while read -r f; do
count=$(find "$f" -maxdepth 1 -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.wav" -o -iname "*.flac" \) | wc -l | tr -d ' ')
# Conta gia convertiti
done_file="$f/.upgraded_tracks"
if [ -f "$done_file" ]; then
done_count=$(wc -l < "$done_file" | tr -d ' ')
remaining=$((count - done_count))
if [ "$remaining" -le 0 ]; then
echo -e " ${GREEN}$(basename "$f")${NC} ($count file - tutti convertiti)"
else
echo -e " ${YELLOW}$(basename "$f")${NC} ($count file - $remaining da convertire)"
fi
else
echo -e " ${YELLOW}$(basename "$f")${NC} ($count file)"
fi
done
echo ""
echo -e "${YELLOW}I file originali verranno sovrascritti!${NC}"
echo -e "${GRAY}I brani gia convertiti verranno saltati automaticamente.${NC}"
read -p "Vuoi continuare? (s/n): " CONFIRM
if [[ ! "$CONFIRM" =~ ^[sS]$ ]]; then
echo "Operazione annullata."
exit 0
fi
# Processa ogni cartella
FOLDER_INDEX=0
echo "$FOLDERS" | while read -r folder; do
((FOLDER_INDEX++))
echo ""
echo -e "${BOLD}>>> Cartella $FOLDER_INDEX/$FOLDER_COUNT <<<${NC}"
process_folder "$folder"
done
else
# Modalita singola cartella
if [ -z "$1" ]; then
echo -e "${CYAN}Inserisci il percorso della cartella da convertire:${NC}"
read -r SOURCE_DIR
else
SOURCE_DIR="$1"
fi
if [ ! -d "$SOURCE_DIR" ]; then
echo -e "${RED}Errore: Directory '$SOURCE_DIR' non trovata${NC}"
exit 1
fi
# Conta file
TOTAL=$(find "$SOURCE_DIR" -maxdepth 1 -type f \( -iname "*.mp3" -o -iname "*.m4a" -o -iname "*.wav" -o -iname "*.flac" \) | wc -l | tr -d ' ')
if [ "$TOTAL" -eq 0 ]; then
echo -e "${RED}Nessun file audio trovato nella cartella${NC}"
exit 1
fi
# Conta gia convertiti
DONE_FILE="$SOURCE_DIR/.upgraded_tracks"
if [ -f "$DONE_FILE" ]; then
DONE_COUNT=$(wc -l < "$DONE_FILE" | tr -d ' ')
REMAINING=$((TOTAL - DONE_COUNT))
echo -e "Cartella: ${YELLOW}$SOURCE_DIR${NC}"
echo -e "Totale: $TOTAL file | ${GREEN}Gia convertiti: $DONE_COUNT${NC} | Da fare: $REMAINING"
else
echo -e "Cartella: ${YELLOW}$SOURCE_DIR${NC}"
echo "Trovati $TOTAL file audio"
fi
echo ""
echo -e "${YELLOW}I file originali verranno sovrascritti!${NC}"
echo -e "${GRAY}I brani gia convertiti verranno saltati automaticamente.${NC}"
read -p "Vuoi continuare? (s/n): " CONFIRM
if [[ ! "$CONFIRM" =~ ^[sS]$ ]]; then
echo "Operazione annullata."
exit 0
fi
process_folder "$SOURCE_DIR"
fi
echo ""
echo "========================================"
echo -e " ${GREEN}COMPLETATO${NC}"
echo "========================================"