Skip to content

ASS File Format Guide

Oneric edited this page Feb 21, 2024 · 10 revisions

This document is a guide for how to generate an ASS file following best practices such that all renderers, muxers, editors and other tools will be able to successfully parse it. It is strongly recommended to adhere to all “best practices” described here.

This is not a specification or any other type of authoritative document. It also does not aim for comprehensiveness and documenting the quirks and behaviour of properties/modifier on all edgecases is an explicit non-goal.

If you want to parse rather than produce ASS files, this document may help to get a general idea, but is not sufficient to cover all technically valid inputs.

This exclusively documents standard ASS features, for libass-specific extensions see libass’ ASS extensions (as those make scripts nonportable, their use is generally discouraged outside of on-the-fly generated, transient subtitle streams (e.g. from a on-demand conversion from another format)).

The focuses lies on ASS (v4+), but the structure of VSFilter-flavoured SSAv4 and the rarely used v4++ (nicknamed ASS2) are also described. New files SHOULD be created in the ASS (v4+) format at the moment. v4++

Preface: Other Format Guides/Specification

Another document commonly referred to as a documentation on or even “specification” of ASS is: http://moodub.free.fr/video/ass-specs.doc

However, this is just a crude early sketch plastered on top of the original Sub Station Alpha v4 documentation. The actual authoritative implementation of ASS later diverged a bit from this sketch and the document retained several features from genuine SSAv4 which do not exists in ASS or VSFilter-flavoured SSAv4 (e.g. authoring-specific features). Furthermore, this early sketch naturally lacks all features added to ASS after its initial creation in 2003.
It is of historic interest, but not recommended for use as an actual format reference.

General

An ASS or SSA subtitle file is commonly also referred to as a “script”.

In the following “whitespace” exclusively refers to ASCII whitespace, i.e. Unicode codepoint 0x20.

Subtitle files consist of multiple INI-like sections. Each section begins with a single line which only consist of an opening rectangular bracket [, the name of the Section and a closing rectangular bracket ]. No whitespace MUST be placed before or after the opening and closing brackets.

Between two sections at least one empty line SHOULD be placed.

Within all but the [Fonts] section, each line is a full, independent statement and a single statement can never be split across several lines.

Sections MUST occur only once and SHOULD appear in the same order as listed here. The [Events] section MUST be the last. Except for the [Fonts] section all MUST appear in the file.

Files MUST be in valid UTF-8 and may use either Unix-style or DOS-style line endings. For the benefit of otherwise buggy editors, an UTF-8 BOM SHOULD be added at the start.

Unless where indicated otherwise, integers and decimals MUST be in base 10 and MUST NOT add any leading or trailing zeroes.

ASS coordinates have their origin ((0, 0)) in the top left. x is the horizontal axis growing to the right and y the vertical axis growing downwards.

Section: Script Info

The section header is [Script Info].

In this section global header values can be set affecting the behaviour of everything else.

Each header consists of a colon-delimited line with the header name being before the colon and its value comes after the colon. The colon SHOULD be followed by a single whitespace.

This section MUST contain at least the ScriptType header.

It SHOULD also at least contain the ScaledBorderAndShadow, YCbCr Matrix, PlayResX, PlayResY, LayoutResX and LayoutResY headers and set their values as recommended in their respective documentation.

If the script is generated by a program or written via an editor, it is customary to insert a comment about this as the first line inside the [Script Info] section. The comment is prefixed by a semicolon and a single whitespace at the start of the line, e.g.:

; Script generated by FooBar version 1.2.3

All available headers are listed below.

Functional Headers

ScriptType

MUST be set to v4.00 for SSAv4, v4.00+ for ASS and v4.00++ for ASS2. This MUST match the format later used in the style and event sections.

ScaledBorderAndShadow

Set this to yes.sbas-no

YCbCr Matrix

Valid ranges are PC for full-range and TV for restricted range. Valid colour spaces are 601 (BT601), 709 (BT709), 240M (SMPTE240M) and FCC. Valid header values are then <range>.<colour space>, e.g. TV.601 and the special value None.

If the video’s colourspace is BT601 or BT709 it MUST be set to exactly match the video’s colourspace and range. Otherwise it MUST be set to None. ycbcr

Following these instructions will ensure, the final colours effectively exactly match the RGB values specified in ASS. Diverging from this, will lead to unmapped colours being mangled as described in ass_types.h. (But colour primaries and tone mapping will always follow the video colourspace regardless)

When porting an existing script to a new video:

  • if the script + original video followed the guidelines here or specifies a value matching the video colourspace, overwrite the header based on the new video using the above instructions. No further action wrt colours should be required.
  • if the original script did not follow the guidelines, overwrite the header and readjust all colours.

LayoutResX and LayoutResY

When authoring a new file, set those to the native display dimensions of the corresponding video. E.g. when subbing a 1920×1080 video set

LayoutResX: 1920
LayoutResY: 1080

Or when subbing an anamorphic 16:9 PAL DVD with a storage resolution of 720×576 and thus a native display resolution of 1024×576, set

LayoutResX: 1024
LayoutResY: 576

When porting an existing script to a new video, those MUST be kept as is if the display aspect ratio of the original video matches the display aspect ratio of the new video. (If the script didn't yet set the headers, treat it as if it set them to the storage resolution of the original video and set it explicitly in the new file.)

If the display aspect ratios do not match, many manual changes/fixups for positions, transforms and other properties are required anyway. Discard the old value, set them as described above and carefully make sure to fix up everything looking odd.

PlayResX and PlayResY

When authoring new subs, use the same values as for LayoutResX and LayoutResY. For existing subs keep them as is unless you need or want to do broad changes anyway.

WrapStyle

Optional, set the global default line-wrapping behaviour. Events can individually override this default using the \q tag.

If present, must be set to eitherq3

  • 0: Overflowing lines are automatically broken on ASCII whitespace 0x20 or explicit \n. Line length is attempted to be kept roughly equal. (This is the default if the header doesn’t appear)
  • 1: Overflowing lines are automatically broken on ASCII whitespace 0x20 or explicit \n exactly before the word causing an overflow. No attempt is made to equalise line lengths.
  • 2: Lines are never broken automatically, only explicitly forced \N breaks occur. (Typesets should activate this mode via \q, but unless doing a pure Sign&Song script it probably doesn't make much sense to enable this globally)

Informational Headers

The following headers do not affecting rendering, but can be used to record metadata about the script: Title, Original Script, Original Translation, Original Editing, Original Timing, Script Updated By, Update Details.

You may put any freeform data into their values as long as it doesn’t contain line breaks or other ASCII control sequences.

If you want to include even more or more fine-grained metadata, you can use the special ! header to do so. It can be specified multiple times, its values are also freeform data and will never affect rendering. Editors should preserve them. For example !: Release Date: 2009-08-07.

Style Sections

The section header and content differs depending on the format version. The section type MUST match what was previously declared in ScriptType.

v4+ (ASS) Style

The section header is [V4+ Styles].

The first line documents the format of the Style: for the benefit of human readers and MUST be:

Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding

After this several style definitions may follow. Each style definition consists of a single line starting with Style: followed by multiple ,-delimited fields. Unlike in the Format: line, no whitespace must follow the delimiting comma.

The field count and order matches the Format: line shown above.

Boolean values MUST use 0 for “false” and -1 for “true” in Style: lines.
Colour values MUST use hexadecimal values with a &H prefix. If the value includes an alpha channel (all colour values in the Style: line do), the order is ABGR. An alpha value of &H00 means fully opaque and a value of of &HFF fully transparent, i.e. invisible. For override tags which do not accept an alpha channel, only BGR and no alpha MUST be specified.

All used font and their variants MUST exists and MUST be attached to the final release.

  • Name MUST be a unique, non-empty string which MUST NOT start or end with whitespace. It is used later to refer to and use the defined style.
  • Fontname sets the family name of the desired font. MUST NOT be longer than 31 characters and the font’s family names MUST match on all platforms.
  • Spacing: floating point; applies spacing between each glyph. It is not advisable to use this with scripts depending on complex shaping.
  • BorderStyle may be either 1 for regular outlines expanding the shape of the glyphs or 3 to use rectangular boxes instead.
  • Alignment: see \an for permissible values
  • Encoding MUST always be set to 1.

Otherwise the type of each field isisr-fp:

  • Fontsize: floating point
  • PrimaryColour, SecondaryColour, OutlineColour, BackColour: a colour value including an alpha channel
  • Bold, Italic, Underline, StrikeOut: boolean
  • ScaleX, ScaleY: floating point
  • Outline, Shadow: floating point
  • Angle: floating point
  • MarginL, MarginR, MarginV: integer

For more information, refer to Aegisub’s style documentation. (In case of conflict between Aegisub documentation and this document, stick to the guidelines laid out here.)

v4++ (ASS2) Style

The section header is [V4++ Styles].

In comparison to ASS MarginV was split into MarginT (top) and MarginB (bottom) and a new RelativeTo field was added at the very end.

RelativeTo MUST be set to 1 for typesets and 0 for dialogue. The former will be guaranteed to always render in the same position within the video frame, while the latter is allowed to be shifted into playback margins and must not expect any particular positioning.

The full format is:

Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginT, MarginB, Encoding, RelativeTo

But unlike for other format versions, v4++ files SHOULD NOT actually include this Format: line.

v4 (SSA v4) Style

The section header is [V4 Styles].

The format of Style: lines is

Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding

Note that alignment values in SSA differ from those in ASS; see \a. AlphaLevel does not affect shadows, those always use &H80 in VSFilter-flavoured SSAv4. AlphaLevel

Section: Fonts

This section is optional and contains fonts embedded into the subtitle file itself. If no fonts are embedded the section MUST be omitted.

If possible you SHOULD attach fonts to the MKV container (or similar multimedia container) instead of embedding them into the subtitle file itself.

Each embedded font spans multiple lines. The first line starts with lowercase fontname: and is then followed by a descriptive all-lowercase(!) name of the embedded file. The following lines contain the encoded binary data of the font file. This MUST be terminated with at least one empty line.

After this more embedded font files can follow or a new section begin.

Binary Encoding Format

ASS/SSA uses a custom encoding to turn arbitrary binary data into uppercase letters and non-alphabetic, non-space symbols.

Binary input data is processed in chunks of 3 bytes. Those bytes in are split into four 6-bit chunks such that most-significant bits are processed first.

To each chunk the value 33 is added and then they are written out as UTF-8/ASCII text. After writing exactly 80 bytes a single linebreak must be inserted. Only the last line may be shorter than 80 characters if the end of the source file is reached.

If at the end of the file only fewer than 3 bytes remain, pad the data beyond the file end with zeros before splitting into 6-bit chunks, but only write out chunks containing actual file data.

Section: Events

The section header is [Events] (regardless of format version).

This section contains two types of events: Dialogues, which will be rendered to the screen at the specified time and position and Comments, which are not rendered but show up in editors. The format of those event lines depends on the format version.

In v4 and v4+ the line immediately after the section header MUST be the human-readable documentation of the event fields matching exactly the Format: lines shown further below.
In v4++ there MUST be no such documenting format line.

Each Dialogue event consists of a single line which MUST start with Dialogue: . The prefix is followed by multiple ,-delimited fields. Unlike in the Format: line, no whitespace must follow the delimiting comma.

The amount and function of the fields depends on the format version. This MUST match the version previously declared in the ScriptType header.

Dialogue line format

v4+ (ASS) Dialogue

Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

Except for the final Text field, no field values are allowed to contain commas.

  • Layer: an integer value in the range [0, 2³¹-1]. Events with a lower Layer value are placed behind events with a higher value. Implicitly positioned events with a different Layer value do never count as colliding.
  • Start/End: The start/end time of the event; it will only be shown in between those times; start is in- and end exclusive. The format is h:mm:ss.dd, with h being hours and can be in the range [0, 595] hoursEditors, mm being minutes and a two-digit value in [00, 60], ss being seconds and also a two-digit value in [00, 60] and dd being deciseconds and a two-digit value in the range [00, 99].
    You MUST NOT use any more or less than two digits for mm, ss and dd!
  • Style: MUST match exactly the name of a previous Style definition. This style definition will be used for the entire event.
  • Name: a freeform, metadata field which primarily is used to indicate the character saying/thinking/... this piece of dialogue. It does not affect rendering.
  • MarginL/MarginR/MarginV: Overrides the corresponding values from the style if non-zero.
  • Effect: A legacy effect to be applied to the event. See the Effects section.
  • Text: contains the text and commands which will be displayed on screen. This field is allowed to contain commas.

v4++ (ASS2) Dialogue

Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginT, MarginB, Effect, Text

This matches ASS, except for MarginV being split into MarginB and MarginT analogous to the style section.

v4 (SSA v4) Dialogue

Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

This matches ASS, except for Layer being replaced by Marked. For each event the content of the Marked field MUST be Marked=0.

Comment line format

Comments follow exactly the same format as Events, just that the line prefix is replaced with Comment:, the fields don’t have any actual effect and nothing will be displayed on screen.

Override Tags

With the exception of \kt descriptions of all available override tags and their general behaviour can be found with examples and images in Aegisub’s documentation.

\fe MUST NOT be used and \blur SHOULD be preferred over \be.

\kt allows to set the start time of the next karaoke syllable relative to the event’s start. ktLibassSupport (In absence of \kt tags the starting time is the sum of all previous karaoke syllable’s duration.)

While \kt is (the only tag) added by v4++ and several tags described by Aegisub are additions of ASS, renderers will accept and process them in any VSFilter-flavoured SSAv4, ASS or v4++ file — regardless of whether it already existed in this base format version.

Effects

Below, all valid effect types and their arguments are listed. fadeaway

You MUST NOT put valid effects names with invalid arguments or a wrong argument count into the field.
You MAY put an empty string or invalid effect names followed by any amount of arguments into the field; those will simply be ignored and no effect applied. invalidEffect

Effect name comes first and is followed by multiple arguments. Arguments are separated with semicolons ; from other arguments and the effect name. If an optional argument is omitted, there MUST be no trailing semicolons.

  • Banner;delay;lefttoright The text is scrolled horizontally across the screen; implies \q2.
    • delay is a positive integer ranging from 1 to 100 inclusive. This value controls the scrolling speed with lower values being faster.
    • lefttoright is optional and can be either 0 (default) or 1. If set to 1 the scrolling direction is left-to-right, otherwise it is right-to-left.
  • Scroll up;y1;y2;delay Scrolls the text across the screen from bottom to top. By convention y1 SHOULD be smaller than y2. At the beginning the event is placed such that its top end is just below y2.
    • y1 the upper bound of the scrolling. The event is clipped beyond this point.
    • y2 the lower bound of the scrolling. The event is clipped beyond this point.
    • delay analogous to Banner’s delay parameter
  • Scroll down;y1;y2;delay Scrolls the text across the screen from top to bottom. At the beginning the event is placed such that its bottom end is just above y1. Otherwise the parameters are equivalent to Scroll up.

Appendix: Example File

[Script Info]
ScriptType: v4.00+
ScaledBorderAndShadow: yes
YCbCr Matrix: None
PlayResX: 640
PlayResY: 360
LayoutResX: 640
LayoutResY: 360
WrapStyle: 0

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,DejaVu Sans,65,&H007F67D0,&H00187DC1,&H00000000,&H00D4AA86,-1,0,0,0,100,100,0,0,1,0.4,0,7,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Comment: 0,0:00:00.00,0:00:06.99,Default,,0,0,0,,Placeholder; replace with proper type later
Dialogue: 0,0:00:00.00,0:00:06.99,Default,,0,0,0,,{\pos(52,72)\an7\1c&HB3B3B3&\p1}m 2 34 l 8 60 112 37 107 24{\p0}
Dialogue: 0,0:00:00.00,0:00:06.99,Default,,0,0,0,,{\q2\shad0\bord2\fs36\org(126.31,107.61)\pos(128.85,116.69)\fax-0.068131\fscx207.70\fscy50.43\frz4.2185\frx25.9522\fry63.2018}Bakery

Appendix: Editors

Editors may add additional sections with authoring or program-specific metadata. E.g. Aegisub has [Aegisub Project Garbage] and [Aegisub Extradata].

Old versions of Aegisub directly dumped this info into [Script Info], but this SHOULD be avoided. A custom, namespaced section is preferable.
If the custom section is short, prefer placing it after [Script Info], if its long or has no definitive bound on possible length, prefer placing it at the very end of the file.

Ideally, this extra data is stripped for the final export of the finished project.

Appendix: Breaking the Rules

Technically standard renderers are more flexible about the layout etc than whats documented here, but e.g. muxers and other tools are usually more strict about this.

But even between renderers there might be problems when straying too far from the recommendations laid out here. In theory all renderers are supposed to match the authoritative implementation, but in practice there are some bugs and missing features. (As some footnotes already pointed out).
There have also been cases of differences due to misuse of libass’ API apiMisuse, but if following this document’s guidelines they too will be avoided.

Thus a file breaking the rules described here may still work fine and perhaps even still work the same across all renderers, but with each deviation it becomes more likely to run into problems.

Therefore it is once again strongly recommended to follow the guidelines laid out here when generating ASS files.


Footnote Text:

v4++: As of writing (2023-12), the v4++ format is barely supported outside of VSFilter itself apart from the \kt override tag.

sbas-no: There is absolutely no benefit in using ScaledBorderAndShadow: no. It only make things more confusing and exists solely for some degree of backwards compatibility with the original Sub Station Alpha.

ycbcr: However, some libass users do not follow the colour mangling instructions laid out in ass_types.h and always act like None regardless. Also some software is unfortunately buggy with values other than *.601, *.709 or None and some struggle(s|ed) even with None.
Following the recommendations should allow you to avoid all those issues.

q3: Note, VSFilters also support a value of 3 for which lines are automatically broken like in \q0, but while trying to keep upper lines shorter than lower ones. This mode is unsupported in libass and just treated the same as 0. Do NOT use 3. If you wish to achieve a specific linebreaking style, instead use 2/\q2 with explicit forced linebreaks \N.

isr-fp: MPC-HC ISR does not accept floating point values in most places and neither did the original guliverkli(2) VSFilter. However, all other renderers do support it for a long time already and floating point values are already widely used in existing releases.

ktLibassSupport: \kt is supported in libass since release 0.17.0 (released 2022-11-30; commit merged 2022-10-14). It has been supported in VSFilter since guliverkli r453, release 2.37 (both 2005-11-25).

AlphaLevel: In genuine Sub Station Alpha SSAv4, AlphaLevel has no effect.

hoursEditors: At the time of writing (2024-01-07), Aegisub and potetntially Kainote don’t easily allow creating multi-digit hour timestamps. The latter even truncates parsed timestamps to less than 10h atm.
There is no reason for this in any recent’ish renderers and muxers, so this limit is expected to be lifted soon.

fadeaway: For all effect types, VSFilter also supports an additional, optional fadeaway parameter after the ones listed here. This is currently not yet supported by libass and thus MUST NOT be used.

invalidEffect: During the authoring process invalid effects being ignored is often abused to tag raw lines for processing by scripts.

apiMisuse: Admittedly those API misuses are most likely to blame on our documentation having been rather poor in the past (and probably still not perfect; patches welcome).
In the past some API users forgot to relay the storage size to libass, resulting in files without LayoutRes{X,Y} headers rendering wrong. All known cases have been fixed by now though.
The other known and still not fully fixed misuse is not correctly mangling colours; see footnote ycbcr.