fix: Untertitel ohne rollendes Fenster verlieren keine wiederholten Blöcke
vtt2txt.py entfernt Überlappungen nur noch, wenn die Datei ein rollendes Fenster zeigt: mindestens die Hälfte der Blöcke wiederholt das Ende des vorigen (YouTube-Auto-Untertitel: 97–99 %). Manuell erstellte Untertitel werden vollständig übernommen, zwei gleiche Blöcke hintereinander bleiben zwei. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
41bcd1eb7b
commit
3da372a941
1 changed files with 53 additions and 10 deletions
25
vtt2txt.py
25
vtt2txt.py
|
|
@ -19,6 +19,9 @@ SENTENCE_END = re.compile(r"[.!?…][\"'»«“”)\]]*(?=\s|$)")
|
|||
LINE_ENDS_SENTENCE = re.compile(r"[.!?…][\"'»«“”)\]]*$")
|
||||
|
||||
MAX_SNAP_SECONDS = 30 # so weit darf ein Zeitraum bis zur nächsten Satzgrenze wachsen
|
||||
# Ab diesem Anteil von Blöcken, die das Ende des vorherigen wiederholen, gelten
|
||||
# die Untertitel als rollendes Fenster (YouTube-Auto-Untertitel: über 95 %)
|
||||
ROLLING_SHARE = 0.5
|
||||
TIME_EXAMPLES = "z. B. 00:05:10, 00:20 (Minute 20) oder 25 (Minute 25)"
|
||||
|
||||
|
||||
|
|
@ -204,21 +207,31 @@ def in_range(time, start, end):
|
|||
return (start is None or time >= start) and (end is None or time < end)
|
||||
|
||||
|
||||
def is_rolling(cues):
|
||||
"""True if most cues repeat the end of the previous one (rolling window)."""
|
||||
pairs = list(zip(cues, cues[1:]))
|
||||
overlapping = sum(1 for previous, cue in pairs if overlap(previous, cue))
|
||||
return bool(pairs) and overlapping >= ROLLING_SHARE * len(pairs)
|
||||
|
||||
|
||||
def timed_lines(vtt):
|
||||
"""Return (cue start, cue end, line) for the new caption lines of a VTT document.
|
||||
|
||||
Auto captions show a rolling window: each cue repeats the end of the previous
|
||||
cue before adding new text. Only the lines after that overlap are new, so a
|
||||
line the speaker really says twice in a row is kept.
|
||||
line the speaker really says twice in a row is kept. Captions without a
|
||||
rolling window (e.g. written by hand) are taken as they are, so identical
|
||||
cues in a row stay separate.
|
||||
"""
|
||||
# Empty cues (YouTube transitions) say nothing about the window
|
||||
cues = [(start, end, cue) for start, end, cue in read_cues(vtt) if cue]
|
||||
rolling = is_rolling([cue for _, _, cue in cues])
|
||||
lines = []
|
||||
previous = []
|
||||
|
||||
for start, end, cue in read_cues(vtt):
|
||||
# Empty cues (YouTube transitions) say nothing about the window
|
||||
if not cue:
|
||||
continue
|
||||
lines.extend((start, end, line) for line in cue[overlap(previous, cue):])
|
||||
for start, end, cue in cues:
|
||||
new = cue[overlap(previous, cue):] if rolling else cue
|
||||
lines.extend((start, end, line) for line in new)
|
||||
previous = cue
|
||||
|
||||
return lines
|
||||
|
|
|
|||
Loading…
Reference in a new issue