예제 #1
0
def open_ass(file):

    try:
        with open(file, "r", encoding="gbk") as f:
            doc = ass.parse(f)
        return doc
    except:
        pass
    try:
        with open(file, "r", encoding="big5") as f:
            doc = ass.parse(f)
        return doc
    except:
        pass
    try:
        with open(file, "r", encoding="utf-8") as f:
            doc = ass.parse(f)
        return doc
    except:
        pass

    try:
        with open(file, 'rb') as f:
            input_bytes = f.read()
            result = chardet.detect(input_bytes)
            conf = result['confidence']
            res_encoding = result['encoding']
        if conf > 0.95:
            with open(file, "r", encoding=res_encoding) as f:
                doc = ass.parse(f)
            return doc
    except:
        pass

    return None
예제 #2
0
    def test_parse_encoding(self):
        with self.test_ass.open("r", encoding='utf_8') as f:
            with self.assertRaises(ValueError):
                ass.parse(f)

        with self.test_ass.open("r", encoding='ascii') as f:
            with self.assertRaises(ValueError):
                ass.parse(f)
예제 #3
0
    def test_dump_encoding(self):
        for encoding in ('utf_8_sig', 'utf-8-sig'):
            with self.test_ass.open("r", encoding=encoding) as f:
                doc = ass.parse(f)

            with self.test_ass.open("r", encoding=encoding.upper()) as f:
                doc = ass.parse(f)

        import tempfile
        with tempfile.TemporaryFile(mode='w', encoding='utf_8') as f:
            with pytest.warns(UserWarning):
                doc.dump_file(f)
예제 #4
0
def load_subs(subsfile):
    '''
    Loads up and parses subtitles from subsfile and returns subsdigest object.
    '''
    with open(subsfile, encoding='utf_8_sig') as f:
        subsdata = subdigest.Subtitles(ass.parse(f), subsfile)
    return subsdata
    def loadSubsAss(self, file):
        with open(file, "r") as f:
            self.subs = ass.parse(f).events

        self.clear()
        g = 0
        # for i in self.subs:
        #     if i.style not in "ED,OP,staff": #*Default": #
        #         self.insertItem(g, i.text.decode('utf_8'))
        #         g = g + 1
        for i in self.subs:
            self.insertItem(g, i.text.decode('utf_8'))
            g = g + 1

        for i in xrange(self.count()):
            self.item(i).setFont(QFont('Meiryo', 16))  # MS Mincho

        i = self.subs[0]
        self.currentSubStart = i.start.total_seconds(
        ) * 1000  # + i.start.microseconds
        self.currentSubEnd = i.end.total_seconds(
        ) * 1000  # + i.end.microseconds
        self.currentRow = 0
        i = self.subs[1]
        self.nextSubStart = i.start.total_seconds(
        ) * 1000  # + i.start.microseconds
        self.nextSubEnd = i.end.total_seconds() * 1000  # + i.end.microseconds
예제 #6
0
	def read_dialogues(self):
		subs = ass.parse(self.contents.splitlines())
		buffer = ''
		for quote in subs.events:
			if isinstance(quote, ass.document.Dialogue):
				buffer += quote.text + '\n'
		return unicode(buffer)
예제 #7
0
def edit_cn_ass_subtitle_style(subtitle_file):
    """
    为ass格式的中文字幕设置style
    :param subtitle_file:
    :return:
    """

    with open(subtitle_file, "r") as f:
        subtitle = ass.parse(f)

        print(subtitle.styles)

        # subtitle.styles[0].fontname = '方正黑体_GBK'
        subtitle.styles[0].fontname = '黑体'
        subtitle.styles[0].fontsize = 21
        subtitle.styles[0].primary_color = '&H00FFFFFF'
        subtitle.styles[0].secondary_color = '&HF0000000'
        subtitle.styles[0].outline_color = '&H006C3300'
        subtitle.styles[0].back_color = '&H00000000'
        subtitle.styles[0].bold = -1
        subtitle.styles[0].border_style = 1
        subtitle.styles[0].outline = 2
        subtitle.styles[0].shadow = 1
        subtitle.styles[0].alignment = 2

        with open(subtitle_file, "w") as f:
            subtitle.dump_file(f)

        if os.path.exists(subtitle_file):
            return subtitle_file
예제 #8
0
def main():
    file_path = sys.argv[1]
    with open(file_path, 'r') as fp:
        doc = ass.parse(fp)

    for i, event in enumerate(doc.events[:]):
        if event.TYPE == 'Dialogue' and event.effect == "fx":
            doc.events[i] = None  # set to None to remove later
            continue

        if (event.TYPE == 'Comment' and event.effect == "karaoke"
                or event.TYPE == 'Dialogue' and not event.effect):
            if "Kanji" in event.style:
                comment_event = ass.document.Comment(**event.fields)
                comment_event.effect = "karaoke"
                new_event = ass.document.Dialogue(**event.fields)
                new_event.effect = "fx"

                # Cannot use str.join because tags might be inbetween text
                parts = re.split(r"(\{[^\}]*\})", new_event.text)
                parts = (f"{c}\\N" if not part.startswith("{") else c
                         for part in parts for c in part)
                new_event.text = "".join(parts)[:-2]

                doc.events[i] = comment_event
                doc.events.append(new_event)

    # remove events flagged for deletion
    doc.events = filter(None, doc.events)

    with open(file_path + "_", 'w') as fp:
        doc.dump_file(fp)
예제 #9
0
def edit_cn_ass_subtitle_style(subtitle_file):
    """
    为ass格式的中文字幕设置style
    :param subtitle_file:
    :return:
    """

    with open(subtitle_file, "r") as f:
        subtitle = ass.parse(f)

        print(subtitle.styles)

        # subtitle.styles[0].fontname = '方正黑体_GBK'
        subtitle.styles[0].fontname = '黑体'
        subtitle.styles[0].fontsize = 21
        subtitle.styles[0].primary_color = '&H00FFFFFF'
        subtitle.styles[0].secondary_color = '&HF0000000'
        subtitle.styles[0].outline_color = '&H006C3300'
        subtitle.styles[0].back_color = '&H00000000'
        subtitle.styles[0].bold = -1
        subtitle.styles[0].border_style = 1
        subtitle.styles[0].outline = 2
        subtitle.styles[0].shadow = 1
        subtitle.styles[0].alignment = 2

        with open(subtitle_file, "w") as f:
            subtitle.dump_file(f)

        if os.path.exists(subtitle_file):
            return subtitle_file
예제 #10
0
def get_timestamps(dialogue):
    '''
    Reads 'chptr' comments from dialogue subs to find timestamps of OP, ED and Eyecatch.
    Chapters must be named in the following format:
        Opening
        Part B
        Ending
        ...
    Returns a dict of timestamps and frame numbers.
    '''
    op = ec = ed = opsync = ecsync = edsync = None

    with open(dialogue, encoding='utf_8_sig') as f:
        dialogue_data = ass.parse(f)

    for event in dialogue_data.events:
        if not isinstance(event, ass.line.Comment) and not event.name == 'chptr':
            continue
        if 'opening' in event.text.lower():
            opsync = event.start
            op = math.ceil(opsync.total_seconds() * 23.976)
        if 'ending'  in event.text.lower():
            edsync = event.start
            ed = math.ceil(edsync.total_seconds() * 23.976)
        if 'part b'  in event.text.lower(): # Part B / Eyecatch 
            ecsync = event.start
            ec = math.ceil(ecsync.total_seconds() * 23.976)

    return {'op': op, 'ec': ec, 'ed': ed, 'opsync': opsync, 'ecsync': ecsync, 'edsync': edsync}
예제 #11
0
    def test_dump_encoding(self):
        with self.test_ass.open("r", encoding='utf_8_sig') as f:
            doc = ass.parse(f)

        import tempfile
        with tempfile.TemporaryFile(mode='w', encoding='utf_8') as f:
            with self.assertWarns(UserWarning):
                doc.dump_file(f)
예제 #12
0
    def test_parse_dump(self):
        with self.test_ass.open("r", encoding='utf_8_sig') as f:
            contents = f.read()

        doc = ass.parse(StringIO(contents))
        out = StringIO()
        doc.dump_file(out)

        assert out.getvalue().strip() == contents.strip()
예제 #13
0
파일: test.py 프로젝트: hualet/python-ass
    def test_parse_dump(self):
        with open("test.ass", "r") as f:
            contents = f.read()

        doc = ass.parse(StringIO(contents))
        out = StringIO()
        doc.dump_file(out)

        self.assertEqual(out.getvalue().strip(), contents.strip())
예제 #14
0
    def test_parse_dump(self):
        with open("test.ass", "r") as f:
            contents = f.read()

        doc = ass.parse(StringIO(contents))
        out = StringIO()
        doc.dump_file(out)

        self.assertEqual(out.getvalue().strip(), contents.strip())
예제 #15
0
def fix_ssa_start_end(basename):
    with open(f'{basename}.ssa') as f:
        d = ass.parse(f)
        prev = d.events[0]
        for i in d.events[1:]:
            i.start = prev.end + datetime.timedelta(seconds=2)
            prev = i

    with open(f'{basename}.ssa', 'w') as f:
        d.dump_file(f)
예제 #16
0
def main():
    parser = argparse.ArgumentParser(description="Automatically merge fonts used in a Matroska file.")
    parser.add_argument('mkv', help="""
    Video where the fonts will go. Must be a Matroska file.
    """)
    parser.add_argument('subtitles', nargs="+", help="""
    Subtitles (can be several) containing fonts to be merged. Must be an ASS file.
    """)
    parser.add_argument('--mkvmerge', metavar="path", help="""
    Path to mkvmerge.exe if not in variable environments.
    """)
    parser.add_argument('--fontfolder', metavar="path", help="""
    Add a file with fonts to use.
    """)
    parser.add_argument('--output', '-o', metavar="path", help="""
    Destination path of the Matroska merged file.
    """)

    args = parser.parse_args()  

    if args.mkvmerge is None and not distutils.spawn.find_executable("mkvmerge.exe"):
        return print(Fore.RED + "fontmerge.py: error: mkvmerge in not in your environnements variable, add it or specify the path to mkvmerge.exe with --mkvmerge." + Fore.WHITE)
    if not is_mkv(args.mkv):
        return print(Fore.RED + "fontmerge.py: error: the file on mkv is not a Matroska file."+ Fore.WHITE)   
    if not is_ass(args.subtitles):
        return print(Fore.RED + "fontmerge.py: error: the file on ass is not an ASS file." + Fore.WHITE)
    if not is_writable(args.mkv):
        return print(Fore.RED + "fontmerge.py: error: unable to create the Matroska file." + Fore.WHITE)
    if args.output is not None :
        if not is_dir(os.path.dirname(args.output)):
            return print(Fore.RED + "fontmerge.py: error: output path is not a valid folder." + Fore.WHITE)
    if args.fontfolder is not None :
        if not is_dir(args.fontfolder):
            return print(Fore.RED + "fontmerge.py: error: font path is not a directory." + Fore.WHITE)
        else:
            if not contains_fonts(args.fontfolder):
                print(Fore.RED + "fontmerge.py: error: font path does not contain any fonts." + Fore.WHITE)
                args.fontfolder = None
        


    fonts_path = []
    installedFonts = get_installed_fonts(args.fontfolder)

    for assf in args.subtitles:
        with open(assf, 'r', encoding='utf_8_sig') as f:
            subtitles = [(os.path.basename(assf), ass.parse(f))]

        fonts_path.extend(get_used_font_path(subtitles, installedFonts))
    
    if len(fonts_path) != len(dict.fromkeys(fonts_path)):
        print("Some fonts are duplicate. Removing.")
        fonts_path = list(dict.fromkeys(fonts_path))

    merge(args.mkv, fonts_path, args.mkvmerge, args.output)
예제 #17
0
def main():
    parser = argparse.ArgumentParser()

    for group in _filter_groups:
        arggroup = parser.add_argument_group(group.__name__)
        for name, member in inspect.getmembers(group):
            if getattr(member, '_filter', False):
                generate_argument(arggroup, member)

    parser.add_argument("-i",
                        "--input",
                        help="Specify input file (default: stdin)")
    parser.add_argument("-o",
                        "--output",
                        help="Specify output file (default: stdout)")
    parser.add_argument("--in-place",
                        action="store_true",
                        help="Perform operations in place")
    args = parser.parse_args()

    if args.input is None or args.input == '-':
        filename = None
        sub_obj = ass.parse(codecs.getreader('utf-8-sig')(sys.stdin.buffer))
    else:
        filename = args.input
        with open(args.input, 'r', encoding='utf-8-sig') as f:
            sub_obj = ass.parse(f)

    sub_obj = Subtitles(sub_obj, filename)

    for func, filter_args in getattr(args, 'chain', []):
        filt = getattr(sub_obj, func)
        sub_obj = filt(*filter_args)

    if args.in_place and args.input is not None:
        args.output = args.input

    if args.output is None or args.output == '-':
        sys.stdout.buffer.write(str(sub_obj).encode('utf-8-sig'))
    else:
        with open(args.output, 'w', encoding="utf-8-sig") as f:
            f.write(str(sub_obj))
예제 #18
0
def tryOpen(f):
	"""Open a .ass file with a bunch of encodings until one works."""
	if not os.path.isfile(f):
		raise Exception('Invalid file: %s' % (f,))
	lastException = None
	for encoding in ('utf-8', 'utf-16', 'utf-16-le'):
		try:
			return ass.parse(open(f, 'r', encoding=encoding).readlines())
		except Exception as e:
			lastException = e
	raise Exception('Cannot find suitable encoding for file %s. Last error: %s' % (f, lastException))
예제 #19
0
	def get_dialogues(self):

		if self.subs_format == 'ass':
			f = open(self.subs, 'r')
			subs = ass.parse(f)
			return [Dialogue(event.text, self.to_ms(event.start), self.to_ms(event.end)) for event in subs.events]
		
			
		elif self.subs_format == 'srt':
			subs = pysrt.open(self.subs)
			return [Dialogue(sub.text, self.to_ms_srt(sub.start), self.to_ms_srt(sub.end)) for sub in subs]
예제 #20
0
def get_dialogues(file_name):
    with open(file_name, "r") as rawFile:
        doc = ass.parse(rawFile)
        dialogues = []
        for event in doc.events:
            dialogues.append({
                "text": regex_process(event.text),
                "start": timedelta_to_ass(event.start),
                "end": timedelta_to_ass(event.end),
                "file": os.path.abspath(file_name)[:-4]
            })
        return dialogues
예제 #21
0
def main(args):

    with open(args.filename, 'r') as f:
        doc = ass.parse(f)

    known = set(style.name for style in doc.styles)
    used = set(event.style for event in doc.events if event.text.strip() != '')
    unknown = used - known
    if unknown:
        raise LookupError('Some styles are not defined: {}'.format(unknown))

    # remove unused styles
    doc.styles = [style for style in doc.styles if style.name in used]

    # rename styles to random names
    if args.rename:
        prefix = hex(random.getrandbits(128))[-8:]

        style_names = {}
        _new_names = set()
        for style in doc.styles:
            while True:
                new_name = hex(random.getrandbits(128))[-8:]
                if new_name not in _new_names:
                    _new_names.add(new_name)
                    break
            style_names[style.name] = '{}-{}'.format(prefix, new_name)

        for style in doc.styles:
            style.name = style_names[style.name]

    # clean up events and remove comments or empty texts.
    events = doc.events
    events = (clean_text(event, args.quotes) for event in events)
    events = (event for event in events if event.text != ''
              and event.TYPE.lower() == 'dialogue')
    doc.events = list(events)

    # rename the styles used in events.
    if args.rename:
        for event in doc.events:
            event.style = style_names[event.style]

    # remove all the third party tools headers (Aegisub etc.)
    fields = doc.fields.items()
    fields = ((k, v) for k, v in fields if k in desired_fields)
    doc.fields = dict(fields)
    if args.title is not None:
        doc.fields['Title'] = args.title

    # dump script
    with open(args.output, 'w') as f:
        doc.dump_file(f)
예제 #22
0
def main(args):

    with open(args.filename, 'r') as f:
        doc = ass.parse(f)

    known = set(style.name for style in doc.styles)
    used = set(event.style for event in doc.events if event.text.strip() != '')
    unknown = used - known
    if unknown:
        raise LookupError('Some styles are not defined: {}'.format(unknown))

    # remove unused styles
    doc.styles = [style for style in doc.styles if style.name in used]

    # rename styles to random names
    if args.rename:
        prefix = hex(random.getrandbits(128))[-8:]

        style_names = {}
        _new_names = set()
        for style in doc.styles:
            while True:
                new_name = hex(random.getrandbits(128))[-8:]
                if new_name not in _new_names:
                    _new_names.add(new_name)
                    break
            style_names[style.name] = '{}-{}'.format(prefix, new_name)

        for style in doc.styles:
            style.name = style_names[style.name]

    # clean up events and remove comments or empty texts.
    events = doc.events
    events = (clean_text(event, args.quotes) for event in events)
    events = (event for event in events
              if event.text != '' and event.TYPE.lower() == 'dialogue')
    doc.events = list(events)

    # rename the styles used in events.
    if args.rename:
        for event in doc.events:
            event.style = style_names[event.style]

    # remove all the third party tools headers (Aegisub etc.)
    fields = doc.fields.items()
    fields = ((k, v) for k, v in fields if k in desired_fields)
    doc.fields = dict(fields)
    if args.title is not None:
        doc.fields['Title'] = args.title

    # dump script
    with open(args.output, 'w') as f:
        doc.dump_file(f)
예제 #23
0
def gomen(subfile, times):
    if times < 0:
        print "Then why are you running this script?"
        sys.exit()
    print "Opening subtitle file..."
    with open(subfile, "r") as subf:
        subs = ass.parse(subf)
    try:
        subs.fields["Title"] = "Gomen"
    except:
        pass

    fullstr = ""
    indexes_to_replace = []
    for dialogue_line in subs.events:
        if type(dialogue_line) is ass.document.Dialogue and dialogue_line.text.find("(") == -1:
            indexes_to_replace.append(subs.events.index(dialogue_line))
            if dialogue_line.text.find("\N") != -1:
                for separ in dialogue_line.text.split("\N"):
                    fullstr += separ + "*"
                fullstr += "^"
            else:
                fullstr += dialogue_line.text + "^"
    translations_to_perform = [lang_list[random.randint(0, len(lang_list) - 1)] for x in range(times)]
    en_to_mystery = translate(fullstr, "en", translations_to_perform[0])
    if times > 1:
        for x in range(times - 1):
            en_to_mystery = translate(en_to_mystery, translations_to_perform[x], translations_to_perform[x + 1])
    if "^" in en_to_mystery:
        translated_list = translate(en_to_mystery, translations_to_perform[times - 1], "en").split("^")
    else:
        print "Our string got messed up in translation."
        sys.exit()
    translated_parsed_list = [replace(item, "*", "\N") for item in translated_list]
    x = 0
    try:
        for index in indexes_to_replace:
            subs.events[index].text = translated_parsed_list[x]
            x += 1
    except:
        print "Indexes are messed up but whatever. That just makes it better, right?"
    if (
        subs.events[0].text.count("\\x") > 2
        or subs.events[1].text.count("\\x") > 2
        or subs.events[2].text.count("\\x") > 2
        or subs.events[3].text.count("\\x") > 2
    ):
        print "Translation failed. Our string got screwed up. Trying again..."
    else:
        print "Finished. Writing to file."
        with open("subs_translated.ass", "w") as subs_out:
            subs.dump_file(subs_out)
예제 #24
0
    def parse(file_path: str) -> Episode:
        with open(file_path, encoding='utf-8-sig') as file:
            serialized_ass = ass.parse(file)

        title = serialized_ass.fields.get('Title')
        production_code = int(serialized_ass.fields.get('Original Script'))

        episode = Episode(production_code, title=title)
        for event in serialized_ass.events:
            line = Line(production_code, event.start, event.end, event.name,
                        event.text)
            episode.add_line(line)
        return episode
예제 #25
0
def parse(filename):
    segments = []
    if filename.endswith(".ass"):
        with open(filename, "r") as f:
            doc = ass.parse(f)
            for event in doc.events:
                if ignore_ass_event(event):
                    continue
                seg = Segment(event.start, event.end, event.tags_stripped())
                segments.append(seg)
    else:
        raise Exception("Invalid file format")
    return segments
예제 #26
0
def tryOpen(f):
    """Open a .ass file with a bunch of encodings until one works."""
    if not os.path.isfile(f):
        raise Exception('Invalid file: %s' % (f, ))
    lastException = None
    for encoding in ('utf-8', 'utf-16', 'utf-16-le'):
        try:
            return ass.parse(open(f, 'r', encoding=encoding).readlines())
        except Exception as e:
            lastException = e
    raise Exception(
        'Cannot find suitable encoding for file %s. Last error: %s' %
        (f, lastException))
예제 #27
0
def extractTextFromSubtitles(fileName):
    tracks = getSubtitleTracks(fileName)
    output = ""
    for track in tracks:
        srtName = exportSRT(fileName, track)
        lines = []
        with open(srtName,"r") as f:
            doc = ass.parse(f)
            for event in doc.events:
                lines.append(cleanLine(event.text))
        combined = "\n".join(lines)
        if "in" in combined or "to" in combined or "for" in combined:
            output += combined
    return output
예제 #28
0
def index_subtitle(index_writer, object_id, file, format):
    if format not in SUPPORTED_SUBTITLE_FORMATS:
        raise ESubtitleFormatNotSupported(format)

    try:
        if format == SRT:
            subtitles = srt.parse(file)
            _index_srt(index_writer, object_id, subtitles)
        else:
            doc = ass.parse(file)
            _index_ass(index_writer, object_id, doc.events)
        index_writer.commit()
    except Exception as e:
        index_writer.cancel()
        raise e
예제 #29
0
파일: merge.py 프로젝트: knitori/asstools
def main():
    used_command = sys.argv.pop(0)

    doc_title = None
    rename_styles = False
    global_sync = 0
    files = []

    while sys.argv:
        arg = sys.argv.pop(0)
        if arg in ('-h', '--help'):
            usage(used_command)
            sys.exit(0)
        elif arg == '-r':
            rename_styles = True
        elif arg == '-t':
            doc_title = sys.argv.pop(0)
        elif arg == '-g':
            global_sync = int(sys.argv.pop(0)) * 1000
        elif arg == '-s':
            file_sync = int(sys.argv.pop(0)) * 1000
            filename = sys.argv.pop(0)
            files.append((file_sync, filename))
        else:
            files.append((None, arg))

    docs = []
    for sync, filename in files:
        if sync is None:
            sync = global_sync

        print('', file=sys.stderr)
        print('File: {}'.format(filename), file=sys.stderr)
        print('  Sync: {}'.format(sync), file=sys.stderr)
        print('', file=sys.stderr)

        with open(filename, 'r') as f:
            doc = ass.parse(f)

        if sync != 0:
            doc = shift(doc, sync)
        docs.append(doc)

    merged_docs = merge(*docs, rename_styles=rename_styles)
    if doc_title is not None:
        merged_docs.fields['Title'] = doc_title

    merged_docs.dump_file(sys.stdout)
예제 #30
0
def main(path):
    path = path or "."
    for f in list_dir(path):
        if f and f.endswith('.ass'):
            if f == 'ok':
                continue

            print ''
            print f
            with open(f, 'r') as f_:
                doc = ass.parse(f_)
                print '    fn:', doc.styles[0].fontname
                print '    fs:', doc.styles[0].fontsize
                print '    bold:', doc.styles[0].bold
                print '    shadow:', doc.styles[0].shadow
                print '    border_style:', doc.styles[0].border_style
                print '    primary_color: ', doc.styles[0].primary_color

                for i in range(len(doc.styles)):
                    doc.styles[i].fontname = 'Microsoft YaHei Light'
                    doc.styles[i].fontsize = 13
                    doc.styles[i].bold = -1
                    doc.styles[i].shadow = 0
                    doc.styles[i].outline = 0
                    doc.styles[i].border_style = 0
                    doc.styles[i].primary_color = Color(r=0xff,
                                                        g=0xff,
                                                        b=0xff,
                                                        a=0x30)

                ok_path = os.path.join(path, 'ok')
                if not os.path.exists(ok_path):
                    os.mkdir(ok_path)

                new_path = f.replace(path, os.path.join(path, 'ok'))
                print new_path
                with open(new_path, 'w') as nf:
                    doc.dump_file(nf)

                with open(new_path, 'r') as nf:
                    txt = nf.read().replace(en_font_name,
                                            'Microsoft YaHei Light').replace(
                                                en_font_size, 'fs11')

                with open(new_path, 'w') as nf:
                    nf.write(txt)
예제 #31
0
def edit_two_lang_style(subtitle_file):
    """
    为ass格式的双语字幕设置style
    :param subtitle_file:
    :return:
    """

    with open(subtitle_file, "r") as f:
        subtitle = ass.parse(f)

        print(subtitle.styles)

        # {\fn宋体\fs20\shad2\4a&H50&\3c&HFF8000&\4c&HFF8000&}
        # Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour,
        # OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut,
        # ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow,
        # Alignment, MarginL, MarginR, MarginV, Encoding
        # Style: Default,方正黑体_GBK,21,&H00FFFFFF,&HF0000000,&H006C3300,
        # &H00000000,-1,0,0,0,100,100,0,0,1,2,1,2,5,5,5,134
        # subtitle.styles[0].fontname = '方正黑体_GBK'
        subtitle.styles[0].fontname = '黑体'
        subtitle.styles[0].fontsize = 21
        subtitle.styles[0].primary_color = '&H00FFFFFF'
        subtitle.styles[0].secondary_color = '&HF0000000'
        subtitle.styles[0].outline_color = '&H006C3300'
        subtitle.styles[0].back_color = '&H00000000'
        subtitle.styles[0].bold = -1
        subtitle.styles[0].border_style = 1
        subtitle.styles[0].outline = 2
        subtitle.styles[0].shadow = 1
        subtitle.styles[0].alignment = 2

        for events in subtitle.events:
            utf8string = events.text.decode("utf-8")
            events.text = utf8string.replace(
                r'\N',
                r'\N{\fn黑体\fs14\b0\c&HFFFFFF&\3c&H2F2F2F&\4c&H000000&}'
            )

        with open(subtitle_file, "w") as f:
            subtitle.dump_file(f)

        if os.path.exists(subtitle_file):
            return subtitle_file
예제 #32
0
def edit_two_lang_style(subtitle_file):
    """
    为ass格式的双语字幕设置style
    :param subtitle_file:
    :return:
    """

    with open(subtitle_file, "r") as f:
        subtitle = ass.parse(f)

        print(subtitle.styles)

        # {\fn宋体\fs20\shad2\4a&H50&\3c&HFF8000&\4c&HFF8000&}
        # Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour,
        # OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut,
        # ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow,
        # Alignment, MarginL, MarginR, MarginV, Encoding
        # Style: Default,方正黑体_GBK,21,&H00FFFFFF,&HF0000000,&H006C3300,
        # &H00000000,-1,0,0,0,100,100,0,0,1,2,1,2,5,5,5,134
        # subtitle.styles[0].fontname = '方正黑体_GBK'
        subtitle.styles[0].fontname = '黑体'
        subtitle.styles[0].fontsize = 21
        subtitle.styles[0].primary_color = '&H00FFFFFF'
        subtitle.styles[0].secondary_color = '&HF0000000'
        subtitle.styles[0].outline_color = '&H006C3300'
        subtitle.styles[0].back_color = '&H00000000'
        subtitle.styles[0].bold = -1
        subtitle.styles[0].border_style = 1
        subtitle.styles[0].outline = 2
        subtitle.styles[0].shadow = 1
        subtitle.styles[0].alignment = 2

        for events in subtitle.events:
            utf8string = events.text.decode("utf-8")
            events.text = utf8string.replace(
                r'\N', r'\N{\fn黑体\fs14\b0\c&HFFFFFF&\3c&H2F2F2F&\4c&H000000&}')

        with open(subtitle_file, "w") as f:
            subtitle.dump_file(f)

        if os.path.exists(subtitle_file):
            return subtitle_file
예제 #33
0
def AssWeTran(SourceFileName):
    SourceFile = open(SourceFileName, 'rb')
    FileEnco = chardet.detect(SourceFile.read()).get('encoding')
    SourceFile.close()
    # 按文件编码重新打开文件
    SourceFile = codecs.open(SourceFileName, 'rb', FileEnco)
    TargetFile = codecs.open(SourceFileName + '.srt', 'w', 'utf-8')

    AssFile = ass.parse(SourceFile)
    TimeDic = dict()

    for event in AssFile.events:
        if not re.match('//', event.text) and not event.text == '':
            StartTime = str(event.start)
            EndTime = str(event.end)
            StartTime = '0' + StartTime
            StartTime = StartTime[:-3]
            StartTime = re.sub(r'\.', ',', StartTime)
            EndTime = '0' + EndTime
            EndTime = EndTime[:-3]
            EndTime = re.sub(r'\.', ',', EndTime)
            Time = StartTime + ' --> ' + EndTime
            SubTitle = re.sub(r'{[^}]*}', '', event.text)
            SubTitle = re.sub(r'\\N', '\n', SubTitle)
            if not Time in TimeDic.keys():
                TimeDic[Time] = SubTitle
            else:
                TimeDic[Time] = TimeDic[Time] + '\n' + SubTitle

    i = 1

    for key, value in TimeDic.items():
        TargetFile.write(str(i))
        TargetFile.write('\n')
        TargetFile.write(key)
        TargetFile.write('\n')
        TargetFile.write(value)
        TargetFile.write('\n')
        TargetFile.write('\n')
        i = i + 1
    TargetFile.close()
    return TargetFile.name
예제 #34
0
 def merge_file(
     self,
     other_file: argparse.FileType(encoding='utf-8-sig')) -> Subtitles:
     """Append the styles and event lines from another file."""
     f = ass.parse(other_file)
     self.sub_file.events.extend(f.events)
     existing_styles = {
         style.name: style.dump()
         for style in self.sub_file.styles
     }
     for style in f.styles:
         if style.name in existing_styles and style.dump(
         ) != existing_styles[style.name]:
             print(
                 f"Warning: Ignoring style {style.name} from "
                 f"{other_file.name}.",
                 file=sys.stderr)
             continue
         self.sub_file.styles.append(style)
     return self
예제 #35
0
    def _import_file(self, imp_definition, styles, events, fields):
        # strip extradata info
        fname = re.sub(r"^\{=\d+(,\d+)*\}", "", imp_definition.text)
        shifted = imp_definition.effect == 'import-shifted'

        self._ms_count += 1
        self._ms_files[self._ms_count] = fname

        path = pathlib.Path(self.filename).parent / fname
        with path.open(encoding='utf-8-sig') as f:
            imp = ass.parse(f)

        if shifted:
            try:
                sync_line = next(line for line in imp.events
                                 if line.effect == 'sync')
            except StopIteration:
                raise ValueError(f"No sync line in {fname}")

            time_diff = imp_definition.start - sync_line.start

            for line in imp.events:
                line.start += time_diff
                line.end += time_diff

        for line in imp.events:
            line.layer += imp_definition.layer
            line.style = f"{self._ms_count}${line.style}"
            events.append(line)

        for style in imp.styles:
            style.name = f"{self._ms_count}${style.name}"
            styles[style.name] = style

        for field, value in imp.fields.items():
            if field in fields and fields[field] != value:
                logging.warning(
                    f"Ignoring conflicting value {value} for {field} from {fname}"
                )
            else:
                fields[field] = value
예제 #36
0
def load_files():
    subtitles = []
    videos = []
    for filename in os.listdir('.'):
        if filename.lower().endswith('.ass'):
            with open(filename, 'r') as f:
                subtitles.append(Ass(filename, ass.parse(f)))
        elif filename.lower().endswith(('.mkv', '.mp4')):
            proc = Popen(
                ['ffprobe', '-i', filename, '-v', 'quiet', '-print_format',
                 'json', '-show_streams'], stdout=PIPE, stderr=DEVNULL)
            out, err = proc.communicate()
            proc.wait()
            data = json.loads(out.decode('ascii'))
            videos.append(Video(filename, data))

    videos.sort()
    subtitles.sort()
    videos = Collection(videos, 'Video files')
    subtitles = Collection(subtitles, 'ASS files')
    return subtitles, videos
예제 #37
0
def ass_parser(filename):
    f = codecs.open(filename, 'r', 'utf8')
    doc = ass.parse(f)
    f.close()
        
    print("length of event is: {}".format(len(doc.events)))
    
    doc.events.sort(key=lambda x:x.start)
    for event in doc.events:
        event.text = re.sub("{.*?}", "", event.text).replace("\\N", "\n")
    
    srtname = filename[:-3] + 'srt'
    f = codecs.open(srtname, 'w', 'utf8')
    
    for index, event in enumerate(doc.events):
        f.write("%d\n"%(index + 1))
        f.write("%s --> %s\n" % (time_string(event.start), time_string(event.end)))
        f.write(event.text)
        f.write("\n\n")
        
    f.close()
예제 #38
0
def readAss(fname):
    if str(fname).endswith('.ass'):

        with open(fname, 'r', encoding='utf-8') as f:
            doc = ass.parse(f)

        dml = []
        for evt in doc.events:
            dm = DanMu()
            dm.createByAss(evt, doc.play_res_x, doc.play_res_y)
            dml.append(dm)

        return doc.styles, dml

    elif str(fname).endswith(".xml"):
        tmpfile = fname + "_tmp.ass"
        print('请自行转换')
        raise


#readAss('dm.ass')
예제 #39
0
def main():
    parser = argparse.ArgumentParser(
        description="Automatically merge fonts used in a Matroska file.")
    parser.add_argument('subtitles',
                        help="""
    Subtitles containing fonts to be merged. Must be an ASS file.    """)
    parser.add_argument('mkv',
                        help="""
    Video where the fonts will go. Must be a Matroska file.
    """)
    parser.add_argument('--mkvmerge',
                        metavar="path",
                        help="""
    Path to mkvmerge.exe if not in variable environments.
    """)

    args = parser.parse_args()

    if not distutils.spawn.find_executable(
            "mkvmerge.exe") and args.mkvmerge is None:
        return print(
            "fontmerge.py: error: mkvmerge in not in your environnements variable, add it or specify the path to mkvmerge.exe with --mkvmerge."
        )
    if not is_mkv(args.mkv):
        return print(
            "fontmerge.py: error: the file on -mkv is not a Matroska file.")
    if not is_ass(args.subtitles):
        return print("fontmerge.py: error: the file is not an Ass file.")
    if not is_writable(args.mkv):
        return print("fontmerge.py: error: unable to create the file.")

    with open(args.subtitles, 'r', encoding='utf_8_sig') as f:
        subtitles = [(os.path.basename(args.subtitles), ass.parse(f))]

    fonts_path = get_used_font_path(subtitles)

    merge(args.subtitles, args.mkv, fonts_path, args.mkvmerge)

    return print("Successfully merging subtitles and mkv")
예제 #40
0
def ssaProcessor(fname: str):
    if not os.path.isfile(fname):
        print(f'Missing file: {fname}')
        return

    with open(fname, encoding='utf_8_sig') as f:
        sub = ssa.parse(f)
    for s in sub.styles:
        transformColour(s.primary_color)
        transformColour(s.secondary_color)
        transformColour(s.outline_color)
        transformColour(s.back_color)

    for e in sub.events:
        transformEvent(e)

    output_fname = os.path.splitext(fname)
    output_fname = output_fname[0] + '.hdr.ass'

    with open(output_fname, 'w', encoding='utf_8_sig') as f:
        sub.dump_file(f)
        print(f'Wrote {output_fname}')
예제 #41
0
파일: sub2xml.py 프로젝트: pyahmed/sub2xml
def sub_load(inp_fname):
    '''
    input = ass subtitle file
    output = subtitle instance and dict with meta_data for easy access (for later)
    '''
    subs_stl = {}
    #f = io.open(inp_fname, "rb")
    #doc = ass.parse(f)
    with open(inp_fname, "r", encoding='utf-8') as f:
        doc = ass.parse(f)
    subs = doc.events
    for i in doc.styles:
        stl_name = i.name
        r = i.primary_color.r
        g = i.primary_color.g
        b = i.primary_color.b
        a = i.primary_color.a
        font_name = i.fontname
        font_size = i.fontsize
        subs_stl.update({str(stl_name): {'r':r, 'g':g, 'b':b, 'a':a,
                                          'font_name':font_name, 
                                          'font_size':font_size}})
    return(subs, subs_stl)
예제 #42
0
파일: 漢字.py 프로젝트: pockethook/jap
def 字数漢字本ass(名):
    with open(名, 'r') as 本:
        字幕 = (文.text for 文 in ass.parse(本).events)
        return 字数漢字(字幕)
예제 #43
0
import argparse
import ass
import datetime
import io
import os
import re
import sys

parser = argparse.ArgumentParser()
parser.add_argument('--file', help='Subtitle file to operate on.', required=True)
parser.add_argument('--operation', help='"add" or "remove".', choices=('add', 'remove'), required=True)
parser.add_argument('--begin', help='Interval begin timestamp as a stringified float (number of seconds).')
parser.add_argument('--end', help='Interval end timestamp as a stringified float (number of seconds).')
args = parser.parse_args()
handle = open(args.file, 'r')
doc = ass.parse(handle.readlines())
handle.close()
begin = datetime.timedelta(seconds=float(args.begin))
end = datetime.timedelta(seconds=float(args.end))
duration = end - begin
assert begin <= end

if args.operation == 'add':
	for e in list(doc.events):
		if e.start > end:                          #  \---int---/
			e.start += duration                #               [---sub---]: Moved forward
			e.end += duration

		elif e.start >= begin and e.start <= end:  #    \-int-/
			e.end += duration                  #  [---sub---]: Extended by interval length
예제 #44
0
 def parse(self, file_name, file_encoding):
     if file_encoding.lower() != "utf-8":
         file_name = get_utf_8_version(file_name, file_encoding)
     with open(file_name) as f:
         self._events = ass.parse(f).events