Merge branch 'fix/review-2077' into fix/community-integration

# Conflicts:
#	docs/dubbing/translation-engines.md
This commit is contained in:
Palash Debnath
2026-09-17 13:48:47 +05:30
3 changed files with 25 additions and 13 deletions
+10 -13
View File
@@ -56,19 +56,6 @@ def _is_index_line(line: str) -> bool:
return stripped.isascii() and stripped.isdigit()
def _uses_index_lines(text: str, first_timing_start: int) -> bool:
"""Initial numbering hint for lenient files without blank separators.
Later cue boundaries are also inspected: mixed indexed/unindexed files
must not leak index lines or delete numeric dialogue.
"""
head = text[:first_timing_start]
for line in reversed(head.split("\n")):
if line.strip():
return _is_index_line(line)
return False
@dataclass
class SrtParseResult:
segments: list[dict]
@@ -94,6 +81,16 @@ def parse_srt(content: str) -> SrtParseResult:
text = content.lstrip("").replace("\r\n", "\n").replace("\r", "\n")
is_webvtt = bool(re.match(r"WEBVTT(?:[ \t]|\n|$)", text.lstrip()))
if is_webvtt:
# Metadata is block-scoped. Filter it BEFORE scanning timings so an
# example timestamp inside a NOTE/STYLE/REGION cannot become speech.
blocks = []
for block in re.split(r"\n[^\S\n]*\n", text):
first = block.strip().split("\n", 1)[0].strip()
if first in {"STYLE", "REGION"} or re.match(r"NOTE(?:[ \t]|$)", first):
continue
blocks.append(block)
text = "\n\n".join(blocks)
raw: list[dict] = []
skipped = 0
# Find every timing line, slice the cue text from there to the next
+2
View File
@@ -261,3 +261,5 @@ Argos accepts Chinese/Simplified Chinese names, Mandarin aliases, and language t
Mixed or malformed SRT files can make a bare number indistinguishable from spoken dialogue. The importer removes numbering only when cue boundaries and sequential numbering support it; ambiguous nonsequential numbers are retained as text to avoid silent data loss. Standard indexed SRT and WebVTT exports avoid this ambiguity.
If the Argos native runtime cannot load, both desktop and browser clients show localized recovery guidance: reinstall the backend or select NLLB. The API returns the stable `argos_runtime_unavailable` error code without exposing native library paths.
WebVTT import excludes NOTE, STYLE, and REGION metadata blocks before parsing timestamps; timing examples in notes never become spoken segments.
+13
View File
@@ -371,3 +371,16 @@ def test_skipped_cue_still_advances_numbering_state():
def test_numeric_only_cue_after_invalid_cue_is_not_discarded():
text = "1\n00:00:01,000 --> 00:00:02,000\nFirst\n\n2\n00:00:04,000 --> 00:00:03,000\nInvalid\n\n3\n00:00:05,000 --> 00:00:06,000\n4\n00:00:07,000 --> 00:00:08,000\nLast"
assert [cue["text"] for cue in parse_srt(text).segments] == ["First", "4", "Last"]
@pytest.mark.parametrize('header', ['NOTE', 'NOTE translator notes', 'NOTE\ttranslator notes', 'STYLE', 'REGION'])
def test_webvtt_metadata_timestamps_never_become_dialogue(header):
text = f'WEBVTT\n\n{header}\n00:00.000 --> 00:02.000\nMetadata only\n\ncue\n00:03.000 --> 00:04.000\nReal dialogue\n'
result = parse_srt(text)
assert [cue['text'] for cue in result.segments] == ['Real dialogue']
assert result.segments[0]['start'] == 3
def test_webvtt_note_words_inside_dialogue_are_retained():
text = 'WEBVTT\n\n00:01.000 --> 00:02.000\nNOTE this is spoken\nSTYLE\nREGION\n'
assert parse_srt(text).segments[0]['text'] == 'NOTE this is spoken\nSTYLE\nREGION'