Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
srt2ass [Le 15/12/2011, 15:22] – modification externe 127.0.0.1 | srt2ass [Le 06/09/2012, 12:11] (Version actuelle) – Amélioration du script, correction de bugs, liste d'exclusions. Crazyfaboo | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ====== SubRip ====== | ||
+ | Les sous-titres SubRip, d' | ||
+ | < | ||
+ | 1 | ||
+ | 00: | ||
+ | Texte du premier sous titre qui | ||
+ | peut s' | ||
+ | lignes. | ||
+ | |||
+ | 2 | ||
+ | 00: | ||
+ | On peut mettre du texte | ||
+ | en < | ||
+ | </ | ||
+ | |||
+ | ====== Advanced Sub Station Alpha ====== | ||
+ | Les sous-titres Advanced Sub Station Alpha, d' | ||
+ | |||
+ | L' | ||
+ | |||
+ | Ce sous-titre est également au format texte : | ||
+ | < | ||
+ | Dialogue: 0, | ||
+ | Dialogue: 0, | ||
+ | Dialogue: 0, | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | ====== Conversion en ligne de commande ====== | ||
+ | |||
+ | Téléchargez le fichier ci-dessous et rendez-le exécutable. | ||
+ | |||
+ | Pour obtenir de l'aide : srt2ass.py -h ou srt2ass.py --help | ||
+ | |||
+ | Supporte les fichiers SRT encodés en ISO-8859-1, UTF-8, UTF-16 (LE/BE), UTF-32 (LE/BE) | ||
+ | |||
+ | Converti les fichiers SRT en ASS et les encodes en UTF-8. | ||
+ | |||
+ | Correction des erreurs de caractères les plus fréquentes. | ||
+ | |||
+ | Comportement par défaut : srt2ass.py executé sans arguments convertira tous les fichiers SRT du dossier courant. Les fichiers SRT ne seront pas supprimés. | ||
+ | |||
+ | <file python srt2ass.py> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | |||
+ | import codecs | ||
+ | import argparse | ||
+ | import sys, os, glob | ||
+ | |||
+ | # Use this list to delete automatically subs containing one of the following words. All in lower case. | ||
+ | exclusion = [" | ||
+ | |||
+ | class Console: | ||
+ | verbose = False | ||
+ | | ||
+ | @classmethod | ||
+ | def l(c, message, linefeed = True): | ||
+ | sys.stdout.write(message) | ||
+ | if linefeed: | ||
+ | sys.stdout.write(" | ||
+ | | ||
+ | @classmethod | ||
+ | def v(c, message, linefeed = True): | ||
+ | if c.verbose: | ||
+ | c.l(message, | ||
+ | | ||
+ | @classmethod | ||
+ | def w(c, message, linefeed = True): | ||
+ | c.v("## | ||
+ | | ||
+ | @classmethod | ||
+ | def nl(c): | ||
+ | if c.verbose: | ||
+ | sys.stdout.write(" | ||
+ | |||
+ | class SubElement: | ||
+ | | ||
+ | def __init__(self, | ||
+ | self.timeStart = start | ||
+ | self.timeEnd = end | ||
+ | self.text = text | ||
+ | | ||
+ | def appendLine(self, | ||
+ | text = text.lstrip().rstrip() | ||
+ | if text != '': | ||
+ | if self.text != '': | ||
+ | self.text += " | ||
+ | self.text += text | ||
+ | | ||
+ | def __repr__(self): | ||
+ | return self.text | ||
+ | |||
+ | class AdvancedSubStationAlphaWriter: | ||
+ | | ||
+ | def __init__(self, | ||
+ | Console.v(' | ||
+ | self.fontRegular = regular | ||
+ | self.fontSize = size | ||
+ | self.filename = filename | ||
+ | self.elements = subElements | ||
+ | self.write() | ||
+ | | ||
+ | def write(self): | ||
+ | f = open(self.filename, | ||
+ | f.write(codecs.BOM_UTF8) | ||
+ | f.write(self.getHeader()) | ||
+ | for e in self.elements: | ||
+ | f.write(self.getLine(e)) | ||
+ | f.close() | ||
+ | | ||
+ | def getLine(self, | ||
+ | start = self.getTime(element.timeStart) | ||
+ | end = self.getTime(element.timeEnd) | ||
+ | text = element.text.replace(" | ||
+ | font = " | ||
+ | | ||
+ | text = text.replace("< | ||
+ | # Fixes the subtitle | ||
+ | if text.find(" | ||
+ | text += " | ||
+ | | ||
+ | return " | ||
+ | | ||
+ | def getTime(self, | ||
+ | ms = t % 1000 | ||
+ | t = (t - ms) / 1000 | ||
+ | s = t % 60 | ||
+ | t = (t - s) / 60 | ||
+ | m = t % 60 | ||
+ | h = (t - m) / 60 | ||
+ | | ||
+ | ms /= 10 | ||
+ | return ' | ||
+ | | ||
+ | def getHeader(self): | ||
+ | return " | ||
+ | + " | ||
+ | + " | ||
+ | + "[V4+ Styles]\n" | ||
+ | + " | ||
+ | + " | ||
+ | + " | ||
+ | + " | ||
+ | + " | ||
+ | |||
+ | #+ " | ||
+ | | ||
+ | |||
+ | class SubRipReader: | ||
+ | | ||
+ | def __init__(self, | ||
+ | Console.v(' | ||
+ | self.filename = filename | ||
+ | self.bomLength = 0 | ||
+ | self.encoding = ' | ||
+ | self.lines = [] | ||
+ | self.elements = [] | ||
+ | self.detectBomAndEncoding() | ||
+ | self.read() | ||
+ | self.parse() | ||
+ | | ||
+ | def detectBomAndEncoding(self): | ||
+ | f = open(self.filename, | ||
+ | begin = f.read(4) | ||
+ | f.close() | ||
+ | if begin.startswith(codecs.BOM_UTF8): | ||
+ | self.encoding = ' | ||
+ | self.bomLength = 3 | ||
+ | elif begin.startswith(codecs.BOM_UTF16_LE): | ||
+ | self.encoding = ' | ||
+ | self.bomLength = 2 | ||
+ | elif begin.startswith(codecs.BOM_UTF16_BE): | ||
+ | self.encoding = ' | ||
+ | self.bomLength = 2 | ||
+ | elif begin.startswith(codecs.BOM_UTF32_LE): | ||
+ | self.encoding = ' | ||
+ | self.bomLength = 4 | ||
+ | elif begin.startswith(codecs.BOM_UTF32_BE): | ||
+ | self.encoding = ' | ||
+ | self.bomLength = 4 | ||
+ | | ||
+ | if self.bomLength > 0: | ||
+ | Console.v(' | ||
+ | else: | ||
+ | Console.v(' | ||
+ | | ||
+ | def read(self): | ||
+ | if not self.read2(): | ||
+ | Console.v(' | ||
+ | self.encoding = ' | ||
+ | self.read2() | ||
+ | | ||
+ | def read2(self): | ||
+ | try: | ||
+ | f = codecs.open(self.filename, | ||
+ | self.lines = f.readlines() | ||
+ | f.close() | ||
+ | if len(self.lines) > 0 and self.bomLength > 0: | ||
+ | self.lines[0] = self.lines[0].encode(' | ||
+ | except: | ||
+ | return False | ||
+ | return True | ||
+ | | ||
+ | def parse(self): | ||
+ | el = None | ||
+ | isJustNew = False | ||
+ | nextCountReady = True | ||
+ | count = 0 | ||
+ | emptySub = [] | ||
+ | skip = False | ||
+ | for line in self.lines: | ||
+ | l = line.encode(' | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | if isJustNew: | ||
+ | skip = False | ||
+ | isJustNew = False | ||
+ | nextCountReady = False | ||
+ | times = l.split(' | ||
+ | el.timeStart = self.parseTime(times[0]) | ||
+ | el.timeEnd = self.parseTime(times[1]) | ||
+ | elif nextCountReady and l.isdigit(): | ||
+ | count += 1 | ||
+ | Console.v(" | ||
+ | if int(l) != count: | ||
+ | Console.nl() | ||
+ | Console.w(" | ||
+ | if el != None: | ||
+ | if el.text == '': | ||
+ | emptySub.append(count - 1) | ||
+ | else: | ||
+ | self.elements.append(el) | ||
+ | el = SubElement(0, | ||
+ | isJustNew = True | ||
+ | else: | ||
+ | if not skip: | ||
+ | skip = self.exclude(l) | ||
+ | if skip: | ||
+ | Console.nl() | ||
+ | Console.w(" | ||
+ | elif len(l) > 0: | ||
+ | l = l.replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | .replace(" | ||
+ | l = self.applyLanguageOnLine(l) | ||
+ | el.appendLine(l) | ||
+ | nextCountReady = True | ||
+ | | ||
+ | if el != None and len(str(el)) > 0: | ||
+ | self.elements.append(el) | ||
+ | | ||
+ | Console.v(' | ||
+ | Console.v(str(len(emptySub)) + ' subtitles were empty: ' + str(emptySub)) | ||
+ | | ||
+ | def parseTime(self, | ||
+ | r1 = time.split(":" | ||
+ | h = int(r1[0]) | ||
+ | m = int(r1[1]) | ||
+ | r2 = r1[2].split(',' | ||
+ | s = int(r2[0]) | ||
+ | ms = int(r2[1]) | ||
+ | return ((h * 60 + m) * 60 + s) * 1000 + ms | ||
+ | | ||
+ | def applyLanguageOnLine(self, | ||
+ | return line | ||
+ | | ||
+ | def exclude(self, | ||
+ | l = line.lower() | ||
+ | for x in exclusion: | ||
+ | if l.find(x) != -1: | ||
+ | return True | ||
+ | return False | ||
+ | |||
+ | class Srt2Ass: | ||
+ | | ||
+ | def __init__(self, | ||
+ | ass = srt.replace(' | ||
+ | subs = SubRipReader(srt) | ||
+ | AdvancedSubStationAlphaWriter(ass, | ||
+ | if delete: | ||
+ | Console.l(" | ||
+ | os.remove(srt) | ||
+ | |||
+ | if __name__ == " | ||
+ | |||
+ | parser = argparse.ArgumentParser(description=' | ||
+ | parser.add_argument(' | ||
+ | parser.add_argument(' | ||
+ | parser.add_argument(' | ||
+ | parser.add_argument(' | ||
+ | parser.add_argument(' | ||
+ | args = parser.parse_args() | ||
+ | | ||
+ | Console.verbose = args.verbose | ||
+ | | ||
+ | srtfiles = [] | ||
+ | if len(args.file) == 0: | ||
+ | os.chdir(" | ||
+ | srtfiles = glob.glob(" | ||
+ | elif len(args.file) == 1: | ||
+ | os.chdir(" | ||
+ | srtfiles = glob.glob(args.file[0]) | ||
+ | else: | ||
+ | srtfiles = args.file | ||
+ | | ||
+ | for srt in srtfiles: | ||
+ | Srt2Ass(srt, | ||
+ | |||
+ | </ | ||
+ | |||
+ | < |