A pysubs2 format plugin that reads SRV3 captions, so they can be written out in any format pysubs2 supports.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-18 22:27:58 +00:00
specs Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
src Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
.gitignore Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
Beep Block Flyway [z0Bc_XEEcE4].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
Best of the Worst: Wheel of the Worst #32 [wetP-Z7gH2E].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
build.rs Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
Cargo.lock Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
Cargo.toml Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
Kizuna AI - AIAIAI (feat. 中田ヤスタカ)【Official Music Video】 [S8dmq5YIUoc].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
MY WHAT??【Hololive Animation|Eng sub】 [u_lcDl6qnh4].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
README.md Replace the Python implementation with a Rust rewrite 2026-09-19 08:26:52 +10:00
Top Story with Tom Llamas - Aug. 23 | NBC News NOW [FVeoC9pm5rI].en-uYU-mmqFLq8.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
x0o0x_ - ⧸ ⧸ ⧸⧸ ⧸ ⧸ [UxM5UgpXYM4].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
ずっと真夜中でいいのに。『低血ボルト』MV (ZUTOMAYO – FASTENING) [COll6PdtI5w].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
ボカロPと絵師が25人集まってダンスロボットダンスMVアレンジメドレーしてみた [Vb-z6AR-2F0].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
メズマライザー ⧸ 初音ミク・重音テトSV [19y8YTbvri8].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00
絶対にチョコミントを食べるアオイチャン [pfkBYHFZAt8].en.srv3 Add srv3topysub2, a pysubs2 reader for YouTube SRV3/YTT captions 2026-08-23 03:20:16 +10:00

srv3topysub2

Convert YouTube SRV3/.ytt captions to ASS, SRT, WebVTT or TTML.

A single static Rust binary. Reading and writing both stream, so memory scales with the number of events, not the input size. ASS is the highest-fidelity target — it alone preserves pen colours, fonts, sizes, opacities, background boxes, edges and window positions.

Install

$ cargo install --path .

Usage

$ srv3topysub2 captions.srv3 -o captions.ass
$ srv3topysub2 captions.srv3 -o captions.ttml        # format from the extension
$ srv3topysub2 captions.srv3 -f srt -o -             # stdout
$ srv3topysub2 *.srv3 -d out/ -f ass                 # batch
$ cat captions.srv3 | srv3topysub2 - -o -            # stdin to stdout
Option Effect
-f, --format ass, srt, vtt, ttml (default: from -o, else ass)
-o, --output Output file; - writes to stdout
-d, --outdir One output per input in a directory
--ruby keep|drop Keep ruby annotations (default) or base text only
--no-position Omit \an/\pos position tags
--order time|document Sort by start time (default) or keep <p> order
--report-irregular List anything outside the modelled vocabulary
--default-duration MS Fallback length for a final event with no d (default 5000)

Errors and findings go to stderr; stdout carries only converted subtitles.

How it works

The SRV3 vocabulary is data, not code: specs/srv3.toml (enums, constants, font names, element vocabulary) and specs/formats.toml (output formats). build.rs turns them into type-safe Rust at compile time, and a missing value fails the build.

The mapping follows FFmpeg's srv3dec.c, so output matches ffmpeg -i captions.srv3 out.ass — 1280×720 canvas, 38px base font, ASS PenN styles, &HBGR colours with inverted alpha, and \an/\pos window positions. Two deliberate departures are documented in src/convert.rs (font style 4/5, and no stray outline under hard shadows).

Real-world oddities — rollup overlap, teletype keystrokes, karaoke reveals, two-track files, bare tracks, padding paragraphs, literal newlines — are all handled and regression-tested.

--report-irregular lists unknown elements/attributes, out-of-range values, unreadable colours, duplicate ids and dangling references, without changing the conversion.

What survives which format

ASS TTML SRT WebVTT
Text, timing ✅ ✅ ✅ ✅
Bold / italic / underline ✅ ✅ ✅ ✅
Font name, colour ✅ ✅ ✗ ✗
Font size ✅ ✗ ✗ ✗
Background box, edges ✅ ✗ ✗ ✗
Window position ✅ ✗ ✗ ✗

Vertical/rotated text, subscript/superscript and packed text have no SubStation equivalent; they emit a warning and are dropped.

Development

$ cargo build
$ cargo test
$ cargo clippy --all-targets --all-features -- -D warnings

cargo test runs the unit suite plus an end-to-end pass over every *.srv3 in the repo root.