# SubStation Alpha and ASS

Canonical URL: https://encode.wiki/codecs/subtitles/ssa/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): 85b65133f5635db2c09de84f0feba507bd5e7464e1e47d1368adaacf64c32f49

SubStation Alpha (SSA, `.ssa`) and its successor Advanced SubStation Alpha (ASS, `.ass`) are text subtitle formats with full control over fonts, colours, outlines, positioning, rotation, animation, karaoke and vector drawings. Anime fansubs, music videos and anything with typeset signs use ASS. The original SubStation Alpha program is long abandoned; the format lives on through [libass](https://github.com/libass/libass), the renderer used by mpv, VLC, FFmpeg, Jellyfin and most players on Linux and Windows, and through editors such as Aegisub and Subtitle Edit.

Players that do not use libass (most TVs, phones, browsers, Apple software) render ASS poorly or not at all. For those, deliver [SRT](/codecs/subtitles/srt/), or burn the subtitles in.

## File structure

```ini
[Script Info]
ScriptType: v4.00+
PlayResX: 1280
PlayResY: 720
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.709

[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,Noto Sans,44,&H00FFFFFF,&H000000FF,&H00000000,&H80000000,0,0,0,0,100,100,0,0,1,2,0,2,48,48,36,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:01.00,0:00:03.50,Default,,0,0,0,,The test begins here.
Dialogue: 0,0:00:04.00,0:00:07.00,Default,,0,0,0,,{\an8\i1}Top of the frame{\i0}\Nsecond line
```

- **`[Script Info]`** sets `PlayResX`/`PlayResY`, the coordinate space all sizes, margins and positions are measured in. libass scales that space to the video, so a script written for 1280×720 still fits 1080p. `ScaledBorderAndShadow: yes` makes outlines scale with it. `YCbCr Matrix` tells the renderer which matrix the video uses, so subtitle colours match colours sampled from the video: set it to the video's range and matrix (`TV.709` for ordinary HD), or `None` for anything that is not BT.601 or BT.709, such as HDR.
- **`[V4+ Styles]`** defines named styles. Events pick one by name; override tags change it per line.
- **`[Events]`** holds the `Dialogue:` lines. Times are `H:MM:SS.cc` (centiseconds, with a period). `\N` is a hard line break; the text field may contain commas.
- **Colours** are `&HAABBGGRR`: alpha first, then **blue, green, red**, the reverse of HTML. Alpha `00` is opaque and `FF` is transparent, so `&H00FFFFFF` is opaque white. Inside override tags the form is `&HBBGGRR&`.
- Lines starting with `;` are comments, and `Comment:` events are ignored by renderers.

## Override tags worth knowing

Tags go in `{braces}` inside the text, and `{\i1}…{\i0}` toggles for part of a line. The full list is in [Aegisub's reference](https://aegisub.org/docs/latest/ass_tags/).

| Tag                     | Effect                                                                              |
| ----------------------- | ----------------------------------------------------------------------------------- |
| `\an1`…`\an9`           | Alignment on the numeric keypad layout (`\an8` is top centre, `\an2` bottom centre) |
| `\pos(x,y)`, `\move(…)` | Place text at a coordinate in the script space, or move it                          |
| `\b1`, `\i1`, `\u1`     | Bold, italic, underline                                                             |
| `\fnName`, `\fs40`      | Font and size                                                                       |
| `\c&HBBGGRR&`           | Primary colour; `\3c` outline, `\4c` shadow                                         |
| `\fad(in,out)`          | Fade in and out (milliseconds)                                                      |
| `\k`, `\kf`, `\ko`      | Karaoke timing (centiseconds)                                                       |
| `\p1`                   | Treat the text as a vector drawing                                                  |

## Fonts: attach them

ASS styles reference fonts by family name, and the viewer must have them. Fonts that are not installed fall back to a default and ruin typesetting. In Matroska, attach the font files to the MKV so mpv, VLC and other libass players load them automatically:

```sh
ffmpeg -i video.mkv -i subs.ass -map 0 -map 1 -c copy -attach NotoSans-Regular.ttf -metadata:s:t:0 mimetype=font/ttf output.mkv
mkvmerge -o output.mkv video.mkv subs.ass --attach-file NotoSans-Regular.ttf
mkvpropedit output.mkv --add-attachment NotoSans-Bold.ttf
```

Set one `-attach` and `mimetype` pair per font (`-metadata:s:t:1`, …). A font installed on your own machine hides a missing attachment, so test on a machine without it. Check that the licence of each font allows redistribution. To extract the fonts from an existing MKV: `ffmpeg -dump_attachment:t "" -i video.mkv` (it ends with "At least one output file must be specified", but the fonts are written), or `mkvextract video.mkv attachments 1 2 3`.

ASS only survives in Matroska. MP4 cannot hold ASS or fonts, and `-c:s mov_text` would reduce it to plain text.

## Burn in

```sh
ffmpeg -i video.mkv -vf ass=subs.ass -c:v libx264 -crf 18 -c:a copy output.mp4
ffmpeg -i video.mkv -vf subtitles=video.mkv -c:v libx264 -crf 18 -c:a copy output.mp4
```

`ass=` reads an `.ass` file. `subtitles=video.mkv` renders the file's first embedded subtitle track and loads its attached fonts (`si=1` picks the second). To use fonts from a folder instead, add `:fontsdir=/path/to/fonts`. Both filters need an FFmpeg built with libass.

## Converting

ASS to SRT or WebVTT keeps the words and basic italics/bold, and drops everything else; FFmpeg leaves `<font size>` wrappers and raw `{\an8}` tags in the SRT. SRT to ASS works cleanly and gives you a basic style to restyle in an editor. See the [subtitle overview](/codecs/subtitles/).
