Skip to content

Instantly share code, notes, and snippets.

@mkyt
Created February 16, 2017 12:58
Show Gist options
  • Save mkyt/3622c2b95c686d36e636ea18ca9ab67c to your computer and use it in GitHub Desktop.
Save mkyt/3622c2b95c686d36e636ea18ca9ab67c to your computer and use it in GitHub Desktop.
Lyrics offset
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import re
import os.path
timecode_pat = re.compile(r'\[(\d{2}:\d{2}:\d{2})\]')
timecode_parser = re.compile(r'(\d{2}):(\d{2}):(\d{2})')
class Chunk:
def __init__(self, timecode, text):
m = timecode_parser.fullmatch(timecode)
mm, ss, cc = map(int, m.groups())
self.time = (mm * 60 + ss) * 100 + cc
self.text = text
def render(self):
t = self.time if self.time > 0 else 0
mm = t // 100 // 60
ss = t // 100 % 60
cc = t % 100
return '[{:02d}:{:02d}:{:02d}]{}'.format(mm, ss, cc, self.text)
def __repr__(self):
return '<Chunk time={}, text="{}">'.format(self.time, self.text)
class LyricsFile:
def __init__(self, path):
_, ext = os.path.splitext(path)
if ext not in ('.kra', '.lrc'):
raise ValueError
self.content = []
for line in open(path).read().split('\n'):
splitted = timecode_pat.split(line)
if splitted[0] != '':
# Oops... doesn't contain timecode at the beginning of the line
continue
l = []
if ext == '.lrc': # line-sync
l.append(Chunk(splitted[1], ''.join(splitted[2:])))
else: # karaoke-sync
for tc, text in zip(*([iter(splitted[1:])]*2)):
l.append(Chunk(tc, text))
self.content.append(l)
def render(self):
return '\n'.join((''.join(c.render() for c in l)) for l in self.content)
def shift(self, offset):
for l in self.content:
for c in l:
c.time += offset
def main(progname, args):
if len(args) < 2:
print('usage: {} [FILENAME] [OFFSET in centisec]'.format(progname))
return 1
fname = args[0]
offset = int(args[1])
l = LyricsFile(fname)
l.shift(offset)
print(l.render())
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[0], sys.argv[1:]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment