| ass_add_lineA | Append a new line. start_ms/end_ms accept milliseconds or time strings such as
"0:00:01.50"; they are clamped into the document timebase and
end < start is an error. Lines are appended at the end of the document
and the returned index is its 0-based position. The call is
snapshot-backed, so :func:ass_undo reverts it.
Returns {"doc_id", "index", "line": <line dict>}. |
| ass_add_linesA | Append several lines in one call. lines is a list of dicts using the :func:ass_add_line keys
(start_ms/end_ms/text/style/actor/effect/layer/
comment/margin_l/margin_r/margin_v) plus an optional
index — the 0-based position the new line is inserted at. Insertion
positions refer to the line list as it is being built (the previous inserts
of this same call are already in place); lines without index go to the
end. All times accept milliseconds or time strings.
Returns {"doc_id", "indices": [<0-based index per input dict>], "count", "lines": [<line dict>, ...]}. |
| ass_closeA | Close a document (optionally saving it first). Args:
doc_id: document to close; the current one when omitted.
save: save before closing (requires a known path). Returns {"doc_id", "closed", "saved", "path", "remaining", "current"}.
Line indices are 0-based. |
| ass_delete_linesA | Delete the selected lines. selection is any selection spelling; None means every line (use with
care). Returns {"doc_id", "deleted": [<0-based indices>], "count", "remaining"}. Snapshot-backed.
|
| ass_document_infoA | Detailed information about one document. Args:
doc_id: document to describe; the current one when omitted. Returns the document summary (see :func:ass_open) extended with
section_kinds, section_headers, section_order (aliases of each
other, in file order), style_names, font_names, graphic_names,
event_count, comment_count, dialogue_count, duration_ms
(sum of dialogue durations), span_ms (last end minus first start),
start_ms/end_ms of the first/last line, info (Script Info keys),
format_order, wrapping, attachments and extradata_count.
Line indices are 0-based. |
| ass_duplicate_linesA | Duplicate the selected lines. Args:
selection: selection spelling; None = all lines.
offset_ms: shift the copies in time by this many ms.
insert_after: put each copy right after (True) or right before
(False) its source. Copies keep every field of the source (style, actor, effect, layer, margins,
comment flag, tags). Returns {"doc_id", "indices": [<0-based index of each copy>], "count", "lines": [...]}. Snapshot-backed. Indices are
0-based. |
| ass_export_textA | Export selected lines as plain text, TSV, SRT or an ASS fragment. Args:
selection: selection spelling; None = every line.
doc_id: document to export; the current one when omitted.
format: "txt" (one line of plain text each), "tsv" (start, end,
style, actor, effect, kind, plain text), "srt" (SubRip) or
"ass-fragment" (the raw Dialogue:/Comment: lines).
line_separator: replacement for the ASS in-line hard break \N (and
\n) in txt/tsv output. The default keeps the ASS escape
for lossless re-import; pass "\n" for one output line per
visual line, or any other string ("|") to flatten explicitly.
srt always uses real newlines (required by the format) and
ass-fragment keeps the original text untouched.
output_path: file to write; when omitted the file is written into
workspace.output_dir (created if needed). txt and srt skip comment lines; tsv and ass-fragment keep
them. Returns {"doc_id", "path", "format", "media_type", "text", "bytes", "line_count", "selection": [<0-based indices>]} where line_count is the
number of exported records (SRT blocks, TSV rows, text lines, events).
|
| ass_find_replaceA | Find and replace text across the selected lines. Args:
pattern: literal text (regex=False) or a Python regular expression
(regex=True, compiled with re.UNICODE; back-references like
\1 work in replacement).
replacement: replacement string (used literally when regex=False).
selection: selection spelling; None = every line.
doc_id: document to edit; the current one when omitted.
regex: treat pattern as a regular expression.
case_sensitive: False makes the match case-insensitive.
fields: which fields to touch; defaults to ["text"]. Any of
text, start, end, style, actor/name,
effect.
dry_run: count only, change nothing.
limit: stop after this many replacements in total. Returns {"doc_id", "pattern", "replacement", "fields", "regex", "dry_run", "total": <replacements made>, "changed": [<0-based indices>], "lines": [{"index", "counts": {field: n}, "count", "text"}...], "limit"}. Snapshot-backed unless dry_run. Indices are 0-based. |
| ass_get_lineB | Full detail for a single line (0-based index). Returns the ass_list_lines line dict extended with: fields — every field of the line exactly as stored.
tags_summary — override-tag counts/structure.
drawing — {"active", "state", "segments", "drawing_segments", "prefix", "path", "suffix"}.
karaoke — {"has_karaoke", "kinds", "total_ms", "syllables"} with
per-syllable start/end times resolved against the line timing.
style/resolved_style — the style name, and the same name only when
that style actually exists in the document (else None).
timing — {"start_ms", "end_ms", "duration_ms", "start", "end", "cps", "characters", "lines"}.
Line indices are 0-based. |
| ass_get_selectionA | Read back the session selection. Returns {"doc_id", "selection": [<0-based indices>], "count", "lines": [<line dicts, same shape as ass_list_lines>]} and drops indices
that are out of range for the current document. Line indices are 0-based. |
| ass_import_srtA | Import a SubRip (.srt) file as new ASS lines. Handles , and . decimal separators, multi-line blocks, CRLF and a
UTF-8 BOM; multi-line subtitle bodies become \N hard breaks. Args:
path: the .srt file to read.
doc_id: document to append to; the current one when omitted.
style: ASS style for the imported lines.
offset_ms: shift every imported line in time. Returns {"doc_id", "path", "count", "indices": [<0-based indices>], "lines": [<dict>], "skipped": <blocks without a timestamp>, "style", "offset_ms"}. Snapshot-backed. |
| ass_list_documentsB | List the open documents. Returns {"documents": [{"doc_id", "path", "dirty", "lines", "encoding", "current"}...], "ids": [...], "current", "count"}. Line indices are
0-based. |
| ass_list_linesA | List lines with paging. Args:
selection: selection spelling (see module docstring); None means all
lines.
doc_id: document to read; the current one when omitted.
offset: number of selected lines to skip (0-based).
limit: maximum number of lines to return; None returns the rest.
include_tags_summary: add a tags_summary dict (tag counts, drawing
flag, karaoke/clip/transform lists) per line.
include_plain_text: include the plain_text field (tags stripped). Returns {"doc_id", "total", "offset", "limit", "returned", "indices", "lines"} where lines are event_dict style dicts: index,
kind, start, end, start_ms, end_ms, duration_ms,
style, actor, effect, layer, margin_l/r/v, text
(raw, tags included), plain_text, comment, drawing, cps.
Indices are 0-based. |
| ass_merge_linesA | Merge the selected lines into the earliest one. The selected lines are sorted by start (then end) time and their raw texts
are joined with separator (default the literal \N) into the
earliest-starting line, which keeps its style, actor, effect, layer and
margins; its span becomes the union of the merged spans. The other
selected lines are removed. Needs at least two lines. Returns {"doc_id", "index": <0-based index of the merged line *after* the merge>, "removed": [<pre-merge 0-based indices of the lines folded away>], "removed_count", "start_ms", "end_ms", "text", "line": <dict>}.
Snapshot-backed. |
| ass_move_linesA | Move the selected lines to another position in the line order. target_index is the 0-based slot in the remaining lines (the
selection is removed first) where the moved block is inserted; it is clamped
to the list length, so a large value appends. Returns {"doc_id", "moved": [old 0-based indices], "target_index", "selection": [new 0-based indices], "count"}. Snapshot-backed.
|
| ass_new_documentA | Create (and register) an empty ASS document. Args:
play_res_x / play_res_y: PlayResX / PlayResY of the new script.
doc_id: optional registry id; one is generated when omitted.
script_type: "v4.00+" (ASS, default) or "v4.00" (SSA). Returns the same summary as :func:ass_document_info minus the document
statistics: doc_id, path, dirty, script_type,
play_res_x, play_res_y, fps, lines, dialogue,
comments, styles, sections, encoding, has_bom,
newline. Line indices are 0-based. |
| ass_openA | Open an ASS/SSA file and make it the current document. Args:
path: file to open. A missing file raises ToolError.
doc_id: optional registry id for the opened document.
encoding: force this encoding instead of the automatic sniff; the file
must decode with it or ToolError is raised. Returns the document summary (doc_id, path, dirty,
script_type, play_res_x, play_res_y, fps, lines,
dialogue, comments, styles, sections, encoding,
has_bom, newline). Line indices are 0-based. |
| ass_redoB | Redo the last undone change. Returns {"doc_id", "redone", "undo_depth", "redo_depth", "dirty"};
redone is False when the redo stack is empty. Line indices are
0-based. |
| ass_saveA | Write a document to disk and report exactly what was written. Args:
doc_id: document to save; the current one when omitted.
path: destination; the document's known path when omitted.
encoding: encoding override for this write.
bom: force the UTF-8/UTF-16 BOM on/off (None keeps the current one).
newline: "\n" / "\r\n" / "\r" override.
create_backup: copy the previous file to <path>.bak first. Returns {"doc_id", "path", "bytes_written", "sha256", "changed", "encoding", "has_bom", "newline", "backup"}. changed is true when the
bytes written differ from whatever was on the destination beforehand (a
brand new destination counts as changed); has_bom is derived from the
bytes actually written. Line indices are 0-based. |
| ass_save_allA | Save every open document that has a known path. Returns {"saved": [<result of ass_save>, ...], "count", "skipped": [doc_id, ...], "errors": [{"doc_id", "error"}, ...], "current"}. Documents created in memory and never saved are reported in
skipped rather than failing the whole call. Line indices are 0-based. |
| ass_selectA | Update the session selection used by "selection". Args:
spec: any selection spelling accepted by base.resolve_indices —
"all"/None, "0-4,7", 5, [0, 2],
{"style": "Default"}, {"text_contains": "hi"}, ...
mode: "set" (replace), "add", "remove" or "toggle". Returns {"doc_id", "mode", "selection": [<0-based indices>], "count"}.
Line indices are 0-based. |
| ass_select_documentA | Make doc_id the current document (clearing the session selection). Returns the document summary; see :func:ass_open. Line indices are
0-based. |
| ass_set_commentA | Convert lines between Dialogue: and Comment:. Args:
selection: selection spelling; None = every line.
comment: True converts to Comment:, False back to
Dialogue:.
drop: delete the selected lines instead of converting them. Returns {"doc_id", "changed": [<0-based indices>], "count", "comment", "dropped"}. Snapshot-backed. Indices are 0-based. |
| ass_sort_linesA | Sort the selected lines in place (document.reorder_events). Args:
selection: selection spelling; None = every line.
keys: sort keys, applied in order; defaults to ["start", "end"].
One of start, end, duration, style, actor/
name, effect, layer, text, comment.
reverse: sort descending. Only the selected lines move: they are re-shuffled among the slots they
already occupy, so unselected lines keep their positions. Returns {"doc_id", "sorted", "selection": [<0-based indices sorted>], "count", "moved": {old 0-based index: new 0-based index}}. |
| ass_split_lineA | Split one line in two at a time strictly inside its span. index is 0-based. at_ms accepts milliseconds or a time string
and must satisfy start < at_ms < end, otherwise ToolError. The cut
sits at the visible character whose position matches the time fraction (each
half keeps at least one visible character). The first half keeps the
original line's text up to the cut; the second half is a new line right
after it that repeats every override block preceding the cut (so {\i1}
prefixes survive) and keeps style, actor, effect, layer and margins.
Returns {"doc_id", "index", "second_index", "at_ms", "first": <dict>, "second": <dict>}. Snapshot-backed. |
| ass_statsC | Statistics for a document. Returns {"doc_id", "path", "lines", "dialogue", "comments", "characters", "words", "total_duration_ms", "average_cps", "mean_line_cps", "min_line_cps", "max_line_cps", "slowest": {"index", "cps"} | None, "style_histogram", "style_names", "actor_histogram", "actors", "over_cps_25", "lines_over_25", "empty_lines", "drawing_lines", "karaoke_lines", "duration_ms", "span_ms"}. average_cps is total characters over total dialogue
duration; the per-line figures only consider lines with a positive duration.
Indices are 0-based. |
| ass_undoB | Undo the last snapshot-backed change of a document. Returns {"doc_id", "undone", "undo_depth", "redo_depth", "dirty"}.
undone is False when the undo stack is empty. Line indices are
0-based. |
| ass_undo_historyA | List the undo steps available for a document. The workspace keeps raw document snapshots and no labels, so the entries are
positional: step 1 is the oldest available snapshot, the highest step is
what :func:ass_undo would restore next. Each entry carries a summary of
the snapshot (line count, first start time, line count difference from the
current state) so it is still possible to tell the steps apart. Returns {"doc_id", "undo_depth", "redo_depth", "entries": [{"step", "label", "lines", "first_start"}...], "redo_entries": [...], "next_undo", "next_redo"}. Line indices are 0-based. |
| ass_update_lineA | Change individual fields of one line; only the fields you pass change. index is 0-based. Times accept milliseconds or time strings.
comment=True turns the line into a Comment:, False back into a
Dialogue:. The call is snapshot-backed (:func:ass_undo reverts it).
Returns {"doc_id", "index", "changed": [field names], "line": <dict>}. |
| ass_update_linesA | Change the same fields on every selected line. Args:
selection: selection spelling (see module docstring); None = all.
doc_id: document to edit; the current one when omitted.
start_ms/end_ms/text/style/actor/effect/layer/comment/margin_l/margin_r/
margin_v: applied only to the lines you pass, as in
:func:ass_update_line.
pad_ms: widen every selected line by this many ms on both sides
(start -= pad_ms, end += pad_ms); negative values trim it.
clamp_to_avoid_overlap: after the edit, pull each selected line's times
back so it no longer overlaps an unselected line (best effort;
worst case a 10 ms line is left in the gap). Returns {"doc_id", "changed": [<0-based indices>], "count", "clamped": [<0-based indices>], "fields": [field names], "lines": [<dict>, ...]}. Snapshot-backed. Line indices are 0-based. |
| ass_list_stylesA | List every style in the document. Args:
doc_id: document id or None for the current document.
include_usage: add used (bool) and usage
({total, dialogue, comment}) to each style, counted over all
event lines (comments included).
include_bbox: render the sample text :data:BBOX_SAMPLE in each style
with libass and add bbox — the ink box in script coordinates
({x, y, x1, y1, width, height}) — plus bbox_error when the
measurement could not be produced (for example no ffmpeg/libass). Returns:
{"doc_id", "count", "styles": [ ... ]} where each style dict holds
every ASS field exactly as stored (Name, Fontname,
Fontsize ... Encoding, colours verbatim), plus index,
section (its [V4+ Styles]/[V4 Styles] header) and
extra_fields (vendor columns not in the ASS vocabulary). |
| ass_get_styleA | Inspect one style, including the font it really resolves to. Args:
name: style name (case-insensitive).
doc_id: document id or None for the current document.
include_glyphs: add a glyphs report (approximate Aegisub "characters
not in font" check via fontconfig) for sample_text.
sample_text: text used for the glyph report. When omitted it defaults
to the plain text of the lines that use the style (capped at 2000
characters). Returns:
{"doc_id", "name", "style", "values", "font", "used", "usage"} —
style holds every ASS field as stored, values the typed view
(numbers/flags, colours verbatim), font the fontconfig resolution:
{requested, bold, italic, available, resolved, resolved_style, file, index, substituted, candidates, error}. With include_glyphs adds
glyphs ({font, missing, fallbacks, covered, checked, coverage_source}) and glyph_sample_text. |
| ass_add_styleA | Create a style, or replace an existing one of the same name. Every value is stored verbatim (/48.0 becomes 48); colour values
given as #RRGGBB are converted into the spelling the document already
uses for that field. Values are validated before anything is written:
font_size must be positive, alignment 1-9, border_style 1 or 3,
margins whole numbers and colours a spelling the document can store. overwrite=True replaces the style: every field is (re)written from
the arguments, so fields left at their defaults go back to those defaults
rather than keeping the old value — use ass_update_style to change a
few fields and leave the rest alone. relative_to is Aegisub's
style-manager setting: it is only written when the document's Format
line already declares a RelativeTo column, otherwise it is listed in
ignored_fields (adding the column would desynchronise the Format
line).
Returns:
{"doc_id", "name", "created", "style", "fields_set", "ignored_fields"} — created is False when overwrite=True
replaced an existing style. |
| ass_update_styleA | Change only the fields that are given, on an existing style. Field names may be written in any spelling: the snake_case parameters above,
the ASS column names (Fontname=, Fontsize=, PrimaryColour=,
MarginV= ...) or any case/space variant — all of them resolve to the
same canonical field. Passing new_name (or Name=) renames the
style and, when update_lines semantics apply, repoints the lines that
used it (this always happens, exactly like ass_rename_style). Args:
name: the style to update (case-insensitive).
doc_id: document id or None for the current document.
aliases: any further field=value pairs, e.g. Fontsize=60. Returns:
{"doc_id", "name", "previous_name", "changed", "style", "lines_updated", "ignored_fields"}. changed maps each field to
{"from", "to"} in stored form; ignored_fields lists values the
document's Format line cannot hold (for example ScaleX in a
[V4 Styles] file). |
| ass_remove_styleA | Delete a style, refusing to orphan lines that still use it. Args:
name: style to delete.
doc_id: document id or None for the current document.
reassign_to: when the style is still used, the name of the style the
lines should be moved to before the style is deleted. Without it a
used style is an error. Returns:
{"doc_id", "name", "removed", "reassigned", "reassign_to"} where
reassigned is the number of lines repointed. |
| ass_rename_styleA | Rename a style and (by default) rewrite the lines that reference it. Args:
old_name: existing style name.
new_name: new name; must not collide with another style.
doc_id: document id or None for the current document.
update_lines: when true, every line whose Style field equals
old_name is rewritten to new_name. Returns:
{"doc_id", "old_name", "new_name", "lines_updated", "style"}. |
| ass_copy_styleB | Copy a style, field for field, under a new name. Args:
source: style to copy.
new_name: name for the copy.
doc_id: document id or None for the current document.
overwrite: replace an existing style of that name instead of failing. Returns:
{"doc_id", "source", "name", "created", "style", "ignored_fields"}. |
| ass_reorder_stylesB | Reorder the style section. Args:
order: the complete list of style names in their new order (a
comma-separated string is also accepted). It must be a permutation
of the styles already present — missing, unknown or duplicated names
are reported in the error.
doc_id: document id or None for the current document. Returns:
{"doc_id", "order", "count"} with the resulting order. |
| ass_style_usageA | Count how styles and actors are used, and name the unused styles. Args:
doc_id: document id or None for the current document.
by: which grouping goes in counts: "style", "actor" or
"effect". Returns:
{"doc_id", "by", "counts", "by_style", "by_actor", "unused_styles", "unknown_styles", "lines"}. Each count bucket is
{"name", "total", "dialogue", "comment"}; unknown_styles maps a
style referenced by lines but absent from the style section to its line
count. |
| ass_style_for_lineA | Effective style values for one line, inline override tags included. The line's Style field is resolved to a style; on top of it the inline
override tags that change font, size, colour, weight, scale, spacing,
border, shadow or alignment are applied, so the caller sees what libass
would actually use. \r/\rStyle restarts from a (possibly other)
style, exactly as the renderer does. Args:
index: 0-based line index in doc.events() order (comments included).
None uses the session selection (ass_select), falling back to
its first index.
doc_id: document id or None for the current document. Returns:
{"doc_id", "index", "style", "style_found", "style_definition", "resolved", "runs", "overrides", "transforms", "warnings", "text", "plain_text"}.
resolved is the typed effective state at the first visible
character; runs splits the visible text into
{start, end, values, sources, style} spans with identical values;
overrides lists the field names that inline tags modified;
transforms lists the \t(...) tags (animation is reported, not
folded into the numbers); colours stay in the spelling the tag/style
used. |
| ass_check_font_substitutionA | Compare every style's requested font with the family fontconfig resolves. Args:
doc_id: document id or None for the current document. Returns:
{"doc_id", "fontconfig", "checked", "substituted", "substitutions", "styles"}. Each entry of styles is
{"name", "requested", "bold", "italic", "resolved", "resolved_style", "file", "substituted", "candidates", "available", "error"};
substitutions lists the style names whose request is substituted,
which is exactly the set of styles that will not render in the font
they ask for. |
| ass_get_script_infoC | Read [Script Info] in file order. Returns:
{"doc_id", "count", "items", "ordered", "values", "duplicates"}.
items is one {"index", "key", "value", "raw", "duplicate"} per
key line, in the order they appear in the file (raw is the line
exactly as stored, so odd spacing such as Title : x survives);
ordered is [[key, value], ...]; values the last-wins map;
duplicates lists keys that appear more than once. |
| ass_set_script_infoA | Set, insert or reposition-free-update a [Script Info] key. Args:
key: the key, e.g. "Title". Matching is case- and
space-insensitive, and the spelling already in the file is kept.
value: new value (converted with str; must not contain a newline).
doc_id: document id or None for the current document.
before: when the key does not exist yet, insert it immediately before
this existing key instead of appending at the end. Returns:
{"doc_id", "key", "value", "created", "index"} where index is
the entry position inside [Script Info]. |
| ass_remove_script_infoB | Remove a [Script Info] key. Returns {"doc_id", "key", "removed"} (removed is False when the key
was not present). |
| ass_set_play_resC | Set PlayResX/PlayResY. Returns {"doc_id", "play_res_x", "play_res_y", "previous_x", "previous_y"}. |
| ass_set_wrap_styleB | Set WrapStyle using Aegisub's numeric codes. Args:
style: 0 smart, 1 end of line, 2 no wrapping, 3 bottom
of line only. The names are accepted too.
doc_id: document id or None for the current document. Returns:
{"doc_id", "wrap_style", "name", "previous"}. |
| ass_set_scaled_border_and_shadowC | Set ScaledBorderAndShadow (yes/no). Returns {"doc_id", "value", "enabled", "previous"}. |
| ass_set_timing_infoA | Set the timing source keys Aegisub stores in [Script Info]. fps writes FPS, video_file writes Video File and
timecodes_file writes Timecodes File. Passing an empty string for a
path removes that key. Calling the tool with no arguments at all changes
nothing and just reports the three keys as they currently are (changes
is then empty), which is the only way to read timing info.
Returns:
{"doc_id", "fps", "video_file", "timecodes_file", "changes"} with
the resulting values (None when a key is absent) and a
changes map of key -> {"from", "to"}. |
| ass_list_attachmentsA | List [Fonts]/[Graphics] attachments with a magic-byte sniff. Args:
doc_id: document id or None for the current document.
kind: "font"/"fonts" or "image"/"graphics" to restrict
the listing; None returns both sections. Returns:
{"doc_id", "count", "attachments": [ ... ]}. Each attachment has
name, kind (the declared kind), section, key,
data_lines, encoded_chars, decoded (is the payload valid
base64), size (exact decoded size, or encoded*3/4 when the data
is not valid base64 — size_exact says which), sha256,
magic (first 8 decoded bytes, hex), sniff (font, image
or unknown from the magic bytes), line_indices and error. |
| ass_add_attachmentA | Attach a file to the document, base64-encoded, like Aegisub's attach menu. Args:
path: file to attach (read from disk; the only filesystem input of this
module besides the workspace itself).
doc_id: document id or None for the current document.
name: name stored in the document; defaults to the file's basename.
kind: "font" or "image"; inferred from the magic bytes, falling
back to the file extension, when omitted. Returns:
{"doc_id", "name", "kind", "section", "path", "bytes", "base64_lines", "sniff", "replaced"}. An attachment with the same
name in the same section is replaced (replaced is True). |
| ass_extract_attachmentA | Decode an attachment and write it into the workspace output directory. Args:
name: attachment name as stored in the document (case-insensitive).
doc_id: document id or None for the current document.
output_path: destination; a relative path is resolved inside
workspace.output_dir. Returns:
{"doc_id", "name", "kind", "path", "bytes", "sha256", "sniff"}. |
| ass_remove_attachmentB | Remove an attachment (its name line and every payload line). Returns {"doc_id", "name", "removed", "lines_removed"}. |
| ass_list_extradataC | List [Aegisub Extradata] entries. Returns:
{"doc_id", "count", "entries"} where each entry is
{"index", "head", "label", "id", "value", "raw", "layout"}
(index is the position inside the section, label the record's
numeric label, id the stored identifier). |
| ass_set_extradataA | Set or remove one [Aegisub Extradata] entry (idempotent). Args:
ident: the entry identifier (matched case-insensitively).
value: value to store; may be omitted when remove=True.
doc_id: document id or None for the current document.
remove: delete every entry with this identifier instead of setting it. Returns:
{"doc_id", "id", "value", "removed", "created"}; setting an
existing identifier updates it in place (never duplicates it). |
| ass_validateA | Structural validation of the whole document. Args:
doc_id: document id or None for the current document. Returns:
{"doc_id", "ok", "counts", "issues"}. ok is True when no issue
has severity error. Every issue is
{"code", "severity", "kind", "index", "message"}; kind says what
index refers to: ``script_info`` index into the ``[Script Info]`` entries
``style`` index into ``doc.styles()``
``line`` 0-based line index in ``doc.events()`` order
``section`` index into ``doc.sections``
``document`` ``index`` is ``None``
Codes: ``duplicate_style_name`` (error), ``duplicate_script_info_key``
(warning), ``missing_script_type`` (warning), ``missing_style`` (error),
``end_before_start`` (error), ``zero_duration`` (warning),
``invalid_timestamp`` (error), ``comments_only_style`` (warning),
``unknown_section`` (warning), ``unknown_record`` (warning),
``malformed_line`` (warning), ``malformed_raw_line`` (warning) and
``field_count_mismatch`` (error).
|
| ass_align_lines_to_silenceA | Move line starts out of audio silence (ffmpeg silencedetect). A line whose start falls inside a silent interval is pushed to the end of
that interval: shift_only="both" (default) moves the end by the same
delta, "start" keeps the end where it is and shortens the line. Lines
that start on audio are left alone and are not reported as suggestions. Args:
selection: lines to consider.
video: media file; defaults to the workspace video/audio.
noise_db: silence threshold in dBFS.
min_silence_s: shortest silence to act on.
doc_id: document id.
dry_run: when True (the default) the plan is returned and nothing is
written.
shift_only: None/"both" or "start".
max_shift_ms: ignore suggestions longer than this. Returns:
The same plan as :func:ass_align_to_silence plus "dry_run" and
"applied" so the caller always knows whether the document changed. |
| ass_align_to_silenceA | Report audio silence intervals and the per-line shifts they suggest. This tool never modifies the document — it exists so an agent can look
before it leaps; :func:ass_align_lines_to_silence applies the same plan
when dry_run=False. Args:
selection: lines to consider.
video: media file; defaults to the workspace video/audio.
noise_db: silence threshold in dBFS (passed to silencedetect).
min_silence_s: shortest silence to report.
doc_id: document id.
shift_only: None/"both" shift start and end together, "start"
moves only the start (shortening the line).
max_shift_ms: ignore suggestions longer than this. Returns:
{"doc_id", "path", "noise_db", "min_silence_s", "shift_only", "max_shift_ms", "silences": [{"start_ms", "end_ms", "duration_ms"}], "suggestions": [{"index", "start_ms", "end_ms", "new_start_ms", "new_end_ms", "delta_ms", "silence", "reason"}], "count", "applied": False, "note"} |
| ass_check_overlapsA | List overlapping pairs of lines, ordered by start time. With layer_strict=True (the default) only lines on the same layer are
compared — two lines on different layers are meant to coincide. Comment
lines never render, so they are not considered. Args:
selection: lines to compare.
doc_id: document id.
layer_strict: compare within each layer only.
tolerate_ms: ignore overlaps of this length or less. Returns:
{"doc_id", "layer_strict", "tolerate_ms", "count", "pairs": [{"a", "b", "layer", "a_start_ms", "a_end_ms", "b_start_ms", "b_end_ms", "overlap_ms"}]} |
| ass_cpsB | Characters per second for every selected line plus the totals. Args:
selection: lines to measure; None/[] means every line.
doc_id: document id. Returns:
{"doc_id", "count", "lines": [{"index", "kind", "characters", "duration_ms", "cps", "drawing", "start_ms", "end_ms"}], "totals": {"characters", "duration_ms", "average_cps", "max_cps", "worst_index"}} |
| ass_fix_timingA | Compute timing fixes and apply them only when dry_run is False. Only end times move. A line shorter than min_duration_ms is extended to
it; a line reading faster than max_cps/target_cps is extended so that
its characters per second fall back to that figure. With avoid_overlap
an extension stops at the next line's start on the same layer, minus
keep_gaps_ms; when there is no room the fix is reported as blocked
instead of being applied. Args:
selection: lines to fix.
doc_id: document id.
dry_run: True (default) returns the plan and writes nothing.
min_duration_ms: shortest acceptable duration.
target_cps: extend faster lines until they read at this rate.
max_cps: same, used when target_cps is not given.
avoid_overlap: stop extensions at the neighbouring line.
keep_gaps_ms: keep this much room before the neighbouring line. Returns:
{"doc_id", "dry_run", "applied", "parameters": {...}, "count", "changes": [{"index", "field", "old_ms", "new_ms", "old", "new", "reason"}], "blocked": [{"index", "reason", "wanted_ms", "limit_ms"}]} |
| ass_frame_from_msA | Convert a time in milliseconds to a frame number. Args:
ms: milliseconds (int/float) or a time string.
fps: frame rate; resolution order is fps argument, workspace video
(dict fps or a probed video path), workspace script config,
document FPS in [Script Info], then a ToolError explaining what
is missing.
doc_id: document id (only used as an fps source). Returns:
{"ms", "seconds", "fps", "fps_source", "frame", "frame_exact", "frame_floor", "frame_ceil"} |
| ass_frame_from_timecodesA | The start time of frame according to the loaded timecodes file. Honours workspace.timecodes (written by :func:ass_read_timecodes) and
falls back to the document/workspace frame rate when no file is loaded;
method says which of the two was used. Both coordinates are returned so
the pair is unambiguous. Args:
frame: frame number.
doc_id: document id, only needed for the fps fallback. Returns:
{"frame", "ms", "seconds", "method", "input", "input_kind", "exact_ms"} |
| ass_load_keyframesA | Load video keyframes into workspace.keyframes (milliseconds). Args:
path: media file. When omitted the workspace video is probed with
render.keyframes.
doc_id: document id; only used as an fps source when frames is given.
frames: explicit frame numbers to convert (needs an fps).
times_ms: explicit keyframe times in milliseconds — used verbatim. Returns:
{"source", "path", "count", "keyframes_ms", "first_ms", "last_ms"} |
| ass_ms_from_frameB | Convert a frame number to its start time in milliseconds. See :func:ass_frame_from_ms for the fps resolution order. Returns:
{"frame", "fps", "fps_source", "ms", "seconds"} |
| ass_ms_from_timecodesB | The frame that contains ms according to the loaded timecodes file. Mirror of :func:ass_frame_from_timecodes; method reports whether the
loaded timecodes or the fallback frame rate was used, and ms is the start
time of the resulting frame. Args:
ms: milliseconds (int/float) or a time string.
doc_id: document id, only needed for the fps fallback. Returns:
{"ms", "frame", "frame_exact", "frame_floor", "frame_ceil", "frame_start_ms", "method", "input", "input_kind"} |
| ass_qcA | QA a selection of lines and return a structured issue report. cps is the number of visible characters — override tags are stripped and
line breaks are not counted — divided by the line's duration in seconds.
Drawing lines ({\\p1}) carry no readable text, so they are skipped by the
text checks and reported once each as an info issue with code
drawing_line.
Args:
selection: lines to check; None/[] means every line.
doc_id: document id.
cps_warn: cps at or above which a line is cps_high (warning).
cps_max: cps at or above which a line is cps_extreme (error).
min_duration_ms: shorter lines are too_short (warning).
max_duration_ms: longer lines are too_long (warning).
max_chars: more visible characters is too_many_chars (warning).
max_lines: more \N-breaks is too_many_lines (warning).
check_overlaps: report overlap_same_layer for lines on the same layer
(different layers never overlap by design).
check_gaps: report gap_tiny for same-layer gaps below 100 ms.
check_empty: report empty_text.
check_styles: report style_missing for styles the document lacks.
check_tags: report unclosed_override_block and unknown_tag. Returns:
{"doc_id", "parameters": {...}, "summary": {"lines_checked", "dialogue", "comments", "drawings", "issues", "errors", "warnings", "infos", "by_code": {...}, "ok", "clean"}, "issues": [{"code", "severity", "index", "message", "details"}]} — ok is False when any
error was found, clean is True only when there are no issues at all.
Issues are sorted by line index then code. |
| ass_read_timecodesA | Parse an Aegisub timecodes file (v1 or v2) and store it on the workspace. Args:
path: path to the .txt/.timecodes file. Returns:
{"path", "version", "default_fps", "fps_changes", "times_ms", "frame_count", "duration_ms", "segments": [{"start_frame", "end_frame", "start_ms", "end_ms", "fps"}]}. v1 files have default_fps and
fps_changes ([{"start_frame", "end_frame", "fps"}]); v2 files
have the per-frame times_ms list. The result is also kept on
workspace.timecodes so the conversion tools can honour it. Malformed input raises a ToolError naming the offending 1-based line number. |
| ass_reading_speedB | Reading speed of a single line. Args:
index: 0-based line index.
doc_id: document id. Returns:
{"doc_id", "index", "kind", "start_ms", "end_ms", "duration_ms", "characters", "lines", "drawing", "cps", "plain_text"} — cps is
None when the line has no duration (and 0.0 when it has no text). |
| ass_scale_timesA | Scale the timing of the selection around an origin. new = origin + (old - origin) * factor is applied to both the start and
the end of every selected line, so the selection stretches or compresses
while the origin stays put.
Args:
selection: lines to scale (see :func:ass_shift_times).
factor: multiplier, must be > 0.
doc_id: document id.
origin: None/"first" (start of the earliest selected line),
"document" (0), or an explicit millisecond value / time string.
round_ms: round the computed times to whole milliseconds before writing. Returns:
{"doc_id", "factor", "origin_ms", "origin", "round_ms", "indices", "count", "changes": [{"index", "start_ms", "end_ms", "new_start_ms", "new_end_ms"}], "span": {"before": {"min_start_ms", "max_end_ms", "span_ms"}, "after": {...}}} |
| ass_set_durationsA | Pull every selected line into the [min_ms, max_ms] duration window. Only the edge named by mode moves — "stretch" (default) keeps the
start and moves the end, "start" keeps the end and moves the start. A
line is never moved past the neighbouring line on the same layer unless
allow_overlap is True, and never past keep gaps (there are none by
default, so the limit is the neighbour's exact start). Args:
selection: lines to adjust.
min_ms: minimum duration; shorter lines are lengthened.
max_ms: maximum duration; longer lines are shortened.
mode: "stretch"/"end" (move the end) or "start" (move the
start).
doc_id: document id.
dry_run: when True (the default) nothing is written — the response shows
exactly what would happen.
allow_overlap: allow the new edge to cross the neighbouring line. Returns:
{"doc_id", "dry_run", "applied", "mode", "window": {"min_ms", "max_ms"}, "allow_overlap", "count", "changes": [{"index", "field", "old_ms", "new_ms", "old", "new", "reason"}], "blocked": [{"index", "reason", "wanted_ms", "limit_ms"}]} |
| ass_set_timesA | Set the start, end and/or duration of one line. Args:
index: 0-based line index.
doc_id: document id.
start_ms: new start — milliseconds or a time string such as
"0:00:01.50".
end_ms: new end (milliseconds or time string). Mutually exclusive with
duration_ms.
duration_ms: new duration; the end becomes start + duration_ms. At least one of the three must be given. An end before the start is
rejected with a ToolError naming both values. Returns:
{"doc_id", "index", "before": {"start_ms", "end_ms", "duration_ms"}, "after": {...}, "changed": ["Start", ...], "applied"} |
| ass_shift_timesA | Shift the start/end of lines by offset_ms (negative shifts allowed). Args:
selection: which lines to shift — None/"all", an index, a list of
indices, "0-4,7" or any selector base.resolve_indices takes.
offset_ms: milliseconds to add; negative values move lines earlier.
doc_id: document id; defaults to the current document.
clamp: when True the shift is limited so that no selected line starts
before zero. The same (reduced) offset is applied to every line so
the relative timing of the selection is preserved.
only_selected: when False every line in the document is shifted and
selection is ignored. Returns:
{"doc_id", "requested_offset_ms", "applied_offset_ms", "clamped", "only_selected", "indices", "count", "applied", "changes": [{"index", "start_ms", "end_ms", "new_start_ms", "new_end_ms", "start", "end"}]}
where the new_* values are what the document actually holds after the
write (ASS stores centiseconds). |
| ass_snap_to_framesB | Snap line start/end times to whole video frames. Args:
selection: lines to snap.
fps: frame rate (see :func:ass_frame_from_ms).
mode: "nearest" (default), "floor" or "ceil".
doc_id: document id.
which: "both" (default), "start" or "end". Returns:
{"doc_id", "fps", "fps_source", "mode", "which", "considered", "count", "changes": [{"index", "field", "old_ms", "new_ms", "old", "new", "frame"}], "applied"} — new_ms is what the document now
holds, count is the number of fields that actually moved and
considered the number that were inspected. |
| ass_snap_to_keyframesA | Snap line times to keyframes loaded in workspace.keyframes. Args:
selection: lines to snap.
which: "both" (default), "start" or "end".
mode: "nearest" (default), "previous" or "next".
forward_only: only consider keyframes at or after the line's time (never
move a time earlier). Contradicts mode="previous".
max_distance_ms: skip a snap when it would move the time further than
this.
doc_id: document id. Returns:
{"doc_id", "mode", "which", "forward_only", "max_distance_ms", "keyframes_loaded", "considered", "count", "applied", "changes": [{"index", "field", "old_ms", "new_ms", "old", "new", "delta_ms", "keyframe_ms"}], "skipped": [{"index", "field", "old_ms", "reason"}]}
— count/changes only list fields that really moved. |
| ass_write_timecodesA | Write an Aegisub timecodes file (v1 or v2) into workspace.output_dir. Args:
path: destination. Relative names land inside workspace.output_dir;
an absolute path is honoured as given. Defaults to
<script name>.timecodes.
fps: frame rate. Resolution order: this argument, the default rate of a
loaded timecodes file, workspace video/script info, the document's
FPS; a ToolError explains what is missing.
v2: True (default) writes a v2 file (one timestamp per frame), False
writes v1 (default rate plus overrides).
doc_id: document id. Returns:
{"path", "version", "fps", "fps_source", "frame_count", "lines", "bytes", "preview": [first lines], "used_timecodes"} |
| ass_karaoke_auto_timingsA | Propose karaoke timings for one line from its duration (no write by default). Argumentsindex the line to analyse (0-based).
mode "syllable" (split on marker), "char", "word" or
"regex" (needs pattern).
weights "char_class" (default), "char" or "even".
start_ms / end_ms
span to distribute; both default to the line's own times.
apply False (default) only proposes the timings and the text that
would be written. True writes the generated \k tags to
the line (after workspace.snapshot). apply is a documented
extension of the required signature: the default is a pure read.
kind tag kind to generate when applying.
Returns{"doc_id", "index", "mode", "split_mode", "weights", "kind", "applied", "start_ms", "end_ms", "span_ms", "span_cs", "syllables": [{"index", "text", "weight", "duration_cs", "duration_ms"}], "durations_cs", "duration_sum_cs", "line_duration_cs", "discrepancy_cs", "matches_line_duration", "message", "proposed_text", "old_text"}
|
| ass_karaoke_exportA | Export syllable timings for other karaoke tools. Writes into workspace.output_dir and returns both the path and the
content. The file is named <document stem>_karaoke.<ext>. Argumentsselection lines to export. None (default) exports every line that
carries karaoke tags; pass a selection to override.
format "srv2" (default) tab-separated interchange with a #
header and columns line, syl, start_ms, end_ms, dur_cs, dur_ms, kind, text; "txt" human-readable
<line_index> <h:mm:ss.cc> <h:mm:ss.cc> <text> rows;
"csv" the same columns as srv2 as RFC 4180 CSV.
include_untimed
also export lines without karaoke tags as a single syllable
covering the line span.
Returns{"doc_id", "format", "path", "filename", "content", "lines": n, "syllables": n, "bytes": n, "output_dir": "..."}
|
| ass_karaoke_generateA | Generate \k tags across a line's syllables. Argumentsselection / index
Which lines to rewrite. index names one line; otherwise
selection goes through :func:base.resolve_indices (None uses
the session selection, and an error is raised when nothing is selected).
start_ms / end_ms
Span the durations are distributed over. When omitted the line's own
Start/End are used. The line's own times are never modified
by this tool (use :func:ass_karaoke_retime for that).
mode marker / char / word / regex (pattern for regex).
kind karaoke tag kind: k, kf, ko or kt.
link how tags attach to the syllables:
"none" one tag per syllable, placed before the syllable's own
override tags;
"syl" the same count but each tag is placed after the
syllable's leading override tags;
"char" one tag per visible character (combining marks stay
with their base character) — the line span is split per character.
weights "char" (visible length), "char_class" (CJK/Latin/space
weighting, see karaoke.syllable_weights_by_char_class) or
"even".
replace_existing
True (default) rewrites existing karaoke tags. False leaves any
line that already carries karaoke tags untouched and reports it in
skipped.
min_cs minimum duration per syllable; a span too short to honour it
raises :class:ToolError instead of silently producing zeros.
snap_to_line
Clamp an explicitly requested span to the line's own span when it would
overshoot (reported in snapped).
Returns{"text_source": "line", "doc_id", "mode", "kind", "link", "weights", "min_cs", "exact_sum_guaranteed": True, "sum_within_one_cs": True, "lines": [{"index", "start_ms", "end_ms", "span_ms", "span_cs", "snapped", "skipped", "reason", "durations_cs", "duration_sum_cs", "line_duration_cs", "discrepancy_cs", "matches_line_duration", "message", "syllables", "text", "old_text"}], "lines_changed": n}
The centisecond durations always sum to exactly span_cs (and therefore
to the line duration when the span came from the line) — better than the
one-centisecond tolerance required, so exact_sum_guaranteed is always
True when a line is written. |
| ass_karaoke_getA | Read the parsed karaoke of one line. Argumentsindex 0-based line index (doc.events() order) of an open document.
doc_id open document id (defaults to the current one).
Returns{"text_source": "line", "index", "doc_id", "line": {...}, "has_karaoke_tags", "untimed", "timings_source", "syllables": [{"index", "text", "raw", "prefix", "kind", "duration_cs", "duration_ms", "start_ms", "end_ms", "start", "end"}], "duration_sum_cs", "duration_sum_ms", "line_duration_cs", "discrepancy_cs", "matches_line_duration", "message", "kind_counts", "kinds"}
start_ms/end_ms are absolute (the line's Start is time zero
internally, the line's own start is added). discrepancy_cs is
sum(syllable durations) - line duration in centiseconds and is reported
explicitly, never corrected here.
|
| ass_karaoke_removeA | Remove \k/\kf/\ko/\kt tags (karaoke.remove_karaoke). drop_markers=True also removes the | syllable markers — they are kept
by default because they are the source data :func:ass_karaoke_generate
re-splits on.
keep_times controls the line's own times. True leaves Start/
End exactly as they were; False (default) retightens the line's
End to Start + karaoke extent when the karaoke extent is shorter
than the line (the trailing silence the karaoke timing defined is dropped).
Returns {"doc_id", "drop_markers", "keep_times", "lines": [{"index", "old_text", "text", "removed_tags": n, "old_start_ms", "old_end_ms", "start_ms", "end_ms", "times_retightened"}], "lines_changed": n, "tags_removed": n}. |
| ass_karaoke_retimeA | Retime existing karaoke to a new span, reporting each syllable before/after. Argumentsselection lines to retime (None uses the session selection).
mode "proportional" keeps the existing relative syllable lengths,
"even" gives every syllable the same duration.
new_start_ms / new_end_ms
new span. When given, the line's own Start/End are set
to them as well (that is what "retime the line" means); when
both are omitted the line's current span is used, optionally
moved by shift_ms or stretched by factor.
shift_ms move the whole span by this many ms (no length change).
factor scale the span length about the line start.
min_cs minimum syllable duration; an impossible span raises
:class:ToolError.
dry_run compute and report without writing anything.
Returns{"doc_id", "mode", "dry_run", "lines": [{"index", "old_text", "text", "old_start_ms", "old_end_ms", "start_ms", "end_ms", "span_cs", "times_changed", "syllables": [{"index", "text", "kind", "before_cs", "after_cs", "before_ms", "after_ms", "delta_cs"}], "duration_sum_cs", "line_duration_cs", "discrepancy_cs", "matches_line_duration", "message"}], "lines_changed": n, "reported_not_stretched": True}
The new centisecond durations sum to the new span exactly; any mismatch
against the line duration is reported rather than stretched. |
| ass_karaoke_scaleA | Multiply every karaoke duration by factor (never below min_cs). scale_times=True also scales the line's own span about its start (the
Start time is kept). Returns the same shape as :func:ass_karaoke_shift
with factor instead of shift_ms; rounding/clamping is reported via
duration_sum_cs/discrepancy_cs/message, never stretched.
|
| ass_karaoke_set_kindA | Convert karaoke tags to another kind (k, kf, ko, kt). only_matching limits the conversion to syllables whose current kind is
that value (e.g. only k -> kf). Durations, text and every other
override tag are untouched. Returns
{"doc_id", "kind", "only_matching", "lines": [{"index", "old_text", "text", "before_kinds", "after_kinds", "changed"}], "lines_changed": n, "tags_converted": n}.
|
| ass_karaoke_set_timingsA | Write explicit per-syllable durations or absolute times. Argumentstimings list of durations, list of {"duration_ms"|"duration_cs"|"start_ms"+ "end_ms"} dicts, or — when unit is an absolute spelling —
one start time per syllable, a list of [start, end] pairs, or
n + 1 boundary times.
unit "ms" / "cs" (values are durations), or
"absolute_ms" / "absolute_cs" / "absolute" /
"times" (values are absolute times). Absolute times must
be monotonically increasing.
kind force every syllable to this kind; None (default) keeps each
syllable's existing kind.
strict True (default): a count mismatch raises :class:ToolError
naming both counts. False pads with zeros / drops extras.
mode/marker/pattern
how to split a line that has no karaoke tags yet.
Returns{"text_source": "line", "doc_id", "unit", "kind", "strict", "lines": [{"index", "syllable_count", "timing_count", "padded", "old_text", "text", "syllables": [{"text", "kind", "duration_cs", "duration_ms"}], "duration_sum_cs", "line_duration_cs", "discrepancy_cs", "matches_line_duration", "message"}], "lines_changed": n, "reported_not_stretched": True}
Durations that do not add up to the line duration are reported in
discrepancy_cs/message; they are never stretched to fit. |
| ass_karaoke_shiftB | Shift every karaoke duration by shift_ms (negative trims, floor 0). shift_times=True also moves the line's own Start/End by the same
amount. Returns {"doc_id", "shift_ms", "shift_times", "lines": [{"index", "old_text", "text", "syllables": [{"index", "text", "kind", "before_cs", "after_cs"}], "duration_sum_cs", "line_duration_cs", "discrepancy_cs", "matches_line_duration", "message", "start_ms", "end_ms"}], "lines_changed": n, "clamped_cs": n} — durations never go below zero, so
the sum is reported rather than stretched.
|
| ass_karaoke_splitA | Split a karaoke line into syllables. Argumentstext / index + doc_id
Either the raw override text, or a 0-based line index in an open
document. "text_source" in the result says which was used.
mode "marker" (split on marker, the usual | workflow),
"char" (one visible character per syllable, combining marks
stay attached to their base character), "word" (whitespace)
or "regex" (split on pattern).
marker the marker string for mode="marker". Default "|".
pattern regex for mode="regex" (a capture-free split pattern).
keep_bom keep a leading U+FEFF in the text (default: strip it).
Returns{"text_source": "text"|"line", "index", "doc_id", "mode", "marker", "pattern", "had_bom", "plain_text", "expected_visible_text", "reconstruction": {"ok", "reconstructed", "expected"}, "syllable_count", "syllables": [{"index", "raw", "text", "prefix", "prefix_tags", "leading_whitespace", "trailing_whitespace", "char_count"}]}
|
| ass_karaoke_stylesA | List (and optionally create) the conventional karaoke template styles. The standard set is Karaoke, Karaoke_2 and Karaoke_3 — the usual
Aegisub template trio — built from one base: Arial 60, white
PrimaryColour, blue SecondaryColour (so \kf/\ko sweeps from
blue into white), black outline, &H80000000& shadow, bold, BorderStyle 1,
Outline 2, Shadow 1, margins 10, Encoding 1. The variants differ only in
Alignment: Karaoke bottom (2), Karaoke_2 top (8), Karaoke_3
middle (5), which is how the tutorial template sets stack their layers.
prefix renames the trio (prefix, prefix_2, prefix_3). create=False reports what exists without touching the document.
Returns {"doc_id", "prefix", "created": [names], "existing": [names], "styles": [{"name", "exists", "created_now", "values": {...}}]}. |
| ass_karaoke_templateA | Expand a karaoke template line into one generated line per syllable. This is a documented subset of the Aegisub karaoke templater. Only
$syl (the syllable text) and $sdur (the syllable duration in
centiseconds) are substituted; the template's other override tags (including
\t transforms) are copied verbatim into every generated line. Classes,
code/once/mixin lines, the rest of the variable set and the
effect library are not supported — see unsupported in the result. Argumentsselection the lines whose syllables are expanded.
template_line / template_index
the template: a raw string, or a 0-based line index. With a
real template index the generated lines are inserted directly
after it and copy its Layer, Actor, Effect, kind, style and
margins; with a raw string they are appended after the last
selected line.
style style for the generated lines (default: the template's style,
else the Karaoke style).
mode how to split the target line when it has no karaoke tags yet
(marker / char / word / regex).
replace_existing
remove previously generated lines (same Effect marker) that sit
immediately after the template line before inserting.
create_styles
create the standard karaoke styles when style names one
that does not exist yet.
dry_run report the lines that would be generated without inserting.
Returns{"doc_id", "template_subset": True, "subset_of_aegisub_karaoke_templater": True, "supported": [...], "unsupported": [...], "variables_used": [...], "unknown_variables": [...], "template": {...}, "dry_run", "inserted_count": n, "replaced_lines": n, "generated": [{"target_index", "syllable_index", "text", "syllable", "duration_cs", "start_ms", "end_ms", "start", "end", "layer", "actor", "style", "kind", "inserted_index"}], "generated_indices": [...]}
|
| ass_add_typesettingA | Build a leading override block out of named typesetting pieces. Args:
selection: selection spelling; every selected line receives the block.
doc_id: document to edit; the current one when omitted.
pos: [x, y] -> \pos(x,y).
an: alignment, a plain integer 1..9 (7 -> \an7). Booleans,
floats and out-of-range values are rejected; \q-style
alignments are not part of this helper.
move: \move animation. Accepted shapes: six numbers
[x1, y1, x2, y2, t1, t2] (times in milliseconds), four
numbers, two pairs, a pair (expanded to a zero-length move), or a
dict with x1/y1/x2/y2 and optional t1/t2.
fade: \fad/\fade. A pair [in_ms, out_ms] produces
\fad(in,out); a 4-tuple [a1, a2, a3, t] produces
\fade(a1,a2,a3,t,t,t,t); the full 7-tuple
[a1, a2, a3, t1, t2, t3, t4] is passed through verbatim; a dict
with a1/a2/a3/t1..t4 also works.
clip: \clip/\iclip. A rectangle [x0, y0, x1, y1], a
drawing path string ("m 0 0 l 100 0 100 100" — it must contain a
drawing command, otherwise the string is rejected instead of being
handed to libass as a no-op), [scale, path],
or a dict {"rect": [...]} / {"drawing": "...", "scale": n}
with "inverse": true to emit \iclip.
org: [x, y] -> \org(x,y).
extra_tags: any additional override text (braces and the leading
backslash are optional) appended to the block in the order given.
reset_first: put \r at the front of the block so the line starts
from the style's values before the new tags are applied.
in_place: write the block back to the document (snapshot-backed,
True by default). With False the planned lines are returned
but the document is left alone. Returns {"doc_id", "tag_string", "override", "reset_first", "count", "changed", "written", "in_place", "lines": [{"index", "before", "text", "changed"}], "text"}. tag_string is the exact tag string produced
(without the braces, e.g. \an8\pos(100,200)); text is the new line
text when the selection resolved to a single line, otherwise None (the
per-line texts are in lines). The block is merged into the line's
existing first block so duplicated tags are updated instead of stacking. |
| ass_apply_tag_to_blockA | Append tags to one override block (or to every block) of a line. Args:
index / text / doc_id: the line to edit (0-based index of doc_id or a
raw string).
block: 0-based override block number, or "all" to touch every block.
Blocks are numbered in line order and, unlike plain indices, count
comment blocks too. When the line has no block at all, block=0
and "all" create one at the start of the line.
override: the tags to append (braces and the leading backslash are
optional; braces inside the payload are rejected).
doc_id: document holding index.
in_place: write back to the document (snapshot-backed). The raw-string
mode never writes. Returns {"source", "index", "doc_id", "block", "blocks_total", "applied_blocks", "override", "text", "plain_text", "changed", "written"}
with applied_blocks listing the block numbers that actually received the
tags. The text inside every block is preserved verbatim and the closing
brace is always kept. |
| ass_convert_tagsA | Normalise legacy SSA override tags to their ASS spelling (or back). Only the inside of override blocks is touched; visible text is never
rewritten, and blocks are rebuilt with their braces intact. Args:
selection: selection spelling (None = every line).
doc_id: document to edit; the current one when omitted.
mode: "to_ass" (default) rewrites the legacy spellings to ASS —
\a1..\a11 (SSA alignment) become the matching \an1..
\an9 and \K becomes \kf. "to_ssa" does the
opposite (\an back to \a, \kf back to \K).
dry_run: report the replacements without writing (no snapshot). Returns {"doc_id", "mode", "dry_run", "count", "changed", "written", "replacement_count", "lines": [{"index", "before", "after", "changed", "replacements": [{"from", "to", "kind", "note"}]}]}; every replacement is
listed individually so the caller can audit the conversion. changed is
the number of lines whose text differs (also in dry_run), written the
number actually stored. Snapshot-backed unless dry_run is set. Indices: override blocks are addressed by position, so no plain-character
index and no raw offset is taken as input. Because only tag names inside
the braces change, both index maps of the visible characters are preserved
exactly: the plain-character index of every visible character and the raw
index of every character in the line are the same before and after. |
| ass_insert_tag_atA | Insert a bare override block at a plain character position. Args:
index / text / doc_id: the line to edit (0-based index of doc_id or a
raw string).
plain_index: plain (visible character) index the block is inserted
at; 0 puts it before the first visible character, plain_len
puts it at the end of the line. Override blocks do not count, so
for "ab{\i1}cd" plain index 2 is between b and c.
override: the tags to insert (braces and the leading backslash are
optional, braces inside the payload are rejected).
after: insert after the character at plain_index instead of before
it. With after=True and plain_index == plain_len the block
is appended at the very end.
doc_id: document holding index.
in_place: write back to the document (snapshot-backed). The raw-string
mode never writes. Returns {"source", "index", "doc_id", "plain_index", "after", "override", "text", "plain_text", "changed", "written"}. plain_index is always a
plain index; the raw offsets of the new block are not reported because the
insertion shifts them. |
| ass_karaoke_tags_onlyA | List only the karaoke tags of a line, with their arguments. Handy right before retiming: it shows the syllable tags in order together
with the visible text each one covers. Args:
text / index / doc_id: the line to inspect (raw string, or 0-based index
inside doc_id). Returns {"source", "index", "doc_id", "has_karaoke", "count", "tags", "plain_text", "syllable_text", "times_ms", "total_ms"}. Each entry of
tags is {"name" (canonical: k, kf, ko or kt), "argument", "raw", "plain_index", "block", "text"} where plain_index is the plain
(visible character) index at which the tag takes effect, block is the
0-based override block it lives in and text is the visible text that
follows it up to the next karaoke tag (the syllable it times).
syllable_text concatenates those chunks and total_ms sums the
integer arguments (\kt/\ko are not durations and are counted in
count but reported as None in times_ms). Read-only; no
snapshot. |
| ass_parse_textA | Tokenise an ASS line into its ordered segments and override tags. Args:
text: a raw ASS Text field (tags included). Use this to inspect a
line that is not (yet) in a document.
index: 0-based line index in doc_id; the line's current Text
field is read from the document.
doc_id: document holding index; the current document when omitted.
Passing both text and index is an error. Returns a dict with: source/index/doc_id
which input was used ("text" or "line").
raw, raw_length
the line exactly as stored (raw index space).
plain_text, plain_length, characters
the visible text and, for every visible character, its index in both
spaces: {"plain_index": i, "char": c, "raw_index": r}.
segments
ordered alternating text runs and {...} blocks. A text segment
carries text plus start/end (raw indices) and
plain_start/plain_end. A block segment carries raw
(including braces), inner, block (0-based block number),
is_override (True when it holds at least one \ tag; a block
without tags is an ASS comment block), the same four offset fields
(plain_start == plain_end for blocks) and tags.
tags
the flat list of every tag in line order, each with name (canonical,
lowercase, e.g. kf for \K), argument ("" for
valueless tags), raw (exact source text), paren (whether the
argument was written in parentheses), is_override and block.
Every parsed tag has is_override True because only
backslash-prefixed content is parsed as a tag; see the block-level flag
for comment blocks.
summary
per-line flags: blocks, tags, tag_names (histogram),
tag_groups (histogram by tag family), has_drawing (drawing mode
is still active at the end of the line, i.e. an unmatched \p),
drawing_state, has_karaoke, has_transform, has_clip and
plain_length. Use tag_names["p"]/tag_groups["drawing"] to
detect a drawing that is switched off again by \p0.
Read-only; no snapshot. start/end are raw indices, everything with
plain in its name is a plain (visible character) index. |
| ass_plain_textA | Strip every override tag, optionally keeping some tags or tag groups. Args:
text / index / doc_id: the line to inspect (raw string or a 0-based line
index of doc_id); exactly one source must be given.
keep: "" (or None) removes everything. Otherwise a comma/space
separated string or a list whose items are either a tag name
("pos", "\an", "1c") or a tag group name. Group names
win over tag names and expand to the whole family, e.g. "clip"
keeps \clip and \iclip, "fade" keeps \fad and
\fade. Known groups: transform, fade, clip, drawing, karaoke,
layout, color, style, reset, animation. Returns {"source", "index", "doc_id", "text", "plain_text", "keep_names", "keep_groups", "kept", "changed"} where text is the stripped line (it
still contains the kept override blocks), plain_text is the fully
tag-free visible text and kept lists the kept tags that were actually
present. Read-only; no snapshot, no indices. |
| ass_remove_tagA | Delete every occurrence of the named override tags. Args:
selection / index / text / doc_id: the usual three input modes.
names: a single tag name ("pos") or a list (["pos", "move"]);
a comma separated string works too. Group names are accepted and
expand to the whole family ("clip" removes \clip and
\iclip).
in_place: write back to the document (snapshot-backed). The raw-string
mode never writes. Returns, single-line: {"source", "index", "doc_id", "names", "removed", "removed_count", "text", "plain_text", "changed", "written"} where
removed lists every deleted occurrence as {"name", "argument", "raw", "block"}; selection mode returns
{"source": "selection", "doc_id", "names", "count", "changed", "written", "in_place", "removed_count", "lines": [{"index", "before", "after", "removed", "changed"}]}. Removing a tag never touches the visible text
and never leaves an unclosed block: emptied blocks are dropped entirely. |
| ass_set_tagA | Insert (or update) a single override tag on a line or a selection. Args:
selection: selection spelling; when given, text/index must be
omitted and every selected line is processed.
index / text / doc_id: single-line source (0-based index inside
doc_id, or a raw string).
name: tag name without the backslash, e.g. "fad", "an",
"pos", "fscx" or "1c". A leading backslash is allowed.
arg: the tag argument, e.g. "200,200" for \fad(200,200) or
"8" for \an8. Parentheses are added automatically when the
argument needs them. Braces and line breaks are rejected, and so is
an out-of-range alignment for \an (1..9) or legacy \a
(1..11) — those are ignored by libass when wrong, so they are caught
here instead.
value: alias for arg; when not None it wins (handy for numeric
callers, e.g. value=8).
doc_id: document for index/selection.
where: where to put the tag. "prepend" merges the tag into a new
leading block (the line's existing first block is reused so that
repeated tags are updated rather than duplicated);
"after_first_block" (default) appends the tag to the end of the
line's first override block, creating that block when the line has
none; "prepend_block" always inserts a brand new leading block;
"append" adds a block at the very end of the line; "wrap"
wraps every visible character and restores the previous value
afterwards (see :func:ass_wrap_range).
only_if_missing: leave the line untouched when a tag with this name is
already present anywhere in the line.
in_place: write back to the document (single-line and selection mode).
Snapshot-backed; the raw-string mode never writes. Indices: this tool edits whole override blocks, so it never takes character
offsets. Neither the plain-character index of the visible text nor the raw
index of the line is used or reported — but every where mode leaves both
maps of the visible characters unchanged (a tag is only ever inserted
between characters). Returns {"source", "index", "doc_id", "name", "argument", "tag", "where", "text", "changed", "written", "skipped", "reason", "warnings"} for a
single line (tag is the exact tag text produced, e.g. \fad(200,200))
or {"source": "selection", "doc_id", "name", "tag", "where", "count", "changed", "written", "in_place", "lines": [...]} for a selection.
duration-style arguments are passed through verbatim. |
| ass_strip_tagsA | Remove override tags from a line, a raw string or a whole selection. This is the bulk "clean up the tags" tool. The keyword names mirror
asscore.tags.strip_tags (keep, keep_groups, remove_groups,
keep_drawing, keep_karaoke); remove and keep_clip are
additions of this tool, where remove lists individual tag names to drop
before stripping and keep_clip is shorthand for
keep_groups=["clip"]. Args:
selection: a selection spelling (None = every line, "0-4",
{"style": "Default"} ...). When given, every selected line is
processed and text/index must be omitted.
text: raw ASS line to process instead of a selection.
index: 0-based index of the line to process inside doc_id.
doc_id: document used by selection/index; the current one when
omitted.
keep: tag names (string or list) to keep, e.g. "pos,an". Group
names are accepted too and move into keep_groups.
keep_groups: tag group names to keep (transform, fade, clip, drawing,
karaoke, layout, color, style, reset, animation).
remove: tag names to delete outright before stripping (string or list).
remove_groups: tag group names to delete outright.
keep_drawing: keep \p/\pbo tags so drawings survive.
keep_karaoke: keep \k-family tags so karaoke timings survive.
keep_clip: keep \clip/\iclip.
in_place: write the result back to the document (line/selection mode
only). Snapshot-backed; the raw-string mode never writes. Returns, in single-line mode: {"source", "index", "doc_id", "text", "plain_text", "changed", "written", "keep_names", "keep_groups", "remove_names", "remove_groups", "keep_drawing", "keep_karaoke", "keep_clip"}; in selection mode: {"source": "selection", "doc_id", "count", "changed", "written", "in_place", "lines": [{"index", "before", "after", "changed"}]}. Plain text is always tag-free; kept tags stay
inside their override blocks. |
| ass_swap_an_posA | Mirror \an vertically and move \pos so the text does not budge. The classic Aegisub helper: \an1 <-> \an7, \an2 <-> \an8,
\an3 <-> \an9 (the middle row 4/5/6 has no vertical mirror and is
left alone). Because the anchor flips between the bottom and the top of the
line, \pos has to move by exactly the line height for the rendered text
to stay where it was. The shift is computed from the real rendered size of the line, measured
with :func:asscore.measure.measure_line_render in script pixels (see
:func:_measure_geometry). height is the vertical anchor separation
(\an7 ink top minus \an1 ink top, both anchored at the same
y), i.e. the line height, and width is the advance width (left side
bearing + ink width + right side bearing, from the \an7/\an9
probes), i.e. the horizontal anchor separation. One numpad row or column
step moves the anchor by half of the corresponding separation, and the
anchor must move the other way for the ink to stay put:: row_step = new_row - row # numpad grid, +-2 for a top/bottom swap
col_step = new_col - col # +-2 for a left/right swap
dy = -(height / 2) * row_step # row 2 is the top of the screen
dx = +(width / 2) * col_step # col 2 is the right of the screen
For \an7 -> \an1 that is row_step = -2 and dy = +height: the
anchor walks down by the line height so the text stays on its screen row.
A purely vertical mirror never changes the column, so dx stays 0
there; horizontal=True additionally mirrors the column
(\an7 <-> \an9, \an1 <-> \an3, \an4 <-> \an6) and then
dx = +width for \an7 -> \an3 (numpad columns grow rightwards, so
the new right-edge anchor has to sit one width further right), which is what
makes the width term reachable. The measured text is the line with its own \pos/\move/\an
removed, rendered with the line's style and the document's PlayRes, so
the height matches what libass does for the real line. Indices: \an/\pos are located inside the override blocks, so no
plain-character index and no raw offset is taken as input. selection
refers to event indices (doc.events() order, 0-based), and the plain text
of every line survives byte for byte, so both index maps are unchanged. Args:
selection: selection spelling; the lines to rewrite.
doc_id: document to edit; the current one when omitted.
margin_mode: how to treat lines that have no \pos. By default they
are skipped (there is nothing to shift). With margin_mode=True
the vertical margin is rewritten instead:
MarginV = PlayResY - MarginV - height, which keeps an
alignment/margin-positioned line in place across the mirror.
dry_run: compute and report the plan without writing (no snapshot).
horizontal: also mirror the alignment column (180 degree mirror) and
shift x by the advance width. Off by default, matching the
Aegisub helper. Returns {"doc_id", "dry_run", "margin_mode", "horizontal", "count", "changed", "written", "geometry_source", "lines": [...]}; each line entry
has index, before, after, old_an, new_an, old_pos,
new_pos, dx, dy, margin_v, measured ({"width", "height", "ink_width", "ink_height", "left_bearing"}), changed,
skipped and reason. Retiming/render checks aside, the check to
apply is that the ink bounding box before and after is identical — see the
test suite, which asserts exactly that with
:func:asscore.measure.measure_render. |
| ass_tag_summaryA | Per-line tag histogram and typesetting sanity check. Args:
index / text / doc_id: inspect a single line (0-based index of doc_id
or a raw string).
selection: inspect a set of lines (None means every line when no
index/text is given). doc_id says which document. Returns {"source", "doc_id", "index", "count", "missing_position", "lines": [...], "totals": {...}}. Every line entry carries index,
raw, plain_text, visible_chars, blocks (number of override
blocks), tags (total), tag_names (per-name histogram), tag_groups
(the same count folded into tag families such as layout, color, karaoke,
clip, transform), has_drawing (drawing mode still active at the end of
the line) / drawing_state,
has_karaoke/has_transform/has_clip,
first_block_has_pos/first_block_has_move and missing_position
(True when the line's first override block has neither \pos nor
\move — the line is then placed by styles and margins only, which is the
usual typesetting smell). missing_position at the top level lists the
indices of those lines; totals sums tags, blocks and flags over the
selection. Read-only; no snapshot. All indices are 0-based line indices,
while visible_chars counts plain (visible) characters. |
| ass_wrap_rangeA | Wrap a character range in an override block, restoring the outer state. Args:
index / text / doc_id: the line to edit (0-based index of doc_id or a
raw string).
start: range start. A plain index when scope="plain" (the
default), a raw index when scope="raw".
end: range end, exclusive. Same index system as start; None
means "to the end of the line" (the visible end / the raw end).
override: the tags to apply, with or without the surrounding braces and
with or without the leading backslash (r"\fscx200",
"fscx200" and r"{\fscx200}" are all accepted). Braces and
line breaks inside the payload are rejected.
doc_id: document holding index.
scope: "plain" (default) counts only visible characters — override
blocks and the \N/\n line-break escapes are not counted, so
the same start/end cover the same glyphs no matter how many
tags precede them. "raw" counts every stored code point
including braces, which is what you want when you already have
offsets into the stored Text field. A raw boundary that would
land inside an override block is refused with a ToolError
instead of silently splitting the block.
in_place: write back to the document (snapshot-backed). The raw-string
mode never writes. The tags that were in effect before start are re-emitted after end
when they changed inside the range, so the override applies to exactly the
requested characters. warnings reports tags that had no previous value
to restore (there is nothing to restore for e.g. \an). Returns {"source", "index", "doc_id", "scope", "start", "end", "raw_start", "raw_end", "plain_start", "plain_end", "override", "text", "plain_text", "changed", "written", "warnings"}. start/end are
echoed in the requested index system; plain_start/plain_end are always
plain (visible character) indices and raw_start/raw_end are always
raw offsets into the stored line, so the two systems stay comparable no
matter which one was passed in. |
| ass_get_drawingA | Inspect the drawing part of a line, or a raw drawing string. Pass exactly one of: index + doc_id -- the line at that 0-based index (doc.events()
order) is split with tags.drawing_parts and its drawing is inspected;
text -- either a full override line (anything containing { or a
\p tag, split the same way) or bare drawing path data.
scale is the \p level in effect for the drawing, so the returned
commands, bbox, size, centre and path length are all in that scale space
(units as written in the file); multiply by
2 ** (1 - scale) for script pixels. normalised_* mirrors of the
bbox/size are provided already converted.
Returns a dict with source ("line" or "text"), doc_id,
index, drawing (the raw drawing text), scale, has_drawing,
commands (list of {kind, args, points, text}), bbox,
normalised_bbox, size, normalised_size, center (aliased as
centre), subpath_count, point_count, path_length,
svg_path and clips (see :func:ass_get_clips for that shape). |
| ass_set_drawingA | Replace the drawing part of line index. drawing_text is parsed and re-serialised with integer coordinates, so
the stored text is canonical (this is the only rewriting applied).
scale, when given, sets the line's \p level (\p<scale>); when
omitted an existing \p tag is left alone and a missing one is added as
\p1 so the drawing actually renders.
keep_tags=True keeps every non-drawing override tag and anything after
the drawing (typically the closing {\p0}); keep_tags=False rebuilds
the line as {\p<scale>}<drawing> and discards all other text.
Returns {doc_id, index, source, old_drawing, drawing, scale, text}. |
| ass_drawing_infoC | Parse a drawing only (no measurement, no line needed). Coordinates are in the drawing's own scale space (see the module
docstring). Returns {source, doc_id, index, drawing, scale, commands, subpaths: [{index, bbox, size, text, point_count}], bbox, size, center (aliased as centre), subpath_count, point_count, path_length}. |
| ass_transform_drawingA | Transform a drawing and return the new path data (or write it back). Coordinates in and out are the drawing's own scale-space units (see the
module docstring); results are serialised with integer coordinates. action and the parameters it uses:
translate dx, dy -- shift every point.
scale factor about (origin_x, origin_y); the origin
defaults to the drawing's bbox centre so it stays put.
scale_to_size dx, dy = target width/height; uniform scale
(aspect ratio kept), drawing moved into (0,0,w,h).
stretch_to_bbox dx, dy = target width/height; independent axes
(aspect ratio deliberately broken).
rotate angle_deg clockwise on screen about the origin
(bbox centre by default).
mirror axis="x" flips left/right, axis="y" top/bottom
about the origin (bbox centre by default).
center/centre_at_origin move the bbox centre to (origin_x, origin_y), default (0, 0).
reverse reverse the winding of every subpath.
flatten replace Bézier/B-spline curves with polylines.
simplify Douglas-Peucker with tolerance factor (default 1.0).
round snap coordinates to the nearest multiple of factor
(factor=1.0 = integers, the default).
in_place=True with index writes the result back into the line (after
workspace.snapshot) and returns the new line text; otherwise no document
is touched and drawing holds the new path data.
Returns {source, doc_id, index, action, drawing, bbox, size, center, centre, changed, written} (centre duplicates center). |
| ass_drawing_bboxA | Bounding box / size / centre of a drawing. Coordinates are in the drawing's own scale space (\p level). The box
is the control polygon box -- Bézier/B-spline handles included -- matching
what VSFilter/Aegisub use for positioning. Returns {source, doc_id, index, scale, bbox, size, center, centre, normalised_bbox, normalised_size, point_count}. |
| ass_drawing_to_svgB | Export a drawing as a standalone .svg file in workspace.output_dir. The path data is the drawing's absolute SVG equivalent (scale space units,
one SVG user unit per drawing unit). padding grows the viewBox on every
side so strokes near the edge are not clipped. path is a filename (resolved inside workspace.output_dir) or an
absolute path; the default is drawing.svg / drawing_<index>.svg and
is overwritten if it exists.
Returns {path, d, view_box, width, height, bbox, source, doc_id, index}. |
| ass_svg_to_drawingA | Convert SVG path data (or a whole .svg file) into ASS drawing text. Either d (one or more d attributes, space separated) or svg_path
(the file is read, its viewBox becomes the origin shift and every
<path d="..."> is converted). view_box given as "x y w h" or
[x, y, w, h] shifts the paths so the box origin becomes (0, 0). scale multiplies every coordinate; round_to is the number of decimal
places kept when serialising (0 = integer coordinates).
SVG and ASS both grow y downwards, so nothing is flipped. Supported
commands: M L H V C S Q T A Z (relative forms too); quadratics are
promoted to cubics and arcs to cubic segments. Returns {drawing, bbox, size, center, path_count, view_box, scale, round_to, source}. |
| ass_split_drawingA | Split a drawing into one string per subpath (no subpath is ever dropped). Commands appearing before the first m/n form their own leading part,
so split followed by :func:ass_join_drawings is lossless.
Coordinates stay in the drawing's own scale space. Returns {source, doc_id, index, scale, count, subpaths: [str, ...], parts: [str, ...] (alias of subpaths), point_counts: [int, ...], bboxes: [...]}. |
| ass_join_drawingsA | Join several drawing strings into one (the inverse of ass_split_drawing). parts is a list of drawing strings (a single string is treated as a
one-element list). Every part must parse; empty strings are rejected so a
subpath can never be silently lost. Coordinates are serialised as integers.
Returns {drawing, count, subpath_count, point_count, bbox, size, doc_id}. |
| ass_get_clipsB | List every \clip / \iclip tag on a line (or in raw text). Each entry has tag ("clip"/"iclip"), inverse, raw
argument, kind ("rect" or "vector"), the explicit scale
(None when omitted) and the effective_scale actually used, plus
coords as authored in the clip's scale space and normalised
coordinates converted to script resolution (multiplied by
2 ** (1 - effective_scale)). bbox is the box in scale space and
normalised_bbox the same box in script resolution. Returns {source, doc_id, index, line_scale, count, clips: [...]}. |
| ass_set_clipA | Set, add or remove a clip on the selected lines. selection accepts anything :func:base.resolve_indices understands
(None = the session selection, or every line when none is set).
Geometry is taken from the first one of these that is given: rect
("x1,y1,x2,y2" or a 4-list, in script resolution unless scale
names the scale space those numbers are written in), drawing_text
(ASS path data), svg_path / svg_d (SVG path data) or spec
(a rectangle string, an ASS drawing, or an SVG path -- SVG is detected by
its H/V/Q/T/A/Z command letters and the result is converted). scale for a vector clip sets the explicit \clip(<scale>,...) level;
when omitted a vector clip is written at level 1 (script resolution).
inverse=True emits \iclip.
mode:
"replace" -- strip every existing clip from the line, then insert.
"add" -- keep existing clips, insert the new one at the front.
"remove" -- strip every clip tag (\clip and \iclip) from the
lines; the geometry arguments are ignored.
Returns {doc_id, mode, kind, tag, scale, inverse, lines: [{index, changed, text, removed, clip}]}. |
| ass_remove_clipB | Strip clip tags from the selected lines. include_inverse=True (the default) removes \iclip as well as
\clip; False keeps inverse clips. Blocks left empty by the removal
are dropped, which is expected for a remove operation.
Returns {doc_id, include_inverse, changed, lines: [{index, removed, changed, text}]}. |
| ass_convert_clip_scaleA | Rewrite vector clip coordinates from their current \p scale to target_scale. A clip made at level S renders each unit at 2 ** (1 - S) script
pixels; to keep the rendered result identical at level T every
coordinate is multiplied by 2 ** (T - S) and rounded to the nearest
integer. The clip is rewritten with an explicit \clip(T,...) level. The tool proves the conversion by measuring the rendered ink bounding
box with measure.measure_render before and after (at the midpoint of the
first selected line) and reporting both, plus converged. Measurement
failing (no ffmpeg) is reported as measurement.error instead of an
exception. Both measurements carry an empty flag: if the line renders no ink at
all (for example a drawing with no \pos/\an whose geometry lands
off-screen) then before and after are both empty and converged
is true for a trivial reason. A caller that wants a real proof must check
not measurement["before"]["empty"] first, which is what the test suite
does. dry_run=True computes everything and reports the measurement proof
without touching the document.
Returns {doc_id, target_scale, dry_run, converted, lines: [{index, source_scale, target_scale, ratio, before_arg, after_arg, text}], measurement: {before, after, delta, converged, time_ms}}. |
| ass_scale_drawingA | Scale the drawing part of each selected line (and its clips) by factor. This is the classic "make everything on the line bigger" helper. The
drawing part and every clip are scaled about one common origin -- the
drawing's bbox centre when the line has a drawing, otherwise the first
clip's own centre -- so the drawing and its clips keep their relative
position instead of each drifting toward its own centre. Coordinates remain
in each clip's own scale space (the \clip(N,...) level is preserved) and
are rounded to integers with the module's explicit half-away-from-zero rule. include_clips=False scales only the \p drawing. dry_run=True
reports the new text without touching the document.
Returns {doc_id, factor, include_clips, dry_run, changed, applied, lines: [{index, old_text, text, drawing_scaled, clips_scaled}]}. |
| ass_list_fontsB | List installed fonts, optionally filtered by a case-insensitive substring. pattern is a plain substring matched against family, style and file --
not a fontconfig pattern expression. limit caps the number of entries.
Returns {pattern, limit, count, fonts: [{family, style, file, index, family_raw}, ...]}. |
| ass_match_fontB | What fontconfig actually resolves for family (with bold/italic). The first candidate is the face that would be used; when its family differs
from the request the subtitle will be rendered in a substitute. Returns {requested, bold, italic, resolved, file, style, substituted, match, candidates}. |
| ass_fonts_with_charA | Which installed family names contain the glyph for char. char must be exactly one character. Returns {char, codepoint, codepoint_hex, count, families} (families sorted case-insensitively).
|
| ass_font_coverageB | Characters of text missing from family (default: the system sans). The family is resolved through fontconfig first, so a substituted request is
reported honestly. Missing characters come back with their codepoints, plus
up to a few installed families that do cover them. Returns {text, requested, default_used, bold, italic, resolved_family, substituted, missing: [{char, codepoint, codepoint_hex, fallbacks}], missing_count, missing_chars, missing_codepoints, covered, checked, coverage_source, font}. requested is the family the check actually ran
against, so it is never None: when family is omitted it is the system
default sans family and default_used is True. |
| ass_glyph_checkA | Missing glyphs for a line's text or for a style's font. The string checked is text when given, otherwise the plain text of
line index (override tags removed). The font comes from family when
given, otherwise from the style named by style (its Fontname,
Bold and Italic) -- when neither is given the style of the line is
used, and failing that the system default sans. Returns {source, doc_id, index, style, requested, resolved_family, substituted, bold, italic, text, missing: [{char, codepoint, codepoint_hex, fallbacks}], missing_count, missing_chars, missing_codepoints, checked, covered, coverage_source}. |
| ass_fonts_usedB | Every font the script asks for, plus embedded font attachments. Styles contribute their Fontname (with the Bold/Italic flags
that affect which face fontconfig resolves); the [Fonts] section
contributes each fontname: attachment. Every family is resolved through
fontconfig so families that are not installed and families that
resolve to a substitute are flagged explicitly. Returns {doc_id, families: [{family, installed, substituted, resolved, file, style, bold, italic, styles: [names], attachment}], attachments: [names], not_installed: [names], substituted: [names], used_count}. |