163 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
import os
import sys
import argparse
import ffmpeg
# Codes des couleurs ANSI
NOIR = "\033[30m"
ROUGE = "\033[31m"
VERT = "\033[32m"
ORANGE = "\033[33m" # On considère le marron comme orange
BLEU = "\033[34m"
VIOLET = "\033[35m"
CYAN = "\033[36m"
GRIS_CLAIR = "\033[37m"
GRIS_FONCE = "\033[90m"
ROUGE_CLAIR = "\033[91m"
VERT_CLAIR = "\033[92m"
JAUNE = "\033[93m"
BLEU_CLAIR = "\033[94m"
VIOLET_CLAIR = "\033[95m"
CYAN_CLAIR = "\033[96m"
BLANC = "\033[97m"
# Styles de texte
NORMAL = "\033[0m" # Normal (pas de style)
GRAS = "\033[1m" # Gras
SOULIGNE = "\033[4m" # Souligné
CLIGNOTANT = "\033[5m" # Clignotant
INVERSE = "\033[7m" # Inversé (texte clair sur fond sombre)
def couleur(nom_fichier, est_dossier):
if est_dossier:
return BLEU + nom_fichier + NORMAL
elif nom_fichier.lower().endswith(('.mp4', '.mkv', '.avi')):
return VIOLET + nom_fichier + NORMAL # 💜 fichier vidéo
else:
return nom_fichier
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.
info = []
max_index_len = len(str(len(probe.get("streams", [])) - 1))
streams = probe.get('streams', [])
# Filtrer pour ne garder que les flux pertinents (video, audio, subtitle)
flux_valides = [stream for stream in streams if stream.get('codec_type') in ['video', 'audio', 'subtitle']]
# Si on n'a pas de flux valide à afficher, on s'arrête
if not flux_valides:
return []
for i, stream in enumerate(flux_valides):
codec_type = stream.get('codec_type', 'und')
codec_name = stream.get('codec_name', 'und')
langue = stream.get('tags', {}).get('language', 'und')
titre = stream.get('tags', {}).get('title', '')
disposition = stream.get('disposition', {})
defaut = f"{ROUGE}défaut{NORMAL}" if disposition.get('default') == 1 else ""
force = f"{ROUGE}forcé{NORMAL}" if disposition.get('forced') == 1 else ""
# Déterminer les informations à afficher
ligne = (
f"{ORANGE}Stream{NORMAL} "
f"{ROUGE}{i}{NORMAL}"
f"{BLANC}:{NORMAL} "
f"{BLEU}{codec_type:<8}{NORMAL} "
f"{BLANC}({codec_name}, {langue}){NORMAL}"
)
# Ajouter les flags défaut/forcé s'ils existent
flags = []
if defaut:
flags.append(defaut)
if force:
flags.append(force)
if flags:
ligne += f" {' '.join(flags)}"
if titre:
ligne += f" {VERT}\"{titre}\"{NORMAL}"
info.append(ligne)
nb_chapitres = len(probe.get('chapters', []))
info.append(
f"{ORANGE}Chapitres{NORMAL} "
f"{BLANC}:{NORMAL} "
f"{VERT}{nb_chapitres}{NORMAL}")
return info
except ffmpeg.Error as e:
return [f"{ROUGE}Erreur ffmpeg : {e}{NORMAL}"]
except Exception as e:
return [f"{ROUGE}Erreur : {e}{NORMAL}"]
def afficher_arborescence(dossier, prefixe="", tout_afficher=False, niveau_max=None, niveau_actuel=0):
if niveau_max is not None and niveau_actuel > niveau_max:
return
try:
elements = sorted(
os.listdir(dossier),
key=lambda x: (not os.path.isdir(os.path.join(dossier, x)), x)
)
except PermissionError:
print(prefixe + "└── [Permission refusée]")
return
if not tout_afficher:
elements = [e for e in elements if not e.startswith('.')]
for index, nom in enumerate(elements):
chemin_complet = os.path.join(dossier, nom)
est_dernier = (index == len(elements) - 1)
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))
if est_dossier:
afficher_arborescence(
chemin_complet,
prefixe + sous_prefixe,
tout_afficher=tout_afficher,
niveau_max=niveau_max,
niveau_actuel=niveau_actuel + 1
)
elif nom.lower().endswith(('.mp4', '.mkv', '.avi')):
infos = analyser_fichier_video(chemin_complet)
for i, ligne in enumerate(infos):
print(prefixe + sous_prefixe + ("└── " if i == len(infos) - 1 else "├── ") + ligne)
def main():
parser = argparse.ArgumentParser(description="Affiche larborescence avec informations sur les fichiers vidéo.")
parser.add_argument("dossiers", nargs="*", default=["."], help="Un ou plusieurs dossiers à analyser")
parser.add_argument("-a", "--tout", action="store_true", help="Afficher les fichiers masqués")
parser.add_argument("-L", "--niveau", type=int, help="Niveau daffichage maximale")
args = parser.parse_args()
try:
for dossier in args.dossiers:
if not os.path.exists(dossier):
print(f"{ROUGE}Erreur : le dossier '{dossier}' n'existe pas.{NORMAL}")
continue
print(couleur(dossier, est_dossier=True))
afficher_arborescence(
dossier,
tout_afficher=args.tout,
niveau_max=args.niveau
)
except KeyboardInterrupt:
sys.exit(0)
if __name__ == "__main__":
main()