#!/usr/bin/python # -*- encoding:utf-8 -*- """Syncs SubRip subtitle files.""" # Author : Ginko # Date : 29/06/2014 # Version : 0.1.b # Licence : CC-By # SubRip example """1 00:00:20,672 --> 00:00:24,972 Entre l’Australia et la South America, dans l’Océan South Pacific…""" import re, sys class formatException(BaseException): pass class SrTime(object): """SubRip Time. Can be negative.""" timePat = re.compile(r'(\d{2})\:(\d{2})\:(\d{2}),(\d{3})') def __init__(self, raw=None, sign='+'): self.sign = sign if raw == None: self.h, self.m, self.s, self.ms = (0,0,0,0) elif type(raw) == str: if raw[0] == '-': self.sign = '-' raw = raw[1:] self.h, self.m, self.s, self.ms = self.parse(raw) elif type(raw) in (list, tuple): self.h, self.m, self.s, self.ms = raw else: self.h, self.m, self.s, self.ms = (0,0,0,0) def parse(self, raw): """Parse da time. SubRip Format""" m = SrTime.timePat.match(raw) if m: return map(int, (m.group(1), m.group(2), m.group(3), m.group(4))) else: raise formatException(raw) def __add__(self, delay): if delay.sign == '-': return self - delay if self.sign == '-': return delay - self result = SrTime() s, result.ms = divmod(self.ms + delay.ms, 1000) m, result.s = divmod(self.s + delay.s + s, 60) h, result.m = divmod(self.m + delay.m + m, 60) result.h += h + delay.h return result def __sub__(self, delay): result = SrTime() s, result.ms = divmod(self.ms - delay.ms, 1000) m, result.s = divmod(self.s - delay.s + s, 60) h, result.m = divmod(self.m - delay.m + m, 60) result.h += h - delay.h if result.h < 0 : result = SrTime() # I could have used the negative sign to respect arithmetics but in subtitle, a negative timestamp is dumb return result def __str__(self): """Print da time. SubRip Format.""" return "{:02}:{:02}:{:02},{:03}".format(self.h, self.m, self.s, self.ms) def __repr__(self): return(str(self)) if __name__ == "__main__": def printHelp(): print("Usage: subsync.py .") print('Time can be negative. Ex.: "-00:02:15,042"') sys.exit(0) def main(fileName, delay): """Read srt file and write a "delayed" file.""" pat = re.compile(r'\-?\d{2}\:\d{2}\:\d{2},\d{3}') def delayIt(rawTime): return str(SrTime(rawTime.group(0)) + delay) with open(fileName, 'r') as infile: with open("{}.delayed.srt".format(fileName.rstrip('.srt')), 'w') as outfile: for i, line in enumerate(infile): try: outfile.write(pat.sub(delayIt, line)) except formatException: print("Bad time format at line {}".format(i)) # I think it cannot happen... just looks cleaner print("Aborting process.") sys.exit(1) if sys.argv[1] in ('-h', '--help'): printHelp() try: fileName, delay = sys.argv[1:3] except ValueError: print("Some arg missing.\n") printHelp() try: delay = SrTime(delay) except formatException: print("Bad time format.\n") printHelp() try: main(fileName, delay) except IOError: print("Can't read or write files.\n") printHelp()