Python can save your ass!
Définition du besoin
Je suis fan de la série NCIS… Et cette semaine j’ai récupéré la première saison en VO. J’ai téléchargé le pack de sous-titres sur www.tvsubtitles.net. Je copie les épisodes et leur sous-titre sur ma FreeBox et lance le premier épisode.
Et la, c’est le drame! Un gros décalage de 2 secondes environ entre la bande sonore et le sous-titre
Un collègue du boulot m’a donné une idée : écrire un programme pour mettre à jour les sous-titres!
En effet, les fichiers de sous-titre sont de simple fichier textes qui sont composés de la manière suivante :
1 00:01:16,577 --> 00:01:18,579 NCIS ENQUETES SPECIALES 2 00:01:53,572 --> 00:01:56,408 "L'affrontement" 3 00:02:01,288 --> 00:02:02,706 Réveille-le.
Il suffit donc d’écrire un petit programme qui lit le fichier et qui analyse les lignes. Si la ligne est une ligne du type : “00:02:01,288 –> 00:02:02,706″ et si c’est le cas, il faut extraire les valeurs numériques pour créer des objets de type date avec et ainsi pouvoir faire le calcul pour ajouter/soustraire un delay. Enfin on écrit chaque ligne dans un nouveau fichier texte.
Comme une série se compose de 23 épisodes et que je suis une loutre, il faut aussi que le programme se débrouille tout seul pour trouver les fichiers sous-titres et les corriger les uns après les autres…
Et oui, Python peut vous sauver la vie!
Résultat
Ce petit programme en Python3 : reprise_sous_titres.py.
#!/usr/bin/python3 #--------------------------------------------------------------------# # Programme : reprise_sous_titres.py # # Auteur : Julien PECQUEUR (JPEC) # # Home : http://julienpecqueur.com # # License : GPL # # # # Description : # # Ce programme va reprendre tous les fichiers de type sous-titre # # contenus dans le répertoire REPERTOIRE et va leur appliquer un # # décalage DECALAGE. # #--------------------------------------------------------------------#
#--------------------------------------------------------------------# # IMPORT DES MODULES # #--------------------------------------------------------------------# import os # Fonctions système import datetime # Fonctions date/heure import re # Expressions régulières
#--------------------------------------------------------------------# # PARAMETRAGE # #--------------------------------------------------------------------# # REPERTOIRE Chemin du répertoire dans lequel se trouvent les # fichiers sous-titre. REPERTOIRE = "/home/jpec/"
# EXTENSION Extension des fichiers de type sous-titre. EXTENSION = ".srt"
# MASQUE Format d'une ligne avec le positionnement horaire.
# ex: 00:02:18,639 --> 00:02:21,099
MASQUE = "([0-9][0-9]):([0-9][0-9]):([0-9][0-9]),([0-9][0-9][0-9])"+\
" --> " + \
"([0-9][0-9]):([0-9][0-9]):([0-9][0-9]),([0-9][0-9][0-9])"
# DECALAGE_* Valeurs du décalage pour les sous-titres. DECALAGE_HEU = 0 # Heures DECALAGE_MIN = 0 # Minutes DECALAGE_SEC = 2 # Secondes DECALAGE_MSC = 500000 # Micro-secondes
# SUPPR_SOURCE Suppression du fichier source? ("OUI" ou "NON")
SUPPR_SOURCE = "NON"
#--------------------------------------------------------------------#
# FONCTIONS #
#--------------------------------------------------------------------#
def corriger(Fichier):
# Fonction corriger(Nom du fichier) - Elle corrige le fichier de
# sous-titre passé en paramêtre en lui appliquant le décalage
# définit : DECALAGE_*.
print("*** Correction fichier '" + Fichier + "\'...")
FichierSource = open(REPERTOIRE + Fichier, \
'r', \
encoding="iso8859_15")
# Fichier temporaire :
FichierCible = open(REPERTOIRE + Fichier + ".tmp", \
'w', \
encoding="iso8859_15")
# On boucle sur les lignes du fichier source pour alimenter le
# fichier temporaire :
for Ligne in FichierSource:
if Regex.match(Ligne):
# On est sur une ligne de positionnement horaire :
StartH = int(Regex.match(Ligne).group(1))
StartM = int(Regex.match(Ligne).group(2))
StartS = int(Regex.match(Ligne).group(3))
Startm = int(Regex.match(Ligne).group(4))*1000
EndH = int(Regex.match(Ligne).group(5))
EndM = int(Regex.match(Ligne).group(6))
EndS = int(Regex.match(Ligne).group(7))
Endm = int(Regex.match(Ligne).group(8))*1000
Start = datetime.datetime(2000, 1, 1, \
StartH,
StartM,
StartS,
Startm)
End = datetime.datetime(2000, 1, 1, \
EndH,
EndM,
EndS,
Endm)
Start = Start + Delay
End = End + Delay
StartH = Start.strftime('%H')
StartM = Start.strftime('%M')
StartS = Start.strftime('%S')
Startm = Start.strftime('%f')[0:3]
EndH = End.strftime('%H')
EndM = End.strftime('%M')
EndS = End.strftime('%S')
Endm = End.strftime('%f') [0:3]
# Construction de la nouvelle ligne :
Ligne = StartH +":"+ StartM +":"+ StartS +","+ Startm \
+ " --> " + \
EndH +":"+ EndM +":"+ EndS +","+ Endm + "\n"
FichierCible.write(Ligne)
# Fermeture des fichiers :
FichierSource.close
FichierCible.close
# Gestion copie/remplace :
if SUPPR_SOURCE == "OUI":
print("*** Suppression fichier source \'" + Fichier + "\'...")
os.remove(REPERTOIRE + Fichier)
print("*** '" + Fichier + ".tmp\' -> \'" + Fichier + "\'...")
os.rename(REPERTOIRE + Fichier + ".tmp", REPERTOIRE + Fichier)
print("*** \'" + Fichier + "\' DONE !")
#--------------------------------------------------------------------#
# CODE #
#--------------------------------------------------------------------#
# Récupération de la liste des fichiers du répertoire de travail :
print("*** Liste des fichiers de \'" + REPERTOIRE + "\'...")
ListeFichiers = os.listdir(REPERTOIRE)
ListeFichiers.sort()
# Création de l'expression régulière pour le masque : Regex = re.compile(MASQUE)
# Création du décalage pour les sous-titres :
Delay = datetime.timedelta(hours=DECALAGE_HEU, \
minutes=DECALAGE_MIN, \
seconds=DECALAGE_SEC, \
microseconds=DECALAGE_MSC)
# Boucle sur les fichiers du répertoire de travail. Si c'est un
# fichier de type sous-titre, alors on appelle la fonction corriger :
print("*** Boucle sur les fichiers de type \'" + EXTENSION + "\'...")
for Fichier in ListeFichiers:
if Fichier[len(Fichier)-len(EXTENSION):len(Fichier)] == EXTENSION:
corriger(Fichier)
#--------------------------------------------------------------------# # FIN DU PROGRAMME # #--------------------------------------------------------------------#




