Documentation
¶
Overview ¶
Package subtitle parses SRT/VTT subtitle text and re-renders it to canonical SRT, per PLAN.md's "Upload safety" section. Ported from ../stash-subs/stash_subs/subtitles.py's parse()/render_srt()/render_vtt(): parsing anchors on the timestamp line and ignores cue numbers, headers and NOTE blocks, so anything unparsed is discarded — that discarding IS the sanitization. Re-rendering rather than storing raw uploaded bytes is what moansubs actually persists in subtitle_tracks.body.
Index ¶
Constants ¶
const ( MaxBytes = 2 * 1024 * 1024 // 2 MiB MaxCues = 10000 )
Caps from PLAN.md "Upload safety": "cap file size and cue count; reject anything absurd." Attacker-controlled upload input gets a hard ceiling before any parsing work happens.
Variables ¶
This section is empty.
Functions ¶
func BaseLang ¶
BaseLang normalizes tag (full BCP-47, e.g. "pt-BR") to its bare ISO 639 subtag (e.g. "pt") — the same reduction plugin/sidecar.go's ResolveCaptionLang applies before writing a caption filename, exposed here so the server's GET /api/v1/subtitles/{id}?format=srt path shares the one implementation instead of duplicating the language.Parse/Base dance. Delegates to CanonicalLang for the Parse/Base/confidence work.
func CanonicalLang ¶
CanonicalLang validates tag and returns its canonical BCP-47 form (e.g. "en_US" -> "en-US", "EN" -> "en") alongside its bare ISO 639 base subtag (e.g. "pt-BR" -> "pt"). Both the canonical form and the base are derived from the same language.Parse call so they can never disagree on what tag they describe.
Base() confidence must be language.High or better (Exact). "und" parses cleanly but Base() only guesses "en" at Low confidence — nobody uploaded English, the tag just carries no language at all — and a private-use tag like "x-klingon" parses with Base() at No confidence. Accepting either would silently misfile the track: this is stored verbatim as the track's language and compared for identical-track dedup (ingest, subtitles.go) and by /browse?lang=, so a guessed-at base isn't good enough. Errors naming the tag rather than guessing.
func RenderSRT ¶
RenderSRT re-renders cues to canonical SRT: sequential numbering, "HH:MM:SS,mmm --> HH:MM:SS,mmm", blank-line separated. This is what gets stored in subtitle_tracks.body (PLAN.md "Data model").
Types ¶
type Cue ¶
Cue is one subtitle cue: a start/end timestamp pair and its (sanitized) text, which may hold multiple newline-separated dialogue lines.
func Parse ¶
Parse extracts cues from SRT or WebVTT input, sanitizing as it goes. Anchored on the timestamp line exactly like subtitles.py:parse(), so cue numbers, the WEBVTT header, cue identifiers and NOTE blocks are all ignored without needing to know which format this is — everything that isn't a recognized timestamp line plus following text is simply dropped.
Rejects: input over MaxBytes, invalid UTF-8, more than MaxCues cues, or input with no parsable cues at all.