Compare commits
2 Commits
efa7127914
...
593df4b028
Author | SHA1 | Date | |
---|---|---|---|
![]() |
593df4b028 | ||
![]() |
d31104a4f0 |
@ -96,7 +96,7 @@ def set_column_width(ws, column_range, width=15):
|
||||
for col in column_range:
|
||||
ws.column_dimensions[col].width = width
|
||||
|
||||
def export_xlsx(lignes, fichier_sortie="résumé.xlsx"):
|
||||
def export_xlsx(lignes, output_directory, fichier_sortie="résumé.xlsx"):
|
||||
# Charger le classeur existant ou en créer un nouveau
|
||||
if os.path.exists(fichier_sortie):
|
||||
wb = openpyxl.load_workbook(fichier_sortie)
|
||||
@ -109,6 +109,9 @@ def export_xlsx(lignes, fichier_sortie="résumé.xlsx"):
|
||||
# Créer une nouvelle feuille
|
||||
ws = wb.create_sheet(title=date)
|
||||
|
||||
# Définir la nouvelle feuille comme active
|
||||
wb.active = ws
|
||||
|
||||
# En-têtes
|
||||
headers = ["Fichier", "Codec", "Résolution", "Action", "Durée", "Taille SRC", "Bitrate SRC",
|
||||
"Taille DES", "Bitrate DES", "Gain %", "Résultat"]
|
||||
@ -143,7 +146,7 @@ def export_xlsx(lignes, fichier_sortie="résumé.xlsx"):
|
||||
gain_percent = calc_gain_percent(input_size, output_size, raw=True)
|
||||
|
||||
row = [
|
||||
file, # string
|
||||
f'=HYPERLINK("{os.path.abspath(output_directory)}/{file}","{file}")', # string
|
||||
codec, # string
|
||||
resolution, # string
|
||||
action, # string
|
||||
@ -550,7 +553,7 @@ def main():
|
||||
))
|
||||
|
||||
xlsx_file = "résumé.xlsx"
|
||||
export_xlsx(lignes, fichier_sortie=xlsx_file)
|
||||
export_xlsx(lignes, output_directory, fichier_sortie=xlsx_file)
|
||||
print(f"📝 Classeur généré : {xlsx_file}")
|
||||
|
||||
lever_inhibit_arret(inhibiteurs)
|
||||
|
@ -40,6 +40,58 @@ def couleur(nom_fichier, est_dossier):
|
||||
else:
|
||||
return nom_fichier
|
||||
|
||||
def nettoyer_tags(tags):
|
||||
"""
|
||||
Crée un dictionnaire normalisé à partir des tags,
|
||||
en supprimant les suffixes comme '-eng', '-fre', etc.
|
||||
Si plusieurs clés mènent à la même base, la première rencontrée est conservée.
|
||||
"""
|
||||
tags_sans_suffixes = {}
|
||||
for cle, valeur in tags.items():
|
||||
base = cle.split('-')[0].strip().upper()
|
||||
if base not in tags_sans_suffixes:
|
||||
tags_sans_suffixes[base] = valeur
|
||||
return tags_sans_suffixes
|
||||
|
||||
def estimer_kbps(stream, probe):
|
||||
"""
|
||||
Estime le débit binaire (kb/s) d’un flux multimédia.
|
||||
Priorité :
|
||||
1. stream['bit_rate']
|
||||
2. stream['stream_size'] + probe['format']['duration']
|
||||
3. stream['tags']['BPS']
|
||||
4. stream['tags']['NUMBER_OF_BYTES'] + stream['tags']['DURATION']
|
||||
"""
|
||||
tags = nettoyer_tags(stream.get('tags', {}))
|
||||
|
||||
try:
|
||||
# Méthode 1 : bit_rate direct
|
||||
if 'bit_rate' in stream:
|
||||
return int(stream['bit_rate']) // 1000
|
||||
|
||||
# Méthode 2 : stream_size + durée globale
|
||||
if 'stream_size' in stream and 'format' in probe and 'duration' in probe['format']:
|
||||
taille = int(stream['stream_size'])
|
||||
duree = float(probe['format']['duration'])
|
||||
return int((taille * 8) / duree / 1000)
|
||||
|
||||
# Méthode 3 : BPS dans les tags
|
||||
if 'BPS' in tags:
|
||||
return int(tags['BPS']) // 1000
|
||||
|
||||
# Méthode 4 : NUMBER_OF_BYTES + DURATION dans les tags
|
||||
if 'NUMBER_OF_BYTES' in tags and 'DURATION' in tags:
|
||||
total_octets = int(tags['NUMBER_OF_BYTES'])
|
||||
duree_texte = tags['DURATION'] # Format HH:MM:SS.microsec
|
||||
h, m, s = duree_texte.split(':')
|
||||
secondes = int(h) * 3600 + int(m) * 60 + float(s)
|
||||
return int((total_octets * 8) / secondes / 1000)
|
||||
|
||||
except (ValueError, TypeError, ZeroDivisionError):
|
||||
pass
|
||||
|
||||
return -1 # Si toutes les méthodes échouent
|
||||
|
||||
def analyser_fichier_video(chemin):
|
||||
try:
|
||||
probe = ffmpeg.probe(chemin, show_chapters=None) # Contrairement à ce que l'on pourrait croire, on demande les chapitres, c'est l'option show_chapters qui ne prend pas de paramètre.
|
||||
@ -69,7 +121,8 @@ def analyser_fichier_video(chemin):
|
||||
f"{ROUGE}{i}{NORMAL}"
|
||||
f"{BLANC}:{NORMAL} "
|
||||
f"{BLEU}{codec_type:<8}{NORMAL} "
|
||||
f"{BLANC}({codec_name}, {langue}){NORMAL}"
|
||||
f"{BLANC}({codec_name:<6}, {langue:<3}){NORMAL} "
|
||||
f"{ORANGE}{estimer_kbps(stream, probe):>5.0f} kb/s{NORMAL}"
|
||||
)
|
||||
|
||||
# Ajouter les flags défaut/forcé s'ils existent
|
||||
@ -99,7 +152,32 @@ def analyser_fichier_video(chemin):
|
||||
except Exception as e:
|
||||
return [f"{ROUGE}Erreur : {e}{NORMAL}"]
|
||||
|
||||
def recuperer_titre_media(chemin):
|
||||
"""
|
||||
@brief Récupère le titre d'un média via ffmpeg.probe.
|
||||
|
||||
@param chemin Chemin vers le fichier média.
|
||||
@return Le titre formaté avec couleurs et guillemets si disponible, sinon chaîne vide.
|
||||
"""
|
||||
try:
|
||||
probe = ffmpeg.probe(chemin)
|
||||
titre = probe.get('format', {}).get('tags', {}).get('title', None)
|
||||
if titre is not None:
|
||||
return f" {VERT}\"{titre}\"{NORMAL}"
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def afficher_arborescence(dossier, prefixe="", tout_afficher=False, niveau_max=None, niveau_actuel=0):
|
||||
"""
|
||||
@brief Affiche l'arborescence d'un dossier avec détails sur les fichiers vidéo.
|
||||
|
||||
@param dossier Dossier à parcourir.
|
||||
@param prefixe Préfixe pour l'affichage en mode arborescence.
|
||||
@param tout_afficher Booléen pour afficher ou non les fichiers cachés.
|
||||
@param niveau_max Profondeur maximale d'affichage (None pour illimité).
|
||||
@param niveau_actuel Niveau courant de récursion (interne).
|
||||
"""
|
||||
if niveau_max is not None and niveau_actuel > niveau_max:
|
||||
return
|
||||
|
||||
@ -120,7 +198,8 @@ def afficher_arborescence(dossier, prefixe="", tout_afficher=False, niveau_max=N
|
||||
branche = "└── " if est_dernier else "├── "
|
||||
sous_prefixe = " " if est_dernier else "│ "
|
||||
est_dossier = os.path.isdir(chemin_complet)
|
||||
print(prefixe + branche + couleur(nom, est_dossier))
|
||||
titre = recuperer_titre_media(chemin_complet)
|
||||
print(prefixe + branche + couleur(nom, est_dossier) + titre)
|
||||
|
||||
if est_dossier:
|
||||
afficher_arborescence(
|
||||
|
Loading…
x
Reference in New Issue
Block a user