muxtools.subtitle.sub
DEFAULT_DIALOGUE_STYLES
module-attribute
SRT_REGEX
module-attribute
SRT_REGEX = '\\d+[\\r\\n](?:(?P<start>\\d+:\\d+:\\d+,\\d+) --> (?P<end>\\d+:\\d+:\\d+,\\d+))[\\r\\n](?P<text>(?:.+\\r?\\n)+(?=(\\r?\\n)?))'
CCC_REPLACEMENTS
module-attribute
CCC_REPLACEMENTS = dict(TopLeft='\\an7', TopRight='\\an9', CenterLeft='\\an4', CenterCenter='\\an5', CenterRight='\\an6', BottomLeft='\\an1', BottomRight='\\an3')
CCC_REPLACEMENTS_REDUCED_MARGINS
module-attribute
CCC_REPLACEMENTS_REDUCED_MARGINS = dict(TopLeft=('\\an7', 25, 25), TopRight=('\\an9', 25, 25), CenterLeft=('\\an4', 25, 25), CenterCenter=('\\an5', 25, 25), CenterRight=('\\an6', 25, 25), BottomLeft=('\\an1', 25, 25), BottomRight=('\\an3', 25, 25))
FontFile
FontFile(file: PathLike | Sequence[PathLike] | GlobSearch, container_delay: int = 0, source: PathLike | None = None, tags: dict[str, str] | None = None)
Bases: MuxingFile
Source code in
muxtools/muxing/muxfiles.py
SubFile
SubFile(file: PathLike | Sequence[PathLike] | GlobSearch, container_delay: int = 0, source: PathLike | None = None, tags: dict[str, str] | None = None, encoding: str = 'utf_8_sig')
Bases: BaseSubFile
Utility class representing an ASS/SSA subtitle file with various functions to run on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
PathLike | Sequence[PathLike] | GlobSearch
|
Can be a string, Path object or GlobSearch. If the GlobSearch returns multiple results or if a list was passed it will merge them. |
required |
container_delay
|
int
|
Set a container delay used in the muxing process later. |
0
|
source
|
PathLike | None
|
The file this sub originates from, will be set by the constructor. |
None
|
encoding
|
str
|
Encoding used for reading and writing the subtitle files. |
'utf_8_sig'
|
Source code in
muxtools/subtitle/sub.py
manipulate_lines
set_header
A function to add headers to the "Script Info" section of the subtitle file.
This will validate the input for known functional headers but also allows arbitrary ones.
If you're planning on setting multiple at the same time, use the set_headers function instead to avoid a lot of I/O.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
header
|
str | ASSHeader
|
The name of the header or a header chosen from the enum. |
required |
value
|
str | int | bool | None
|
The value of the header. None will remove the header unless it's the Matrix header because None has a meaning there. |
required |
Source code in
muxtools/subtitle/sub.py
set_headers
A function to add headers to the "Script Info" section of the subtitle file. This will validate the input for known functional headers but also allows arbitrary ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
headers
|
tuple[str | ASSHeader, str | int | bool | None]
|
Any amount of tuples with the same typing as the single header function. |
()
|
Source code in
muxtools/subtitle/sub.py
clean_styles
Deletes unused styles from the document.
Source code in
muxtools/subtitle/sub.py
clean_garbage
Removes the "Aegisub Project Garbage" section from the file.
clean_extradata
Removes the "Aegisub Extradata" section from the file.
clean_comments
autoswapper
autoswapper(allowed_styles: list[str] | None = DEFAULT_DIALOGUE_STYLES, print_swaps: bool = False, inline_marker: str = '*', line_marker: str = '***', inline_tag_markers: str | None = None, exact_names: bool = True) -> Self
autoswapper allows replacing text in the script with a different text. Useful for creating honorific tracks.
Assuming the markers are as default:
{*}abc{*def}becomes{*}def{*abc}(AB Swap)abc{**def}becomesabc{*}def{*}(Show Word)abc{*}def{*}becomesabc{**def}(Hide Word)
Note: AB Swap and Hide Word will remove {} from the swapped text, to ensure the comment isn't broken.
You can also comment in or out entire lines by using the line marker in either the effect or name field.
- A dialogue line with effect or name set to *** will be commented.
- A comment line with effect or name set to *** will be set to a dialogue.
inline_tag_markers can be used to swap ASS tags as well. Keep in mind that "\" and "/" will be swapped, so override tags aren't applied.
Assuming the markers are as default, except inline_tag_markers = []:
- {*}{\i1}abc{*[/b1]def} becomes {*}{\b1}def{*[/i1]abc} (AB Swap)
- abc{**[/b1]def} becomes abc{*}{\b1}def{*} (Show Word)
- abc{*}{\b1}def{*} becomes abc{**[/b1]def} (Hide Word)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
allowed_styles
|
list[str] | None
|
List of allowed styles to do the swapping on (case insensitive)
Will run on every line if passed |
DEFAULT_DIALOGUE_STYLES
|
print_swaps
|
bool
|
Prints the swaps |
False
|
inline_marker
|
str
|
Marker to use for inline swaps.
Should be one character. Default |
'*'
|
line_marker
|
str
|
Marker to use for full-line swaps. Default |
'***'
|
inline_tag_markers
|
str | None
|
Two characters that will be replaced with |
None
|
exact_names
|
bool
|
Match style names in full instead of substring matching as mentioned above. (still case-insensitive) |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
This SubTrack |
Source code in
muxtools/subtitle/sub.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | |
unfuck_cr
unfuck_cr(default_style: str = 'Default', keep_flashback: bool = True, dialogue_styles: list[str] | None = ['main', 'default', 'narrator', 'narration', 'bottomcenter'], top_styles: list[str] | None = ['top'], italics_styles: list[str] | None = ['italics', 'internal'], alt_style: str = 'Alt', alt_styles: list[str] | None = None, exact_names: bool = False, custom_replacements: dict[str, str] | dict[str, tuple[str, int, int]] = CCC_REPLACEMENTS_REDUCED_MARGINS) -> Self
Removes any top/positional and italics styles and replaces them with tags.
Style names are case-insensitive and use substring matching.
i.e. if top_styles=["top"], "MainTop" or "main_top" would both be considered top styles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default_style
|
str
|
The default style that everything will be set to |
'Default'
|
keep_flashback
|
bool
|
If not it will set the flashback styles to default_style |
True
|
dialogue_styles
|
list[str] | None
|
Styles that will be set to default_style |
['main', 'default', 'narrator', 'narration', 'bottomcenter']
|
top_styles
|
list[str] | None
|
Styles that will be set to default_style and an8 added to tags |
['top']
|
italics_styles
|
list[str] | None
|
Styles that will be set to default_style and i1 added to tags |
['italics', 'internal']
|
alt_style
|
str
|
The default alt/overlap style that lines will be set to |
'Alt'
|
alt_styles
|
list[str] | None
|
Possible identifiers for styles that should be set to the alt_style |
None
|
exact_names
|
bool
|
Match style names in full instead of substring matching as mentioned above. (still case-insensitive) |
False
|
custom_replacements
|
dict[str, str] | dict[str, tuple[str, int, int]]
|
Other styles to replace with Default and where custom tags might want to be prepended. If any of these get matched then the other operations will be skipped. Defaults to the positional Styles (with custom margins) that the annoying CCC subs from Crunchyroll have. Keep in mind that the margins of the restyle presets might not look great for these positional styles. The tuple value option stands for (TagsToPrepend, MarginL, MarginR). |
CCC_REPLACEMENTS_REDUCED_MARGINS
|
Source code in
muxtools/subtitle/sub.py
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | |
shift_0
shift_0(timesource: TimeSourceT = None, timescale: TimeScaleT = None, allowed_styles: list[str] | None = DEFAULT_DIALOGUE_STYLES) -> Self
Does the famous shift by 0 frames to fix frame timing issues. (It's basically just converting time to frame and back)
This does not currently exactly reproduce the aegisub behaviour but it should have the same effect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timesource
|
TimeSourceT
|
The source of timestamps/timecodes. For details check the docstring on the type. |
None
|
timescale
|
TimeScaleT
|
Unit of time (in seconds) in terms of which frame timestamps are represented. For details check the docstring on the type. |
None
|
allowed_styles
|
list[str] | None
|
A list of style names this is run on (case-insensitive). Runs on every line if None. |
DEFAULT_DIALOGUE_STYLES
|
Source code in
muxtools/subtitle/sub.py
merge
merge(file: PathLike | GlobSearch | FileMixin, sync: None | int | str = None, sync2: None | str = None, timesource: TimeSourceT = None, timescale: TimeScaleT = None, use_actor_field: bool = False, no_error: bool = False, sort_lines: bool = False, shift_mode: ShiftMode = ShiftMode.FRAME, oob_mode: OutOfBoundsMode = OutOfBoundsMode.ERROR) -> Self
Merge another subtitle file with syncing if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
PathLike | GlobSearch | FileMixin
|
The file to be merged. |
required |
sync
|
None | int | str
|
Can be None to not adjust timing at all, an int for a frame number or a string for a syncpoint name. |
None
|
sync2
|
None | str
|
The syncpoint you want to use for the second file. This is needed if you specified a frame for sync and still want to use a specific syncpoint. |
None
|
timesource
|
TimeSourceT
|
The source of timestamps/timecodes. For details check the docstring on the type. |
None
|
timescale
|
TimeScaleT
|
Unit of time (in seconds) in terms of which frame timestamps are represented. For details check the docstring on the type. |
None
|
use_actor_field
|
bool
|
Checks the actor field instead of effect for the names if True. |
False
|
no_error
|
bool
|
Don't error and warn instead if syncpoint not found. |
False
|
sort_lines
|
bool
|
Sort the lines by the starting timestamp. This was done by default before but may cause issues with subtitles relying on implicit layering. |
False
|
shift_mode
|
ShiftMode
|
Choose what to shift by. Defaults to shifting by frames. |
FRAME
|
oob_mode
|
OutOfBoundsMode
|
What to do with lines that are out of bounds after shifting. |
ERROR
|
Source code in
muxtools/subtitle/sub.py
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 | |
collect_fonts
collect_fonts(use_system_fonts: bool = True, search_current_dir: bool = True, additional_fonts: list[PathLike] = [], collect_draw_fonts: bool = True, error_missing: bool = False, use_ntfs_compliant_names: bool | None = None) -> list[FontFile]
Collects fonts for current subtitle. Note that this places all fonts into the workdir for the episode/Setup and all fonts in it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
use_system_fonts
|
bool
|
Parses and checks against all installed fonts |
True
|
search_current_dir
|
bool
|
Recursively checks the current work directory for fonts |
True
|
additional_fonts
|
list[PathLike]
|
Can be a directory or a path to a file directly (or a list of either) |
[]
|
collect_draw_fonts
|
bool
|
Whether or not to include fonts used for drawing (usually Arial) See https://github.com/libass/libass/issues/617 for details. |
True
|
error_missing
|
bool
|
Raise an error instead of just warnings when a font is missing. This is deprecated and will be removed at some point in the future.
Please use |
False
|
use_ntfs_compliant_names
|
bool | None
|
Ensure that filenames will work on a NTFS (Windows) filesystem.
The |
None
|
Returns:
| Type | Description |
|---|---|
list[FontFile]
|
A list of FontFile objects |
Source code in
muxtools/subtitle/sub.py
restyle
restyle(styles: Style | list[Style], clean_after: bool = True, delete_existing: bool = False, adjust_styles: bool = True) -> Self
Add (and replace existing) styles to the subtitle file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
styles
|
Style | list[Style]
|
Either a single or a list of ass Styles |
required |
clean_after
|
bool
|
Clean unused styles after |
True
|
delete_existing
|
bool
|
Delete all existing styles before adding new ones |
False
|
adjust_styles
|
bool
|
Resize the styles to match the script resolution. This assumes 1080p for the actual style res as all the presets are that. |
True
|
Source code in
muxtools/subtitle/sub.py
resample
resample(video: PathLike | None = None, src_width: int | None = None, src_height: int | None = None, use_arch: bool | None = None, quiet: bool = True) -> Self
Resample subtitles to match the resolution of the specified video.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
video
|
PathLike | None
|
Path to a video. Will resort to a 1080p dummy video if None. |
None
|
src_width
|
int | None
|
The width of the resolution the subs are currently at |
None
|
src_height
|
int | None
|
The height of the resolution the subs are currently at Both of the above params will be taken from the sub file if not given. (Assuming 640 x 360 if nothing is given in the document) |
None
|
use_arch
|
bool | None
|
Uses arch1t3cht's perspective resampler script to fix any perspective stuff after resampling. This requires arch.Resample.moon in either of your autoload folders. None means it will use it if it can find the script. True will try to force it. |
None
|
Source code in
muxtools/subtitle/sub.py
separate_signs
separate_signs(styles: list[str] = DEFAULT_DIALOGUE_STYLES, inverse: bool = False, heuristics: bool = False, print_heuristics: bool = True, exact_names: bool = True) -> Self
Basically deletes lines that have any of the passed styles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
styles
|
list[str]
|
List of style names to get rid of (case-insensitive) |
DEFAULT_DIALOGUE_STYLES
|
inverse
|
bool
|
Treat the list as the opposite. Will remove lines that don't have any of those styles. |
False
|
heuristics
|
bool
|
Also use heuristics for detecting signs. |
False
|
exact_names
|
bool
|
Match style names in full instead of substring matching as mentioned above. (still case-insensitive) |
True
|
Source code in
muxtools/subtitle/sub.py
change_layers
change_layers(styles: list[str] = DEFAULT_DIALOGUE_STYLES, layer: int | None = None, additive: bool = True) -> Self
Set layer to the specified number or adds the number to the existing one on every line with a style you selected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
styles
|
list[str]
|
List of styles to look for (case-insensitive) |
DEFAULT_DIALOGUE_STYLES
|
layer
|
int | None
|
The layer you want. Defaults to 50 for additive and 99 otherwise. |
None
|
additive
|
bool
|
Add specified layer number instead of replacing the existing one. |
True
|
Source code in
muxtools/subtitle/sub.py
purge_macrons
Removes romaji macrons from every dialogue line. German subs use this a lot and a lot of fonts don't support it, so I like to purge them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
styles
|
list[str] | None
|
List of styles to look for (case-insensitive). Runs on all styles if None. |
DEFAULT_DIALOGUE_STYLES
|
Source code in
muxtools/subtitle/sub.py
shift
shift(frames: int, timesource: TimeSourceT = None, timescale: TimeScaleT = None, oob_mode: OutOfBoundsMode = OutOfBoundsMode.ERROR, before: int | None = None, after: int | None = None) -> Self
Shifts all lines by any frame number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frames
|
int
|
Number of frames to shift by. |
required |
timesource
|
TimeSourceT
|
The source of timestamps/timecodes. For details check the docstring on the type. |
None
|
timescale
|
TimeScaleT
|
Unit of time (in seconds) in terms of which frame timestamps are represented. For details check the docstring on the type. |
None
|
oob_mode
|
OutOfBoundsMode
|
What to do with lines that are out of bounds after shifting. |
ERROR
|
before
|
int | None
|
Only shift timestamps before or equal to this frame number. |
None
|
after
|
int | None
|
Only timestamps after or equal to this frame number. |
None
|
Source code in
muxtools/subtitle/sub.py
copy
Creates a new copy of the current SubFile object, including its file. So you can run anything on the new one without impacting the other one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
PathLike
|
Use a specific filename for this copy. Don't include an extension. If this is a dir it will have the same name and be placed in the dir. |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
A new SubFile instance |
Source code in
muxtools/subtitle/sub.py
from_srt
classmethod
from_srt(file: PathLike, an8_all_caps: bool = True, style_all_caps: bool = True, timesource: TimeSourceT = Fraction(24000, 1001), timescale: TimeScaleT = TimeScale.MKV, encoding: str = 'UTF8') -> Self
Convert srt subtitles to an ass SubFile. Automatically applies Gandhi styling. Feel free to restyle. Also worth noting that this creates a file that assumes 1920x1080. Use the resample function if you need something else.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
PathLike
|
Input srt file |
required |
an8_all_caps
|
bool
|
Automatically an8 every full caps line with over 7 characters because they're usually signs. |
True
|
style_all_caps
|
bool
|
Also set the style of these lines to "Sign" wether it exists or not. |
True
|
timesource
|
TimeSourceT
|
The source of timestamps/timecodes. For details check the docstring on the type. |
Fraction(24000, 1001)
|
timescale
|
TimeScaleT
|
Unit of time (in seconds) in terms of which frame timestamps are represented. For details check the docstring on the type. |
MKV
|
encoding
|
str
|
Encoding used to read the file. Defaults to UTF8. |
'UTF8'
|
Source code in
muxtools/subtitle/sub.py
from_mkv
classmethod
from_mkv(file: PathLike, track: int = 0, preserve_delay: bool = False, quiet: bool = True, **kwargs: Any) -> Self
Extract subtitle from mkv.
The track must be either an ASS or SRT subtitle. SRT will be converted automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
PathLike
|
Input mkv file |
required |
track
|
int
|
Relative track number |
0
|
preserve_delay
|
bool
|
Preserve existing container delay |
False
|
kwargs
|
Any
|
Other args to pass to |
{}
|