You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wubloader/chat_to_subtitle.py

75 lines
2.0 KiB
Python

import json
import sys
import argh
CHAT_BOX = (1220, 100, 1910, 810)
def encode_time(time):
hours, time = divmod(time, 3600)
mins, secs = divmod(time, 60)
return f"{int(hours)}:{int(mins):02d}:{secs:05.2f}"
def encode_dialogue(start, end, text):
return f"Dialogue: {encode_time(start)}, {encode_time(end)}, Chat, {text}"
def message_to_line(message, time_base):
time = message["time"] - time_base
tags = message.get("tags", {})
sender = tags.get("display-name")
if sender is None:
sender = message["sender"]
content = message["params"][1]
if content.startswith("\x01"):
content = content[1:-1].split(" ", 1)[1]
text = f"{sender} {content}"
else:
text = f"{sender}: {content}"
color = tags.get("color")
if color is None:
color = "FFFFFF"
else:
color = color.lstrip("#")
text = f"{{ \\c&H{color}& }}" + text
return time, text
def lines_to_dialogue(start, end, lines):
lines = "\\N".join([text for start, text in lines][::-1])
clip_args = ",".join(map(str, CHAT_BOX))
text = f"{{ \\clip({clip_args}) }}" + lines
return encode_dialogue(start, end, text)
def gen_dialogues(messages, time_base, message_ttl=10):
window = []
prev_start = None
for message in messages:
next_start, text = message_to_line(message, time_base)
while window and window[0][0] + message_ttl < next_start:
end = window[0][0] + message_ttl
yield lines_to_dialogue(prev_start, end, window)
window.pop(0)
prev_start = end
window.append((next_start, text))
if prev_start is not None:
yield lines_to_dialogue(prev_start, next_start, window)
prev_start = next_start
# flush remaining messages
while window:
end = window[0][0] + message_ttl
yield lines_to_dialogue(prev_start, end, window)
window.pop(0)
prev_start = end
def main(time_base=0):
messages = sys.stdin.read().strip().split("\n")
messages = [json.loads(line) for line in messages]
for dialogue in gen_dialogues(messages, time_base):
print(dialogue)
if __name__ == '__main__':
argh.dispatch_command(main)