diff --git a/README.md b/README.md index 183ea6a..03023b0 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,27 @@ -##**SubFixer** +# SubFixer SubFixer does a bit of string manipulation and datetime math to shift your subtitles to match your film and decode string to unicode and fix problems with Persian. SubFixer is based on [Ali Vakilzade](https://github.com/aliva/) SubtitleFixer and [delwin](https://github.com/enceladus/) subtitle-shifter. -###Install SubFixer +## Install SubFixer ``` $ pip install subfixer ``` -###Fix persian subtitles -``` -$ subfixer input_file_name.srt --fix_persian -``` +## Usage -###Shift time -``` -$ subfixer input_file_name.srt --shif 10 #shift 10 secound +Simple fix subtitles: + +```shell +$ subfixer input.srt ``` -###More help and options +Shifting some second times: +```shell +$ subfixer input.srt --shif 10 # Shift 10 secound ``` + +for more help and options: +```shell $ subfixer --help ``` diff --git a/subfixer.py b/subfixer.py index e302928..11296a3 100644 --- a/subfixer.py +++ b/subfixer.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -__author__ = 'itmard' +__author__ = "itmard" +import codecs import sys import re import datetime @@ -12,85 +13,88 @@ class SubtitleFixer: def __init__(self): - self.time = '\d\d:\d\d:\d\d,\d\d\d' - self.number = u'۰۱۲۳۴۵۶۷۸۹' + self.time = r"\d\d:\d\d:\d\d,\d\d\d" + self.number = u"۰۱۲۳۴۵۶۷۸۹" - self.string = '' + self.string = "" def fix_encoding(self): - assert isinstance(self.string, str), repr(self.string) + assert isinstance(self.string, bytes), repr(self.string) try: - self.string.decode('utf8', 'strict') - self.string = self.string.decode('utf8') - return 'utf8' + self.string.decode("utf8", "strict") + self.string = self.string.decode("utf8") + return "utf8" except UnicodeError: pass try: - self.string.decode('utf16', 'strict') - self.string = self.string.decode('utf16') - return 'utf16' + self.string.decode("utf16", "strict") + self.string = self.string.decode("utf16") + return "utf16" except UnicodeError: pass - self.string = self.string.decode('windows-1256') - return 'windows-1256' + self.string = self.string.decode("windows-1256") + return "windows-1256" def fix_italic(self): - self.string = self.string.replace('', '') - self.string = self.string.replace('', '') + self.string = self.string.replace("", "") + self.string = self.string.replace("", "") def fix_arabic(self): - self.string = self.string.replace(u'ي', u'ی') - self.string = self.string.replace(u'ك', u'ک') + self.string = self.string.replace(u"ي", u"ی") + self.string = self.string.replace(u"ك", u"ک") def fix_question_mark(self): # quistion mark in persina is ؟ not ? - self.string = self.string.replace('?', u'؟') + self.string = self.string.replace("?", u"؟") def fix_other(self): - self.string = self.string.replace(u'\u202B', u'') + self.string = self.string.replace(u"\u202B", u"") - lines = self.string.split('\n') - string = '' + lines = self.string.split("\n") + string = "" for line in lines: - if re.match('^%s\s-->\s%s$' % (self.time, self.time), line): + if re.match(r"^%s\s-->\s%s$" % (self.time, self.time), line): string += line - elif re.match('^%s\s-->\s%s$' % (self.time, self.time), line[:-1]): + elif re.match(r"^%s\s-->\s%s$" % (self.time, self.time), line[:-1]): string += line - elif line.strip() == '': + elif line.strip() == "": string += line - elif re.match('^\d+$', line): + elif re.match(r"^\d+$", line): string += line - elif re.match('^\d+$', line[:-1]): + elif re.match(r"^\d+$", line[:-1]): + string += line + elif re.match(r"<.*>.*<\/.*>", line): string += line else: # this should be subtitle - s = re.match('^([\.!?]*)', line) + s = re.match(r"^([\.!?]*)", line) try: - line = re.sub('^%s' % s.group(), '', line) + line = re.sub(r"^%s" % s.group(), "", line) except: pass # use persian numbers for i in range(0, 10): + re.sub("\d", self.number[i], line) line = line.replace(str(i), self.number[i]) - # for ltr problems some peoples put '-' on EOL + # for ltr problems some peoples put "-" on EOL # it should be in start - if len(line) != 0 and line[-1] == '-': - line = '- %s' % line[:-1] + if len(line) != 0 and line[-1] == "-": + line = "- %s" % line[:-1] line += s.group() # put rtl char in start of line # it forces some player to show that line rtl - string += u'\u202B' + unicode(line) + string += u"\u202B" + str(line) # noting to see here - string += '\n' + string += "\n" self.string = string @@ -122,10 +126,10 @@ def change_time(hour, minute, second, time_diff): try: return current_time + difference except OverflowError: - print 'ERROR: Date value out of range.' + click.echo("ERROR: Date value out of range.") sys.exit() except: - print 'ERROR: Error changing time.' + click.echo("ERROR: Error changing time.") return None @@ -138,10 +142,10 @@ def process_time_string(s, time_diff): """ # Ignore milliseconds - s = s.split(',') + s = s.split(",") # Convert to time object - dt = time.strptime(s[0], '%H:%M:%S') + dt = time.strptime(s[0], "%H:%M:%S") # Apply time difference dt = change_time(dt.tm_hour, dt.tm_min, dt.tm_sec, time_diff) @@ -150,80 +154,80 @@ def process_time_string(s, time_diff): minutes = str(dt.minute) seconds = str(dt.second) if len(minutes) == 1: - minutes = '0%s' % (minutes,) + minutes = "0%s" % (minutes,) if len(seconds) == 1: - seconds = '0%s' % (seconds,) + seconds = "0%s" % (seconds,) - new_time_string = '0%s:%s:%s,%s' % (str(dt.hour), minutes, seconds, s[1]) + new_time_string = "0%s:%s:%s,%s" % (str(dt.hour), minutes, seconds, s[1]) return new_time_string def is_time_string(s): - """ Determines if a string 's' is an SRT file time string + """ Determines if a string "s" is an SRT file time string Format: HH:MM:SS,MMS --> HH:MM:SS,MMS """ - if re.match(r'^\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}$', s): + if re.match(r"^\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}$", s): return True return False @click.command() -@click.argument('input', type=click.Path(exists=True)) -@click.argument('output', type=click.Path(), required=False) -@click.option('--fix_persian', is_flag=True, help='Decode Unicode and fix issues with Persian') -@click.option('--shift', type=int, help='The change in seconds to shift the subtitles, e.g. --shift 2 or --shift -5') -def cli(input, output, fix_persian, shift): - ''' +@click.argument("input", type=click.Path(exists=True)) +@click.argument("output", type=click.Path(), required=False) +@click.option("--shift", type=int, help="The change in seconds to shift the subtitles, e.g. --shift 2 or --shift -5") +def cli(input, output, shift): + """ SubFixer does a bit of string manipulation and datetime math to shift your subtitles to match your film and decode string to unicode and fix problems with Persian. - ''' - if input[-4:] not in ('.srt', '.SRT'): - click.echo('%s is not a srt file.' % click.format_filename(input)) + """ + if input[-4:] not in (".srt", ".SRT"): + click.echo("%s is not a srt file." % click.format_filename(input)) exit() - if not fix_persian and not shift: - raise click.BadParameter('''Enter an option --fix_persian or --shift \ - \nUse subfixer --help for more info''') - if fix_persian: - with open(input, 'r') as f: - lines = f.read() + with open(input, "rb") as f: + lines = f.read() - sub_title_fixer = SubtitleFixer() + sub_title_fixer = SubtitleFixer() - lines = sub_title_fixer.decode_string(lines) + lines = sub_title_fixer.decode_string(lines) - write_file_name = input[:-4] + '_fixed.srt' + write_file_name = input[:-4] + "_fixed.srt" - if output: - write_file_name = output - with open(write_file_name, 'w') as f: - f.write(lines.encode('utf-8')) + if output: + write_file_name = output + with open(write_file_name, "wb") as f: + f.write(lines.encode("utf-8")) + + click.echo("%s Persian fixed" % input) + click.echo("New subtitle is on : %s" % write_file_name) - click.echo('%s Persian fixed' % input) - click.echo('New subtitle is on : %s' % write_file_name) if shift: new_lines = [] - with open(input, 'r') as f: + with open(input, "r") as f: for line in f.readlines(): - line = line[:-2] # removes '\r\n' from line + line = line[:-2] # removes "\r\n" from line if is_time_string(line): - times = line.split(' --> ') # split up the two times + times = line.split(" --> ") # split up the two times new_times = [] for t in times: new_times.append(process_time_string(t, shift)) - line = new_times[0] + ' --> ' + new_times[1] - new_lines.append(line + '\r\n') # adds back in '\r\n' + line = new_times[0] + " --> " + new_times[1] + new_lines.append(line + "\r\n") # adds back in "\r\n" - write_file_name = input[:-4] + '_fixed.srt' + write_file_name = input[:-4] + "_fixed.srt" if output: write_file_name = output - with open(write_file_name, 'w') as f: + with open(write_file_name, "w") as f: for line in new_lines: f.write(line) - click.echo('%s Time shift done for ' % input) - click.echo('New subtitle is on : %s' % write_file_name) + click.echo("%s Time shift done for " % input) + click.echo("New subtitle is on : %s" % write_file_name) + + +if __name__ == "__main__": + cli()