skrt

Crates.ioskrt
lib.rsskrt
version0.1.1
created_at2026-01-20 01:53:23.817804+00
updated_at2026-01-20 01:57:44.753971+00
descriptionLightweight, zero-copy SubRip Text (SRT) subtitle library for Rust - std only, no dependencies
homepagehttps://github.com/smackysnacks/skrt
repositoryhttps://github.com/smackysnacks/skrt
max_upload_size
id2055651
size41,408
Mack Stump (smackysnacks)

documentation

https://docs.rs/skrt/

README

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.

Commit count: 21

cargo fmt