Skip to content

Instantly share code, notes, and snippets.

@ookiineko
Last active April 23, 2023 01:45
Show Gist options
  • Save ookiineko/214a91df104b8f639e51798288e285c3 to your computer and use it in GitHub Desktop.
Save ookiineko/214a91df104b8f639e51798288e285c3 to your computer and use it in GitHub Desktop.
lolita subtitle font changer
#!/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