Convert non-SRT downloads to SRT #213

Closed
opened 2026-08-24 22:36:47 +01:00 by naps62-yolo · 1 comment
Owner

DESIGN.md §15 says sidecars are SRT. Providers serve other things:
SubtitleFormat already names Ass and Vtt alongside Srt (#184), and
its own docs say converting "is not this crate's decision to make silently".

No issue makes that decision. As it stands a downloaded ASS or VTT file
would either be written into the title folder under an .srt name while not
being SRT, or dropped on the floor — neither is right.

Convert to SRT in arr-subs after decoding (see the encoding issue this
depends on) and before sync and write:

  • Vtt to SRT: strip the WEBVTT header and cue settings, rewrite the
    ./, millisecond separator, renumber cues.
  • Ass to SRT: take the dialogue events in time order, strip override tags
    ({\an8} and friends), and drop styling. Losing styling is the accepted
    cost of §15's one-format-on-disk rule.
  • Srt passes through untouched.
  • Anything else (SubtitleFormat::Other) is a failed attempt with a reason,
    not a silent skip.

arr_subs::srt::Cue from #190 is the target shape — rendering it is already
written, so this is a parser per input format, not a new writer.

Found while implementing #190.

Depends on: #184, #190

DESIGN.md §15 says sidecars are SRT. Providers serve other things: `SubtitleFormat` already names `Ass` and `Vtt` alongside `Srt` (#184), and its own docs say converting "is not this crate's decision to make silently". No issue makes that decision. As it stands a downloaded ASS or VTT file would either be written into the title folder under an `.srt` name while not being SRT, or dropped on the floor — neither is right. Convert to SRT in `arr-subs` after decoding (see the encoding issue this depends on) and before sync and write: - `Vtt` to SRT: strip the `WEBVTT` header and cue settings, rewrite the `.`/`,` millisecond separator, renumber cues. - `Ass` to SRT: take the dialogue events in time order, strip override tags (`{\an8}` and friends), and drop styling. Losing styling is the accepted cost of §15's one-format-on-disk rule. - `Srt` passes through untouched. - Anything else (`SubtitleFormat::Other`) is a failed attempt with a reason, not a silent skip. `arr_subs::srt::Cue` from #190 is the target shape — rendering it is already written, so this is a parser per input format, not a new writer. Found while implementing #190. Depends on: #184, #190
naps62-yolo added this to the Subtitles milestone 2026-08-24 22:36:47 +01:00
naps62-yolo added the area/subsphase/9-subtitlestype/featuredifficulty/moderate labels 2026-08-24 22:36:47 +01:00
naps62-yolo added a new dependency 2026-08-24 22:37:27 +01:00
naps62-yolo added a new dependency 2026-08-24 22:37:27 +01:00
naps62-yolo added a new dependency 2026-08-24 22:37:28 +01:00
Author
Owner

Implemented conversion of downloaded non-SRT subtitles to SRT in arr-subs, per DESIGN.md §15's one-format-on-disk rule. Added crates/arr-subs/src/convert.rs, exposing Fetched::to_srt(&self): SRT passes through untouched, VTT is parsed (WEBVTT header/NOTE/STYLE/REGION blocks and cue settings stripped, . millisecond separator, optional-hours timestamps) into Cues and rendered with the existing srt::render from #190, ASS/SSA Dialogue: events from [Events] are parsed, sorted into time order, override tags ({\an8} etc.) stripped and \N/\n turned into real line breaks, then rendered the same way. SubtitleFormat::Other and any parser rejection produce a new Error::Convert { candidate, format, detail } rather than a silent skip. 8 new unit tests cover passthrough, header/settings stripping, hours-optional VTT timestamps, ASS time-ordering/tag-stripping/line-breaks, and malformed-input failure for both formats.

Branch: subtitles/213-to-srt (based on blitz/subtitles), pushed.

just ci passed: 564/564 tests, clippy and fmt clean.

Findings

None outside this issue's scope.

Implemented conversion of downloaded non-SRT subtitles to SRT in `arr-subs`, per DESIGN.md §15's one-format-on-disk rule. Added `crates/arr-subs/src/convert.rs`, exposing `Fetched::to_srt(&self)`: SRT passes through untouched, VTT is parsed (WEBVTT header/NOTE/STYLE/REGION blocks and cue settings stripped, `.` millisecond separator, optional-hours timestamps) into `Cue`s and rendered with the existing `srt::render` from #190, ASS/SSA `Dialogue:` events from `[Events]` are parsed, sorted into time order, override tags (`{\an8}` etc.) stripped and `\N`/`\n` turned into real line breaks, then rendered the same way. `SubtitleFormat::Other` and any parser rejection produce a new `Error::Convert { candidate, format, detail }` rather than a silent skip. 8 new unit tests cover passthrough, header/settings stripping, hours-optional VTT timestamps, ASS time-ordering/tag-stripping/line-breaks, and malformed-input failure for both formats. Branch: `subtitles/213-to-srt` (based on `blitz/subtitles`), pushed. `just ci` passed: 564/564 tests, clippy and fmt clean. ## Findings None outside this issue's scope.
naps62-yolo added a new dependency 2026-08-25 00:41:34 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yolo/arr#213