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"
Conversion d'une liste de vidéos en mp4
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
Code complet "conversion_mp4_multi.py"
Réparation d'une vidéo
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
Code complet "repare_video.py"
Extraction audio d'une vidéo
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
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 !
Partager