Skip to content

fix: subtitle timestamp ms overflow; checkpoint KeyError on manifest-only stages#325

Open
0xDevNinja wants to merge 2 commits into
calesthio:mainfrom
0xDevNinja:fix/subtitle-ts-overflow-and-checkpoint-keyerror
Open

fix: subtitle timestamp ms overflow; checkpoint KeyError on manifest-only stages#325
0xDevNinja wants to merge 2 commits into
calesthio:mainfrom
0xDevNinja:fix/subtitle-ts-overflow-and-checkpoint-keyerror

Conversation

@0xDevNinja

Copy link
Copy Markdown
Contributor

Two independent defects that corrupt output / crash on ordinary inputs. Separate atomic commits.

1. subtitle_gen — millisecond overflow (commit 1)

_ts_srt/_ts_vtt computed seconds and ms independently (ms = round((seconds % 1) * 1000)), which rounds to 1000 when the fraction is >= 0.9995 — emitting a malformed 4-digit …,1000 with no carry into the seconds/minutes/hours field. 0.9999s -> 00:00:00,1000 (should be 00:00:01,000); 59.9999 -> 00:00:59,1000 (should be 00:01:00,000). ASR word/segment end-times hit these boundaries routinely, and the cue is rejected/mistimed by strict SRT/VTT parsers (ffmpeg subtitles, VLC, WebVTT). Fixed by decomposing from a single rounded total-ms value via a shared _hmsms helper so the carry propagates.

2. checkpoint — KeyError on manifest-only stages (commit 2)

_validate_artifacts_for_stage did an unconditional CANONICAL_STAGE_ARTIFACTS[stage], but valid stages come from the pipeline manifest (get_pipeline_stages), which declares stages beyond the 9 canonical ones (e.g. character-animations character_design/rig_plan). Those pass the stage in valid_stages guard, then raise an unhandled KeyError, so the stage can never be checkpointed. Fixed with a defensive .get() that skips the required-artifact check when the stage has no canonical artifact; canonical stages still require theirs when completed.

Tests

  • tests/tools/test_subtitle_timestamps.py — ms carry across second/minute/hour boundaries, normal values unchanged, all outputs well-formed HH:MM:SS,mmm.
  • tests/lib/test_checkpoint_noncanonical_stage.py — manifest-only stage validates without KeyError; canonical stage still requires its artifact; premise guarded (manifest really declares the stage).
pytest tests/tools/test_subtitle_timestamps.py tests/lib/test_checkpoint_noncanonical_stage.py -q -> 7 passed

Confirmed the behavioral tests fail on main before the fix (checkpoint raises KeyError: character_design).

Closes #324

_ts_srt/_ts_vtt computed the seconds and millisecond fields independently:
`ms = int(round((seconds % 1) * 1000))`. When the fractional part is >= 0.9995
that rounds to 1000, emitting a malformed 4-digit `…,1000` value with no carry
into the seconds field (and, at 59.9999/3599.9999, no carry into minutes/hours).
For example 0.9999s became `00:00:00,1000` instead of `00:00:01,000`. ASR word
and segment end-times routinely land on such fractional boundaries, and the
resulting cue is rejected or mistimed by strict SRT/VTT parsers (ffmpeg
subtitles filter, VLC, browser WebVTT).

Decompose from a single rounded total-milliseconds value so the carry
propagates across all fields. Both formatters now share one `_hmsms` helper.
…l artifact

_validate_artifacts_for_stage looked up CANONICAL_STAGE_ARTIFACTS[stage]
unconditionally, but the valid stage list comes from the pipeline manifest via
get_pipeline_stages(), which declares stages beyond the 9 canonical ones — e.g.
character-animation adds `character_design`/`rig_plan`. Such a stage passes the
`stage in valid_stages` guard, then raised an unhandled KeyError on the
canonical lookup, so those stages could never be checkpointed (the crash hits
write/read_checkpoint and friends, even for in_progress checkpoints).

Look the canonical artifact up defensively with `.get()` and skip the
required-artifact check when there is none. Canonical stages still require their
artifact when completed.
@0xDevNinja 0xDevNinja requested a review from calesthio as a code owner July 7, 2026 10:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Subtitle timestamps overflow to 4-digit ms; checkpoint validation KeyErrors on manifest-only stages

1 participant