Uno script per la ricerca di file mp3 corrotti nella libreria musicale

Trova i file mp3 corrotti nella tua libreria musicale

Recentemente ho implementato un servizio di streaming musicale con Navidrome sul raspberry pi, per poter ascoltare la mia musica anche quando sono fuori casa tramite una qualsiasi applicazione compatibile con le API di Subsonic, ce ne sono diverse sul play store.

Ebbene, mentre ero in giro in bicicletta ascoltando la mia musica in streaming tramite l’app, ho notato che a volte la coda di riproduzione si fermava. Quando ho controllato per vedere cosa era successo ho visto che la traccia che sarebbe dovuta partire non partiva, premendo play non succedeva niente, per continuare la riproduzione dovevo passare alla traccia successiva, fino a quando non si bloccava ancora.

La causa di questo comportamento era dovuta al fatto che c’erano dei file mp3 corrotti, e quindi l’app giustamente si bloccava e non proseguiva la sua coda di riproduzione, dico giustamente perchè se se così non fosse, se l’app avesse saltato quel brano e fosse passato al successivo, probabilmente non mi sarei neanche accorto di avere dei file mp3 corrotti nella mia libreria musicale.

Come trovare tutti gli mp3 corrotti?

A questo punto il mio primo pensiero è stato: “Quanti altri file mp3 corrotti ci saranno nella mia libreria msicale?” e soprattutto: “Come faccio a individuarli?” Anche perchè di solito le collezioni musicali raggiungono facilmente grandi dimensioni, parliamo di migliaia di file, è impensabile farli passare tutti uno a uno.

Da qui l’idea di creare uno script ad-hoc per scovare tutti gli mp3 corrotti. In primo luogo ho cercato in rete un comando per verificare l’integrità di un file audio, e mi sono imbattuto in questo che usa ffmpeg, il popolare software open-source per la gestione di file multimediali:

ffmpeg -v error -i song.mp3 -f null -

Se è tutto ok il comando non produrrà alcun output, se invece trova anche la più piccola anomalia la segnala. Come vedremo più aventi, non è detto però che il file sia irriproducibile, è però un segnale che c’è qualche cosa che non va.

Quindi ora abbiamo il comando per verificare l’integrità di un file mp3, l’idea è di usare questo comando in un ciclo in modo che venga eseguito per tutti i file mp3 nella directory corrente e tutte le eventuali sottocartelle. In pratica, se il comando viene dato dalla directory che contiene tutte le cartelle della collezione musicale verranno scansionati tutti gli mp3 della libreria musicale.

È anche possibile scansionare solo le cartelle desiderate spostandosi nella cartella che si vuole controllare. Qui sotto puoi vedere la parte dello script che si occupa della scansione:

for root, dirs, files in os.walk("."):
    for file in files:
        if file.endswith(".mp3"):
            filepath = os.path.join(root, file)
            # Esegui il comando ffmpeg e cattura sia stdout che stderr
            result = subprocess.run(
                ["ffmpeg", "-v", "error", "-i", filepath, "-f", "null", "-"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            # Controlla se il comando è stato eseguito correttamente e se non ci sono errori nell'output
            if result.returncode == 0 and not result.stderr:
                print(f"{file} ok")
            else:
                # Stampa il messaggio di errore nel terminale in rosso
                print_red(f"{file} corrotto")
                # Aggiungi il nome del file al file di log
                with open(logfile, "a") as log:
                    log.write(filepath + "\n")
                # Aggiungi il file alla lista dei file corrotti
                corrupted_files.append(filepath)

ogni volta che viene trovato un file corrotto il nome del file viene aggiunto a un file di log (il file di log viene creato dallo script nella directory corrente con il nome corrupted_mp3.log) e viene anche memorizzato in una lista il percorso assoluto del file, questo servirà dopo, ma ci arriviamo.

Se invece il file analizzato è a posto verrà stampato il nome del file con un ok. Inoltre ogni volta che si avvia una scansione il file di log (se presente) viene svuotato.

Come riparare i file mp3 corrotti?

Adesso che abbiamo automatizzato il controllo dei file e fatto in modo di creare anche un file di log con tutte le occorrenze trovate, non ci resta che sistemare i file corrotti tentando di ripararli. Ora bisogna fare una precisazione, durante il processo di scansione della libreria musicale, è possibile che alcuni file mp3 vengano segnalati come corrotti ma è importante notare che non tutti i file indicati come corrotti sono necessariamente irriproducibili. In alcuni casi, i file corrotti possono comunque essere ascoltati senza apparenti problemi.

Il nostro script, alla fine della scansione, nel caso fossero stati trovati file corrotti stamperà la lista dei file e ti chiederà se vuoi tentare di ripararli e se si risponde di si tenterà di riparare i file mp3 usando mp3val. Tuttavia, è importante essere consapevoli che il tentativo di riparazione potrebbe anche fallire, In questi casi, il file corrotto potrebbe rimanere irriproducibile o con difetti audio.

Se il tentativo di riparazione fallisce, sarà necessario sostituire i file corrotti con nuove copie funzionanti. Di seguito puoi vedere un video che mostra il funzionamento dello script.

Questo è solo un esempio per mostrare il funzionamento. Quando ho scansionato la mia intera collezione ho trovato alla fine una ventina di file corrotti che neanche mp3val è riuscito a riparare e un’altra ventina circa che risultavano corrotti ma che erano ancora riproducibili, in questo caso mp3val li ha riparati e alla seconda scansione non venivano più rilevati come corrotti.

Di seguito trovate lo script completo che potete scaricare da qui, prima di usarlo assicuratevi di avere installato i pacchetti ffmpeg e mp3val. Su ubuntu e derivate puoi facilmente installarli dal terminale con:

sudo apt install ffmpeg mp3val

e qui lo script completo:

#!/usr/bin/env python

import os
import subprocess

# Definisci il file di log
logfile = "corrupted_mp3.log"

# Svuota il file di log se esiste
with open(logfile, "w") as log:
    log.write("")

# Lista dei file corrotti
corrupted_files = []

# Funzione per stampare il testo in rosso
def print_red(text):
    print("\033[91m" + text + "\033[0m")

# Trova e verifica tutti i file .mp3 nella directory corrente e sottodirectory
for root, dirs, files in os.walk("."):
    for file in files:
        if file.endswith(".mp3"):
            filepath = os.path.join(root, file)
            # Esegui il comando ffmpeg e cattura sia stdout che stderr
            result = subprocess.run(
                ["ffmpeg", "-v", "error", "-i", filepath, "-f", "null", "-"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            # Controlla se il comando è stato eseguito correttamente e se non ci sono errori nell'output
            if result.returncode == 0 and not result.stderr:
                print(f"{file} ok")
            else:
                # Stampare il messaggio di errore nel terminale in rosso
                print_red(f"{file} corrotto")
                # Aggiungi il nome del file al file di log
                with open(logfile, "a") as log:
                    log.write(filepath + "\n")
                # Aggiungi il file alla lista dei file corrotti
                corrupted_files.append(filepath)

# Se sono stati trovati file corrotti, chiedi all'utente se vuole tentarne la riparazione
if corrupted_files:
    print_red("Sono stati trovati i seguenti file corrotti:")
    for file in corrupted_files:
        print(file)
    
    response = input("Vuoi tentare di ripararli con mp3val? (s/n): ").strip().lower()
    if response == 's':
        for file in corrupted_files:
            print(f"Tentando di riparare {file}...")
            repair_result = subprocess.run(
                ["mp3val", "-f", "-nb", file],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            if repair_result.returncode == 0:
                print(f"{file} riparato con successo.")
            else:
                print_red(f"Errore nella riparazione di {file}.")
    else:
        print("Riparazione dei file corrotti annullata.")

print(f"Controllo completato. Vedi {logfile} per i dettagli.")

Lo script è commentato in modo chiaro, per quanto riguarda la parte che si occupa della riparazione del file mp3 l’unica cosa che potreste voler modificare è l’opzione -nb in quanto mp3val, quando tenta di riparare il file, crea un backup del file stesso che sta tentando di riparare, rinominandolo con lo stesso nome ma aggiungendo .bak alla fine (per esempio titolo-canzone.mp3.bak).

Se si vuole creare il backup del file che si sta tentando di riparare allora vi basterà cancellare l’opzione -nb in modo che la riga diventi:

["mp3val", "-f", file],

Una volta salvato lo script per esempio in /usr/local/bin ed avergli dato i permessi di esecuzione con sudo +x /usr/local/bin/check_mp3.py potete posizionarvi nella cartella che desiderate e lanciarlo con:

python /usr/local/bin/check_mp3.py

Questo è tutto, spero che questo script possa esserti utile per scovare tutti gli mp3 corrotti nella tua libreria musicale. Se hai domande o vuoi solo dirmi come è andata, puoi lasciare un commento qui sotto.

Alla prossima!

Lascia il primo commento

Mettiti in contatto

WordPress Maintenance Form