#1 Le 11/08/2022, à 10:28
- DonutMan75
[RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Bonjour à tous,
j'ai un fichier audio (récupéré par youtube-dl) que je souhaite découper en plusieurs fichiers mp3 selon un fichier qui contient les timetags.
Voici le fichier des timetags en question :
$ more titres_small
01. Once Upon a Time - 00:00
02. Start Menu - 01:28
03. Your Best Friend - 02:00
04. Fallen Down - 02:24
05. Ruins - 03:21
Je dois donc parser ce fichier, et pour chaque ligne je fais appel à ffmpeg pour venir extraire l'audio à partir du timecode indiqué sur la ligne.
Petite subtilité, comme la ligne en question ne contient que le début du morceau et ni la fin ni la durée, j'ai fait un algorithme en deux passes.
Ainsi quand on lit la ligne N :
1) on extrait l'audio pour la piste N à partir du timecode de la ligne N
2) on revient sur la piste N-1 et on extrait l'audio sur une durée de t_N- t_(N-1)
Voici mon code (remarquez que les deux appels à ffmpeg sont commentés) :
#! /bin/bash
ts_prev_second=""
fout_prev=""
fin="./in/in.mp3"
# First we clean output directory
rm ./pass1/*mp3
rm ./pass2/*mp3
while read -r ligne; do
echo "-----------------------------------"
echo Processing line : $ligne
n=$(echo $ligne | awk -F. '{print $1}')
fout="./pass1/${n}_"$(echo $ligne | awk -F- '{print $1}' | awk -F"." '{print $2}' | sed 's/^ //' | sed 's/ $//' | tr " " "_" | sed 's/,//g').mp3
ts=$(echo $ligne | awk -F- '{print $2}' | sed 's/^ //')
# Incorrect time evaluation if MM:SS instead of HH:MM:SS
[ ${#ts} -eq 5 ] && ts="00:$ts"
ts_second=$(date --date $ts +%s)
echo " - n = $n"
echo " - fout = $fout"
echo " - ts = $ts"
echo " - ts_second = $ts_second"
# Step 1 : on extrait la vidéo à partir de ts jusqu'à la fin
echo " "
echo " - First extraction of file $fout from $ts..."
echo " " ffmpeg -hide_banner -loglevel error -y -i "$fin" -ss $ts -c:a copy "$fout"
#ffmpeg -hide_banner -loglevel error -y -i "$fin" -ss $ts -c:a copy "$fout"
# Step 2 : si on a déjà traité un fichier précédent, on revient dessus...
[ "$fout_prev" ] && (
dt=$(( $ts_second - $ts_prev_second ))
echo " "
echo " - Second extraction of file $fout_prev up to $dt seconds..."
fout_prev_pass2=$(echo $fout_prev | sed 's/pass1/pass2/')
echo " " ffmpeg -hide_banner -loglevel error -y -i "$fout_prev" -t "$dt" -c:a copy "$fout_prev_pass2"
#ffmpeg -hide_banner -loglevel error -y -i "$fout_prev" -t "$dt" -c:a copy "$fout_prev_pass2"
)
# Step 3 : mise-à-jour des variables previous
fout_prev="$fout"
ts_prev_second="$ts_second"
done < ./titres_small
# Final step : the last mp3 should also be copied in the pass2 directory
f_last=$(ls -t ./pass1/*mp3 | head -n 1)
cp "$f_last" ./pass2/
Je sais que les récupérations des variables ne sont pas très propres... Néanmoins, quand j'exécute le script, il me sort des trucs pertinents.
En particulier, les lignes commençant par "Processing line : XXXX" correspondent toutes à une ligne du fichier titres_small.
On constate aussi que les arguments sont bien parsés.
$ ./debug_parse_audio.sh
-----------------------------------
Processing line : 01. Once Upon a Time - 00:00
- n = 01
- fout = ./pass1/01_Once_Upon_a_Time.mp3
- ts = 00:00:00
- ts_second = 1660168800
- First extraction of file ./pass1/01_Once_Upon_a_Time.mp3 from 00:00:00...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:00:00 -c:a copy ./pass1/01_Once_Upon_a_Time.mp3
-----------------------------------
Processing line : 02. Start Menu - 01:28
- n = 02
- fout = ./pass1/02_Start_Menu.mp3
- ts = 00:01:28
- ts_second = 1660168888
- First extraction of file ./pass1/02_Start_Menu.mp3 from 00:01:28...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:01:28 -c:a copy ./pass1/02_Start_Menu.mp3
- Second extraction of file ./pass1/01_Once_Upon_a_Time.mp3 up to 88 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/01_Once_Upon_a_Time.mp3 -t 88 -c:a copy ./pass2/01_Once_Upon_a_Time.mp3
-----------------------------------
Processing line : 03. Your Best Friend - 02:00
- n = 03
- fout = ./pass1/03_Your_Best_Friend.mp3
- ts = 00:02:00
- ts_second = 1660168920
- First extraction of file ./pass1/03_Your_Best_Friend.mp3 from 00:02:00...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:02:00 -c:a copy ./pass1/03_Your_Best_Friend.mp3
- Second extraction of file ./pass1/02_Start_Menu.mp3 up to 32 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/02_Start_Menu.mp3 -t 32 -c:a copy ./pass2/02_Start_Menu.mp3
-----------------------------------
Processing line : 04. Fallen Down - 02:24
- n = 04
- fout = ./pass1/04_Fallen_Down.mp3
- ts = 00:02:24
- ts_second = 1660168944
- First extraction of file ./pass1/04_Fallen_Down.mp3 from 00:02:24...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:02:24 -c:a copy ./pass1/04_Fallen_Down.mp3
- Second extraction of file ./pass1/03_Your_Best_Friend.mp3 up to 24 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/03_Your_Best_Friend.mp3 -t 24 -c:a copy ./pass2/03_Your_Best_Friend.mp3
-----------------------------------
Processing line : 05. Ruins - 03:21
- n = 05
- fout = ./pass1/05_Ruins.mp3
- ts = 00:03:21
- ts_second = 1660169001
- First extraction of file ./pass1/05_Ruins.mp3 from 00:03:21...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:03:21 -c:a copy ./pass1/05_Ruins.mp3
- Second extraction of file ./pass1/04_Fallen_Down.mp3 up to 57 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/04_Fallen_Down.mp3 -t 57 -c:a copy ./pass2/04_Fallen_Down.mp3
ls: impossible d'accéder à './pass1/*mp3': Aucun fichier ou dossier de ce type
cp: impossible d'évaluer '': Aucun fichier ou dossier de ce type
Maintenant, je décommente les deux appels à ffmpeg. Vous observez alors que les lignes "Processing line : XXXX" sont toutes incorrectes sauf la premières...
$ ./debug_parse_audio.sh
rm: impossible de supprimer './pass1/*mp3': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './pass2/*mp3': Aucun fichier ou dossier de ce type
-----------------------------------
Processing line : 01. Once Upon a Time - 00:00
- n = 01
- fout = ./pass1/01_Once_Upon_a_Time.mp3
- ts = 00:00:00
- ts_second = 1660168800
- First extraction of file ./pass1/01_Once_Upon_a_Time.mp3 from 00:00:00...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:00:00 -c:a copy ./pass1/01_Once_Upon_a_Time.mp3
-----------------------------------
Processing line : t Menu - 01:28
- n = t Menu - 01:28
- fout = ./pass1/t Menu - 01:28_.mp3
- ts = 00:01:28
- ts_second = 1660168888
- First extraction of file ./pass1/t Menu - 01:28_.mp3 from 00:01:28...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:01:28 -c:a copy ./pass1/t Menu - 01:28_.mp3
- Second extraction of file ./pass1/01_Once_Upon_a_Time.mp3 up to 88 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/01_Once_Upon_a_Time.mp3 -t 88 -c:a copy ./pass2/01_Once_Upon_a_Time.mp3
-----------------------------------
Processing line : Best Friend - 02:00
- n = Best Friend - 02:00
- fout = ./pass1/Best Friend - 02:00_.mp3
- ts = 00:02:00
- ts_second = 1660168920
- First extraction of file ./pass1/Best Friend - 02:00_.mp3 from 00:02:00...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:02:00 -c:a copy ./pass1/Best Friend - 02:00_.mp3
- Second extraction of file ./pass1/t Menu - 01:28_.mp3 up to 32 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/t Menu - 01:28_.mp3 -t 32 -c:a copy ./pass2/t Menu - 01:28_.mp3
-----------------------------------
Processing line : n Down - 02:24
- n = n Down - 02:24
- fout = ./pass1/n Down - 02:24_.mp3
- ts = 00:02:24
- ts_second = 1660168944
- First extraction of file ./pass1/n Down - 02:24_.mp3 from 00:02:24...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:02:24 -c:a copy ./pass1/n Down - 02:24_.mp3
- Second extraction of file ./pass1/Best Friend - 02:00_.mp3 up to 24 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/Best Friend - 02:00_.mp3 -t 24 -c:a copy ./pass2/Best Friend - 02:00_.mp3
-----------------------------------
Processing line : s - 03:21
- n = s - 03:21
- fout = ./pass1/s - 03:21_.mp3
- ts = 00:03:21
- ts_second = 1660169001
- First extraction of file ./pass1/s - 03:21_.mp3 from 00:03:21...
ffmpeg -hide_banner -loglevel error -y -i ./in/in.mp3 -ss 00:03:21 -c:a copy ./pass1/s - 03:21_.mp3
- Second extraction of file ./pass1/n Down - 02:24_.mp3 up to 57 seconds...
ffmpeg -hide_banner -loglevel error -y -i ./pass1/n Down - 02:24_.mp3 -t 57 -c:a copy ./pass2/n Down - 02:24_.mp3
Je ne comprends pas du tout ce qu'il se passe...
Avez-vous une idée ?
Donut
Dernière modification par DonutMan75 (Le 11/08/2022, à 10:33)
Hors ligne
#2 Le 11/08/2022, à 10:33
- DonutMan75
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Bonjour,
bon je viens de trouver en testouillant,
il faut rajouter l'option -nostdin dans ffmpeg et ça passe tout seul !
Je passe à Résolu.
Donuit
Hors ligne
#3 Le 11/08/2022, à 14:23
- Watael
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
salut,
on ne nettoie pas la cuisine avant de préparer le repas.
awk|awk|sed|sed|sed c'est pas possible : awk sait faire ce que fait sed.
de plus, les enregistrements du fichier sont clairement séparés par un point ou un tiret :
while IFS='.-' read piste titre debut
do
: ...
done < fichier.in
et je mettrais tout ça dans des tableaux, pour les parcourir après, et ainsi pouvoir facilement faire référence à l'indice suivant
while IFS='.-' read piste titre debut
do
pistes++( "$piste" )
titres+=( "$titre" )
debuts+=( "$début" )
done < fichier.in
for i in ${!pistes[*]}
do
echo "$pistes[i]}. ${titres[i]} - ${debuts[i]} fin: ${debuts[i+1]}"
done
il y a encore à faire en sorte de ne pas tenir compte de la première ligne, et des espaces à enlever...
edit: ${debuts[ i ]}
Dernière modification par Watael (Le 11/08/2022, à 15:46)
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#4 Le 11/08/2022, à 14:32
- iznobe
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Bonjour , question bete , mais le debut de la piste n+1 n ' est pas la fin de la piste n ?
retour COMPLET et utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .
Hors ligne
#5 Le 11/08/2022, à 15:47
- Watael
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
le début de la piste courante ($i) est connu, c'est la fin de la piste qui est le début de la suivante ($i+1).
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#6 Le 12/08/2022, à 08:28
- DonutMan75
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Bonjour à tous,
merci Watael pour tes remarques, j'ignorais en particulier qu'il était possible de définir une liste d'IFS avec read !
Je vais nettoyer un peu tout ça.
A bientôt,
Donut
Hors ligne
#7 Le 12/08/2022, à 09:37
- iznobe
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
le début de la piste courante ($i) est connu, c'est la fin de la piste qui est le début de la suivante ($i+1).
oui si on traduit ton code . mais finalement ca revient a dire la meme chose .
Pour ma culture personnelle , c' est possible d' obtenir le meme resultat en imbriquant la boucle for dans la boucle while ?
je pense que oui , mais pourrais tu expliquer pourquoi ne pas l' avoir fait ou pourquoi ne faut il pas le faire stp ?
Dernière modification par iznobe (Le 12/08/2022, à 09:42)
retour COMPLET et utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .
Hors ligne
#8 Le 12/08/2022, à 10:15
- Watael
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
oui si on traduit ton code . mais finalement ca revient a dire la meme chose .
pas du tout.
en inversant les propositions, on peut embrouiller la situation.
on ne peut pas utiliser le tableau alors qu'il n'existe pas encore.
mais on pourrait traiter le fichier précédent en lisant la piste suivante (qui est en fait la piste courante), mais je ne trouve pas ça plus simple.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#9 Le 12/08/2022, à 10:37
- iznobe
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Aller une petite dernière pour la route
dans cette partie :
for i in ${!pistes[*]}
que veut dire le " ! " ?
en general , ce signe signifie : inverse , mais j ' ai l' impression que là ca n' est pas le cas .
Dernière modification par iznobe (Le 12/08/2022, à 10:39)
retour COMPLET et utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .
Hors ligne
#10 Le 12/08/2022, à 11:58
- Hizoka
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Salut,
Il ne faut pas hésiter à tester :
pistes=("oui" "non" "je ne sais pas")
echo "${!pistes[*]}"
# 0 1 2
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#11 Le 12/08/2022, à 14:20
- iznobe
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
Salut,
Il ne faut pas hésiter à tester
ok , mais ca ne me dis pas en quoi il consiste dans cette commande ...
il sert peut etre a afficher les indices au lieu du contenu des variables du tableau ?
retour COMPLET et utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .
Hors ligne
#12 Le 12/08/2022, à 14:40
- Watael
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
c'est ça, l'indice au lieu de la valeur.
bien utile pour "joindre" des tableaux.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#13 Le 12/08/2022, à 15:55
- iznobe
Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??
ok merci bien c ' est quand meme un langage de malade , pour ceux qui maitrisent .
Encore merci pour ces explications .
retour COMPLET et utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .
Hors ligne