IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Python Discussion :

Traitements vidéos avec ffmpeg lancé par Python


Sujet :

Contribuez Python

  1. #1
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut Traitements vidéos avec ffmpeg lancé par Python
    PROBLEMATIQUE

    Le multimédia prend de plus en plus d'importance, et nous permet beaucoup de plaisirs à voir et à écouter. Mais les fichiers vidéos qu'on peut se procurer ne sont pas toujours dans un format ni dans un état acceptables pour notre usage. Aussi il faut des programmes permettant de modifier ou de réparer ces vidéos. Il existe des programmes graphiques pour ça, souvent payant, mais aussi un programme gratuit multiplateforme et utilisable en console: ffmpeg. Voir ici:
    https://ffmpeg.org/

    Ce programme ffmpeg très connu est très puissant mais aussi très complexe, avec une multitude d'options nécessitant souvent une connaissance approfondie des techniques vidéos. Il suffit de jeter un coup d'oeil sur sa documentation pour s'en rendre compte:
    https://ffmpeg.org/documentation.html

    Pour télécharger ffmpeg, c'est ici:
    https://ffmpeg.org/download.html
    Sous Windows, il ne s'installe pas: on le désarchive, et on le met où on veut sur le disque. Dans les codes ci-dessous, on précisera bien sûr l'adresse exacte des exécutables utilisés (ffmpeg et ffprobe).

    Je ne prétends pas en être un spécialiste! Je dois peut-être en utiliser moins de 5% de ses possibilités, mais j'ai sélectionné quelques lignes de commande avec les bonnes options, qui couvrent la grand majorité de mes besoins. Si vous avez d'autres besoins, il vous sera facile d'adapter les codes ci-dessous.


    PRESENTATION GENERALE

    Comme je n'aime pas écrire des lignes de commandes dans la console, j'ai préparé des "lanceurs" en Python pour exécuter ffmpeg avec les bonnes options. Ces lanceurs doivent être adaptés au traitement voulu dans un éditeur de texte quelconque (j'utilise spyder), et exécutés ensuite avec affichage en console.

    Dans ces codes, les données de traitement sont présentées au début du code, et sont les seules informations à modifier. Ce qui suit ces données, c'est la "machinerie" nécessaire au traitement, qui n'a pas besoin d'être modifiée une fois le programme au point.

    Le fait d'écrire les options de ffmpeg dans un éditeur de texte plutôt que dans une console est plus qu'un problème de confort: il permet:
    - de se rappeler ce qu'on a fait la dernière fois (mémoire entre cessions)
    - d'avoir les explications en commentaires sur les options utilisées
    - de garder en commentaires des options en réserve pour des cas particuliers

    Ceci permet de gagner du temps, même si on n'a pas fait ça depuis 6 mois!

    Voilà les 5 traitements dont je me sers le plus souvent:
    - Recherche d'informations sur une vidéo
    - Conversion d'une vidéo en mp4
    - Conversion d'une liste de vidéos en mp4
    - Réparation d'une vidéo
    - Extraction audio d'une vidéo

    Avant, on va décrire quelques fonctions de bibliothèques que tous les codes utilisent, et qui figureront dans un fichier "biblio.py" destiné à être importé.


    FONCTIONS DE BIBLIOTHEQUE

    Fonction "cejour()"

    Date du jour sous le format "jj/mm/aaaa_hh:mm:ss". Simplement utilisée pour avoir la date et l'heure d'un traitement. Surtout utile quand il y a un fichier log qu'on veut conserver.

    Fonction "affichedelai(secs)"

    Affichage d'un délai connu en secondes, afin de lire plus clairement le délai d'un traitement sous forme "hh:mm:ss.sss". Par exemple, 2748.562 secondes sera affiché comme "45:48.562", qui se lira facilement: 45 minutes et 48.562 secondes.

    Méthode "print2(...)"

    Méthode issue de la classe "Print2()", pour afficher des informations pendant le traitement, avec en plus, leur enregistrement dans un fichier log si un tel fichier est fourni.

    Fonction "execproc(...)"

    Exécution dans un sous-processus permettant d'appeler l'exécutable (ici ffmpeg ou ffprobe) avec les bons arguments, et de renvoyer à la fin le statut d'exécution (0 pour ok).

    Il s'agit ici d'un codage très inhabituel de Popen de subprocess: "branché" directement sur sys.stdin et sys.stdout, il permet d'avoir un affichage identique à celui qu'on aurait en lançant le programme dans la console, y compris avec l'affichage des couleurs quand il y en a.

    Code complet du module "biblio.py" à importer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    # -*- coding: utf-8 -*-
     
    """
    Biliothèque générale
    """
     
    import sys
    from datetime import datetime
    from subprocess import Popen
     
    #############################################################################
    def cejour(sepdate='/', septemps='_', sepheure=':'):
        """Retourne la date du jour sous le format "jj/mm/aaaa_hh:mm:ss"
           Possibilité de changer les séparateurs
         """
        jour = datetime.today().strftime('%d/%m/%Y_%H:%M:%S')
        return jour.replace('/', sepdate).replace('_', septemps).replace(':', sepheure)
     
    #############################################################################
    def affichedelai(secs):
        """Retourne une chaîne pour affichage d'un délai exprimé en secondes. Le
           résultat peut comporter jours, heures, minutes et secondes.
           Exemple: 2748.562 sec  => "45:48.562" soit 45 mn et 48.562 sec
           Un éventuel signe négatif est neutralisé dans le calcul mais restitué
           au résultat final
        """
        sign = "" if secs>=0 else "-"
        secs = abs(secs)
        j, r = divmod(secs, 86400) # 86400: 3600x24
        h, r = divmod(r, 3600)
        m, s = divmod(r, 60)
        j, h, m = int(j), int(h), int(m)
        if j>0:
            return "{}{:d}:{:02d}:{:02d}:{:06.3f}".format(sign, j, h, m, s)
        elif h>0:
            return "{}{:02d}:{:02d}:{:06.3f}".format(sign, h, m, s)
        elif m>0:
            return "{}{:02d}:{:06.3f}".format(sign, m, s)
        else:
            return "{}{:6.3f}".format(sign, s)
     
    ##############################################################################
    def execproc(commande, encodage="utf-8", dictenv=None, shell=False):
        """Appelle l'exécutable et ses arguments (commande) dans un processus.
           - commande: ligne de commande (liste ou chaine de caractères)
           - encodage: encodage des sorties du processus (défaut: 'utf-8)
           - dictenv: dict. d'environnement à passer au processus (défaut: None)
           - shell: si True, accepte les instructions console (défaut: False)
           Retourne le statut d'exécution du programme
        """
        with Popen(commande, bufsize=1, stdin=sys.stdin, stdout=sys.stdout,
                stderr=sys.stdout, shell=shell, env=dictenv,
                universal_newlines=True, encoding=encodage, errors='replace')\
                as proc:
     
            while proc.poll() is None: # on attend tant que le programme est actif
                pass
     
            rc = proc.poll() # statut d'exécution du programme terminé
     
        return rc # retourne le statut d'exécution du programme
     
    ##############################################################################
    class Print2:
        """Affiche le déroulement du traitement dans la console
           Si demandé, enregistre sur disque en plus de l'affichage sur la console
        """
     
        #=========================================================================
        def __init__(self, fichierlog="", modw="w", encodage="utf-8",
                                                                    affiche=True):
            """Initialise l'affichage et l'ouverture du fichier log (fichierlog)
               - fichierlog: si non vide: nom de fichier log à créer (avec chemin)
               - modw: mode d'écriture du fichierlog. Si 'a': ne détruit pas avant
               - encodage: encodage du fichierlog
               - affiche: si True, affiche sur le périphérique de sortie
            """
            self.flog = None
            if fichierlog:
                try:
                    self.flog = open(fichierlog, modw, encoding=encodage)
                except Exception:
                    # fichier log donné non conforme ou inaccessible
                    self.flog = None # aucun enregistrement ne sera fait
            self.affiche = affiche
     
        #=========================================================================
        def __call__(self, *v):
            """Affiche sur console et enregistre dans le fichier log si demandé
            """
            if self.affiche:
                print(*v, end='\n', flush=True) # affichage périphérique de sortie
            if self.flog:
                # enregistrement sur disque
                print(*v, end='\n', file=self.flog, flush=True)
     
        #=========================================================================
        def ferme(self):
            """Ferme le fichier log s'il existe et qu'il est ouvert
            """
            if self.flog:
                self.flog.close()

    PROGRAMMES DE TRAITEMENT VIDEO

    Pour mettre au point ces programme en fonction du contexte d'exécution, il ne faudra pas oublier de préciser l'adresse des exécutables "ffmpeg" et "ffprobe".

    Information sur une vidéo

    Code complet "infos_video.py"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    # -*- coding: utf-8 -*-
    """ Donne des informations sur une vidéo donnée
    """
    import os
     
    ##############################################################################
    # Données de traitement
     
    # fichier vidéo dont on cherche les informations
    source = r"\\MULTINET\public\video\clips\Hiromi Uehara\Hiromi - Desire.mp4"
     
    # si fichier log => détourne l'affichage console vers le fichier
    fichierlog = "" #"infos_video.txt" # si "" => pas de fichier log
     
    # arguments:  toutes les valeurs sont des chaînes de caractères
    arguments =[
    "-hide_banner", # cache la bannière
    "-v", "error", # affiche les erreurs
    "-select_streams",  "v:0", # 0: 1er flux vidéo
    "-show_format", # affiche les infos du format
    "-show_streams", # affiche les infos du flux
    source # fichier vidéo dont on cherche les informations
    ]
     
    ##############################################################################
    ##############################################################################
    # Données de programme
     
    programme = r"D:\progsup\ffmpeg\bin\ffprobe.exe"
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = os.environ.copy() # variables d'environnement (possible: None)
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    # Ajoute le programme à ses arguments
    commande = [programme] + arguments
     
    if fichierlog:
        commande = commande + ["1>>", fichierlog, "2>&1"] # ">>" pour ajout
        shell = True # True nécessaire pour le détournement vers le fichier log
     
    #############################################################################
    # Importations
     
    import sys
    from time import perf_counter # pour calcul du temps de traitement
     
    # Importation des fonctions de bibliothèque
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    # Exécution
    if __name__ == "__main__":
     
        #==========================================================================
        # valide la source
        if not os.path.exists(source):
            print()
            print("Erreur: fichier source non trouvée")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
     
        #========================================================================
        # lance la fonction d'affichage (et d'enregistrement si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("INFORMATIONS SUR LA VIDEO ({})".format(cejour()))
        print2("Source:", source)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #========================================================================
        # ferme le fichier log pour permettre l'affichage de ffmpeg
        print2.ferme()
     
        #==========================================================================
        # Lance le processus de traitement
        tps = perf_counter() # compteur de temps pour le traitement
     
        rc = execproc(commande, encodage, dictenv, shell)
     
        tps = perf_counter()-tps # temps de traitement
     
        #==========================================================================
        # Fin de traitement
        print2 = Print2(fichierlog, "a") # "a" pour continuer avec fichierlog
     
        #==========================================================================
        # Affiche le temps de traitement et le statut d'exécution
        print2()
        print2("Fin du traitement. Statut d'exécution:", rc)
        print2("Temps d'exécution: {}".format(affichedelai(tps)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
     
        ##############################################################################
        # Fin d'exécution
        _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console

    Conversion d'une vidéo en mp4


    Code complet "conversion_mp4.py"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    # -*- coding: utf-8 -*-
    """ Convertit en mp4 la vidéo donnée
    """
    import os
     
    #############################################################################
    # Données de traitement
     
    # fichier vidéo à convertir
    source = r"\\MULTINET\public\video\videos\TV\Brokenwood_2022-04-24.ts"
     
    # fichier converti (défaut: dans le répertoire source)
    destination = os.path.splitext(source)[0] + ".mp4"
     
    sautexiste = True # si True: ne remplace pas la destination existante
     
    # si fichier log => détourne l'affichage console vers le fichier
    fichierlog = "" #"conversion_mp4.txt" # si "" => pas de fichier log
     
    # arguments:  toutes les valeurs sont des chaînes de caractères
    arguments =[
    "-i", source, # fichier vidéo à convertir
    "-hide_banner", # cache la bannière
    "-nostdin", # empêche les questions pendant le traitement
    "-y", # permet de remplacer un fichier existant sans demander
    "-c:v", "libx264", # utilise le pilote vidéo mp4
    "-c:a", "aac", # utilise le pilote audio AAC
    destination # => fichier mp4 à créer
    ]
     
    """
    Réserve de codes
    "-aspect", "2.4",  # changement ratio (cinema:1920:800)
    "-aspect", "16:9",  # changement ratio (full HD:1920:1080)
     
    "-vf", "scale=1920:800", # change taille et ratio (cinema:1920:800)
    "-vf", "scale=-2:800", # change taille sans changer ratio
    "-vf", "scale=1920:-2", # change taille sans changer ratio
    "-vf", "scale=iw*2:ih", # change taille en utilisant les variables iw et ih
    """
     
    #############################################################################
    #############################################################################
    # Données de programme
     
    programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe"
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = os.environ.copy() # variables d'environnement (possible: None)
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    # Ajoute le programme à ses arguments
    commande = [programme] + arguments
     
    if fichierlog:
        commande = commande + ["1>>", fichierlog, "2>&1"] # ">>" pour ajout
        shell = True # True nécessaire pour le détournement vers le fichier log
     
    #############################################################################
    # Importations
     
    import sys
    from time import perf_counter # pour calcul du temps de traitement
     
    # Importation des fonctions de bibliothèque
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    # Exécution
    if __name__ == "__main__":
     
        #==========================================================================
        # valide la source
        if not os.path.exists(source):
            print()
            print("Erreur: Fichier source non trouvé")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        source = os.path.abspath(os.path.expanduser(source))
     
        #==========================================================================
        # valide la destination
        if sautexiste and os.path.exists(destination):
            print()
            print("La destination existe déjà")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        destination = os.path.abspath(os.path.expanduser(destination))
     
        #========================================================================
        # lance la fonction d'affichage (et d'enregistrement si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("CONVERSION VIDEO EN MP4 ({})".format(cejour()))
        print2("Source:", source)
        print2("Destination:", destination)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #========================================================================
        # ferme le fichier log pour permettre l'affichage du processus
        print2.ferme()
     
        #==========================================================================
        # Lance le processus de traitement
        tps = perf_counter() # compteur de temps pour le traitement
     
        rc = execproc(commande, encodage, dictenv, shell)
     
        tps = perf_counter()-tps # temps de traitement
     
        #==========================================================================
        # Réouvre le fichier log pour poursuivre l'enregistrement
        print2 = Print2(fichierlog, "a") # "a" pour continuer fichierlog
     
        #==========================================================================
        # Affiche le temps de traitement et le statut d'exécution
        print2()
        print2("Fin du traitement. Statut d'exécution:", rc)
        print2("Temps d'exécution: {}".format(affichedelai(tps)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
     
        ##############################################################################
        # Fin d'exécution
        _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
    Conversion d'une liste de vidéos en mp4

    Code complet "conversion_mp4_multi.py"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    # -*- coding: utf-8 -*-
    """Convertit en mp4 les fichiers vidéo qui satisfont les motifs wildcard
    """
    import os
     
    ##############################################################################
    # Données de traitement
     
    # répertoire source
    repsrce = r"\\MULTINET\public\video\videos\TV"
     
    # répertoire destination (si "" => même répertoire que le répertoire source)
    repdest = r""
     
    # motifs wildcard des fichiers sources à convertir (séparateur = ';')
    inclusfics = "*.avi;*.mkv;*.mpg;*.mpeg;*.divx;*.vob;*.ts"
     
    sautexiste = True # si True: ne remplace pas la destination existante
     
    # si fichier log => détourne l'affichage console vers le fichier
    fichierlog = "" # "conversion_mp4_multi.txt" # si "" => pas de fichier log
     
    arguments = lambda ficsrce, ficdest: [
    "-i", ficsrce, # fichier vidéo à convertir
    "-hide_banner", # cache la bannière
    "-nostdin", # empêche les questions pendant le traitement
    "-y", # permet de remplacer un fichier existant sans demander
    "-c:v", "libx264", # utilise le pilote vidéo mp4
    "-c:a", "aac", # utilise le pilote audio AAC
    ficdest # => fichier mp4 à créer
    ]
     
    """
    Réserve de codes
    "-aspect", "1920:800",  # changement aspect (cinema:1920:800)
     
    "-vf", "scale=1920:800", # change taille et ratio (cinema:1920:800)
    "-vf", "scale=-2:800", # change taille sans changer ratio
    "-vf", "scale=1920:-2", # change taille sans changer ratio
    "-vf", "scale=iw*2:ih", # change taille en utilisant les variables iw et ih
    """
     
    ##############################################################################
    ##############################################################################
    # Données de programme
     
    programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe"
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = os.environ.copy() # variables d'environnement (possible: None)
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    #############################################################################
    # Importations
     
    import sys
    from time import perf_counter # pour calcul du temps de traitement
    from glob import iglob
     
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    if __name__ == "__main__":
     
        #==========================================================================
        # valide le répertoire source
        if not os.path.exists(repsrce):
            print()
            print("Erreur: répertoire source non trouvé")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        repsrce = os.path.abspath(os.path.expanduser(repsrce))
     
        #==========================================================================
        # valide le répertoire destination
        if not repdest:
            repdest = repsrce
        if not os.path.exists(repdest):
            os.mkdir(repdest) # crée le répertoire destination
        repdest = os.path.abspath(os.path.expanduser(repdest))
     
        #========================================================================
        # lance la fonction d'affichage (et d'enregistrement si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("CONVERSION DE VIDEOS EN MP4 ({})".format(cejour()))
        print2("Répertoire source:", repsrce)
        print2("Répertoire destination:", repdest)
        print2("Motifs wildcard de recherche:", inclusfics)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #==========================================================================
        # cherche tous les fichiers correspondant aux motifs de recherche
     
        fichiers = []
        for motif in inclusfics.split(";"):
            for fichier in iglob(os.path.join(repsrce, motif)):
                if os.path.isfile(fichier):
                    fichiers.append(fichier)
     
        #==========================================================================
        # traite tous les fichiers un par un
     
        tps0 = 0 # compteur de temps pour l'ensemble des vidéos
     
        for fichiersrce in fichiers:
     
            #==========================================================================
            # calcule le fichier destination
            nomfic = os.path.basename(fichiersrce) # chemin retiré
            fichierdest = os.path.join(repdest, os.path.splitext(nomfic)[0]+".mp4")
     
            if sautexiste and os.path.exists(fichierdest):
                print2()
                print2("="*79)
                print2("Ce fichier destination existe déjà:", fichierdest)
                print2()
                continue # => fichier suivant
     
            #==========================================================================
            # Affiche le titre pour chaque vidéo
            print2()
            print2("="*79)
            print2("Source:     ", fichiersrce)
            print2("Destination:", fichierdest)
            print2()
     
            #==========================================================================
            # Calcule la ligne de commande
            commande = [programme] + arguments(fichiersrce, fichierdest)
     
            #==========================================================================
            # redirige l'affichage console vers le fichier log si demandé
            if fichierlog:
                commande = commande + ["1>>", fichierlog, "2>&1"]
                shell = True # nécessaire pour la redirection
     
            #========================================================================
            # ferme le fichier log pour permettre l'affichage du processus
            print2.ferme()
     
            #==========================================================================
            # Lance le processus de traitement
            tps = perf_counter() # compteur de temps pour le traitement
     
            rc = execproc(commande, encodage, dictenv, shell)
     
            tps = perf_counter()-tps # temps de traitement
            tps0 += tps
     
            #==========================================================================
            # Réouvre le fichier log pour poursuivre l'enregistrement
            print2 = Print2(fichierlog, "a") # "a" pour continuer fichierlog
     
            #==========================================================================
            # Fin de traitement de la vidéo
            print2()
            print2("Fin du traitement de la vidéo. Statut d'exécution:", rc)
            print2("Temps d'exécution: {}".format(affichedelai(tps)))
            print2()
     
        #==========================================================================
        # Fin de traitement pour l'ensemble des vidéos
        print2()
        print2("="*79)
        print2("Fin du traitement des vidéos")
        print2("Temps total d'exécution: {}".format(affichedelai(tps0)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
     
        ##############################################################################
        # Fin d'exécution
        _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
    Réparation d'une vidéo

    Code complet "repare_video.py"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    # -*- coding: utf-8 -*-
    """ Répare la vidéo donnée
    """
    import os
     
    #############################################################################
    # Données de traitement
     
    # Fichier source à réparer
    source = r"\\MULTINET\public\video\clips\Ben Heppner - Jules Massenet - Le Cid - O Souverain.mp4"
     
    # Fichier destination réparé
    destination = r"\\MULTINET\public\video\clips\Ben Heppner - Jules Massenet - Le Cid - O Souverain_ok.mp4"
     
    sautexiste = False # si True: ne remplace pas la destination existante
     
    # si fichier log => détourne l'affichage console vers le fichier
    fichierlog = "" #"repare_video.txt" # si "" => pas de fichier log
     
    # arguments:  toutes les valeurs sont des chaînes de caractères
    arguments =[
    "-i", source, # fichier à réparer
    "-hide_banner", # cache la bannière
    "-nostdin",  # empêche les questions pendant le traitement
    "-y", # permet de remplacer un fichier existant sans demander
    "-c:v", "copy", # recopie le flux vidéo
    "-c:a", "copy", # recopie le flux audio
    destination # => fichier réparé
    ]
     
    #############################################################################
    #############################################################################
    # données de programme
     
    programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe"
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = os.environ.copy() # variables d'environnement (possible: None)
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    # Ajoute le programme à ses arguments
    commande = [programme] + arguments
     
    if fichierlog:
        commande = commande + ["1>>", fichierlog, "2>&1"] # ">>" pour ajout
        shell = True # True nécessaire pour le détournement vers le fichier log
     
    #############################################################################
    # Importations
     
    import sys
    from time import perf_counter # pour calcul du temps de traitement
     
    # Importation des fonctions de bibliothèque
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    # Exécution
    if __name__ == "__main__":
     
        #==========================================================================
        # valide la source
        if not os.path.exists(source):
            print()
            print("Erreur: Fichier source non trouvé")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        source = os.path.abspath(os.path.expanduser(source))
     
        #==========================================================================
        # valide la destination
        if sautexiste and os.path.exists(destination):
            print()
            print("La destination existe déjà")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        destination = os.path.abspath(os.path.expanduser(destination))
     
        #========================================================================
        # lance la fonction d'affichage et d'enregistrement (si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("REPARATION VIDEO ({})".format(cejour()))
        print2("Source:", source)
        print2("Destination:", destination)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #========================================================================
        # ferme le fichier log pour permettre l'affichage du processus
        print2.ferme()
     
        #==========================================================================
        # Lance le processus de traitement
        tps = perf_counter() # compteur de temps pour le traitement
     
        rc = execproc(commande, encodage, dictenv, shell)
     
        tps = perf_counter()-tps # temps de traitement
     
        #==========================================================================
        # Réouvre le fichier log pour poursuivre l'enregistrement
        print2 = Print2(fichierlog, "a") # 'a' pour continuer fichierlog
     
        #==========================================================================
        # Affiche le temps de traitement et le statut d'exécution
        print2()
        print2("Fin du traitement. Statut d'exécution:", rc)
        print2("Temps d'exécution: {}".format(affichedelai(tps)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
     
        ##############################################################################
        # Fin d'exécution
        _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
    Extraction audio d'une vidéo

    Code complet "extrait_audio.py"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    # -*- coding: utf-8 -*-
    """ Extrait l'audio d'une vidéo donnée
    """
    import os
     
    ##############################################################################
    # Données de traitement
     
    # fichier vidéo à extraire
    source = r"\\MULTINET\public\video\clips\Hiromi Uehara\Hiromi - Suite Escapism  in Between.mp4"
     
    # fichier audio extrait
    destination = r"\\MULTINET\public\music\Hiromi\Hiromi - Suite Escapism  in Between_3.mp3"
     
    sautexiste = False # si True: ne remplace pas la destination existante
     
    canalaudio = 0 # numéro canal audio à extraire  (0 => 1er canal audio)
     
    # si fichier log => détourne l'affichage console vers le fichier log
    fichierlog = "" #"extrait_audio.txt" # si "" => pas de fichier log
     
    # arguments:  toutes les valeurs sont des chaînes de caractères
    arguments =[
    "-i", source, # source fichier video
    "-hide_banner", # cache la bannière
    "-nostdin", # empêche les questions pendant le traitement
    "-y", # permet de remplacer un fichier existant sans demander
    "-map", "0:a:"+str(canalaudio), # => copie canal audio
    destination # fichier audio destination (mp3, aac, ...)
    ]
     
    """
    Réserve de codes
    "-c", "copy", # extrait audio sans réencodage
    "-map", "0:a", # sélectionne tous les canaux audio
    """
     
    ##############################################################################
    ##############################################################################
    # données de programme
     
    programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe"
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = os.environ.copy() # variables d'environnement (possible: None)
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    # Ajoute le programme à ses arguments
    commande = [programme] + arguments
     
    if fichierlog:
        commande = commande + ["1>>", fichierlog, "2>&1"] # ">>" pour ajout
        shell = True # True nécessaire pour le détournement vers le fichier log
     
    #############################################################################
    # Importations
     
    import sys
    from time import perf_counter # pour calcul du temps de traitement
     
    # Importation des fonctions de bibliothèque
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    # Exécution
    if __name__ == "__main__":
     
        #==========================================================================
        # valide la source
        if not os.path.exists(source):
            print()
            print("Erreur: Fichier source non trouvé")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        source = os.path.abspath(os.path.expanduser(source))
     
        #==========================================================================
        # valide la destination
        if sautexiste and os.path.exists(destination):
            print()
            print("La destination existe déjà")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        destination = os.path.abspath(os.path.expanduser(destination))
     
        #========================================================================
        # lance la fonction d'affichage et d'enregistrement (si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("EXTRACTION AUDIO D'UNE VIDEO ({})".format(cejour()))
        print2("Source:", source)
        print2("Destination:", destination)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #========================================================================
        # ferme le fichier log pour permettre l'affichage de ffmpeg
        print2.ferme()
     
        #==========================================================================
        # Lance le processus de traitement
        tps = perf_counter() # compteur de temps pour le traitement
     
        rc = execproc(commande, encodage, dictenv, shell)
     
        tps = perf_counter()-tps # temps de traitement
     
        #==========================================================================
        # Réouvre le fichier log pour poursuivre l'enregistrement
        print2 = Print2(fichierlog, "a") # "a" pour continuer avec fichierlog
     
        #==========================================================================
        # Affiche le temps de traitement et le statut d'exécution
        print2()
        print2("Fin du traitement. Statut d'exécution:", rc)
        print2("Temps d'exécution: {}".format(affichedelai(tps)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
     
        ##############################################################################
        # Fin d'exécution
        _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console

    EXEMPLE D'EXPLOITATION

    On place les 6 codes (5 codes de traitement + code de la bibliothèque) dans le même répertoire appelé, par exemple, "utilvideos".

    J'utilise Spyder comme outil de développement (https://pypi.org/project/spyder/). Pour rendre son utilisation plus facile, je conseille la configuration suivante:
    - afficher les "fichiers" pour pouvoir naviguer dans l'arborescence des fichiers du disque
    - définir la console de l'OS (cmd.exe pour Windows) comme périphérique de sortie.

    Avec Spyder, on crée sur le bureau un raccourci qui lance:
    /chemin/vers/spyder - p /chemin/vers/utilvideos

    Après un double-clic sur le raccourci, Spyder se charge, et affiche le répertoire "utilvideos" et son contenu. Un double-clic sur le nom du code souhaité le fera venir dans l'éditeur de texte. Après édition et enregistrement des données de traitement, il suffira de cliquer sur l'icone d'exécution, et tout se déroulera dans la console. Avec la mémoire du fichier log s'il a été déclaré.

    Mais, bien sûr, un autre éditeur de texte pourrait convenir! Cependant, attention à "idle" livré avec Python, qui va bien pour l'édition de texte, mais pas pour l'exécution à cause de l'affichage dans la console interne.

    J'ai développé et j'utilise tout ça sous Windows, mais il y a peu de codes spécifiques, aussi il est hautement probable que ça fonctionne aussi sous les "unix" (linux, macOS), ou avec un peu d'adaptation. Que ceux qui essaient donnent ici le résultat de leur tentative!


    Bons traitements vidéos !
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 826
    Points : 7 123
    Points
    7 123
    Par défaut
    Bonjour,

    Plusieurs choses à dire :

    Sur l'idée je trouve cela très bien ffmpeg est une usine avec de multitudes d'options et c'est pas toujours simple de s'y retrouver. L'utilisateur a souvent besoin pour ses besoins des mêmes options et ton travail permettra sans doute de ne pas chercher dans les méandres des docs ffmpeg et d'utiliser ffmpeg pour des cas concrets.

    Pour Python,

    Je comprends pas pourquoi tu ne respectes plus les conventions du langages
    1. des importations en dessous du code
    2. des constantes en minuscules
    3. classes situés plus bas que les fonctions
    4. franglais
    5. noms de fonctions mal choisis (print2 ? cejour ? ... ?) [ne pas oublier qu'une fonction est une action donc un verbe et en anglais]
    6. pourquoi deux modules pour convertir une vidéo et plusieurs vidéos ?


    tu as aussi du code répétitif, pourquoi ne pas le placer dans un module et l'importer dans chacun des autres modules ?

    Pour un programme console, je te conseille très fortement le module typer.

    Je suis un peu déçu je m'attendais à du code plus robuste de ta part, à mon sens, en tant que puriste, ce type de code ne me donne pas envie de le télécharger.
    Désolé, je donne un point de vue assez dur, mais venant de toi, je m'attendais à tellement mieux
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 574
    Points : 2 017
    Points
    2 017
    Par défaut
    Bonjour,

    loin de moi l'idée de critiquer le code présenté ici.

    Mais voir des imports de librairies disséminées en plein milieu du code, ça me choque un brin. J'ai trop l'habitude de voir des imports glissés dès le départ, dans les premières lignes du fichier.

    Je vois aussi des paramètres à modifier à la main dans certains fichiers pour que le programme "colle" à notre configuration.

    Là aussi, je suis plus habitué à voir tous les paramétrages glissés dans un fichier .env en tant que variables d'environnement, ou bien dans un fichier JSON ou YAML. Tout au même endroit.

    En outre, je n'ai vu aucun test. Là aussi, je n'ai plus l'habitude de ne pas en voir.

    Maintenant que j'ai dis tout ça, je ne cherchais en aucun cas à vexer l'auteur du programme.

    C'est juste mon ressenti personnel.

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut
    Bonjour fred1599 et Arioch

    Merci pour vos critiques que j'attendais un peu.

    Je suis conscient d'avoir sauvagement piétiné quelques bonnes règles de programmation en Python, et pourtant, c'est bien comme ça que j'ai conçu ces codes pour moi, et que je les trouve les plus pratiques et les plus rapides à l'utilisation. Je suis en train de programmer ma quinzaine d'utilitaires courants de cette façon, et j'en suis très satisfait.

    Le fait de commencer en haut de la page de code par les données vient du fait que c'est la partie qu'on voit lors du chargement dans un éditeur, et c'est la seule partie qu'on modifie pour le traitement qu'on veut faire.

    Je ne changerai donc pas ce que j'utilise, mais il est vrai que je ne voudrais pas donner de mauvaises pratiques de programmation aux plus jeunes. Aussi, il vaudrait mieux que je supprime ce post. Je le laisse le temps que vous preniez connaissance de ce message.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 826
    Points : 7 123
    Points
    7 123
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Bonjour fred1599 et Arioch

    Merci pour vos critiques que j'attendais un peu.

    Je suis conscient d'avoir sauvagement piétiné quelques bonnes règles de programmation en Python, et pourtant, c'est bien comme ça que j'ai conçu ces codes pour moi, et que je les trouve les plus pratiques et les plus rapides à l'utilisation. Je suis en train de programmer ma quinzaine d'utilitaires courants de cette façon, et j'en suis très satisfait.

    Le fait de commencer en haut de la page de code par les données vient du fait que c'est la partie qu'on voit lors du chargement dans un éditeur, et c'est la seule partie qu'on modifie pour le traitement qu'on veut faire.

    Je ne changerai donc pas ce que j'utilise, mais il est vrai que je ne voudrais pas donner de mauvaises pratiques de programmation aux plus jeunes. Aussi, il vaudrait mieux que je supprime ce post. Je le laisse le temps que vous preniez connaissance de ce message.
    C'est ton post, tu es libre d'en faire ce que tu souhaites, mais je ne pense pas que tu l'ais posté pour là supprimer peu de temps après, suite à quelques remarques.

    Pourquoi modifier un code console alors que tu peux modifier via des options lors de l'exécution, c'est bien plus simple, et typer est le module parfait pour faire cela ?

    Tout ça à mon sens ne tient qu'en 2 modules python, un module avec deux classes (Video et VideoList [pour faire du SOLID, c'est pas obligatoire]) et un module principal où tu utilises typer pour contrôler les options utilisateurs.
    J'étais justement en train d'écrire un exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    import subprocess
    import json
     
    class Video:
        def __init__(self, filepath):
            self.filepath = filepath
            self.format = None
            self.metadata = {}
            self.status = "OK"
            self.duration = None
            self.resolution = None
            self.bitrate = None
            self.audio_tracks = []
            self.subtitles = []
            self.codec = None
     
            self.get_metadata()
     
        def get_metadata(self):
            command = [
            "ffprobe",
            "-v", "quiet",
            "-print_format", "json",
            "-show_format",
            "-show_streams",
            self.filepath
        ]
     
            result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            metadata = json.loads(result.stdout)
            self.metadata = metadata
            self._parse_metadata(metadata)
     
        def _parse_metadata(self, metadata):
            """ Analyse les métadonnées et attribue les valeurs aux attributs de la classe """
            if 'format' in metadata:
                self.format = metadata['format'].get('format_name')
                self.duration = float(metadata['format'].get('duration', 0.0))
                self.bitrate = int(metadata['format'].get('bit_rate', 0))
     
            for stream in metadata.get('streams', []):
                if stream['codec_type'] == 'video':
                    self.resolution = f"{stream.get('width')}x{stream.get('height')}"
                    self.codec = stream.get('codec_name')
                elif stream['codec_type'] == 'audio':
                    self.audio_tracks.append(stream.get('codec_name'))
                elif stream['codec_type'] == 'subtitle':
                    self.subtitles.append(stream.get('codec_name'))
     
        def convert(self, output_format):
            # Convertir la vidéo dans un autre format
            pass
     
        def repair(self):
            # Réparer la vidéo
            pass
     
        def extract_audio(self):
            # Extraire l'audio de la vidéo
            pass
     
    # Classe pour gérer une liste de vidéos
    class VideoList:
        def __init__(self, video_list):
            self.video_list = video_list
     
        def convert_all(self, output_format):
            # Convertir toutes les vidéos de la liste
     
            pass
    et mon module main.py (le nom du package sera exécuté par la suite)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import subprocess
    import platform
    import sys
     
    from video.video import Video
     
    def is_tool_installed(name):
        """ Vérifie si un outil est installé """
        try:
            command = "where" if platform.system() == "Windows" else "which"
            subprocess.run([command, name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
            return True
        except subprocess.CalledProcessError:
            return False
     
    def print_colored(text, color):
        """ Affiche le texte avec la couleur spécifiée """
        colors = {"red": "\033[91m", "green": "\033[92m"}
        reset = "\033[0m"
        print(f"{colors.get(color, '')}{text}{reset}")
     
    def check_ffmpeg_and_ffprobe():
        """ Vérifie si ffmpeg et ffprobe sont installés """
        if is_tool_installed("ffmpeg") and is_tool_installed("ffprobe"):
            print_colored("ffmpeg et ffprobe sont installés correctement.", "green")
        else:
            print_colored("ffmpeg ou ffprobe ne sont pas installés.", "red")
            sys.exit(1)
     
     
    if __name__ == "__main__":
        check_ffmpeg_and_ffprobe()
        # utilisation de typer
        video = Video("/home/fred1599/Téléchargements/docker.mp4") # juste pour test, faudra contrôler les options utilisateur
    Voici la structure du projet

    Nom : Capture d’écran_2023-12-13_13-29-55.png
Affichages : 370
Taille : 6,1 Ko

    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je ne changerai donc pas ce que j'utilise, mais il est vrai que je ne voudrais pas donner de mauvaises pratiques de programmation aux plus jeunes.
    Bricoler des scripts qui répondent à des besoins précis et montrer ce qu'on peut faire avec ffmpeg n'a pas besoin de se conformer à quoi que ce soit.
    Vous partagez des codes qui vous sont utiles.
    Et pour autant qu'il y ait de bonnes pratiques - j'en connais des mauvaises et des meilleures mais jamais de bonnes car elles seront toujours perfectibles-, elles n'apportent que du non fonctionnel.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut
    Merci wiztricks. C'est aussi mon avis.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  8. #8
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 115
    Points : 4 473
    Points
    4 473
    Par défaut
    bonjour
    Citation Envoyé par tyrtamos Voir le message
    c'est bien comme ça que j'ai conçu ces codes pour moi, et que je les trouve les plus pratiques et les plus rapides à l'utilisation
    J'ai bien compris (dans un sujet précédent), mais il faut voir que ce qui te convient à merveille risque d'être repoussant pour les autres.

    Tu pourrais, par exemple, faire un script générique, puis pour ton besoin spécifique, faire un "wrappeur" ?

    Un seul générique (intéressant pour tous) (cli.py) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/usr/bin/env python
    import click
     
    def convertir(name: str, zoom: int = 100, ext="mp4"):
        """ code métier """
        print(f"convertir fichier vidéo: `{name}`, taille: {zoom}% en fichier `.{ext}`")
     
    @click.command()
    @click.option("--zoom", default=100, help="reduire/augmenter taille en %")
    @click.option("--ext", default="mp4", help="type de fichier en sortie")
    @click.argument("name", required=True)
    def executer(name: str, zoom: int, ext: str):
        convertir(name=name, zoom=zoom, ext=ext)
     
     
    if __name__ == "__main__":
        executer()
    Ton (ou tes) wrapper, intéressant(s) pour toi (main.py) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import cli    # voir import metier.video
     
    MA_VIDEO = "truc.mp4"
    ZOOM = 200
    EXTENSION = "ts"
     
    if __name__ == "__main__":
        cli.convertir(
            name=MA_VIDEO,
            zoom=ZOOM,
            ext=EXTENSION,
        )
    résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ./cli.py machin.ts --ext mp4 --zoom 150
    convertir fichier vidéo: `machin.ts`, taille: 150% en fichier `.mp4`
     
    ./main.py
    convertir fichier vidéo: `truc.mp4`, taille: 200% en fichier `.ts`
    ---------
    Encore mieux, si le code métier n'est pas dans "cli", alors le wrapper importe directement le code métier et ne connait pas l'interface utilisateur générique. Mais cela va entrainer une arborescence que je suppose ne pas désirer.
    $moi= ( !== ) ? : ;

  9. #9
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Je ne comprends pas les difficultés que vous rencontrez avec la programmation spécifique de mes petits utilitaires.

    Je voulais trouver une solution intermédiaire entre:
    - l'écriture d'une longue et complexe ligne de commande dans la console
    - l'écriture des données dans un programme graphique, qu'il a fallu développer avant, et qui sera difficile à faire évoluer en fonction des besoins.

    Prenons un exemple concret: la conversion d'une vidéo "avi" en "mp4". Si je retire les commentaires, voilà les données que je dois rentrer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    source = r"chemin\vers\mavideo.avi"
    destination = r"chemin\vers\mavideo.mp4"
    sautexiste = True
    fichierlog = ""
    arguments =[
    "-i", source,
    "-hide_banner",
    "-nostdin",
    "-y",
    "-c:v", "libx264",
    "-c:a", "aac",
    destination
    ]
    Que mon programme soit graphique ou que j'écrive une ligne de commande dans la console, j'aurais dû de toute façon écrire ces données. Ce n'est pas de la programmation, c'est de la saisie de données.

    La suite de la page de code, c'est la "machinerie" du programme que je n'ai pas besoin de voir une fois ce programme au point. D'ailleurs, dans la version "graphique", je n'y aurais pas eu accès.

    L'ajout des commentaires a, comme je l'ai dit dans mon 1er message, trois avantages:
    - se rappeler ce qu'on a fait la dernière fois (mémoire entre cessions)
    - avoir les explications en commentaires sur les options utilisées
    - garder en commentaires des options en réserve pour des cas particuliers

    A noter qu'on n'aurait pas eu ces informations ni dans le programme graphique, ni dans la version console, à part recours systématique à un manuel.

    Voilà un extrait de la sortie en console du programme pendant la conversion en mp4 de la vidéo. A noter que ce serait aussi le contenu d'un fichier log si j'en avais donné le nom:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    CONVERSION VIDEO EN MP4 (14/12/2023_04:14:21)
    Source: r"chemin\vers\mavideo.avi"
    Destination: r"chemin\vers\mavideo.mp4"
     
    Input #0, avi, from 'mavideo.avi':
      Metadata:
        software        : FairUse Wizard - http://fairusewizard.com
      Duration: 01:29:04.64, start: 0.000000, bitrate: 1098 kb/s
      Stream #0:0: Video: mpeg4 (Advanced Simple Profile) (XVID / 0x44495658), yuv420p, 608x336 [SAR 1:1 DAR 38:21], 960 kb/s, 25 fps, 25 tbr, 25 tbn
      Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 48000 Hz, stereo, fltp, 128 kb/s
    Stream mapping:
      Stream #0:0 -> #0:0 (mpeg4 (native) -> h264 (libx264))
      Stream #0:1 -> #0:1 (mp3 (mp3float) -> aac (native))
    [mpeg4 @ 0000020825279f80] Video uses a non-standard and wasteful way to store B-frames ('packed B-frames'). Consider using the mpeg4_unpack_bframes bitstream filter without encoding but stream copy to fix it.
    [libx264 @ 0000020824c238c0] using SAR=1/1
    [libx264 @ 0000020824c238c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
    [libx264 @ 0000020824c238c0] profile High, level 2.2, 4:2:0, 8-bit
    [libx264 @ 0000020824c238c0] 264 - core 164 - H.264/MPEG-4 AVC codec - Copyleft 2003-2022 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=10 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
    Output #0, mp4, to 'mavideo.mp4':
      Metadata:
        software        : FairUse Wizard - http://fairusewizard.com
        encoder         : Lavf59.16.100
      Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(progressive), 608x336 [SAR 1:1 DAR 38:21], q=2-31, 25 fps, 12800 tbn
        Metadata:
          encoder         : Lavc59.18.100 libx264
        Side data:
          cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
      Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s
        Metadata:
          encoder         : Lavc59.18.100 aac
    frame=133617 fps=657 q=-1.0 Lsize=  333006kB time=01:29:04.56 bitrate= 510.4kbits/s dup=2 drop=0 speed=26.3x
    video:244714kB audio:84321kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.206817%
    ...
    ...
    ...
    frame=133617 fps=657 q=-1.0 Lsize=  333006kB time=01:29:04.56 bitrate= 510.4kbits/s dup=2 drop=0 speed=26.3x
    video:244714kB audio:84321kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.206817%
    [libx264 @ 0000020824c238c0] frame I:1523  Avg QP:19.60  size: 13521
    [libx264 @ 0000020824c238c0] frame P:55106 Avg QP:22.40  size:  2990
    [libx264 @ 0000020824c238c0] frame B:76988 Avg QP:24.27  size:   848
    [libx264 @ 0000020824c238c0] consecutive B-frames:  2.2% 62.6%  0.8% 34.3%
    [libx264 @ 0000020824c238c0] mb I  I16..4:  4.2% 92.5%  3.3%
    [libx264 @ 0000020824c238c0] mb P  I16..4:  1.0%  3.9%  0.2%  P16..4: 57.0% 11.7%  7.7%  0.0%  0.0%    skip:18.4%
    [libx264 @ 0000020824c238c0] mb B  I16..4:  0.1%  0.5%  0.0%  B16..8: 31.6%  1.9%  0.3%  direct: 1.4%  skip:64.3%  L0:40.1% L1:55.1% BI: 4.8%
    [libx264 @ 0000020824c238c0] 8x8 transform intra:82.0% inter:89.5%
    [libx264 @ 0000020824c238c0] coded y,uvDC,uvAC intra: 65.6% 74.1% 22.8% inter: 14.5% 26.6% 0.2%
    [libx264 @ 0000020824c238c0] i16 v,h,dc,p: 23% 16% 10% 51%
    [libx264 @ 0000020824c238c0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 20% 15% 36%  4%  5%  5%  5%  5%  5%
    [libx264 @ 0000020824c238c0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 14% 15%  7%  9%  9%  8%  7%  5%
    [libx264 @ 0000020824c238c0] i8c dc,h,v,p: 53% 19% 22%  6%
    [libx264 @ 0000020824c238c0] Weighted P-Frames: Y:4.4% UV:1.8%
    [libx264 @ 0000020824c238c0] ref P L0: 61.3% 11.9% 18.3%  8.2%  0.4%
    [libx264 @ 0000020824c238c0] ref B L0: 85.5% 10.9%  3.7%
    [libx264 @ 0000020824c238c0] ref B L1: 98.3%  1.7%
    [libx264 @ 0000020824c238c0] kb/s:375.08
    [aac @ 0000020824c24640] Qavg: 673.293
     
    Fin du traitement. Statut d'exécution: 0
    Temps d'exécution: 03:24.158
     
    Tapez "entrée" pour arrêter
    Bien sûr, on peut constater après que la conversion a réussi, et que la nouvelle vidéo "mp4" s'affiche bien.

    A l'usage, cette façon de programmer les petits utilitaires est extrêmement pratique et rapide! Même quand on n'y a pas touché depuis 6 mois!

    Essayez !
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je ne comprends pas les difficultés que vous rencontrez avec la programmation spécifique de mes petits utilitaires.
    Ce sont des programmes et les professionnels ont une vue biaisée de ce que cela peut être.

    Déjà on veut délimiter ses limites de responsabilités. Normal, lorsqu'on livre un truc supposé répondre à un cahier des charges. Puis on chiade le traitement des erreurs (dans la saisie des paramètres) pour que l'utilisateur sache quoi faire (sans faire sonner notre téléphone).

    Une façon simple de définir la frontière est de se réserver le droit de coder et/ou de ne pas demander à l’utilisateur de paramétrer directement le code (via un script python) mais de préférer des fichiers INI, JSON, ...: ce sont des données externes qu'on va pouvoir valider avant de les utiliser,...

    Votre façon d'utiliser python (un aide mémoire exécutable) ne respecte pas cette séparation... et choque un peu le programmeur "professionnel" qui va toujours commencer par tracer ses limites de responsabilités et les traduire par des class, de l'encapsulation, ...

    Là ou le bas blesse est que Python reste un langage de scripting: ces limites sont assez imaginaires (et illusoires).
    Peut être que ça choquerait moins d'écrire vos aides mémoires avec bash (qui n'est pas fait pour programmer) plutôt qu'avec Python (qu'on aimerait voir comme bien plus qu'un simple bash).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut
    Merci wiztricks, je comprends mieux les insatisfactions des intervenants.

    En fait, j'ai conçu ces utilitaires comme des outils de travail pour le programmeur lui-même (à commencer par moi!), et pas dans la perspective d'une vente, ce qui nécessiterait, effectivement, une séparation développeur-utilisateur.

    Je sais faire cette séparation, tout en utilisant Python pour les données de traitement, afin de bénéficier de sa syntaxe (meilleure que le bash). Il suffit de faire en sorte que cette page Python de données de traitement soit importée par le programme.
    Pour chaque application, il suffit d'appeler le programme en donnant la page des données de traitement comme argument au lancement. Il faut dans ce cas que l'importation soit faite avec le nom du fichier à importer, c'est à dire avec le module importlib.

    A noter qu'une telle méthode est compatible avec la conversion du programme en "standalone" (cx_freeze, pyinstaller) qui accepte l'importation de ma page Python sans problème! Cela faciliterait la diffusion, y compris pour des PC qui n'ont pas Python installé.

    Je vais essayer de proposer un exemple.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je sais faire cette séparation, tout en utilisant Python pour les données de traitement, afin de bénéficier de sa syntaxe (meilleure que le bash). Il suffit de faire en sorte que cette page Python de données de traitement soit importée par le programme.
    A votre place, je ne ferais rien car il est assez vain de se battre contre des principes: on va toujours y trouver à redire quoi qu'on y fasse. Ici on pourra toujours dire qu'une coquille dans le fichier importé pourra foutre une grouille bien plus difficile à détecter que la lecture de données depuis un fichier JSON (et ce sera vrai).

    note: je ne suis pas contre les "principes" mais ils n'ont de sens que dans leur contexte.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #13
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 574
    Points : 2 017
    Points
    2 017
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Merci wiztricks, je comprends mieux les insatisfactions des intervenants.

    Pour ma part, je n'ai pas exprimé d'insatisfactions, mais plutôt un feedback à chaud, en lisant les différents codes que tu nous présentais et en fonction de mon expérience ou de mes habitudes personnelles.

    Si le code te convient tel quel et convient à d'autres, c'est parfait

  14. #14
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 608
    Points : 2 072
    Points
    2 072
    Par défaut
    Merci tyrtamos pour ce programme car j'ai justement des vidéos à convertir.
    J'ai essayé quelques modifs pour faire tourner la version multi sous Ubuntu, sans succès.
    J'ai notamment modifié cela et cela semble coincé (à moins que la durée de traitement soit vraiment très longue) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe"
    programme = r"ffmpeg"
    Pas d'aide par mp.

  15. #15
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 826
    Points : 7 123
    Points
    7 123
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    A votre place, je ne ferais rien car il est assez vain de se battre contre des principes: on va toujours y trouver à redire quoi qu'on y fasse. Ici on pourra toujours dire qu'une coquille dans le fichier importé pourra foutre une grouille bien plus difficile à détecter que la lecture de données depuis un fichier JSON (et ce sera vrai).

    note: je ne suis pas contre les "principes" mais ils n'ont de sens que dans leur contexte.

    - W
    Le contexte ici est de présenter un code à des développeurs python censés connaître les conventions du langage, alors je dirais que les critiques sont justifiés quand aux conventions du langage. On est dans "Contribuez" où l'on s'attend à proposer des améliorations qui peuvent être à prendre ou à laisser, et dans ce cas de figure j'apporte mon lot de contributions.

    et choque un peu le programmeur "professionnel" qui va toujours commencer par tracer ses limites de responsabilités et les traduire par des class, de l'encapsulation, ...
    oui, (un réflexe chez un développeur professionnel) et la manière dont elle peut évoluée, déboguée (ce qui représente sans doute tes ... dans ta phrase).
    Il y a toujours une réflexion pour voir plus loin, rendre flexible, solide et lisible, parce-qu'un cahier des charges change souvent, les idées des clients ne sont pas toujours claires et faut prévoir le cas où, se poser les bonnes questions et souvent interpréter ce qui n'est pas clair.
    Tout ça tu connais bien mieux que moi

    @Tyrtamos,

    J'ai rien contre les codes "anarchiques" (j'entend hors convention, avec une organisation personnelle qu'on maîtrise bien mais que d'autres ne pourraient comprendre) quand c'est du code perso et qui fonctionne.
    J'ai proposé des solutions plus conventionnelles mais tout n'est pas à prendre, cependant certaines choses peuvent être reprises sans tout autant détruire le fonctionnement de l'application...

    A l'usage, cette façon de programmer les petits utilitaires est extrêmement pratique et rapide! Même quand on n'y a pas touché depuis 6 mois!
    Chacun sa vision des choses, ce n'est absolument pas la mienne, et tu là connais maintenant, mais si ça te convient, alors c'est l'essentiel... Cependant comme je l'ai déjà dis, si je devais avoir ce besoin, je préfère le coder moi même que d'utiliser ce type de code.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  16. #16
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut Adaptation à Linux de la conversion en mp4 multifichiers
    Bonjour marco056

    Citation Envoyé par marco056 Voir le message
    J'ai essayé quelques modifs pour faire tourner la version multi sous Ubuntu, sans succès.
    J'ai essayé sur Linux Mint (enfant d'Ubuntu), et ça marche avec les petites modifications suivantes:

    - mettre, bien sûr, les bonnes adresses pour les répertoires source et destination, ainsi que pour le fichier log s'il y en a un. Pour le programme sous Linux, "ffmpeg" a suffit.

    - subprocess.Popen sous Linux ne semble pas supporter le passage de la commande en list, et il faut donc lui donner une ligne de commande complète en str. Mais il y a une conséquence: toutes les adresses disques doivent être passées entre guillements pour le cas où elles comporteraient des espaces.

    - une autre conséquence pour les motifs wildcard: Linux et MacOS tiennent compte de la casse (majuscules-minuscules) et donc, si on donne "*.avi", on ne trouvera pas les fichiers "xxx.AVI". Il faut donc ajouter les motifs wildcard en majuscule et en minuscule, ou avoir une fonction de recherche de fichiers qui neutralise la casse, ce que glob ne fait pas à part sous Windows. Si tu en cherches une, je peux te faire une proposition.

    Voilà donc le code modifié en conséquence pour la conversion en mp4 multifichiers qui fonctionnera en multiplatforme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    # -*- coding: utf-8 -*-
    """Convertit en mp4 les fichiers vidéo qui satisfont les motifs wildcard
    """
    import os
     
    ##############################################################################
    # Données de traitement
     
    # répertoire source
    repsrce = "/home/tyrtamos/Progsup/utilscripts/video-audio/Documentaires" # Linux
    repsrce = r"\\MULTINET\public\video\videos\TV" # Windows sur NAS
     
    # répertoire destination (si "" => même répertoire que le répertoire source)
    repdest = ""
     
    # motifs wildcard des fichiers sources à convertir (séparateur = ';')
    inclusfics = "*.avi;*.mkv;*.mpg;*.mpeg;*.divx;*.vob;*.ts" # "*.AVI" #
     
    sautexiste = True # si True: ne remplace pas la destination existante
     
    # si fichier log => détourne l'affichage console vers le fichier
    fichierlog = "" #"conversion_mp4_multi.txt" # si "" => pas de fichier log
     
    arguments = lambda ficsrce, ficdest: [
    "-i", ficsrce, # fichier vidéo à convertir
    "-hide_banner", # cache la bannière
    "-nostdin", # empêche les questions pendant le traitement
    "-y", # permet de remplacer un fichier existant sans demander
    "-c:v", "libx264", # utilise le pilote vidéo mp4
    "-c:a", "aac", # utilise le pilote audio AAC
    ficdest # => fichier mp4 à créer
    ]
     
    """
    Réserve de codes
    "-aspect", "1920:800",  # changement aspect (cinema:1920:800)
     
    "-vf", "scale=1920:800", # change taille et ratio (cinema:1920:800)
    "-vf", "scale=-2:800", # change taille sans changer ratio
    "-vf", "scale=1920:-2", # change taille sans changer ratio
    "-vf", "scale=iw*2:ih", # change taille en utilisant les variables iw et ih
    """
     
    ##############################################################################
    ##############################################################################
    # Données de programme
     
    programme = "ffmpeg" # Linux
    programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe" # Windows
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = os.environ.copy() # variables d'environnement (possible: None)
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    #############################################################################
    # Importations
     
    import sys
    from time import perf_counter # pour calcul du temps de traitement
    from glob import iglob # pour recherche de fichiers
     
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    if __name__ == "__main__":
     
        #==========================================================================
        # valide le répertoire source
        if not os.path.exists(repsrce):
            print()
            print("Erreur: répertoire source non trouvé")
            print()
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        repsrce = os.path.abspath(os.path.expanduser(repsrce))
     
        #==========================================================================
        # valide le répertoire destination
        if not repdest:
            repdest = repsrce
        if not os.path.exists(repdest):
            os.mkdir(repdest) # crée le répertoire destination
        repdest = os.path.abspath(os.path.expanduser(repdest))
     
        #========================================================================
        # lance la fonction d'affichage (et d'enregistrement si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("CONVERSION DE VIDEOS EN MP4 ({})".format(cejour()))
        print2("Répertoire source:", repsrce)
        print2("Répertoire destination:", repdest)
        print2("Motifs wildcard de recherche:", inclusfics)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #==========================================================================
        # cherche tous les fichiers correspondant aux motifs de recherche
     
        fichiers = []
        for motif in inclusfics.split(";"):
            for fichier in iglob(os.path.join(repsrce, motif)):
                if os.path.isfile(fichier):
                    fichiers.append(fichier)
     
        #==========================================================================
        # traite tous les fichiers un par un
     
        tps0 = 0 # compteur de temps pour l'ensemble des vidéos
     
        for fichiersrce in fichiers:
     
            #==========================================================================
            # calcule le fichier destination
            nomfic = os.path.basename(fichiersrce) # chemin retiré
            fichierdest = os.path.join(repdest, os.path.splitext(nomfic)[0]+".mp4")
     
            if sautexiste and os.path.exists(fichierdest):
                print2()
                print2("="*79)
                print2("Ce fichier destination existe déjà:", fichierdest)
                print2()
                continue # => fichier suivant
     
            #==========================================================================
            # Affiche le titre pour chaque vidéo
            print2()
            print2("="*79)
            print2("Source:     ", fichiersrce)
            print2("Destination:", fichierdest)
            print2()
     
            #==========================================================================
            # Calcule la ligne de commande (list)
            fichiersrce, fichierdest = '"'+fichiersrce+'"', '"'+fichierdest+'"'
            commande = [programme] + arguments(fichiersrce, fichierdest)
     
            # si fichier log => redirige les affichages sur le fichier donné
            if fichierlog:
                fichierlog = '"'+fichierlog+'"'
                commande = commande + ["1>>", fichierlog, "2>&1"]
                shell = True # nécessaire pour la redirection
     
            # convertit en str
            commande = " ".join(commande)
     
            #========================================================================
            # ferme le fichier log pour permettre l'affichage du processus
            print2.ferme()
     
            #==========================================================================
            # Lance le processus de traitement
            tps = perf_counter() # compteur de temps pour le traitement
     
            rc = execproc(commande, encodage, dictenv, shell)
     
            tps = perf_counter()-tps # temps de traitement
            tps0 += tps
     
            #==========================================================================
            # Réouvre le fichier log pour poursuivre l'enregistrement
            print2 = Print2(fichierlog, "a") # "a" pour continuer fichierlog
     
            #==========================================================================
            # Fin de traitement de la vidéo
            print2()
            print2("Fin du traitement de la vidéo. Statut d'exécution:", rc)
            print2("Temps d'exécution: {}".format(affichedelai(tps)))
            print2()
     
        #==========================================================================
        # Fin de traitement pour l'ensemble des vidéos
        print2()
        print2("="*79)
        print2("Fin du traitement des vidéos")
        print2("Temps total d'exécution: {}".format(affichedelai(tps0)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
     
        ##############################################################################
        # Fin d'exécution
        _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
    J'ai trouvé l'exécution sur Linux lente (env. 40 minutes pour un fichier avi de 730Mo), mais mon PC dédié Linux est vieux. En tout cas, le résultat en mp4 s'affiche parfaitement.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  17. #17
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 608
    Points : 2 072
    Points
    2 072
    Par défaut
    Merci, je vais tester cela.
    J'ai réussi à faire ce que je voulais (sur un autre fil). Malheureusement, la télé ne veut ni du mkv, ni du mp4, ni de l'avi.
    C'est étrange car d'habitude, je n'ai pas de souci avec ces extensions.
    Pas d'aide par mp.

  18. #18
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 465
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 465
    Points : 9 257
    Points
    9 257
    Billets dans le blog
    6
    Par défaut Séparation entre données et traitement pour la conversion en mp4
    Voici une version de la conversion vidéo en mp4 qui sépare nettement les données et le traitement, et qui respecte un peu mieux les recommandations traditionnelles de codage en Python. J'en ai profité pour adapter le code à Linux (quelqu'un peut-il essayer avec MacOS?). Je me suis limité ici à la conversion en mp4 parce que c'est ça que j’utilise, mais le code peut être adapté facilement pour un autre format vidéo.

    Le principe est simple: les données de traitement et de programme se trouvent dans le 1er fichier (appelé ici "conv_mp4.py"), et c'est lui qui doit être adapté au traitement à faire dans l'éditeur de texte. Je rappelle qu'il y a un grand intérêt à ce que l'écriture des données profitent de la syntaxe Python, par rapport aux autres solutions type "script console" ou fichiers ".ini", ou même base de données.

    A la fin du code, le module de traitement est importé (appelé ici "conv_mp4_mod.py"), et l'appel de la fonction d'exécution "execdatas(...)" est faite avec les données comme arguments. Je me suis même demandé si cette partie d'exécution pouvait être commune, et donc en bibliothèque. Mais non, parce qu'il y a toujours des parties spécifiques à chacun des traitements.

    Bien sûr, l'exécution du traitement produit toujours le même résultat qu'avant: la vidéo est bien convertie, et le temps de traitement est identique.

    Fichier "conv_mp4.py" pour les données:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    # -*- coding: utf-8 -*-
    """ Convertit en mp4 la vidéo (données de traitement)
    """
     
    ##############################################################################
    # Données de traitement
     
    # fichier vidéo à convertir
    source = r"chemin/vers/mavideo.avi"
     
    # fichier vidéo converti
    destination = r"chemin/vers/mavideo.mp4"
     
    sautexiste = False # si True: ne remplace pas la destination existante
     
    # si fichier log => détourne l'affichage console vers le fichier
    fichierlog = "" #"conversion_mp4.txt" # si "" => pas de fichier log
     
    # arguments:  toutes les valeurs sont des chaînes de caractères
    arguments = lambda srce, dest: [
    "-i", srce, # fichier vidéo à convertir
    "-hide_banner", # cache la bannière
    "-nostdin", # empêche les questions pendant le traitement
    "-y", # permet de remplacer un fichier existant sans demander
    "-c:v", "libx264", # utilise le pilote vidéo mp4
    "-c:a", "aac", # utilise le pilote audio AAC
    dest # => fichier vidéo converti (à créer)
    ]
     
    """
    Réserve de codes
    "-aspect", "2.4",  # changement ratio (cinema:1920:800)
    "-aspect", "16:9",  # changement ratio (full HD:1920:1080)
     
    "-vf", "scale=1920:800", # change taille et ratio (cinema:1920:800)
    "-vf", "scale=-2:800", # change taille sans changer ratio
    "-vf", "scale=1920:-2", # change taille sans changer ratio
    "-vf", "scale=iw*2:ih", # change taille en utilisant les variables iw et ih
    """
     
    ##############################################################################
    # Données de programme
     
    programme = r"D:\progsup\ffmpeg\bin\ffmpeg.exe"
     
    encodage = "utf-8" #"cp1252":windows, "cp850":console DOS, "iso-8859-1":latin-1
     
    dictenv = None
     
    shell = False # True pour utiliser les instructions spécifiques console
     
    #############################################################################
    #############################################################################
    # Exécution
    from conv_mp4_mod import execdatas
    execdatas(source, destination, sautexiste, fichierlog, arguments, programme,
                encodage, dictenv, shell)
    _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
    Fichier "conv_mp4_mod.py" pour le traitement:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    # -*- coding: utf-8 -*-
    """ Convertit en mp4 la vidéo donnée. Appelé par le fichier des données
    """
    import os
    import sys
    from time import perf_counter # pour calcul du temps de traitement
     
    # Importe les fonctions de bibliothèque
    from biblio import (cejour, affichedelai, execproc, Print2)
     
    #############################################################################
    # Exécution
     
    def execdatas(source, destination, sautexiste, fichierlog, arguments,
                  programme, encodage, dictenv, shell):
        """ Exécute le traitement en utilisant toutes les données transmises comme
            arguments
        """
     
        #==========================================================================
        # valide la source
        if not os.path.exists(source):
            print("Erreur: Fichier source non trouvé")
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        source = os.path.abspath(os.path.expanduser(source))
     
        #==========================================================================
        # valide la destination
        if sautexiste and os.path.exists(destination):
            print("La destination existe déjà")
            _ = input('Tapez "entrée" pour arrêter') # retarde fermeture console
            sys.exit()
        destination = os.path.abspath(os.path.expanduser(destination))
     
        #========================================================================
        # lance la fonction d'affichage (et d'enregistrement si demandé)
        print2 = Print2(fichierlog)
     
        #========================================================================
        # Affiche le titre
        print2()
        print2("CONVERSION VIDEO EN MP4 ({})".format(cejour()))
        print2("Fichier source:", source)
        print2("Fichier destination:", destination)
        if fichierlog:
            print2("Fichier log:", fichierlog)
        print2()
     
        #========================================================================
        # ferme le fichier log pour permettre l'affichage du processus
        print2.ferme()
     
        #==========================================================================
        # Calcule la ligne de commande (list)
        source, destination = '"'+source+'"', '"'+destination+'"'
        commande = [programme] + arguments(source, destination)
     
        # si fichier log => redirige les affichages sur le fichier donné
        if fichierlog:
            fichierlog = '"'+fichierlog+'"'
            commande = commande + ["1>>", fichierlog, "2>&1"] # ">>" pour ajout
            shell = True # True nécessaire pour le détournement vers fichier log
     
        # convertit en str
        commande = " ".join(commande)
     
        #==========================================================================
        # Lance le processus de traitement
        tps = perf_counter() # compteur de temps pour le traitement
        rc = execproc(commande, encodage, dictenv, shell)
        tps = perf_counter()-tps # temps de traitement
     
        #==========================================================================
        # Réouvre le fichier log pour poursuivre l'enregistrement
        print2 = Print2(fichierlog, "a") # "a" pour continuer fichierlog
     
        #==========================================================================
        # Affiche le temps de traitement et le statut d'exécution
        print2()
        print2("Fin du traitement. Statut d'exécution:", rc)
        print2("Temps d'exécution: {}".format(affichedelai(tps)))
        print2()
     
        #==========================================================================
        # ferme le fichier log s'il existe
        print2.ferme()
    Rappel de la bibliothèque "biblio.py" qui n'a pas changée:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    # -*- coding: utf-8 -*-
    """
    Biliothèque générale
    """
     
    import sys
    from datetime import datetime
    from subprocess import Popen
     
    #############################################################################
    def cejour(sepdate='/', septemps='_', sepheure=':'):
        """Retourne la date du jour sous le format "jj/mm/aaaa_hh:mm:ss"
           Possibilité de changer les séparateurs
         """
        jour = datetime.today().strftime('%d/%m/%Y_%H:%M:%S')
        return jour.replace('/', sepdate).replace('_', septemps).replace(':', sepheure)
     
    #############################################################################
    def affichedelai(secs):
        """Retourne une chaîne pour affichage d'un délai exprimé en secondes. Le
           résultat peut comporter jours, heures, minutes et secondes.
           Exemple: 2748.562 sec  => "45:48.562" soit 45 mn et 48.562 sec
           Un éventuel signe négatif est neutralisé dans le calcul mais restitué
           au résultat final
        """
        sign = "" if secs>=0 else "-"
        secs = abs(secs)
        j, r = divmod(secs, 86400) # 86400: 3600x24
        h, r = divmod(r, 3600)
        m, s = divmod(r, 60)
        j, h, m = int(j), int(h), int(m)
        if j>0:
            return "{}{:d}:{:02d}:{:02d}:{:06.3f}".format(sign, j, h, m, s)
        elif h>0:
            return "{}{:02d}:{:02d}:{:06.3f}".format(sign, h, m, s)
        elif m>0:
            return "{}{:02d}:{:06.3f}".format(sign, m, s)
        else:
            return "{}{:6.3f}".format(sign, s)
     
    ##############################################################################
    def execproc(commande, encodage="utf-8", dictenv=None, shell=False):
        """Appelle l'exécutable et ses arguments (commande) dans un processus.
           - commande: ligne de commande (liste ou chaine de caractères)
           - encodage: encodage des sorties du processus (défaut: 'utf-8)
           - dictenv: dict. d'environnement à passer au processus (défaut: None)
           - shell: si True, accepte les instructions console (défaut: False)
           Retourne le statut d'exécution du programme
        """
        with Popen(commande, bufsize=1, stdin=sys.stdin, stdout=sys.stdout,
                stderr=sys.stdout, shell=shell, env=dictenv,
                universal_newlines=True, encoding=encodage, errors='replace')\
                as proc:
     
            while proc.poll() is None: # on attend tant que le programme est actif
                pass
     
            rc = proc.poll() # statut d'exécution du programme terminé
     
        return rc # retourne le statut d'exécution du programme
     
    ##############################################################################
    class Print2:
        """Affiche le déroulement du traitement dans la console
           Si demandé, enregistre sur disque en plus de l'affichage sur la console
        """
     
        #=========================================================================
        def __init__(self, fichierlog="", modw="w", encodage="utf-8",
                                                                    affiche=True):
            """Initialise l'affichage et l'ouverture du fichier log (fichierlog)
               - fichierlog: si non vide: nom de fichier log à créer (avec chemin)
               - modw: mode d'écriture du fichierlog. Si 'a': ne détruit pas avant
               - encodage: encodage du fichierlog
               - affiche: si True, affiche sur le périphérique de sortie
            """
            self.flog = None
            if fichierlog:
                try:
                    self.flog = open(fichierlog, modw, encoding=encodage)
                except Exception:
                    # fichier log donné non conforme ou inaccessible
                    self.flog = None # aucun enregistrement ne sera fait
            self.affiche = affiche
     
        #=========================================================================
        def __call__(self, *v):
            """Affiche sur console et enregistre dans le fichier log si demandé
            """
            if self.affiche:
                print(*v, end='\n', flush=True) # affichage périphérique de sortie
            if self.flog:
                # enregistrement sur disque
                print(*v, end='\n', file=self.flog, flush=True)
     
        #=========================================================================
        def ferme(self):
            """Ferme le fichier log s'il existe et qu'il est ouvert
            """
            if self.flog:
                self.flog.close()
    Exemple d'exécution (extrait):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    CONVERSION VIDEO EN MP4 (24/12/2023_04:58:47)
    Fichier source: mavideo.avi
    Fichier destination: mavideo.mp4
     
    Input #0, avi, from 'mavideo.avi':
      Metadata:
        software        : FairUse Wizard - http://fairusewizard.com
      Duration: 01:29:04.64, start: 0.000000, bitrate: 1098 kb/s
      Stream #0:0: Video: mpeg4 (Advanced Simple Profile) (XVID / 0x44495658), yuv420p, 608x336 [SAR 1:1 DAR 38:21], 960 kb/s, 25 fps, 25 tbr, 25 tbn
      Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 48000 Hz, stereo, fltp, 128 kb/s
    Stream mapping:
      Stream #0:0 -> #0:0 (mpeg4 (native) -> h264 (libx264))
      Stream #0:1 -> #0:1 (mp3 (mp3float) -> aac (native))
    [mpeg4 @ 00000121948692c0] Video uses a non-standard and wasteful way to store B-frames ('packed B-frames'). Consider using the mpeg4_unpack_bframes bitstream filter without encoding but stream copy to fix it.
    [libx264 @ 00000121947c6f80] using SAR=1/1
    [libx264 @ 00000121947c6f80] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
    [libx264 @ 00000121947c6f80] profile High, level 2.2, 4:2:0, 8-bit
    ...
    ...
    ...
      Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s
        Metadata:
          encoder         : Lavc59.18.100 aac
    frame=133617 fps=643 q=-1.0 Lsize=  333006kB time=01:29:04.56 bitrate= 510.4kbits/s dup=2 drop=0 speed=25.7x
    video:244714kB audio:84321kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.206817%
    [libx264 @ 00000121947c6f80] frame I:1523  Avg QP:19.60  size: 13521
    [libx264 @ 00000121947c6f80] frame P:55106 Avg QP:22.40  size:  2990
    [libx264 @ 00000121947c6f80] frame B:76988 Avg QP:24.27  size:   848
    [libx264 @ 00000121947c6f80] consecutive B-frames:  2.2% 62.6%  0.8% 34.3%
    [libx264 @ 00000121947c6f80] mb I  I16..4:  4.2% 92.5%  3.3%
    [libx264 @ 00000121947c6f80] mb P  I16..4:  1.0%  3.9%  0.2%  P16..4: 57.0% 11.7%  7.7%  0.0%  0.0%    skip:18.4%
    [libx264 @ 00000121947c6f80] mb B  I16..4:  0.1%  0.5%  0.0%  B16..8: 31.6%  1.9%  0.3%  direct: 1.4%  skip:64.3%  L0:40.1% L1:55.1% BI: 4.8%
    [libx264 @ 00000121947c6f80] 8x8 transform intra:82.0% inter:89.5%
    [libx264 @ 00000121947c6f80] coded y,uvDC,uvAC intra: 65.6% 74.1% 22.8% inter: 14.5% 26.6% 0.2%
    [libx264 @ 00000121947c6f80] i16 v,h,dc,p: 23% 16% 10% 51%
    [libx264 @ 00000121947c6f80] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 20% 15% 36%  4%  5%  5%  5%  5%  5%
    [libx264 @ 00000121947c6f80] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 14% 15%  7%  9%  9%  8%  7%  5%
    [libx264 @ 00000121947c6f80] i8c dc,h,v,p: 53% 19% 22%  6%
    [libx264 @ 00000121947c6f80] Weighted P-Frames: Y:4.4% UV:1.8%
    [libx264 @ 00000121947c6f80] ref P L0: 61.3% 11.9% 18.3%  8.2%  0.4%
    [libx264 @ 00000121947c6f80] ref B L0: 85.5% 10.9%  3.7%
    [libx264 @ 00000121947c6f80] ref B L1: 98.3%  1.7%
    [libx264 @ 00000121947c6f80] kb/s:375.08
    [aac @ 00000121947d4cc0] Qavg: 673.293
     
    Fin du traitement. Statut d'exécution: 0
    Temps d'exécution: 03:28.912
     
    Tapez "entrée" pour arrêter

    Bonnes conversions, et bonnes fêtes de fin d'année!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

Discussions similaires

  1. débuter le traitement d'image par python
    Par you.kri dans le forum Calcul scientifique
    Réponses: 0
    Dernier message: 27/02/2017, 20h57
  2. Traitement Vidéo avec Python
    Par Tangoscar dans le forum Général Python
    Réponses: 1
    Dernier message: 07/07/2016, 14h51
  3. Problème avec script lancé par cron
    Par maximeh2 dans le forum Général Python
    Réponses: 2
    Dernier message: 28/07/2015, 15h34
  4. Arrêt non souhaité programme Python lancé par Java
    Par a1331 dans le forum Général Java
    Réponses: 14
    Dernier message: 13/08/2013, 14h34
  5. Traitement XML avec python
    Par diaboloche dans le forum Général Python
    Réponses: 5
    Dernier message: 02/03/2008, 00h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo