Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 11/08/2022, à 11: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, à 11:33)

Hors ligne

#2 Le 11/08/2022, à 11: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, à 15: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, à 16:46)


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#4 Le 11/08/2022, à 15: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 utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .

Hors ligne

#5 Le 11/08/2022, à 16: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, à 09: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, à 10:37

iznobe

Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??

Watael a écrit :

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, à 10:42)


retour utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .

Hors ligne

#8 Le 12/08/2022, à 11: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. big_smile
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. hmm


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#9 Le 12/08/2022, à 11:37

iznobe

Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??

Aller une petite dernière pour la route tongue
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, à 11:39)


retour utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .

Hors ligne

#10 Le 12/08/2022, à 12: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, à 15:20

iznobe

Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??

Hizoka a écrit :

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 utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .

Hors ligne

#12 Le 12/08/2022, à 15: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, à 16:55

iznobe

Re : [RESOLU] ffmpeg qui fout la grouille dans une boucle bash ??

ok merci bien wink c ' est quand meme un langage de malade , pour ceux qui maitrisent .

Encore merci pour ces explications .


retour utilisable de commande
MSI Z490A-pro , i7 10700 , 32 GB RAM .

Hors ligne