Last active
April 23, 2023 01:45
-
-
Save ookiineko/214a91df104b8f639e51798288e285c3 to your computer and use it in GitHub Desktop.
lolita subtitle font changer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
lolita subtitle font changer | |
""" | |
from argparse import ArgumentParser, Namespace | |
from typing import List | |
from typing import NoReturn | |
from os.path import exists | |
from sys import exit as die | |
from platform import system | |
if system() == 'Windows': | |
EX_OK = 0 | |
EX_DATAERR = 65 | |
EX_NOINPUT = 66 | |
else: | |
from os import EX_OK | |
from os import EX_DATAERR | |
from os import EX_NOINPUT | |
def _loli_ify(content: str, target: str) -> str: | |
buff = [] | |
flag = False | |
font_idx = -1 | |
cnt = 0 | |
for lineno, line in enumerate(content.split('\n')): | |
stripped_line = line.strip() | |
if stripped_line and not stripped_line.startswith(';'): | |
if stripped_line.startswith('[') and stripped_line.endswith(']'): | |
tag_name = stripped_line[1:-1].strip() | |
if tag_name: | |
flag = tag_name == 'V4+ Styles' | |
font_fmt = -1 | |
elif flag: | |
if stripped_line.count(':') < 1: | |
print('syntax error at line %d' % lineno) | |
die(EX_DATAERR) | |
else: | |
idx = stripped_line.index(':') | |
field_name = stripped_line[:idx].strip() | |
value = stripped_line[idx + 1:].strip() | |
if field_name == 'Format': | |
if font_idx == -1: | |
if value: | |
fmt_list = value.split(',') | |
for fmt_idx, fmt in enumerate(fmt_list): | |
stripped_fmt = fmt.strip() | |
if stripped_fmt == 'Fontname': | |
font_idx = fmt_idx | |
break | |
else: | |
print('no \'Fontname\' in \'Format field\' at line %d', lineno) | |
die(EX_DATAERR) | |
else: | |
print('empty value in \'Format\' field at line %d' % lineno) | |
die(EX_DATAERR) | |
else: | |
print('duplicated \'Format\' field in \'V4+ Styles\' tag at line %d' % lineno) | |
die(EX_DATAERR) | |
elif field_name == 'Style': | |
prop_list = value.split(',') | |
if font_idx == -1: | |
print('don\'t know where is the font property at line %d' % lineno) | |
die(EX_DATAERR) | |
if prop_list[font_idx] != target: | |
prop_list[font_idx] = target | |
new_value = ','.join(prop_list) | |
buff.append(f'{field_name}: {new_value}') | |
cnt += 1 | |
continue | |
buff.append(line) | |
if cnt > 0: | |
print('replaced %d style(s) to loli' % cnt) | |
return '\n'.join(buff) | |
def loli_ify(sub_files: List[str], dry_run: bool, target: str): | |
for sub_file in sub_files: | |
stripped_subfile = sub_file.strip() | |
if stripped_subfile and exists(stripped_subfile): | |
print('handle file \'%s\'' % stripped_subfile) | |
in_fd = open(sub_file, 'r', encoding='utf-8') | |
content = in_fd.read() | |
in_fd.close() | |
new_content = _loli_ify(content, target) | |
if content != new_content: | |
if not dry_run: | |
with open(sub_file, 'w', encoding='utf-8') as out_fd: | |
out_fd.write(new_content) | |
else: | |
print('\'%s\' does not exist' % sub_file) | |
die(EX_NOINPUT) | |
def main(args: Namespace) -> NoReturn: | |
sub_files = args.sub_file | |
dry_run = args.dry_run | |
if dry_run: | |
print('dry run enabled') | |
target = args.target | |
print('start') | |
loli_ify(sub_files, dry_run, target) | |
print('Done!') | |
die(EX_OK) | |
if __name__ == '__main__': | |
parser = ArgumentParser(description='shitty tool for changing all fonts in SSA sub to lolita', epilog='powered by Python') | |
parser.add_argument('-d', '--dry-run', action='store_true', help='dry run') | |
parser.add_argument('-t', '--target', type=str, help='target font (defaults to \'Heiti SC\')', default='Heiti SC') | |
parser.add_argument('sub_file', nargs='+', type=str, help='SSA subtitle file') | |
args = parser.parse_args() | |
main(args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment