diff --git a/autokara.py b/autokara.py index 1f9c1c3fbe8027cd63b4f2dcf2dab88c5ad182ef..c77abb49f10ebd14c15837c28463e2b89e63a49f 100644 --- a/autokara.py +++ b/autokara.py @@ -11,9 +11,9 @@ from autosyl.segment import segment parser = argparse.ArgumentParser(description='AutoKara - Automatic karaoke timing tool') parser.add_argument("source_file", type=str, help="The video/audio file to time") -parser.add_argument("ass_file", type=str, help="The ASS file in which to output the karaoke") +parser.add_argument("ass_file", type=str, help="The ASS file with lyrics to time") parser.add_argument("--vocals", action="store_true", help="Treat the input as vocals file, i.e. do not perform vocals extraction") -parser.add_argument("--ref", help="Use an ASS file as reference") +parser.add_argument("-o", "--output", help="Write output to specified file. If absent, overwrite source file") args = parser.parse_args() @@ -40,19 +40,21 @@ if not args.vocals : else: vocals_file = args.source_file -if args.ref: - reference_file = args.ref -else: - reference_file = None + print("Identifying syl starts...") -syls = segment(vocals_file, reference_file=reference_file) + + +reference_syls, line_meta = getSyls(ass_file) +syls = segment(vocals_file, reference_syls=reference_syls) print(syls) +print(line_meta) print("Syls found, writing ASS file...") +header = getHeader(ass_file) writer = AssWriter() -writer.openAss(ass_file) -writer.writeHeader(header=getHeader(reference_file)) -writer.writeSyls(syls) +writer.openAss(args.output if args.output else ass_file) +writer.writeHeader(header=header) +writer.writeSyls(syls, line_meta) writer.closeAss() diff --git a/autosyl/assUtils.py b/autosyl/assUtils.py index 37b517c22fb3fa0e4ab7d11d1c65ae39c379f24d..7d2e6c2dfbe3972858ba7d2df98b45678d009ae3 100644 --- a/autosyl/assUtils.py +++ b/autosyl/assUtils.py @@ -25,20 +25,28 @@ def dateToTime(date): def getSyls(ass_file): SYLS = [] + META = [] with open(ass_file, 'r') as f: CONTENT = f.read() - LINES_KARA = re.compile(r"Comment:.*(\d+:\d{2}:\d{2}.\d{2}),(\d+:\d{2}:\d{2}.\d{2}),.*,karaoke,(.*)\n"); + LINES_KARA = re.compile(r"Comment:.*(\d+:\d{2}:\d{2}.\d{2}),(\d+:\d{2}:\d{2}.\d{2}),([^,]*),([^,]*),(\d+),(\d+),(\d+),karaoke,(.*)\n"); RGX_TAGS = re.compile(r"\{\\k(\d+)\}([^\{\n\r]*)") for line in LINES_KARA.findall(CONTENT): syl_line = [] lastTime = dateToTime(line[0]) - for couple in RGX_TAGS.findall(line[2]): + for couple in RGX_TAGS.findall(line[7]): if(couple[1] != '' and not couple[1].isspace()): syl_line.append([lastTime, couple[1], int(couple[0])]) lastTime += int(couple[0]) syl_line.append([lastTime, '', 0]) SYLS.append(syl_line) - return SYLS + line_meta = {} + line_meta['stylename'] = line[2] + line_meta['actor'] = line[3] + line_meta['margin_l'] = int(line[4]) + line_meta['margin_r'] = int(line[5]) + line_meta['margin_v'] = int(line[6]) + META.append(line_meta) + return SYLS, META def getHeader(ass_file): @@ -106,16 +114,18 @@ Comment: 0,0:00:05.68,0:00:05.68,Default,,0,0,0,, ''' self.file.write(header) - def writeSyls(self, syl_timings): - bottom = False - for syl_line in syl_timings: - start_time = timeToDate(syl_line[0][0]) - end_time = timeToDate(syl_line[-1][0]) - v_margin = (150 if bottom else 50) - line = f'Dialogue: 0,{start_time},{end_time},Default,,0,0,{v_margin:d},,' - for i in range(len(syl_line) - 1): - syl_dur = round((syl_line[i+1][0] - syl_line[i][0]) * 100) - line += f'{{\k{syl_dur:d}}}{syl_line[i][1]:s}' + def writeSyls(self, syl_timings, line_meta): + for line_index in range(len(syl_timings)): + start_time = timeToDate(syl_timings[line_index][0][0]) + end_time = timeToDate(syl_timings[line_index][-1][0]) + margin_v = line_meta[line_index]['margin_v'] + margin_l = line_meta[line_index]['margin_l'] + margin_r = line_meta[line_index]['margin_r'] + style = line_meta[line_index]['stylename'] + actor = line_meta[line_index]['actor'] + line = f'Dialogue: 0,{start_time},{end_time},{style},{actor},{margin_l:d},{margin_r:d},{margin_v:d},,' + for i in range(len(syl_timings[line_index]) - 1): + syl_dur = round((syl_timings[line_index][i+1][0] - syl_timings[line_index][i][0]) * 100) + line += f'{{\k{syl_dur:d}}}{syl_timings[line_index][i][1]:s}' line += '\n' - self.file.write(line) - bottom = not bottom \ No newline at end of file + self.file.write(line) \ No newline at end of file diff --git a/autosyl/segment.py b/autosyl/segment.py index b2373508b3be039d414fe560acc50a2fc37abc02..cc8e3fe1d42106952b49dc65c03da6b13bc4a7fd 100644 --- a/autosyl/segment.py +++ b/autosyl/segment.py @@ -11,16 +11,11 @@ from autosyl.LyricsAlignment.wrapper import align, preprocess_from_file -def segment(songfile, reference_file=None, syls_per_line=10, last_syl_dur=500): +def segment(songfile, reference_syls=None, syls_per_line=10, last_syl_dur=500): delay = -4 backtrack = False - if reference_file: - reference_syls = getSyls(reference_file) - else: - reference_syls = [] - print(reference_syls) audio_file = songfile # pre-computed source-separated vocals; These models do not work with mixture input.