0
# Subtitle Files
1
2
File-level operations for SubRip subtitle files, including parsing, saving, batch operations, and file format handling. The SubRipFile class provides a list-like interface for managing collections of subtitles.
3
4
## Capabilities
5
6
### File Creation and Loading
7
8
Create new subtitle files or load existing ones with automatic encoding detection.
9
10
```python { .api }
11
class SubRipFile:
12
def __init__(self, items=None, eol=None, path=None, encoding='utf-8'):
13
"""
14
Create a new SubRipFile instance.
15
16
Args:
17
items (list, optional): List of SubRipItem instances
18
eol (str, optional): End of line character (defaults to os.linesep)
19
path (str, optional): File path for saving
20
encoding (str): File encoding (default: 'utf-8')
21
"""
22
23
@classmethod
24
def open(cls, path='', encoding=None, error_handling=0):
25
"""
26
Open and parse a SubRip file from filesystem.
27
28
Args:
29
path (str): Path to subtitle file
30
encoding (str, optional): File encoding (auto-detected if None)
31
error_handling (int): Error handling mode (ERROR_PASS/ERROR_LOG/ERROR_RAISE)
32
33
Returns:
34
SubRipFile: Parsed subtitle file
35
"""
36
37
@classmethod
38
def from_string(cls, source, **kwargs):
39
"""
40
Create SubRipFile from string content.
41
42
Args:
43
source (str): Subtitle content as string
44
**kwargs: Additional arguments passed to constructor
45
46
Returns:
47
SubRipFile: Parsed subtitle file
48
"""
49
```
50
51
### File Saving and Output
52
53
Save subtitle files with encoding and format control.
54
55
```python { .api }
56
def save(self, path=None, encoding=None, eol=None):
57
"""
58
Save subtitles to file.
59
60
Args:
61
path (str, optional): Output path (uses instance path if None)
62
encoding (str, optional): Output encoding (uses instance encoding if None)
63
eol (str, optional): End of line character (uses instance eol if None)
64
"""
65
66
def write_into(self, output_file, eol=None):
67
"""
68
Write subtitles to file-like object.
69
70
Args:
71
output_file: Any object with write() method
72
eol (str, optional): End of line character
73
"""
74
```
75
76
### Streaming Parser
77
78
Stream subtitles as they are parsed without storing them in memory.
79
80
```python { .api }
81
@classmethod
82
def stream(cls, source_file, error_handling=0):
83
"""
84
Generator that yields SubRipItem instances as they are parsed.
85
86
Args:
87
source_file: Iterable yielding unicode strings (file-like object)
88
error_handling (int): Error handling mode
89
90
Yields:
91
SubRipItem: Parsed subtitle items
92
"""
93
94
def read(self, source_file, error_handling=0):
95
"""
96
Parse subtitles from file-like object and add to current instance.
97
98
Args:
99
source_file: Iterable yielding unicode strings
100
error_handling (int): Error handling mode
101
102
Returns:
103
SubRipFile: Self for method chaining
104
"""
105
```
106
107
### Time-based Filtering
108
109
Filter subtitles based on timing constraints.
110
111
```python { .api }
112
def slice(self, starts_before=None, starts_after=None, ends_before=None, ends_after=None):
113
"""
114
Filter subtitles by time constraints.
115
116
Args:
117
starts_before: SubRipTime or coercible - filter items starting before this time
118
starts_after: SubRipTime or coercible - filter items starting after this time
119
ends_before: SubRipTime or coercible - filter items ending before this time
120
ends_after: SubRipTime or coercible - filter items ending after this time
121
122
Returns:
123
SubRipFile: New instance with filtered subtitles (references original items)
124
"""
125
126
def at(self, timestamp=None, **kwargs):
127
"""
128
Get subtitles visible at specific timestamp.
129
130
Args:
131
timestamp: SubRipTime or coercible, or None to use kwargs
132
**kwargs: Time components (hours, minutes, seconds, milliseconds)
133
134
Returns:
135
SubRipFile: New instance with subtitles visible at timestamp
136
"""
137
```
138
139
### Batch Operations
140
141
Apply operations to all subtitles in the file.
142
143
```python { .api }
144
def shift(self, *args, **kwargs):
145
"""
146
Shift timing of all subtitles.
147
148
Args:
149
*args: Positional time arguments (hours, minutes, seconds, milliseconds)
150
**kwargs: Named time arguments or ratio for proportional scaling
151
152
Supported kwargs:
153
hours (int): Hours to add
154
minutes (int): Minutes to add
155
seconds (int): Seconds to add
156
milliseconds (int): Milliseconds to add
157
ratio (float): Multiply all times by this ratio
158
"""
159
160
def clean_indexes(self):
161
"""
162
Sort subtitles by start time and renumber sequentially.
163
Should be called after operations that may disorder subtitles.
164
"""
165
```
166
167
### Properties
168
169
Access file-level information and computed properties.
170
171
```python { .api }
172
@property
173
def text(self):
174
"""
175
Combined text content of all subtitles.
176
177
Returns:
178
str: All subtitle text joined with newlines
179
"""
180
181
@property
182
def eol(self):
183
"""
184
End of line character used in file.
185
186
Returns:
187
str: EOL character (\\n, \\r\\n, or \\r)
188
"""
189
190
@property
191
def path(self):
192
"""File path if set during creation or opening."""
193
194
@property
195
def encoding(self):
196
"""File encoding used for reading/writing."""
197
```
198
199
### List Interface
200
201
SubRipFile inherits from UserList and supports standard list operations.
202
203
```python { .api }
204
# Indexing and slicing
205
item = subs[0] # Get first subtitle
206
items = subs[1:5] # Get range of subtitles
207
208
# Iteration
209
for sub in subs: # Iterate over all subtitles
210
print(sub.text)
211
212
# Length and membership
213
count = len(subs) # Number of subtitles
214
has_item = item in subs # Check if item is in file
215
216
# Modification
217
subs.append(new_item) # Add subtitle to end
218
subs.extend(more_items) # Add multiple subtitles
219
subs.insert(0, first_item) # Insert at specific position
220
subs.remove(item) # Remove specific item
221
del subs[0] # Delete by index
222
223
# Sorting
224
subs.sort() # Sort by start time (default)
225
subs.reverse() # Reverse order
226
```
227
228
### Constants
229
230
```python { .api }
231
ERROR_PASS: int = 0 # Ignore parsing errors
232
ERROR_LOG: int = 1 # Log parsing errors to stderr
233
ERROR_RAISE: int = 2 # Raise exceptions on parsing errors
234
DEFAULT_ENCODING: str = 'utf_8' # Default file encoding
235
```
236
237
## Usage Examples
238
239
### Basic File Operations
240
241
```python
242
import pysrt
243
244
# Load subtitle file
245
subs = pysrt.open('movie.srt')
246
print(f"Loaded {len(subs)} subtitles")
247
248
# Handle encoding explicitly
249
subs = pysrt.open('movie.srt', encoding='latin1')
250
251
# Error handling
252
try:
253
subs = pysrt.open('malformed.srt', error_handling=pysrt.ERROR_RAISE)
254
except pysrt.Error as e:
255
print(f"Parsing error: {e}")
256
```
257
258
### Time Manipulation
259
260
```python
261
# Shift all subtitles 2.5 seconds forward
262
subs.shift(seconds=2, milliseconds=500)
263
264
# Convert framerate from 23.976 to 25 fps
265
subs.shift(ratio=25/23.976)
266
267
# Get subtitles visible at 1 minute mark
268
minute_subs = subs.at(minutes=1)
269
270
# Get subtitles in first 30 seconds
271
early_subs = subs.slice(ends_before={'seconds': 30})
272
```
273
274
### File Processing
275
276
```python
277
# Stream processing for large files
278
for subtitle in pysrt.stream(open('large_movie.srt', 'r', encoding='utf-8')):
279
if 'profanity' in subtitle.text.lower():
280
subtitle.text = '[CENSORED]'
281
print(subtitle)
282
283
# Create from string content
284
srt_content = """1
285
00:00:01,500 --> 00:00:05,000
286
Hello, World!
287
288
2
289
00:00:06,000 --> 00:00:10,000
290
Welcome to PySRT!
291
"""
292
subs = pysrt.from_string(srt_content)
293
```
294
295
### Batch Processing
296
297
```python
298
# Clean up subtitle file
299
subs = pysrt.open('messy_subtitles.srt')
300
subs.clean_indexes() # Sort and renumber
301
subs.shift(milliseconds=500) # Fine-tune timing
302
subs.save('clean_subtitles.srt')
303
304
# Split subtitles into multiple files
305
full_movie = pysrt.open('full_movie.srt')
306
first_half = full_movie.slice(ends_before={'minutes': 60})
307
second_half = full_movie.slice(starts_after={'minutes': 60})
308
second_half.shift(minutes=-60) # Reset timing for second part
309
first_half.save('part1.srt')
310
second_half.save('part2.srt')
311
```