#1 Le 14/01/2019, à 22:33
- vallo
[Résolu]Boucle pour convertir par lot des wav en mp3
Bonjour
J'essaie - mais en vain - d'écrire un script shell pour convertir plusieurs fichiers .wav en .mp3 avec ffmpeg.
Ces fichiers sont disséminés sur un gros disque utilisé par des applications musicales ou matériels (home studio).
Logique du programme :
- lancer une recherche des fichiers .wav par find avec sortie dans un fichier texte (nom avec chemin relatif;taille en octets)
- lecture en boucle du fichier obtenu avec while read ligne
- suppression de l'extension .wav pour chaque ligne et mise en variable temporaire
- ajout de l'extension .mp3 à la variable temporaire pour chaque ligne
- ffmpeg -i fichier_wav fichier_mp3
Tous les essais faits en matière d'écriture des variables (backquote, simple quote, double quote, {} ....) se soldent par un échec.
#!/bin/bash
ficout="FilesToConvert.txt" # contient chemin complet et nom des fichiers à convertir
while read ligne
do
echo "ligne inscrite dans le fichier => " ${ligne} # affiche le nom du fichier complet à traiter
fic=$(echo -e "$ligne\n"|cut -d';' -f1) # fichier à traiter avec son chemin complet. Le champ 2 est la taille du fichier
echo "Nom complet du fichier à traiter => "$fic # affiche la ligne "interprétée". Tronquée aux passages 2 et 4
fic_supp=${fic%.*} #suppression de l'extension
echo "Fichier à traiter sans extension => " $fic_supp
ficmp3=${fic_supp}.mp3 # ajout de l'extension .mp3
echo "Fichier devant normalement être obtenu =>" $ficmp3
ffmpeg -i $fic $ficmp3
echo "ffmpeg est fini"
echo
done < $ficout
Le dernier test fait sur 4 fichiers .wav situés dans le même répertoire (cf. ci-dessous) aboutit à la conversion d'1 fichier sur 2.
Le suivi des variables dans la boucle montre qu'aux second et quatrième passages, le nom du fichier pris en variable de lecture est tronqué sans que je ne m'explique pourquoi alors que les 4 fichiers sont dans le même dossier et ont donc un début de nom identique. Par suite ffmpeg ne peut convertir les fichiers lors de ces 2 passages.
Merci pour vos solutions.
Pour info le contenu du fichier test est le suivant :
./Matériel/H4N/PROJ001b/TRK2-00.wav;7276430
./Matériel/H4N/PROJ001b/TRK1-00.wav;9280910
./Matériel/H4N/PROJ001b/TRK4-00.wav;5607822
./Matériel/H4N/PROJ001b/TRK3-00.wav;4303498
Pour info, la lecture de chaque ligne dans le fichier de stockage donne pour chaque passage :
- au premier passage, ligne est bien lue => ./Matériel/H4N/PROJ001b/TRK2-00.wav;7276430
- au second passage ligne est tronquée => iel/H4N/PROJ001b/TRK1-00.wav;9280910
- au troisième passage, ligne est bien lue => ./Matériel/H4N/PROJ001b/TRK4-00.wav;5607822
- au quatrième passage ligne est tronquée => riel/H4N/PROJ001b/TRK3-00.wav;4303498
Dernière modification par vallo (Le 17/01/2019, à 10:33)
Hors ligne
#2 Le 14/01/2019, à 23:21
- vallo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Complément à mon problème
Je viens de faire tourner le code décrit dans ma question en supprimant la ligne ffmpeg
A ma grande surprise, toutes les variables sont OK puisque chacune des 4 lignes du fichier de stockage est correctement lue !!!
C'est donc ffmpeg qui foire !!! Quid ???
Sortie obtenue
ligne inscrite dans le fichier => ./Matériel/H4N/PROJ001b/TRK2-00.wav;7276430
Nom complet du fichier à traiter => ./Matériel/H4N/PROJ001b/TRK2-00.wav
Fichier à traiter sans extension => ./Matériel/H4N/PROJ001b/TRK2-00
Fichier devant normalement être obtenu => ./Matériel/H4N/PROJ001b/TRK2-00.mp3
ffmpeg est fini
ligne inscrite dans le fichier => ./Matériel/H4N/PROJ001b/TRK1-00.wav;9280910
Nom complet du fichier à traiter => ./Matériel/H4N/PROJ001b/TRK1-00.wav
Fichier à traiter sans extension => ./Matériel/H4N/PROJ001b/TRK1-00
Fichier devant normalement être obtenu => ./Matériel/H4N/PROJ001b/TRK1-00.mp3
ffmpeg est fini
ligne inscrite dans le fichier => ./Matériel/H4N/PROJ001b/TRK4-00.wav;5607822
Nom complet du fichier à traiter => ./Matériel/H4N/PROJ001b/TRK4-00.wav
Fichier à traiter sans extension => ./Matériel/H4N/PROJ001b/TRK4-00
Fichier devant normalement être obtenu => ./Matériel/H4N/PROJ001b/TRK4-00.mp3
ffmpeg est fini
ligne inscrite dans le fichier => ./Matériel/H4N/PROJ001b/TRK3-00.wav;4303498
Nom complet du fichier à traiter => ./Matériel/H4N/PROJ001b/TRK3-00.wav
Fichier à traiter sans extension => ./Matériel/H4N/PROJ001b/TRK3-00
Fichier devant normalement être obtenu => ./Matériel/H4N/PROJ001b/TRK3-00.mp3
ffmpeg est fini
Dernière modification par vallo (Le 14/01/2019, à 23:25)
Hors ligne
#3 Le 15/01/2019, à 08:18
- DonutMan75
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Hello,
que renvoie la commande si tu :
1) commentes tout tes "echo"
2) remplace la ligne ffmpeg par : echo ffmpeg -i $fic $ficmp3
?
Par ailleurs, je suggère de mettre des quotes systématiquement pour protéger tes variables : $fic --> "$fic"
Bon courage pour la suite
Donut
Hors ligne
#4 Le 15/01/2019, à 08:50
- pingouinux
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Bonjour,
J'ai l'impression que le problème vient du fait que ffmpeg pose des questions et lit sur l'entrée standard.
Essaye ceci :
while read -u 3 ligne
do
.........................................................;;
done 3< "$ficout"
Hors ligne
#5 Le 15/01/2019, à 09:16
- kholo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
salut,
outre les variables à quotter,
ffmpeg -i "$fic" "$ficmp3"
le fait d'utiliser une fois du bash et une fois cut n'est pas terrible non plus :
pour rappel
maVariable="un texte avec égale (=) en séparateur=des choses et d'autres"
echo "${maVariable}
${maVariable##*=} ; après le dernier =
${maVariable#*=} ; après le premier =
${maVariable%%=*} ; avant le premier =
${maVariable%=*} ; avant le dernier =
"
Hors ligne
#6 Le 15/01/2019, à 09:48
- pingouinux
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Et pour simplifier l'écriture :
while read -u 3 ligne
do
fici=${ligne%;*}
fico=${fici/%.wav/.mp3}
ffmpeg -i "$fici" "$fico"
echo "ffmpeg est fini"
echo
done 3<"$ficout"
Hors ligne
#7 Le 15/01/2019, à 10:32
- kholo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
je dirais même plus :
echo -e "ffmpeg est fini\n..."
...
ou
ffmpeg -i "$fici" "$fico" && echo -e "${fici} compressé" || echo -e "problème avec ${fici}"
bon, tu me diras en cas de soucis, on aura un retour d'erreur de ffmpeg
donc
ffmpeg -i "$fici" "$fico" && echo -e "${fici} compressé"
suffirait
Hors ligne
#8 Le 15/01/2019, à 11:27
- vallo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Hello,
que renvoie la commande si tu :
1) commentes tout tes "echo"
2) remplace la ligne ffmpeg par : echo ffmpeg -i $fic $ficmp3
?Par ailleurs, je suggère de mettre des quotes systématiquement pour protéger tes variables : $fic --> "$fic"
Bon courage pour la suite
Donut
La lecture de ligne est correcte et la boucle est nickel, comme ce que j'avais obtenu en commentant la ligne ffmpeg.
J'obtiens ça
ffmpeg -i ./Matériel/H4N/PROJ001b/TRK2-00.wav ./Matériel/H4N/PROJ001b/TRK2-00.mp3
ffmpeg est fini
ffmpeg -i ./Matériel/H4N/PROJ001b/TRK1-00.wav ./Matériel/H4N/PROJ001b/TRK1-00.mp3
ffmpeg est fini
ffmpeg -i ./Matériel/H4N/PROJ001b/TRK4-00.wav ./Matériel/H4N/PROJ001b/TRK4-00.mp3
ffmpeg est fini
ffmpeg -i ./Matériel/H4N/PROJ001b/TRK3-00.wav ./Matériel/H4N/PROJ001b/TRK3-00.mp3
ffmpeg est fini
Ce qui me fait dire que c'est bien ffmpeg qui met la grouille.
Pour ce qui est de la protection des variables, comme je l'ai dit aussi, j'ai essayé avec backquote, simple quote, double quote .... et résultat toujours identique.
C'est le 2° et 4° passages qui coincent avec une lecture tronquée de la ligne dans le fichier de stockage.
Tous les essais aboutissent à une troncature toujours sur le même caractère mais différent pour la passage 2 et le passage 4.
Je vais essayer les propositions de kholo et pingouinux
Hors ligne
#9 Le 15/01/2019, à 11:42
- vallo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
ffmpeg -i "$fici" "$fico" && echo -e "${fici} compressé"
En mettant cette ligne, j'obtiens toujours le même résultat
Je continue à tester vos solutions
Hors ligne
#10 Le 15/01/2019, à 22:20
- vallo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Bonjour,
J'ai l'impression que le problème vient du fait que ffmpeg pose des questions et lit sur l'entrée standard.
Essaye ceci :while read -u 3 ligne do .........................................................;; done 3< "$ficout"
TROP FORT pingouinux !!!
Ça marche nickel sur mes 4 fichiers.
J'ai testé une boucle incluant ces 4 fichiers + 5 autres fichiers situés dans un autre répertoire et ÇA MARCHE !
Alors maintenant, je suis obligé de compléter ma demande car j'ai trop galéré sur cette p....n de boucle while read pour ne pas comprendre la solution
- que font les options et/ou paramètres -u et 3 après le while read
- que signifie le 3 "collé" à <"$ficout" ?
Mes recherches m'ont conduit sur plusieurs sites parlant de lire et/ou écrire un fichier en utilisant des "file descriptor" pour éviter tous mélange avec l'entrée standard mais ce n'est pas trop clair pour moi qui n'avait jamais vu ni entendu parler de ce sujet.
Juste une petite synthèse ou un lien expliquant simplement le fd 3 serait super. Je suis persuadé que le sujet va intéresser ceux qui écrivent de petits scripts.
Une lecture et ses pages associées
Autre lecture
Merci encore. Je ne tarderai pas à mettre Résolu
Dernière modification par vallo (Le 15/01/2019, à 23:55)
Hors ligne
#11 Le 16/01/2019, à 00:05
- vallo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
Encore une petite question pour pingouinux
Tu proposes de simplifier mon script avec notamment cette ligne
fico=${fici/%.wav/.mp3}
Je comprends ceci :
- par le %.wav je supprime à partir de la fin du nom de fichier les caractères .wav (donc l'extension)
- par /%.wav/.mp3 je substitue en fait .mp3 à .wav
mais ai-je bon ?
Hors ligne
#12 Le 16/01/2019, à 07:08
- pingouinux
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
@vallo #10 :
fd=0 : stdin
fd=1 : stdout
fd=2 : stderr
Si tu ne précises rien pour read, il utilise stdin, ainsi que ffmpeg. Quand ce dernier pose une question et attend une réponse, il lit quelques octets sur $ficout, et le read suivant est décalé.
Pour ne pas mélanger les entrées, il suffit d'utiliser un autre fd pour le read (j'ai choisi 3, mais tu peux utiliser n'importe quel nombre supérieur à 2) :
while read -u 3 ligne
do
.........................................................;;
done 3< "$ficout"
@vallo #11 : Oui
${parameter/pattern/string}
Pattern substitution. The pattern is expanded to produce a pattern just as
in pathname expansion. Parameter is expanded and the longest match of pat‐
tern against its value is replaced with string. If pattern begins with /,
all matches of pattern are replaced with string. Normally only the first
match is replaced. If pattern begins with #, it must match at the beginning
of the expanded value of parameter. If pattern begins with %, it must match
at the end of the expanded value of parameter. If string is null, matches
of pattern are deleted and the / following pattern may be omitted. If
parameter is @ or *, the substitution operation is applied to each posi‐
tional parameter in turn, and the expansion is the resultant list. If
parameter is an array variable subscripted with @ or *, the substitution
operation is applied to each member of the array in turn, and the expansion
is the resultant list.
Dernière modification par pingouinux (Le 16/01/2019, à 07:08)
Hors ligne
#13 Le 16/01/2019, à 07:56
- vallo
Re : [Résolu]Boucle pour convertir par lot des wav en mp3
fd=0 : stdin
fd=1 : stdout
fd=2 : stderr
Ça, je l'avais appris il y a bien bien longtemps, mais j'avoue que je ne souvenais pas que c'était un "file descriptor" et surtout que l'on pouvait en créer d'autres !
En fait, ne serait-il pas judicieux, dans des cas de boucles telles que la mienne, de mettre systématiquement des fd tant pour le fichier en entrée que pour celui en sortie s'il y en a un ?
A ma décharge aussi, c'est vrai aussi que l'on voit peu de scripts avec un fd >2 - en tous cas moi - et que donc, il fallait tomber sur un cas particulier pour revenir aux sources.
MERCI encore pour ce dépannage et cet éclairage.
Hors ligne