skrt 0.1.0

Lightweight, zero-copy SubRip Text (SRT) subtitle library for Rust - std only, no dependencies
Documentation
  • Coverage
  • 94.87%
    37 out of 39 items documented15 out of 24 items with examples
  • Size
  • Source code size: 40.65 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 4.35 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 17s Average build duration of successful builds.
  • all releases: 16s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • smackysnacks

skrt

A fast, zero-copy parser and serializer for SubRip Text (SRT) subtitle files in Rust.

Features

  • Zero-copy parsing - Subtitle text borrows directly from the input string when possible
  • Flexible input handling - Supports LF and CRLF line endings, optional UTF-8 BOM, trailing whitespace, and missing final newlines
  • Shift timestamps forward or backward with millisecond precision
  • Create subtitle files programmatically
  • Detailed error reporting

Installation

Add skrt to your Cargo.toml:

[dependencies]
skrt = "0.1"

Usage

Parsing an SRT file

use skrt::Srt;

let data = r#"1
00:00:01,000 --> 00:00:04,000
Hello, world!

2
00:00:05,000 --> 00:00:08,000
This is a subtitle.

"#;

let srt = Srt::try_parse(data).unwrap();

for subtitle in srt.iter() {
    println!("[{}] {}", subtitle.start(), subtitle.text());
}

Building subtitles programmatically

use skrt::{Srt, Timestamp};

let mut srt = Srt::new();

srt.add_subtitle(
    Timestamp::from_millis(1000).unwrap(),
    Timestamp::from_millis(4000).unwrap(),
    "First subtitle".into(),
);

srt.add_subtitle(
    Timestamp::from_millis(5000).unwrap(),
    Timestamp::from_millis(8000).unwrap(),
    "Second subtitle".into(),
);

let output = srt.serialize();
println!("{output}");

Shifting timestamps

use skrt::Srt;

let data = "1\n00:00:01,000 --> 00:00:04,000\nHello\n\n";
let mut srt = Srt::try_parse(data).unwrap();

// Shift all subtitles forward by 5 seconds
for sub in srt.iter_mut() {
    sub.set_start(sub.start().shift_millis(5000).unwrap());
    sub.set_end(sub.end().shift_millis(5000).unwrap());
}

println!("{}", srt.serialize());

Working with timestamps

use skrt::Timestamp;

let ts = Timestamp::from_millis(5025000).unwrap(); // 1h 23m 45s
assert_eq!("01:23:45,000", ts.to_string());
assert_eq!(5025000, ts.to_millis());

// Timestamps are comparable
let ts2 = Timestamp::from_millis(5025500).unwrap();
assert!(ts < ts2);

Format Details

SRT files consist of subtitle blocks separated by blank lines. Each block contains:

  1. A sequence number (positive integer)
  2. A timestamp line: HH:MM:SS,mmm --> HH:MM:SS,mmm
  3. One or more lines of text

This crate handles common real-world variations:

  • Both LF (\n) and CRLF (\r\n) line endings
  • Optional UTF-8 BOM at the start of the file
  • Trailing whitespace after timestamp lines
  • Files that don't end with a trailing blank line

Development

Fuzz Testing

Install cargo-fuzz with cargo +nightly install cargo-fuzz, then cd fuzz && cargo +nightly fuzz run -j $(grep -c processor /proc/cpuinfo) parse_srt.