Fix
This commit is contained in:
parent
1d5f8e1f65
commit
853ad895cc
|
@ -0,0 +1,81 @@
|
||||||
|
import re
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
VTT_TIMECODE_PATTERN = r"((?:\d{2}:)?\d{2}:\d{2}\.\d{3}) --> ((?:\d{2}:)?\d{2}:\d{2}\.\d{3})"
|
||||||
|
VTT_LINE_NUMBER_PATTERN = r"^\d+$"
|
||||||
|
|
||||||
|
def parse_vtt(vtt_string):
|
||||||
|
parts = re.split(r'\n\n+', vtt_string.strip())
|
||||||
|
|
||||||
|
if parts[0].startswith('WEBVTT'):
|
||||||
|
parts.pop(0)
|
||||||
|
|
||||||
|
subtitles = []
|
||||||
|
for part in parts:
|
||||||
|
lines = part.split('\n')
|
||||||
|
match = re.match(VTT_TIMECODE_PATTERN, lines[0])
|
||||||
|
if not match:
|
||||||
|
if re.match(VTT_LINE_NUMBER_PATTERN, lines[0]):
|
||||||
|
lines.pop(0)
|
||||||
|
match = re.match(VTT_TIMECODE_PATTERN, lines[0])
|
||||||
|
if not match:
|
||||||
|
continue
|
||||||
|
|
||||||
|
start, end = match.groups()
|
||||||
|
content = '\n'.join(lines[1:])
|
||||||
|
|
||||||
|
subtitles.append({
|
||||||
|
'start': start,
|
||||||
|
'end': end,
|
||||||
|
'content': content
|
||||||
|
})
|
||||||
|
|
||||||
|
return subtitles
|
||||||
|
|
||||||
|
def to_vtt(subtitles):
|
||||||
|
vtt_content = "WEBVTT\n\n"
|
||||||
|
for idx, subtitle in enumerate(subtitles):
|
||||||
|
# print(subtitle, idx)
|
||||||
|
start = subtitle['start']
|
||||||
|
end = subtitle['end']
|
||||||
|
content = subtitle['content']
|
||||||
|
vtt_content += f"{start} --> {end}\n{content}\n\n"
|
||||||
|
return vtt_content.strip()
|
||||||
|
|
||||||
|
|
||||||
|
with open("example.vtt", "r") as f:
|
||||||
|
vtt_content = f.read()
|
||||||
|
|
||||||
|
parsed_vtt = parse_vtt(vtt_content)
|
||||||
|
#print(len(parsed_vtt))
|
||||||
|
|
||||||
|
buffer = []
|
||||||
|
linebuf = []
|
||||||
|
|
||||||
|
for line in parsed_vtt:
|
||||||
|
# print(line["content"].strip())
|
||||||
|
content = line["content"].strip()
|
||||||
|
if "".join([i["content"] for i in linebuf]).count(".") < 4 or len(linebuf) < 5:
|
||||||
|
linebuf.append(line)
|
||||||
|
else:
|
||||||
|
linebuf.append(line)
|
||||||
|
buffer.append(linebuf)
|
||||||
|
linebuf = []
|
||||||
|
|
||||||
|
# print(buffer)
|
||||||
|
|
||||||
|
sub = []
|
||||||
|
for section in buffer:
|
||||||
|
strbuf = ""
|
||||||
|
for scene in section:
|
||||||
|
strbuf += scene["content"]
|
||||||
|
# if scene["content"][-1] == ".":
|
||||||
|
strbuf += "\n"
|
||||||
|
# else:
|
||||||
|
# strbuf += " "
|
||||||
|
scene["content"] = strbuf
|
||||||
|
sub.append(scene)
|
||||||
|
|
||||||
|
# print(buffer[0])
|
||||||
|
|
||||||
|
print(to_vtt(sub))
|
71
vttmaker.py
71
vttmaker.py
|
@ -60,6 +60,8 @@ def mark_start():
|
||||||
print("Please load first..")
|
print("Please load first..")
|
||||||
return
|
return
|
||||||
current_subtitle["content"] = current_subtitle.get("content","") + script_lines[line_index]
|
current_subtitle["content"] = current_subtitle.get("content","") + script_lines[line_index]
|
||||||
|
# current_subtitle["content"] = script_lines[line_index]
|
||||||
|
current_subtitle["index"] = line_index
|
||||||
update_display()
|
update_display()
|
||||||
print(f"\n{timestamp} --> ", end="")
|
print(f"\n{timestamp} --> ", end="")
|
||||||
|
|
||||||
|
@ -94,8 +96,6 @@ def on_done_press(event = None):
|
||||||
return
|
return
|
||||||
if current_subtitle["start"] == None:
|
if current_subtitle["start"] == None:
|
||||||
current_subtitle["content"] = ""
|
current_subtitle["content"] = ""
|
||||||
current_subtitle["start"] = None
|
|
||||||
load_next_line()
|
|
||||||
update_display()
|
update_display()
|
||||||
return
|
return
|
||||||
timestamp = player.get_time() / 1000.0
|
timestamp = player.get_time() / 1000.0
|
||||||
|
@ -113,16 +113,20 @@ def on_back(event = None):
|
||||||
messagebox.showerror("Error", f"No subtitle to remove.")
|
messagebox.showerror("Error", f"No subtitle to remove.")
|
||||||
return
|
return
|
||||||
if current_subtitle["start"]:
|
if current_subtitle["start"]:
|
||||||
if not messagebox.askokcancel("Warning", f"\nDeleting \"{current_subtitle.get("content")}\" \n You need to go back and mark start again."):
|
if not messagebox.askokcancel("Warning", f"\nDeleting current #{current_subtitle.get("index")}.\n You need to go back and mark start again."):
|
||||||
return
|
return
|
||||||
if len(subtitles) > 2:
|
|
||||||
current_subtitle["content"] = subtitles[-2]["content"] + "\n"
|
|
||||||
current_subtitle["content"] = ""
|
current_subtitle["content"] = ""
|
||||||
|
if len(subtitles) > 1:
|
||||||
|
current_subtitle["content"] = subtitles[-1]["content"] + "\n"
|
||||||
current_subtitle["start"] = None
|
current_subtitle["start"] = None
|
||||||
else:
|
else:
|
||||||
if not messagebox.askokcancel("Warning", f"\nDeleting \"{subtitles[-1].get("content")}\" \n You need to go back and mark start again."):
|
if not messagebox.askokcancel("Warning", f"\nDeleting previous #{subtitles[-1].get("index")}.\n You need to go back and mark start again."):
|
||||||
return
|
return
|
||||||
del(subtitles[-1])
|
del(subtitles[-1])
|
||||||
|
current_subtitle["content"] = ""
|
||||||
|
if len(subtitles) > 2:
|
||||||
|
current_subtitle["content"] = subtitles[-1]["content"] + "\n"
|
||||||
|
current_subtitle["start"] = None
|
||||||
print(f"\nCurrent: #{len(subtitles)+1} {current_subtitle}")
|
print(f"\nCurrent: #{len(subtitles)+1} {current_subtitle}")
|
||||||
load_next_line(diff = -1)
|
load_next_line(diff = -1)
|
||||||
|
|
||||||
|
@ -144,8 +148,12 @@ def to_time(seconds):
|
||||||
return f"{hours}:{minute:02}:{second:06.3f}"
|
return f"{hours}:{minute:02}:{second:06.3f}"
|
||||||
|
|
||||||
def update_display():
|
def update_display():
|
||||||
|
listbox_scroll_pos = script_listbox.yview()
|
||||||
|
text_scroll_index = subtitle_text.index(tk.INSERT)
|
||||||
|
|
||||||
script_listbox.delete(0, tk.END)
|
script_listbox.delete(0, tk.END)
|
||||||
script_listbox.selection_clear(0, tk.END)
|
script_listbox.selection_clear(0, tk.END)
|
||||||
|
|
||||||
subtitle_text.config(state=tk.NORMAL)
|
subtitle_text.config(state=tk.NORMAL)
|
||||||
subtitle_text.delete("1.0", tk.END)
|
subtitle_text.delete("1.0", tk.END)
|
||||||
|
|
||||||
|
@ -172,6 +180,11 @@ def update_display():
|
||||||
if player.is_playing() or not audio_started:
|
if player.is_playing() or not audio_started:
|
||||||
script_listbox.see(min(line_index + 5, len(script_lines)))
|
script_listbox.see(min(line_index + 5, len(script_lines)))
|
||||||
subtitle_text.see(tk.END)
|
subtitle_text.see(tk.END)
|
||||||
|
else:
|
||||||
|
script_listbox.yview_moveto(listbox_scroll_pos[0])
|
||||||
|
subtitle_text.see(text_scroll_index)
|
||||||
|
|
||||||
|
info_label.config(text="[ Current stack ]\n" + current_subtitle.get('content', ""))
|
||||||
|
|
||||||
subtitle_text.config(state=tk.DISABLED)
|
subtitle_text.config(state=tk.DISABLED)
|
||||||
|
|
||||||
|
@ -396,6 +409,24 @@ def show_console_output_screen():
|
||||||
def on_prev_line():
|
def on_prev_line():
|
||||||
load_next_line(diff=-1)
|
load_next_line(diff=-1)
|
||||||
|
|
||||||
|
speedex = 1
|
||||||
|
|
||||||
|
def inc_playrate():
|
||||||
|
global speedex
|
||||||
|
speedex = round(speedex * 1.2, 2)
|
||||||
|
playrate()
|
||||||
|
|
||||||
|
def dec_playrate():
|
||||||
|
global speedex
|
||||||
|
speedex = round(speedex / 1.2, 2)
|
||||||
|
playrate()
|
||||||
|
|
||||||
|
def playrate():
|
||||||
|
speed_label.config(text=f"x{speedex:.2f}")
|
||||||
|
print(f"Playback rate x{speedex:.2f}")
|
||||||
|
player.set_rate(speedex)
|
||||||
|
|
||||||
|
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
root.title("Subtitle Timing Editor")
|
root.title("Subtitle Timing Editor")
|
||||||
root.geometry('1000x800')
|
root.geometry('1000x800')
|
||||||
|
@ -441,6 +472,20 @@ timestamp_label = tk.Label(root, text="0.00s / 0.00s")
|
||||||
timestamp_label.pack(side=tk.BOTTOM, pady=5)
|
timestamp_label.pack(side=tk.BOTTOM, pady=5)
|
||||||
|
|
||||||
|
|
||||||
|
ctrl_frame = tk.Frame(root, borderwidth=0, relief="solid")
|
||||||
|
ctrl_frame.pack(side=tk.BOTTOM, padx=5)
|
||||||
|
|
||||||
|
one_button = tk.Button(ctrl_frame, text='-', borderwidth=0, command=dec_playrate)
|
||||||
|
one_button.pack(side=tk.LEFT, padx=(5,0), pady=5)
|
||||||
|
|
||||||
|
speed_label = tk.Label(ctrl_frame, text="x1")
|
||||||
|
speed_label.pack(side=tk.LEFT, padx=0, pady=5)
|
||||||
|
|
||||||
|
two_button = tk.Button(ctrl_frame, text='+', borderwidth=0, command=inc_playrate)
|
||||||
|
two_button.pack(side=tk.LEFT, padx=(0,5), pady=5)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
btn_frame = tk.Frame(root, borderwidth=0, relief="solid")
|
btn_frame = tk.Frame(root, borderwidth=0, relief="solid")
|
||||||
btn_frame.pack(side=tk.BOTTOM, padx=5)
|
btn_frame.pack(side=tk.BOTTOM, padx=5)
|
||||||
|
|
||||||
|
@ -504,12 +549,14 @@ skip_time_entry.insert(0, "0")
|
||||||
info_frame = tk.Frame(root, borderwidth=0, relief="solid", width=10, height=10, padx=10)
|
info_frame = tk.Frame(root, borderwidth=0, relief="solid", width=10, height=10, padx=10)
|
||||||
info_frame.pack(side=tk.TOP, expand=True, anchor="nw", padx=(5,15), pady=(10,15))
|
info_frame.pack(side=tk.TOP, expand=True, anchor="nw", padx=(5,15), pady=(10,15))
|
||||||
|
|
||||||
info_label = tk.Label(info_frame, text='' \
|
info_label = tk.Label(info_frame, text='[ Current stack ]\n', width=20, font=("monospace", 8), anchor="nw", justify=tk.LEFT)
|
||||||
# 'VTT Maker by @morgan9e\n\n' \
|
|
||||||
'Usage:\n Mark <\'>\n Next <;>\n Done <Return>\n' \
|
# info_label = tk.Label(info_frame, text='' \
|
||||||
'\n- Creates \"stacked\" subtitles easily.\n- Stacks subtitle from previous scene.' \
|
# # 'VTT Maker by @morgan9e\n\n' \
|
||||||
'\n- Load audio before restoring progress.\n- You can Edit, Merge, Delete script with left click.' \
|
# 'Usage:\n Mark <\'>\n Next <;>\n Done <Return>\n' \
|
||||||
, font=("monospace", 8), wraplength=140, justify=tk.LEFT)
|
# '\n- Creates \"stacked\" subtitles easily.\n- Stacks subtitle from previous scene.' \
|
||||||
|
# '\n- Load audio before restoring progress.\n- You can Edit, Merge, Delete script with left click.' \
|
||||||
|
# , font=("monospace", 8), wraplength=140, justify=tk.LEFT)
|
||||||
|
|
||||||
info_label.pack(side=tk.TOP, anchor="nw")
|
info_label.pack(side=tk.TOP, anchor="nw")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue