Pages : 1
#1 Le 03/06/2009, à 21:17
- Totor
ffmpeg + barre de progression
Bonsoir,
Bien souvent, je vois une demande sans solution concernant ffmpeg associé à une barre de progression.
La solution n'est pas évidente de part le format de restitution des informations de ffmpeg.
Je me suis donc penché sur le problème et en voici une solution valable à la fois pour conversions de vidéos et d'audios :
#!/bin/bash
ffmpeg <les options ffmpeg qui vont bien> 2>&1 </dev/null | awk --re-interval ' BEGIN { dureeTotale=0; pctEncode=0; oldPct=0; print 0; fflush();} /Duration/ {p=match($0, /[0-9]{2}:[0-9]{2}:[0-9]{2}/, r); v=r[0]; s=3600; while ( match(v,/[0-9]{2}/,d) > 0) { dureeTotale=d[0]*s+dureeTotale; s=s/60; v=substr(v, RSTART+RLENGTH)}; RS="\r" } /time=.*/ {p=match($0,/time.*=/,r); duree=r[0]; gsub(/[[:alpha:]=[:blank:]]/,"",duree); pctEncode=int(duree*100/dureeTotale); ;if (pctEncode != oldPct) { oldPct=pctEncode; print pctEncode; fflush()}; }' | zenity --progress --auto-close --auto-kill
Enjoy !
EDIT :
- ajout de --auto-kill pour Zenity
- ATTENTION : L'utilisation de l'option -t de ffmpeg rend le calcul du pourcentage d'évolution erroné. (légère modification à apporter plus tard)
Dernière modification par Totor (Le 03/06/2009, à 21:59)
-- Lucid Lynx --
Hors ligne
#2 Le 03/06/2009, à 21:37
- wido
Re : ffmpeg + barre de progression
Bonjour, vraiment excellent
tu es un dieu
Hors ligne
#3 Le 03/06/2009, à 22:01
- loicm54
Re : ffmpeg + barre de progression
Bonsoir,
pour ma part ... :-/
awk: not an option: --re-interva
ça a l'air interessant sinon
ubuntu 9,04 jaunty/ core2duo E8400@3.6Ghz / hd4850 Golden Sample
Hors ligne
#4 Le 03/06/2009, à 22:16
- wido
Re : ffmpeg + barre de progression
est-ce que l'on peut l'adapter à du convertissage de masse? une vingtaine de vidéo avec un bon petit script nautilus-scripts?
Hors ligne
#5 Le 04/06/2009, à 08:45
- Totor
Re : ffmpeg + barre de progression
awk: not an option: --re-interva
l'option est --re-interval et non --re-interva mais je ne pense pas que tu l'aies oublié en faisant un copier/coller.
est-ce que l'on peut l'adapter à du convertissage de masse? une vingtaine de vidéo avec un bon petit script nautilus-scripts?
il faudrait que je connaisse la durée totale de toutes les sources à convertir. mais c'est jouable J'ai déjà ma petite idée sur le sujet !
Par ailleurs, il est possible d'effectuer plusieurs passe avec ffmpeg, je ne l'ai jamais fait mais je pense que le script ne fonctionnera pas dans ce cas...
-- Lucid Lynx --
Hors ligne
#6 Le 04/06/2009, à 15:46
- loicm54
Re : ffmpeg + barre de progression
En effet, erreur sur le c/c,, l'erreur est bien :
awk: not an option: --re-interval
sous jaunty x64, sans dépots particuliers...
ubuntu 9,04 jaunty/ core2duo E8400@3.6Ghz / hd4850 Golden Sample
Hors ligne
#7 Le 04/06/2009, à 19:57
- Totor
Re : ffmpeg + barre de progression
En effet, erreur sur le c/c,, l'erreur est bien :
awk: not an option: --re-interval
sous jaunty x64, sans dépots particuliers...
moi aussi sous jaunty en x64.
Je pense que tu utilises awk et non gawk !
Vérifie ton lien symbolique :
> ls -l $(which awk)
lrwxrwxrwx 1 root root 21 2008-09-15 22:18 /usr/bin/awk -> /etc/alternatives/awk
> ls -l /etc/alternatives/awk
lrwxrwxrwx 1 root root 13 2009-05-10 21:11 /etc/alternatives/awk -> /usr/bin/gawk
Si c'est le cas, change awk par gawk dans mon script.
-- Lucid Lynx --
Hors ligne
#8 Le 04/06/2009, à 21:59
- loicm54
Re : ffmpeg + barre de progression
gawk n'était pas installé, une fois fait, l'alternative est bien gawk et tout roule
ubuntu 9,04 jaunty/ core2duo E8400@3.6Ghz / hd4850 Golden Sample
Hors ligne
#9 Le 05/06/2009, à 04:03
- Totor
Re : ffmpeg + barre de progression
est-ce que l'on peut l'adapter à du convertissage de masse? une vingtaine de vidéo avec un bon petit script nautilus-scripts?
J'ai modifié le script pour qu'il puisse effectuer un traitement de masse et aussi pour prendre en compte différents type de conversion (nécessite un paramètrage).
Cependant, je ne connais pas nautilus-script, je laisse donc le soin aux personnes averties de s'en charger.
#!/bin/bash
FIC_PARAM=~/.pffmpegrc
# tests d'usage
if [ $# -lt 2 ]; then
cat <<EOF >&2
Nombre de paramètres incorrectes.
$(basename "$0") : TypeDeConversion ListeFichiers
TypeDeConversion : Défini dans le fichier ~/.pffmpegrc, il fait le lien entre les paramètres ffmpeg à appliquer et l'extension souhaitée.
ListeFichiers : Liste des fichiers à convertir.
Le fichier ~/.pffmpegrc se compose de 3 colonnes séparées par un ";".
1ère colonne : TypeDeConversion
2nde colonne : extension souhaitée
3ème colonne : paramètres ffmpeg. Ne pas y inclure le paramètre "-i" car "$(basename "$0")" s'en charge pour le positionner en 1ère position des paramètres. Il est cependant possible de spécifier sa position avec le mot <SOURCE>.
Exemple de contenu :
#type de conversion video pour psp
psp;mp4;-threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272
# type de conversion mp3
audio;mp3;-y -ar 44100 -ab 160 -ac 2
Exemple d'utilisation :
$(basename "$0") psp /video/*.avi
EOF
exit 1
fi
typeConv="$1"
shift
# récupération extension finale et ligne de commande correspondant au type de conversion
oldIFS="${IFS}"
IFS=";"
infosffmpeg=( $(grep "^${typeConv};" "${FIC_PARAM}"|head -1) )
if [ ${#infosffmpeg[@]} -ne 3 ]; then
echo "Type de conversion non trouvée !" >&2
exit 1
fi
extffmpeg="${infosffmpeg[1]}"
cmdffmpeg="${infosffmpeg[2]}"
IFS="${oldIFS}"
# récupération de la durée totale des fichiers à convertir
dureeTotale=0
indice=0
for fichier in "$@"
do
if [ ! -f "${fichier}" ]; then
echo "'${fichier}' n'est pas un fichier valide !" >&2
exit 1
fi
duration="$(ffmpeg -i "${fichier}" 2>&1| grep Duration | egrep -o "[0-9]{2}:[0-9]{2}:[0-9]{2}")"
duration=( ${duration//:/ } )
duree=$(( ${duration[0]}*3600 + ${duration[1]}*60 + ${duration[2]} ))
dureeFichier[${indice}]=${duree}
dureeTotale=$(( duree + dureeTotale ))
indice=$((indice+1))
done
# conversion des fichiers
dureeEcoulee=0
indice=0
for fichier in "$@"
do
rm -f "${fichier}.${extffmpeg}" >&/dev/null
SOURCE="-i \"${fichier}\""
if [[ "${cmdffmpeg}" =~ \<SOURCE\> ]]; then
cmd="${cmdffmpeg/<SOURCE>/${SOURCE}}"
else
cmd="${SOURCE} ${cmdffmpeg}"
fi
eval "ffmpeg ${cmd} \"${fichier}.${extffmpeg}\"" 2>&1 | awk -v dureeEcoulee=${dureeEcoulee} -v dureeTotale=${dureeTotale}--re-interval ' BEGIN {RS="\r"; pctEncode=int(dureeEcoulee*100/dureeTotale); oldPct=pctEncode; print pctEncode; fflush();} /time=.*/ {p=match($0,/time.*=/,r); duree=r[0]; gsub(/[[:alpha:]=[:blank:]]/,"",duree); pctEncode=int((dureeEcoulee+duree)*100/dureeTotale); if (pctEncode != oldPct) { oldPct=pctEncode; print pctEncode; fflush(); } }'
dureeEcoulee=$(( dureeFichier[${indice}] + dureeEcoulee ))
indice=$((indice+1))
done | zenity --progress --auto-close --auto-kill --text="Conversion de type ${typeConv}"
-- Lucid Lynx --
Hors ligne
#10 Le 05/06/2009, à 20:25
- Totor
Re : ffmpeg + barre de progression
Pour ceux que cela intéresse, voilà une autre version mais avec un affichage de la progression unitaire et total (en console) :
#!/bin/bash
FIC_PARAM=~/.pffmpegrc
# tests d'usage
if [ $# -lt 2 ]; then
cat <<EOF >&2
Nombre de paramètres incorrectes.
$(basename "$0") : TypeDeConversion ListeFichiers
TypeDeConversion : Défini dans le fichier ~/.pffmpegrc, il fait le lien entre les paramètres ffmpeg à appliquer et l'extension souhaitée.
ListeFichiers : Liste des fichiers à convertir.
Le fichier ~/.pffmpegrc se compose de 3 colonnes séparées par un ";".
1ère colonne : TypeDeConversion
2nde colonne : extension souhaitée
3ème colonne : paramètres ffmpeg. Ne pas y inclure le paramètre "-i" car "$(basename "$0")" s'en charge pour le positionner en 1ère position des paramètres. Il est cependant possible de spécifier sa position avec le mot <SOURCE>.
Exemple de contenu :
#type de conversion video pour psp
psp;mp4;-threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272
# type de conversion mp3
audio;mp3;-y -ar 44100 -ab 160 -ac 2
Exemple d'utilisation :
$(basename "$0") psp /video/*.avi
EOF
exit 1
fi
typeConv="$1"
shift
# récupération extension finale et ligne de commande correspondant au type de conversion
oldIFS="${IFS}"
IFS=";"
infosffmpeg=( $(grep "^${typeConv};" "${FIC_PARAM}"|head -1) )
if [ ${#infosffmpeg[@]} -ne 3 ]; then
echo "Type de conversion non trouvée !" >&2
exit 1
fi
extffmpeg="${infosffmpeg[1]}"
cmdffmpeg="${infosffmpeg[2]}"
IFS="${oldIFS}"
# récupération de la durée totale des fichiers à convertir
dureeTotale=0
indice=0
for fichier in "$@"
do
if [ ! -f "${fichier}" ]; then
echo "'${fichier}' n'est pas un fichier valide !" >&2
exit 1
fi
duration="$(ffmpeg -i "${fichier}" 2>&1| grep Duration | egrep -o "[0-9]{2}:[0-9]{2}:[0-9]{2}")"
duration=( ${duration//:/ } )
duree=$(( ${duration[0]}*3600 + ${duration[1]}*60 + ${duration[2]} ))
dureeFichier[${indice}]=${duree}
dureeTotale=$(( duree + dureeTotale ))
indice=$((indice+1))
done
function affiche_evolution
{
type_conv="${1}"
options_conv="${2}"
# sauvegarde de la position du curseur:
echo "Type de conversion : ${type_conv}"
echo "Options de conversion : ${options_conv}"
i=0
fichier=""
while read -a infos
do
# restauration de la position du curseur
if [ ${i} -eq 1 ]; then
#echo -en "\033[u"
echo -en "\r\033[1A"
fi
i=1
# transformation de la chaine en tableau
# 0 : % total
# 1 : % ecoule courant
# ... : Fichier courant
evolution=( ${infos} )
pctTotal=" "${infos[0]}
pctTotal="${pctTotal:$((${#pctTotal}-3))} %"
pctCourant=" "${infos[1]}
pctCourant="${pctCourant:$((${#pctCourant}-3))} %"
infos[0]=""
infos[1]=""
courant=${infos[@]}
echo "Progression totale : ${pctTotal}"
if [ "${fichier}" != "${courant}" ]; then
# changement de fichier, on efface tout le contenu du précédant affichage afin d'éviter des bugs d'affichage
echo -n "Fichier ${fichier//?/ } : "
fichier=${courant}
fi
echo -en "\rFichier ${fichier} : ${pctCourant}"
done
echo
}
# conversion des fichiers
dureeEcoulee=0
indice=0
for fichier in "$@"
do
rm -f "${fichier}.${extffmpeg}" >&/dev/null
SOURCE="-i \"${fichier}\""
if [[ "${cmdffmpeg}" =~ \<SOURCE\> ]]; then
cmd="${cmdffmpeg/<SOURCE>/${SOURCE}}"
else
cmd="${SOURCE} ${cmdffmpeg}"
fi
eval "ffmpeg ${cmd} \"${fichier}.${extffmpeg}\"" 2>&1 | awk -v dureeEcoulee=${dureeEcoulee} -v dureeTotale=${dureeTotale} -v unFichier="${fichier}" -v dureeFichier=${dureeFichier[${indice}]} --re-interval ' BEGIN {RS="\r"; pctEncode=int(dureeEcoulee*100/dureeTotale); oldPct=pctEncode; print pctEncode " " 0 " " unFichier; fflush();} /time=.*/ {p=match($0,/time.*=/,r); duree=r[0]; gsub(/[[:alpha:]=[:blank:]]/,"",duree); pctEncode=int(duree*100/dureeFichier); if (pctEncode != oldPct) { oldPct=pctEncode; print int((duree+dureeEcoulee)*100/dureeTotale) " " pctEncode " " unFichier; fflush(); } }'
dureeEcoulee=$(( dureeFichier[${indice}] + dureeEcoulee ))
indice=$((indice+1))
done | affiche_evolution "${typeConv}" "${cmdffmpeg}"
EDIT : je précise que l'affichage est multi-lignes :
1ère ligne : type de conversion
2nde ligne : options de conversion
3ème ligne : progression totale
4ème ligne : progression unitaire (fichier en cours)
Seules les 2 dernières sont rafraichies (le pavé n'est pas ré-affiché à chaque fois).
EDIT2 : correction d'un bug d'affichage pouvant se produire au changement de fichier
Dernière modification par Totor (Le 06/06/2009, à 09:22)
-- Lucid Lynx --
Hors ligne
#11 Le 06/06/2009, à 11:08
- benoit2600
Re : ffmpeg + barre de progression
une idée pour utiliser la commande avec gtkdialog plutot que zenity ?
Hors ligne
#12 Le 06/06/2009, à 11:38
- wido
Re : ffmpeg + barre de progression
petit souci avec un gros fichier (.vob) il me met une progression totale de 402% et on dirait que c'est aléatoire, je ne sais pas si ça a joué mais j'étais en train d'encoder une vidéo avec ffmpeg.
[wido@desktop ~]$ '/home/wido/new file' psp '/media/HDD120/film.vob'
Type de conversion : psp
Options de conversion : -threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272
Progression totale : 402 %
Fichier /media/HDD120/film.vob : 402 %
[wido@desktop ~]$
Hors ligne
#13 Le 06/06/2009, à 12:03
- Totor
Re : ffmpeg + barre de progression
une idée pour utiliser la commande avec gtkdialog plutot que zenity ?
Je ne connais pas gtkdialog car non formalisme ne m'attire pas. Je trouve cela très lourd et c'est pourquoi je n'ai jamais mis le nez dedans.
Cependant, dans ma dernière version, awk renvoie sur une même ligne :
- le %total de la progresssion (1ère colonne)
- le % du fichier en cours de traitement (2nde colonne)
- le nom du fichier en cours de traitement (toute les autres colonnes)
le tout séparé par un espace (attention aux noms de fichiers contenant au moins un espace).
il faut "simplement" modifier la fonction affiche_evolution et l'adapter à gtkdialog.
Demande à AnsuzPeorth, Hizoka ou frafra qui maitrisent cette techno.
petit souci avec un gros fichier (.vob) il me met une progression totale de 402% et on dirait que c'est aléatoire, je ne sais pas si ça a joué mais j'étais en train d'encoder une vidéo avec ffmpeg.
je regarde ça ! Je n'ai jamais travaillé avec des vob... je dois donc m'en fournir un et étudier la chose...
-- Lucid Lynx --
Hors ligne
#14 Le 06/06/2009, à 13:22
- Totor
Re : ffmpeg + barre de progression
petit souci avec un gros fichier (.vob) il me met une progression totale de 402% et on dirait que c'est aléatoire, je ne sais pas si ça a joué mais j'étais en train d'encoder une vidéo avec ffmpeg.
[wido@desktop ~]$ '/home/wido/new file' psp '/media/HDD120/film.vob' Type de conversion : psp Options de conversion : -threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272 Progression totale : 402 % Fichier /media/HDD120/film.vob : 402 % [wido@desktop ~]$
Il y avait une anomalie dans le calcul de la durée totale du fichier qui provenait d'une limite bash.
Je l'ai corrigé mais j'ai des soucis avec ffmpeg qui ne connait pas le format VOB. Il faut que je regarde ça... (Depuis que je suis passé sous Jaunty, j'ai pas mal de pb avec ffmpeg que je dois recompiler à la mano )
Voici la correction :
#!/bin/bash
FIC_PARAM=~/.pffmpegrc
function affiche_evolution
{
type_conv="${1}"
options_conv="${2}"
# sauvegarde de la position du curseur:
echo "Type de conversion : ${type_conv}"
echo "Options de conversion : ${options_conv}"
i=0
fichier=""
ligne=""
while read -a infos
do
# restauration de la position du curseur
if [ ${i} -eq 1 ]; then
#echo -en "\033[u"
echo -en "\r\033[1A"
fi
i=1
# transformation de la chaine en tableau
# 0 : % total
# 1 : % ecoule courant
# ... : Fichier courant
evolution=( ${infos} )
pctTotal=" "${infos[0]}
pctTotal="${pctTotal:$((${#pctTotal}-3))} %"
pctCourant=" "${infos[1]}
pctCourant="${pctCourant:$((${#pctCourant}-3))} %"
infos[0]=""
infos[1]=""
courant=${infos[@]}
echo "Progression totale : ${pctTotal}"
if [ "${fichier}" != "${courant}" ]; then
# changement de fichier, on efface tout le contenu du précédant affichage afin d'éviter des bugs d'affichage
echo -en "${ligne//?/ }"
fichier=${courant}
fi
ligne="Fichier ${fichier} : ${pctCourant}"
echo -en "\r${ligne}"
done
echo
}
# tests d'usage
if [ $# -lt 2 ]; then
cat <<EOF >&2
Nombre de paramètres incorrectes.
$(basename "$0") : TypeDeConversion ListeFichiers
TypeDeConversion : Défini dans le fichier ~/.pffmpegrc, il fait le lien entre les paramètres ffmpeg à appliquer et l'extension souhaitée.
ListeFichiers : Liste des fichiers à convertir.
Le fichier ~/.pffmpegrc se compose de 3 colonnes séparées par un ";".
1ère colonne : TypeDeConversion
2nde colonne : extension souhaitée
3ème colonne : paramètres ffmpeg. Ne pas y inclure le paramètre "-i" car "$(basename "$0")" s'en charge pour le positionner en 1ère position des paramètres. Il est cependant possible de spécifier sa position avec le mot <SOURCE>.
Exemple de contenu :
#type de conversion video pour psp
psp;mp4;-threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272
# type de conversion mp3
audio;mp3;-y -ar 44100 -ab 160 -ac 2
Exemple d'utilisation :
$(basename "$0") psp /video/*.avi
EOF
exit 1
fi
typeConv="$1"
shift
# récupération extension finale et ligne de commande correspondant au type de conversion
oldIFS="${IFS}"
IFS=";"
infosffmpeg=( $(grep "^${typeConv};" "${FIC_PARAM}"|head -1) )
if [ ${#infosffmpeg[@]} -ne 3 ]; then
echo "Type de conversion non trouvée !" >&2
exit 1
fi
extffmpeg="${infosffmpeg[1]}"
cmdffmpeg="${infosffmpeg[2]}"
IFS="${oldIFS}"
# récupération de la durée totale des fichiers à convertir
dureeTotale=0
indice=0
for fichier in "$@"
do
if [ ! -f "${fichier}" ]; then
echo "'${fichier}' n'est pas un fichier valide !" >&2
exit 1
fi
dureeFichier[${indice}]=0
while read duration
do
duration=( ${duration//:/ } )
duree=$(bc <<< "${duration[0]}*3600 + ${duration[1]}*60 + ${duration[2]}")
dureeFichier[${indice}]=$(bc <<< "${dureeFichier[${indice}]} + ${duree}")
done < <(ffmpeg -i "${fichier}" 2>&1| grep Duration | egrep -o "[0-9]{2}:[0-9]{2}:[0-9]{2}")
dureeTotale=$( bc <<< "${dureeFichier[${indice}]} + ${dureeTotale}")
((indice++))
done
# conversion des fichiers
dureeEcoulee=0
indice=0
for fichier in "$@"
do
rm -f "${fichier}.${extffmpeg}" >&/dev/null
SOURCE="-i \"${fichier}\""
if [[ "${cmdffmpeg}" =~ \<SOURCE\> ]]; then
cmd="${cmdffmpeg/<SOURCE>/${SOURCE}}"
else
cmd="${SOURCE} ${cmdffmpeg}"
fi
eval "ffmpeg ${cmd} \"${fichier}.${extffmpeg}\"" 2>&1 | awk -v dureeEcoulee=${dureeEcoulee} -v dureeTotale=${dureeTotale} -v unFichier="${fichier}" -v dureeFichier=${dureeFichier[${indice}]} --re-interval ' BEGIN {RS="\r"; pctEncode=int(dureeEcoulee*100/dureeTotale); oldPct=pctEncode; print pctEncode " " 0 " " unFichier; fflush();} /time=.*/ {p=match($0,/time.*=/,r); duree=r[0]; gsub(/[[:alpha:]=[:blank:]]/,"",duree); pctEncode=int(duree*100/dureeFichier); if (pctEncode != oldPct) { oldPct=pctEncode; print int((duree+dureeEcoulee)*100/dureeTotale) " " pctEncode " " unFichier; fflush(); } }'
dureeEcoulee=$(( dureeFichier[${indice}] + dureeEcoulee ))
((indice++))
done | affiche_evolution "${typeConv}" "${cmdffmpeg}"
Dernière modification par Totor (Le 06/06/2009, à 22:10)
-- Lucid Lynx --
Hors ligne
#15 Le 07/06/2009, à 20:50
- Totor
Re : ffmpeg + barre de progression
Nouvelle version avec un affichage plus détaillé :
#!/bin/bash
FIC_PARAM=~/.pffmpegrc
function formaterSecondes
{
secondes="${1}"
format="$(awk ' { secondes=$0; heure=int(secondes/3600); minute=int((secondes-3600*heure)/60); seconde=secondes-3600*heure-60*minute;print heure" "minute " " seconde } ' <<< ${secondes})"
elements=( ${format} )
for((idx=0;idx<${#elements[@]};idx++))
do
elements[${idx}]="0${elements[${idx}]}"
elements[${idx}]=${elements[${idx}]:$(( ${#elements[${idx}]} - 2))}
done
echo "${elements[0]}:${elements[1]}:${elements[2]}"
}
function affiche_evolution
{
type_conv="${1}"
options_conv="${2}"
nb_fichier="${3}"
duree_totale="${4}"
duree_totaleHHMMSS="$(formaterSecondes ${duree_totale})"
echo "Type de conversion : ${type_conv}"
echo "Options de conversion : ${options_conv}"
echo
echo "Progression totale :"
echo -e "\tDurée Totale à traiter : ${duree_totaleHHMMSS}"
i=0
fichier=""
ligneFichier=""
ligneDuree=""
while read infos
do
setterm -cursor off
# restauration de la position du curseur
if [ ${i} -eq 1 ]; then
echo -en "\r\033[4A"
fi
i=1
# transformation de la chaine en tableau
# 0 : % total
# 1 : % ecoule courant
# ... : Fichier courant
oldIFS="${IFS}"
IFS=";"
infos=( ${infos} )
numFichier="${infos[0]}"
nomFichier="${infos[1]}"
dureeFichierTraitee="${infos[2]}"
dureeFichierTotale="${infos[3]}"
dureeTotaleTraitee="${infos[4]}"
IFS="${oldIFS}"
dureeFichierTraiteeHHMMSS="$(formaterSecondes ${dureeFichierTraitee})"
dureeFichierTotaleHHMMSS="$(formaterSecondes ${dureeFichierTotale})"
dureeTotaleTraiteeHHMMSS="$(formaterSecondes ${dureeTotaleTraitee})"
pctTotal=" $(awk '{print int($1*100/$2)}' <<< "${dureeTotaleTraitee} ${duree_totale}")"
pctTotal="${pctTotal:$((${#pctTotal}-3))} %"
pctCourant=" $(awk '{print int($1*100/$2)}' <<< "${dureeFichierTraitee} ${dureeFichierTotale}")"
pctCourant="${pctCourant:$((${#pctCourant}-3))} %"
echo -e "\tDurée totale traitée : ${dureeTotaleTraiteeHHMMSS} (${pctTotal})\n"
if [ "${nomFichier}" != "${fichier}" ]; then
# changement de fichier, on efface tout le contenu du précédant affichage afin d'éviter des bugs d'affichage
echo -en "${ligneFichier//?/ }\r"
fichier=${nomFichier}
fi
ligneFichier="Fichier ${numFichier}/${nb_fichier} : ${fichier}"
echo "${ligneFichier}"
echo -e "\tDurée : ${dureeFichierTotaleHHMMSS}"
echo -en "\t${ligneDuree//?/ }\r"
ligneDuree="Durée traitée : ${dureeFichierTraiteeHHMMSS} (${pctCourant})"
echo -en "\t${ligneDuree}"
setterm -cursor on
done
echo
}
# tests d'usage
if [ $# -lt 2 ]; then
cat <<EOF >&2
Nombre de paramètres incorrectes.
$(basename "$0") : TypeDeConversion ListeFichiers
TypeDeConversion : Défini dans le fichier ~/.pffmpegrc, il fait le lien entre les paramètres ffmpeg à appliquer et l'extension souhaitée.
ListeFichiers : Liste des fichiers à convertir.
Le fichier ~/.pffmpegrc se compose de 3 colonnes séparées par un ";".
1ère colonne : TypeDeConversion
2nde colonne : extension souhaitée
3ème colonne : paramètres ffmpeg. Ne pas y inclure le paramètre "-i" car "$(basename "$0")" s'en charge pour le positionner en 1ère position des paramètres. Il est cependant possible de spécifier sa position avec le mot <SOURCE>.
Exemple de contenu :
#type de conversion video pour psp
psp;mp4;-threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272
# type de conversion mp3
audio;mp3;-y -ar 44100 -ab 160 -ac 2
Exemple d'utilisation :
$(basename "$0") psp /video/*.avi
EOF
exit 1
fi
typeConv="$1"
shift
# récupération extension finale et ligne de commande correspondant au type de conversion
oldIFS="${IFS}"
IFS=";"
infosffmpeg=( $(grep "^${typeConv};" "${FIC_PARAM}"|head -1) )
if [ ${#infosffmpeg[@]} -ne 3 ]; then
echo "Type de conversion non trouvée !" >&2
exit 1
fi
extffmpeg="${infosffmpeg[1]}"
cmdffmpeg="${infosffmpeg[2]}"
IFS="${oldIFS}"
# récupération de la durée totale des fichiers à convertir
dureeTotale=0
indice=0
for fichier in "$@"
do
if [ ! -f "${fichier}" ]; then
echo "'${fichier}' n'est pas un fichier valide !" >&2
exit 1
fi
dureeFichier[${indice}]=0
while read duration
do
duration=( ${duration//:/ } )
duree=$(bc <<< "${duration[0]}*3600 + ${duration[1]}*60 + ${duration[2]}")
dureeFichier[${indice}]=$(bc <<< "${dureeFichier[${indice}]} + ${duree}")
done < <(ffmpeg -i "${fichier}" 2>&1| grep Duration | egrep -o "[0-9]{2}:[0-9]{2}:[0-9]{2}")
dureeTotale=$( bc <<< "${dureeFichier[${indice}]} + ${dureeTotale}")
((indice++))
done
# conversion des fichiers
dureeEcoulee=0
indice=0
for fichier in "$@"
do
rm -f "${fichier}.${extffmpeg}" >&/dev/null
SOURCE="-i \"${fichier}\""
if [[ "${cmdffmpeg}" =~ \<SOURCE\> ]]; then
cmd="${cmdffmpeg/<SOURCE>/${SOURCE}}"
else
cmd="${SOURCE} ${cmdffmpeg}"
fi
# numFichier;nomFichier;dureeEcouleeFichier;dureeTotaleFichier;dureeEcouleeTotale
eval "ffmpeg ${cmd} \"${fichier}.${extffmpeg}\"" 2>&1 | awk -v numFichier=$((${indice}+1)) -v dureeTotaleFichier=${dureeFichier[${indice}]} -v dureeEcoulee=${dureeEcoulee} -v dureeTotale=${dureeTotale} -v unFichier="${fichier}" -v dureeFichier=${dureeFichier[${indice}]} --re-interval ' BEGIN {RS="\r"; print numFichier";"unFichier";"0";"dureeTotaleFichier";"dureeEcoulee ; fflush();} /time=.*/ {p=match($0,/time.*=/,r); duree=r[0]; gsub(/[[:alpha:]=[:blank:]]/,"",duree);duree=int(duree); pctEncode=int(duree*100/dureeFichier); print numFichier";"unFichier";"duree";"dureeTotaleFichier";"duree+dureeEcoulee; fflush(); }'
dureeEcoulee=$(( dureeFichier[${indice}] + dureeEcoulee ))
((indice++))
done | affiche_evolution "${typeConv}" "${cmdffmpeg}" "$#" "${dureeTotale}"
EDIT :
- à venir : Affichage des délais de traitements en plus des durées traitées (totale et unitaire)
Dernière modification par Totor (Le 07/06/2009, à 21:10)
-- Lucid Lynx --
Hors ligne
#16 Le 08/06/2009, à 20:30
- Totor
Re : ffmpeg + barre de progression
Comme convenu :
ajout des informations globales et unitaires suivante :
- heure de début de traitement
- durée de traitement
- fin de traitement prévisionnelle
#!/bin/bash
FIC_PARAM=~/.pffmpegrc
trap "finScript" SIGINT SIGTERM
function restaure_curseur
{
setterm -cursor on
setterm -linewrap on
}
function finScript
{
echo
echo "Traitement interrompu." >&2
restaure_curseur
exit 1
}
function formaterSecondes
{
secondes="${1}"
format="$(awk ' { secondes=$0; heure=int(secondes/3600); minute=int((secondes-3600*heure)/60); seconde=secondes-3600*heure-60*minute;print heure" "minute " " seconde } ' <<< ${secondes})"
elements=( ${format} )
for((idx=0;idx<${#elements[@]};idx++))
do
# si un seul caractère alors on ajoute 0. (pas de test au delas de 2 caractères pour une durée > 99h59min59sec
if [ ${#elements[${idx}]} -eq 1 ]; then
elements[${idx}]="0${elements[${idx}]}"
fi
done
echo "${elements[0]}:${elements[1]}:${elements[2]}"
}
function ajuste_longueur
{
texte="$1"
longueur=$2
caractere="${3:-" "}"
while [ ${#texte} -lt ${longueur} ]
do
texte="${texte}${caractere}"
done
texte="${texte:0:${longueur}}"
echo "${texte}"
}
function ajuste_multiligne
{
texte="$1"
longueur=$2
caractere="${3:-" "}"
local chaineResultat=""
while [ ${#texte} -gt ${longueur} ];
do
if [ ! "${chaineResultat}" ]; then
chaineResultat="${texte:0:${longueur}}"
else
chaineResultat="${chaineResultat}\n${texte:0:${longueur}}"
fi
texte="${texte:${longueur}}"
done
texte="$(ajuste_longueur "${texte}" ${longueur})"
if [ ! "${chaineResultat}" ]; then
chaineResultat="${texte}"
else
chaineResultat="${chaineResultat}\n${texte}"
fi
echo "${chaineResultat}"
}
function format_ligne
{
local ligneType="${1}"
local dureeVide="${2}"
shift 2
for((idx=1;idx<=5;idx++))
do
ligneType="${ligneType/${dureeVide}/ $1 }"
shift
done
ligneType="${ligneType/ xxx % / ${1} }"
echo "${ligneType}"
}
function affiche_evolution
{
type_conv="${1}"
options_conv="${2}"
nb_fichier="${3}"
duree_totale="${4}"
duree_totaleHHMMSS="$(formaterSecondes ${duree_totale})"
secondes_debut="${5}"
# Conversion en HH:MM:SS des secondes depuis @
heure_debut="$(date +'%H:%M:%S' -d "@${secondes_debut}")"
i=0
fichier=""
ligneFichier=""
ligneDuree=""
setterm -cursor off
setterm -linewrap off
nbCols=$(($(tput cols)-1))
ligneTiret=$(ajuste_longueur "" ${nbCols} "-")
dureeVide=" -------- "
dureeVierge=" "
ligneInfoType="|${dureeVide}|${dureeVide}|${dureeVide}|${dureeVide}|${dureeVide}| xxx % |"
ligneInfoVide="${ligneInfoType//[-x%]/ }"
nbColNomFichier=$((${nbCols}-${#ligneInfoType}-3))
# affichage des informations de conversion (static)
echo -e "\n${ligneTiret}"
echo "$(ajuste_longueur "| Type de conversion : ${type_conv}" $((${nbCols}-1)))|"
uneChaine="Options de conversion : ${options_conv}"
uneChaine="$(ajuste_multiligne "${uneChaine}" $((${nbCols}-4)))"
echo -e "| ${uneChaine//\\n/ |\\n| } |"
echo "${ligneTiret}"
# affichage de la légende
echo "$(ajuste_longueur "| Légende : " $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| Fichier : Fichier en cours de conversion" $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| HDT : Heure de Début de Traitement" $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| DTE : Durée de Traitement Ecoulée" $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| HFP : Heure de Fin de traitement Prévisionnelle" $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| DTF : Durée à Traiter du Fichier" $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| DCF : Durée Convertie du Fichier" $((${nbCols}-1)))|"
echo "$(ajuste_longueur "| EVO : EVOlution du traitement" $((${nbCols}-1)))|"
echo "${ligneTiret}"
# affichage entete
echo "| $(ajuste_longueur "Fichier" ${nbColNomFichier}) $(format_ligne "${ligneInfoType}" "${dureeVide}" " HDT " " DTE " " HFP " " DTF " " DCF " " EVO ")"
echo "${ligneTiret}"
while read infos
do
oldIFS="${IFS}"
IFS=";"
infos=( ${infos} )
numFichier="${infos[0]}"
#nomFichier="$(ajuste_longueur ${infos[1]} 300 "x")"
nomFichier="#${numFichier} - ${infos[1]}"
dureeFichierTraitee="${infos[2]}"
dureeFichierTotale="${infos[3]}"
dureeTotaleTraitee="${infos[4]}"
secondes_fichier="${infos[5]}"
debut_fichier="$(date +'%H:%M:%S' -d "@${secondes_fichier}")"
IFS="${oldIFS}"
# restauration de la position du curseur au nivau des inforamtions de la progression
if [ ${i} -eq 1 ]; then
if [ "${fichier}" != "${nomFichier}" ]; then
chaineRetour="\033[1A"
else
chaineRetour="\033[${nbLigne}A"
fi
echo -en "\r${chaineRetour}"
echo -en "\033[$((nbColNomFichier+2))C"
fi
secondes_traitement="$(date +'%s')"
delai_total=$((${secondes_traitement}-${secondes_debut}))
delai_totalHHMMSS="$(formaterSecondes ${delai_total})"
dureeFichierTraiteeHHMMSS="$(formaterSecondes ${dureeFichierTraitee})"
dureeFichierTotaleHHMMSS="$(formaterSecondes ${dureeFichierTotale})"
dureeTotaleTraiteeHHMMSS="$(formaterSecondes ${dureeTotaleTraitee})"
delai_fichier=$((${secondes_traitement}-${secondes_fichier}))
delai_fichierHHMMSS="$(formaterSecondes ${delai_fichier})"
pctTotal="$(awk '{printf("%1.0f",$1*100/$2)}' <<< "${dureeTotaleTraitee} ${duree_totale}")"
heureFinTotalHHMMSS="--:--:--"
if [ ${pctTotal} -ne 0 ]; then
secTotalFin="$(awk '{printf("%1.0f",$1*100/$2)}' <<< "${delai_total} ${pctTotal}")"
((secTotalFin+=secondes_debut))
heureFinTotalHHMMSS="$(date +'%H:%M:%S' -d "@${secTotalFin}")"
fi
pctTotal=" ${pctTotal} %"
pctTotal="${pctTotal:$((${#pctTotal}-5))}"
pctCourant="$(awk '{printf("%1.0f",$1*100/$2)}' <<< "${dureeFichierTraitee} ${dureeFichierTotale}")"
heureFinFichierHHMMSS="--:--:--"
if [ ${pctCourant} -ne 0 ]; then
secFichierFin="$(awk '{printf("%1.0f",$1*100/$2)}' <<< "${delai_fichier} ${pctCourant}")"
((secFichierFin+=secondes_fichier))
heureFinFichierHHMMSS="$(date +'%H:%M:%S' -d "@${secFichierFin}")"
fi
pctCourant=" ${pctCourant} %"
pctCourant="${pctCourant:$((${#pctCourant}-5))}"
if [ "${fichier}" != "${nomFichier}" ]; then
# changement de fichier, on affiche le nouveau nom de fichier
uneChaine="$(ajuste_multiligne "${nomFichier}" ${nbColNomFichier})"
echo -ne "\r| ${uneChaine//\\n/ \\n| }"
nbLigne="$(echo -e "${uneChaine}"|wc -l)"
nbLigne=$((nbLigne+2))
# on remonte de nbLigne-3 (i.e si l'affichage du nom de fichier s'effectue sur plusieurs lignes)
if [ ${nbLigne} -gt 3 ]; then
chaineRetour="\033[$((nbLigne-3))A"
echo -en "${chaineRetour}"
fi
fi
echo -e " $(format_ligne "${ligneInfoType}" "${dureeVide}" "${debut_fichier}" "${delai_fichierHHMMSS}" "${heureFinFichierHHMMSS}" "${dureeFichierTotaleHHMMSS}" "${dureeFichierTraiteeHHMMSS}" "${pctCourant}")"
ligneSep=""
if [ "${fichier}" != "${nomFichier}" ]; then
ligneSep="\r\033[$((nbColNomFichier+3))C${ligneInfoVide}"
fi
for((idx=4;idx<=${nbLigne};idx++));
do
echo -e "${ligneSep}"
done;
fichier="${nomFichier}"
echo "${ligneTiret}"
echo -e "| $(ajuste_longueur "Total (${nb_fichier} fichier(s))" ${nbColNomFichier}) $(format_ligne "${ligneInfoType}" "${dureeVide}" "${heure_debut}" "${delai_totalHHMMSS}" "${heureFinTotalHHMMSS}" "${duree_totaleHHMMSS}" "${dureeTotaleTraiteeHHMMSS}" "${pctTotal}")"
echo -n "${ligneTiret}"
i=1
done
echo
restaure_curseur
}
# tests d'usage
if [ $# -lt 2 ]; then
cat <<EOF >&2
Nombre de paramètres incorrectes.
$(basename "$0") : TypeDeConversion ListeFichiers
TypeDeConversion : Défini dans le fichier ~/.pffmpegrc, il fait le lien entre les paramètres ffmpeg à appliquer et l'extension souhaitée.
ListeFichiers : Liste des fichiers à convertir.
Le fichier ~/.pffmpegrc se compose de 3 colonnes séparées par un ";".
1ère colonne : TypeDeConversion
2nde colonne : extension souhaitée
3ème colonne : paramètres ffmpeg. Ne pas y inclure le paramètre "-i" car "$(basename "$0")" s'en charge pour le positionner en 1ère position des paramètres. Il est cependant possible de spécifier sa position avec le mot <SOURCE>.
Exemple de contenu :
#type de conversion video pour psp
psp;mp4;-threads 4 -y <SOURCE> -r 29.97 -acodec libfaac -ab 128kb -ac 2 -ar 48000 -vcodec libx264 -level 21 -b 768kb -coder 1 -f psp -flags +loop -cmp +chroma -trellis 2 -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me_method umh -subq 6 -trellis 1 -refs 3 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -g 250 -s 480x272
# type de conversion mp3
audio;mp3;-y -ar 44100 -ab 160 -ac 2
Exemple d'utilisation :
$(basename "$0") psp /video/*.avi
EOF
exit 1
fi
typeConv="$1"
shift
# récupération extension finale et ligne de commande correspondant au type de conversion
oldIFS="${IFS}"
IFS=";"
infosffmpeg=( $(grep "^${typeConv};" "${FIC_PARAM}"|head -1) )
if [ ${#infosffmpeg[@]} -ne 3 ]; then
echo "Type de conversion non trouvée !" >&2
exit 1
fi
extffmpeg="${infosffmpeg[1]}"
cmdffmpeg="${infosffmpeg[2]}"
IFS="${oldIFS}"
# récupération de la durée totale des fichiers à convertir
dureeTotale=0
indice=0
for fichier in "$@"
do
if [ ! -f "${fichier}" ]; then
echo "'${fichier}' n'est pas un fichier valide !" >&2
exit 1
fi
dureeFichier[${indice}]=0
while read duration
do
duration=( ${duration//:/ } )
duree=$(bc <<< "${duration[0]}*3600 + ${duration[1]}*60 + ${duration[2]}")
dureeFichier[${indice}]=$(bc <<< "${dureeFichier[${indice}]} + ${duree}")
done < <(ffmpeg -i "${fichier}" 2>&1| grep Duration | egrep -o "[0-9]{2}:[0-9]{2}:[0-9]{2}")
dureeTotale=$( bc <<< "${dureeFichier[${indice}]} + ${dureeTotale}")
((indice++))
done
# conversion des fichiers
dureeEcoulee=0
indice=0
secondes_debut="$(date +'%s')"
for fichier in "$@"
do
rm -f "${fichier}.${extffmpeg}" >&/dev/null
SOURCE="-i \"${fichier}\""
if [[ "${cmdffmpeg}" =~ \<SOURCE\> ]]; then
cmd="${cmdffmpeg/<SOURCE>/${SOURCE}}"
else
cmd="${SOURCE} ${cmdffmpeg}"
fi
# numFichier;nomFichier;dureeEcouleeFichier;dureeTotaleFichier;dureeEcouleeTotale;secondes_fichier (nb secondes depuis @)
eval "ffmpeg ${cmd} \"${fichier}.${extffmpeg}\"" 2>&1 | awk -v secondes_fichier="$(date +'%s')" -v numFichier=$((${indice}+1)) -v dureeTotaleFichier=${dureeFichier[${indice}]} -v dureeEcoulee=${dureeEcoulee} -v dureeTotale=${dureeTotale} -v unFichier="${fichier}" -v dureeFichier=${dureeFichier[${indice}]} --re-interval ' BEGIN {RS="\r"; print numFichier";"unFichier";"0";"dureeTotaleFichier";"dureeEcoulee";"secondes_fichier ; fflush();} /time=.*/ {p=match($0,/time.*=/,r); duree=r[0]; gsub(/[[:alpha:]=[:blank:]]/,"",duree);duree=int(duree); pctEncode=int(duree*100/dureeFichier); print numFichier";"unFichier";"duree";"dureeTotaleFichier";"duree+dureeEcoulee";"secondes_fichier; fflush(); }'
dureeEcoulee=$(( dureeFichier[${indice}] + dureeEcoulee ))
((indice++))
done | affiche_evolution "${typeConv}" "${cmdffmpeg}" "$#" "${dureeTotale}" "${secondes_debut}"
EDIT :
+ suppression affichage curseur (permet un meilleur affichage)
+ gestion de l'arrêt du script pour rétablir le curseur
+ Amélioration du rendu des informations (au détriment des perfs)
+ Modification du mécanisme d'affichage pour tenter de gagner en perf.
-----
+ 23/06/2009 : Refonte de l'interface afin d'avoir une historisation des fichiers traités
Dernière modification par Totor (Le 23/06/2009, à 20:15)
-- Lucid Lynx --
Hors ligne
#17 Le 10/06/2009, à 08:37
- redisded
Re : ffmpeg + barre de progression
Bonjour à tous,
une fois de plus, immense respect à Totor...
Je n'ai pas acces au net facilement pour le moment mais cela devrait etre réglé la semaine prochaine.
Si certaines personnes sont toujours intéréssées, je verrais pour jeter un oeil à l'integration de Gtkdialog.
Encore merci à Totor, cette fonctionnalité manquait cruellement à ffmpeg.
Hors ligne