Convertir des fichiers flac en fichiers mp3

Un livre de Wikilivres.
Aller à : navigation, rechercher
Broom icon.svg
Cette page est une feuille volante

Il faudrait la ranger dans un wikilivre où elle aurait sa place.

Introduction[modifier | modifier le wikitexte]

Cette page explique comment réaliser un script Bash permettant la conversion d'un lots de fichiers au format FLAC vers le format mp3.


Buts[modifier | modifier le wikitexte]

  • Profiter des avantages de l'écoute de nos CD préférés sur notre ordinateur avec une compression sans perte de qualité grâce au format FLAC
  • Les lecteurs de formats audio compressés (autoradio, par exemple) ne supportent malheureusement que le mp3 et le wma
  • Conversion des fichiers en masse, avec la propagation des tags (informations sur l'artiste, le genre, etc)

Procédé[modifier | modifier le wikitexte]

Les CD encodés se trouvent, par exemple, dans le répertoire:

 ~/musique/flac/ARTISTE/ALBUM 

Le but est de retrouver la même arborescence pour nos mp3:

 ~/musique/mp3/ARTISTE/ALBUM 

Avant la conversion, les fichiers FLAC devront êtres vérifiés (j'ai personnellement eu des erreurs). Après conversion, une seconde vérification sera faite sur le fichier de sortie. Si le fichier de destination existe déjà, il sera vérifié et reconvertis s'il est défectueux. Un fichier de log est créé dans le répertoire racine des fichiers FLAC.

Prérequis[modifier | modifier le wikitexte]

  • Un système avec Bash (Linux, OSX, BSD ou autre UNIX)
  • Les paquets flac, lame, id3, mp3check

Le script[modifier | modifier le wikitexte]

Le script est organisé en fonctions:

  • Navigation dans les répertoires / sous répertoires de façon récursive
  • Création des répertoires cibles
  • Tests des fichiers
  • Conversions
  • Tests d'erreurs

Attention ![modifier | modifier le wikitexte]

Ce script écrit des données sur le disque, et n'est pas un logiciel éprouvé ! N'hésitez pas à l'analyser avant de l'exécuter. Encore mieux, créez une session de test sur votre machine. Vous voilà prévenus !

Edition du script[modifier | modifier le wikitexte]

  • Renseigner la variable SRC_ROOT avec l'emplacement des fichiers FLAC
  • Renseigner la variable DEST_ROOT pour l'emplacement des fichiers mp3

Exécution[modifier | modifier le wikitexte]

Il suffit d'exécuter, tout est automatisé. Il est possible de passer un autre répertoire de source FLAC en premier argument.

#!/bin/bash

# WARNING:
# This software writes to discs, it can be Dangerous !
# Use it at your own risk ! Never as root !!
# NO WARANTY, for every damage than can be encoured !

# LICENCE:
# This software is free software
# Please read the GPL Licence aviable here:
# http://www.gnu.org/copyleft/gpl.html

# AUTHORS:
# Philippe Steinmann, largement aidé par
# l'exemple tiré de http://pvanhoof.be/wiki/index.php/Converting_flac_to_mp3

# Packets requis:
# flac
# lame
# id3
# mp3check

# Repertoire source (le / de fin est important!)
SRC_ROOT="$HOME/musique/flac/"
if [ ! -z "$1" ]
then
        SRC_ROOT="$1"
fi

if [ ! -e "$SRC_ROOT" ]
then
        echo "$SRC_ROOT n'existe pas - abandon"
        exit 1
fi

# Racine de destination (chemin absolu)
DEST_ROOT="$HOME/musique/mp3"
#DEST_ROOT="/tmp/tests_mp3"

# Format de date
DATE=$(date +%d-%m-%Y)

# Fichier de logs
LOG_FILE="$SRC_ROOT"/flac_to_mp3-$DATE.log

# Variables globales
ARTIST=''
TITLE=''
ALBUM=''
GENRE=''
TRACKNUMBER=''
FDATE=''

# Teste l'état de $? pour connaître l'état de sortie de la dernière commande
# Si l'argument 1 est renseigné, le texte affiché contiendra ce qui y est passé
# Si l'argument 2 contient la chaîne "QUIT", le script s'arrête en cas d'erreur
function test_err() {
        if [ "$?" != "0" ]
        then
                if [ -z "$1" ]
                then
                        echo "Une erreur est survenue !"
                        echo "Une erreur est survenue !" >> "$LOG_FILE"
                        if [ "$2" == "QUIT" ]
                        then
                                echo "-> Abandon !"
                                exit -1
                        fi
                else
                        echo "Une erreur est survenue lors $1"
                        echo "Une erreur est survenue lors $1" >> "$LOG_FILE"
                        if [ "$2" == "QUIT" ]
                        then
                                echo "-> Abandon !"
                                exit -1
                        fi
                fi
                return 1
        else
                return 0
        fi
}

# Cette fonction stocke les méta-données du
# fichier flac passe en $1
# Il faut que la validité du fichier soit
# testée avant !
function get_meta_flac()
{
        ARTIST=$(metaflac "$1" --show-tag=ARTIST | sed s/.*=//g)
        TITLE=$(metaflac "$1" --show-tag=TITLE | sed s/.*=//g)
        ALBUM=$(metaflac "$1" --show-tag=ALBUM | sed s/.*=//g)
        TRACKNUMBER=$(metaflac "$1" --show-tag=TRACKNUMBER | sed s/.*=//g)
        FDATE=$(metaflac "$1" --show-tag=DATE | sed s/.*=//g)
        GENRE=$(metaflac "$1" --show-tag=GENRE | sed s/.*=//g)
}


# Tester la validité des fichiers flac
# du répertoire passé en $1
function test_flac()
{
        local FILE
        local EXT
        local LEN
        local ERR=0

        for FILE in "$1"/*
        do
                # Fichiers uniquement
                if [ -f "$FILE" ]
                then
                        # On ne prend que les extensions .flac
                        LEN=$(echo "$FILE" | wc -m)
                        LEN=$(($LEN - 6))
                        EXT=${FILE:LEN}
                        if [ "$EXT" == ".flac" ]
                        then
                                echo "Test de $FILE"
                                flac --test -s "$FILE"
                                if [ "$?" != "0" ]
                                then
                                        echo "renommage $FILE en $FILE.defect"
                                        mv "$FILE" "$FILE.defect"
                                        echo "FLAC défectueux: $FILE" >> "$LOG_FILE"
                                else
                                        # On poursuit avec ce fichier
                                        get_meta_flac "$FILE"
                                        encode_mp3 "$FILE"
                                fi
                        fi
                fi
        done
}

# Cette fonction crée un répertoire portant
# le nom passé en $1, dans le rép destination
function make_dest_dir()
{
        local LEN
        local DEST_DIR
        local REL

        LEN=$(echo "$SRC_ROOT" | wc -m)
        LEN=$((LEN - 1))
        DEST_DIR=${1:LEN}
        DEST_DIR="$DEST_ROOT"/"$DEST_DIR"
        REL=${DEST_DIR::1}
        if [ "$REL" != "/" ]
        then
                echo "Chemin relatif -> ignoré"
                return 1
        fi

        #echo "dest: $DEST_DIR"

        if [ ! -e "$DEST_DIR" ]
        then
                echo "création de $DEST_DIR"
                mkdir -p "$DEST_DIR"
                test_err "la création de $DEST_DIR"
        fi
}

# Cette fonction encode les mp3 passés en $1
# en le plaçant dans les rep de destination
function encode_mp3()
{
        local LEN
        local DEST_FILE
        local REL

        # Déterminer chemin destination
        LEN=$(echo "$SRC_ROOT" | wc -m)
        LEN=$((LEN - 1))
        DEST_FILE=${1:LEN}
        DEST_FILE="$DEST_ROOT"/"$DEST_FILE"
        # Changer extension
        DEST_FILE=$(echo "$DEST_FILE" | sed s/\.flac/.mp3/g)
        # Éviter les chemins relatifs
        REL=${DEST_FILE::1}
        if [ "$REL" != "/" ]
        then
                echo "Chemin relatif -> ignoré"
                return 1
        fi

        # Si le fichier existe, on le vérifie
        if [ -f "$DEST_FILE" ]
        then
                echo "mp3 déjà existant: $DEST_FILE"
                echo "-> test $DEST_FILE"
                mp3check -e -B -G "$DEST_FILE"
                if [ "$?" == "0" ]
                then
                        echo "-->valide: $DEST_FILE"
                else
                        echo "-->invalide -> réencode $DEST_FILE"
                        # Encodage: je fais confiance aux presets LAME (lame --preset help)
                        flac -c -d "$1" | lame -h --preset standard -s 44.1 - "$DEST_FILE"
                fi
        else
                echo "encode $DEST_FILE"
                # Encodage: je fais confiance aux presets LAME (lame --preset help)
                flac -c -d "$1" | lame -h --preset standard -s 44.1 - "$DEST_FILE"
                if [ "$?" != "0" ]
                then
                        echo "Erreur encodage de $DEST_FILE" >> "$LOG_FILE"
                        return 1
                fi
        fi


        # id3 tags
        echo "id3 tags sur $DEST_FILE"
        id3 -t "$TITLE" -T "$TRACKNUMBER" -a "$ARTIST" -A "$ALBUM" -y "$FDATE" "$DEST_FILE"
        # Si le genre est inconnu, id3 quitte, c'est pourquoi on sépare
        id3 -g "$GENRE" "$DEST_FILE"
        # Tester si l'encodage est OK
        mp3check -e -B -G "$DEST_FILE"
        if [ "$?" != "0" ]
        then
                echo "Echec encodage $DEST_FILE"
                echo "Echec encodage $DEST_FILE" >> "$LOG_FILE"
        fi
        echo "DONE -> test $DEST_FILE"
        echo ""
}

# Cette fonction sera appelée par travel_dir
# elle recevra le nom du répertoire courant en $1
# et son chemin complet en $2
function exec_in_dir()
{
        make_dest_dir "$2"
        test_flac "$2"
}

# Utiliser cette fonction pour descendre récursivement dans les 
# répertoires
function travel_dir()
{
        local DIR
        local FILE

        # test droit de lecture et si $1 est un répertoire
        if [ -r "$1" ]
        then
                if [ -d "$1" ]
                then
                        DIR="$1"
                        #echo "traitement de $DIR"
                else
                        #echo "$1 n'est pas un répertoire"
                        return
                fi
        else
                return
        fi

        # Ajout au tableau DIRSTACK (voir man Bash)
        pushd "$DIR" > /dev/null

        # Pour tout le contenu, si rep, descendre
        for FILE in *
        do
                if test -d "$FILE" ; then
                        #echo "Descente dans $FILE"
                        travel_dir "$FILE"
                fi
        done

        exec_in_dir "$DIR" "$PWD"

        # retrait du tableau
        popd > /dev/null
}




# Main
echo "" >> "$LOG_FILE"
echo "$0" >> "$LOG_FILE"
echo "Encodage flac -> mp3" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
travel_dir "$SRC_ROOT"

Inspiration[modifier | modifier le wikitexte]

Un article similaire, en anglais [1], notamment pour l'utilisation des outils (lame, metaflac, id3), ainsi que la technique pour accéder de manière récursive dans les sous répertoires.