Advanced, expressive, production-safe subtitle manager for `.srt` files.
Project description
๐ฌ SRTManager
Advanced, expressive, production-safe subtitle manager for .srt files.
SRTManager is a high-level abstraction built on top of the srt Python library that enforces strict subtitle invariants while providing powerful transformation utilities like shifting, slicing, scaling, merging, gap compression, content mapping, and more.
โจ Features
- โ Automatic sorting & reindexing
- โ Overlap detection
- โ Timestamp validation (no negative times)
- โ Immutable-style transformations
- โ Shift subtitles forward/backward
- โ Merge subtitle files safely
- โ Clip/slice by time range
- โ Search by text
- โ Split & join subtitle segments
- โ Gap compression
- โ Duration scaling
- โ Functional content transformations
๐ฆ Installation
pip install srtmanager
Then place SRTManager in your project.
๐ง Core Invariants
Every SRTManager instance guarantees:
- Subtitles are sorted by start time
- Subtitles are sequentially indexed from
1 - No overlapping subtitles
- All timestamps are โฅ 0
If any invariant is violated:
SRTValidationError
is raised.
๐ Quick Start
from srtmanager import SRTManager
# Load from file
subs = SRTManager.from_file("input.srt")
# Shift forward by 2 seconds
shifted = subs >> 2
# Search for text
hello_lines = subs["hello"]
# Slice between 10s and 30s
clip = subs[10:30]
# Save result
shifted.save("output.srt")
๐ API Documentation
๐น Constructors
SRTManager.from_file(path: str)
Load subtitles from .srt file.
subs = SRTManager.from_file("movie.srt")
SRTManager.from_string(raw: str)
Parse subtitles from raw string.
๐น Basic Properties
len(manager)
Returns number of subtitles.
manager.start
Start timestamp of first subtitle.
manager.end
End timestamp of last subtitle.
manager.duration
Total duration (end - start).
You can also scale duration:
subs.duration = 120 # scale entire timeline to 120 seconds
๐น Time Shifting
shift(seconds: float) -> SRTManager
new_subs = subs.shift(2.5)
Operator Overloads
subs >> 2 # shift forward 2 seconds
subs << 1 # shift backward 1 second
๐น Merge
combined = subs1 + subs2
- Automatically shifts second file to avoid overlap.
- Maintains invariants.
๐น Slice (Time Clipping)
clip = subs.slice(10, 30)
# or
clip = subs[10:30]
- Clips subtitles within range
- Adjusts start/end if partially overlapping
๐น Find (Search)
results = subs.find("hello")
results = subs.find("HELLO", case_sensitive=True)
# Shortcut
results = subs["hello"]
Returns new SRTManager containing matches.
๐น Split
Split subtitles using delimiter:
parts = subs.split("<line>")
Returns list of SRTManager instances.
๐น Join as Single Subtitle
single = subs.join_as_single()
Returns one merged srt.Subtitle.
๐น Gap Compression
Removes silent gaps between subtitles while preserving durations:
tight = subs.compress_gaps()
๐น Content Transformation
Functional style mapping:
upper = subs.map_content(lambda text: text.upper())
๐น Plain Text Export
text = subs.to_plain_text()
๐น Save
subs.save("output.srt")
๐น Add Raw Subtitles (Validated)
subs.add_raw(new_subtitles)
Re-validates:
- Sorting
- Indexing
- Overlaps
Raises SRTValidationError if invalid.
๐ก Error Handling
SRTValidationError
Raised when:
- Negative timestamps
- End before start
- Overlapping subtitles
Example:
try:
subs = SRTManager(invalid_subtitles)
except SRTValidationError as e:
print("Invalid SRT:", e)
๐งฉ Design Philosophy
This library follows:
- Immutability-first transformations
- Strong invariants
- Operator overloading for expressiveness
- Functional programming patterns
- Production-safe validation
๐ฎ Example Workflow
subs = (
SRTManager.from_file("raw.srt")
.shift(1.2)
.map_content(str.strip)
.compress_gaps()
)
subs.save("cleaned.srt")
๐ Ideal Use Cases
- Subtitle synchronization
- Post-processing AI-generated subtitles
- Timeline alignment
- Subtitle merging pipelines
- Research projects
- Video automation tools
๐ง Author Notes
Built for developers who want:
- Clean abstraction
- No silent timeline corruption
- Predictable transformations
- Composable subtitle workflows
Below are advanced, production-level usage patterns for your SRTManager implementation
These go beyond basic examples and show how to build real subtitle pipelines.
๐ฅ Advanced Usage Examples
1๏ธโฃ Auto-Sync Two Subtitle Files
๐ฏ Problem
You have:
dialogue.srttranslated.srt(starts earlier)
You want to align them safely and merge.
from srtmanager import SRTManager
dialogue = SRTManager.from_file("dialogue.srt")
translated = SRTManager.from_file("translated.srt")
# Align translated to dialogue start
offset = (dialogue.start - translated.start).total_seconds()
translated_aligned = translated.shift(offset)
# Merge safely (no overlap corruption)
final = dialogue + translated_aligned
final.save("merged.srt")
โ Automatically prevents overlap โ Keeps indexes clean โ Guarantees invariants
2๏ธโฃ Normalize AI-Generated Subtitles
๐ฏ Problem
AI subtitles often contain:
- Extra spaces
- Broken casing
- Random gaps
๐ง Clean Pipeline
def clean_text(text: str) -> str:
return " ".join(text.strip().split()).capitalize()
subs = (
SRTManager.from_file("ai_output.srt")
.map_content(clean_text)
.compress_gaps()
)
subs.save("clean_ai_output.srt")
โ Removes weird spacing โ Fixes formatting โ Eliminates timing gaps
3๏ธโฃ Clip Scene + Retime to New Duration
๐ฏ Problem
You want only the segment from 60sโ120s Then stretch it to exactly 30 seconds.
clip = SRTManager.from_file("movie.srt")[60:120]
# Scale duration to 30 seconds
clip.duration = 30
clip.save("scene_shortened.srt")
โ Automatically scales proportionally โ Keeps relative timing intact
4๏ธโฃ Subtitle Chunking (Episode Segmentation)
๐ฏ Problem
You use <line> as delimiter to mark chapter breaks.
subs = SRTManager.from_file("lecture.srt")
parts = subs.split("<line>")
for i, part in enumerate(parts, 1):
part.save(f"chapter_{i}.srt")
โ Clean segmentation โ Maintains proper indexing
5๏ธโฃ Build a Search Engine on Subtitles
๐ฏ Problem
Extract all dialogue containing a keyword.
subs = SRTManager.from_file("podcast.srt")
crypto_mentions = subs["blockchain"]
print(crypto_mentions.to_plain_text())
โ Returns only matching subtitles โ Keeps original timestamps
6๏ธโฃ Remove Silence but Keep Flow
๐ฏ Problem
You want subtitles to play continuously without silent gaps.
tight = (
SRTManager.from_file("documentary.srt")
.compress_gaps()
)
tight.save("no_silence.srt")
Original:
00:00:01 โ 00:00:03
00:00:10 โ 00:00:12
Compressed:
00:00:01 โ 00:00:03
00:00:03 โ 00:00:05
โ Keeps duration of each subtitle โ Removes dead air
7๏ธโฃ Subtitle Stitching (Multiple Episodes โ Movie Cut)
๐ฏ Problem
Combine multiple SRT files into one continuous timeline.
ep1 = SRTManager.from_file("ep1.srt")
ep2 = SRTManager.from_file("ep2.srt")
ep3 = SRTManager.from_file("ep3.srt")
movie_cut = ep1 + ep2 + ep3
movie_cut.save("full_movie.srt")
โ Automatically offsets later files โ No overlap errors
8๏ธโฃ Build a Subtitle Analytics Tool
๐ฏ Word Frequency Counter
from collections import Counter
subs = SRTManager.from_file("debate.srt")
words = subs.to_plain_text().lower().split()
freq = Counter(words)
print(freq.most_common(20))
โ Works perfectly because to_plain_text() strips formatting
9๏ธโฃ Convert Subtitles to Voice Script
๐ฏ Create Narration Script
subs = SRTManager.from_file("course.srt")
script = subs.join_as_single(sep=" ")
with open("script.txt", "w") as f:
f.write(script.content)
โ Preserves full timeline span โ Merges content cleanly
๐ Real Production Pipeline Example
def production_pipeline(path_in: str, path_out: str):
subs = (
SRTManager.from_file(path_in)
.shift(0.5)
.map_content(lambda t: t.replace("uh", "").strip())
.compress_gaps()
)
subs.save(path_out)
production_pipeline("raw.srt", "final.srt")
โ Sync correction โ Filler word removal โ Timeline tightening โ Safe save
โ๏ธ Advanced Pattern: Functional Chaining
Because transformations return new SRTManager instances:
final = (
SRTManager.from_file("input.srt")
>> 1.2
.map_content(str.upper)
.slice(30, 90)
.compress_gaps()
)
This enables:
- Declarative pipelines
- Immutable-style transformations
- Predictable behavior
๐ Design Strength Shown in Advanced Use
Your architecture supports:
- Deterministic transformations
- Strong validation
- Clean composition
- Safe timeline arithmetic
- Operator expressiveness
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file srtmanager-0.1.0.tar.gz.
File metadata
- Download URL: srtmanager-0.1.0.tar.gz
- Upload date:
- Size: 6.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88a4cecf1b7388f184a9a9930b0e0220f9cf12e912210bab77d283021d66ed2a
|
|
| MD5 |
1e53ff462a4a5073753fe0aa01c799b1
|
|
| BLAKE2b-256 |
ab4f98f57cf5c1cf0050a110d0f5c4f10daffc0f16d2ba2c90f9b5af99f12617
|
File details
Details for the file srtmanager-0.1.0-py3-none-any.whl.
File metadata
- Download URL: srtmanager-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ce6d8ca4bf039ec8b806654eb86d5bac837f06c480c695fbd3f17470b12e2a0
|
|
| MD5 |
960ac2898a01852079acae45c0ed553b
|
|
| BLAKE2b-256 |
94546c03a1c9967c259aaa77edaefba62a3ff0a4e10f267a0b4705b02a6392b7
|