ass (“Advanced SubStation Alpha” (v4.00+))

doc

https://ffmpeg.org/ffmpeg-filters.html#subtitles-1, https://ffmpeg.org/ffmpeg-filters.html#ass, https://en.wikipedia.org/wiki/SubStation_Alpha, http://moodub.free.fr/video/ass-specs.doc

Note

I believed that the format of the timestamp is “00:00:00.00”. And still ffmpeg’s ass engine accepts this without a problem. However, the specification is actually:

0:00:00:00 format ie. Hrs:Mins:Secs:hundredths. … . Note that there is a single digit for the hours!

Therefore, be careful if you want to use `ass’ from other than ffmpeg.

simple example

Watch on youtube.com

Texts embeded in this video was made by using with “Advanced SubStation Alpha (v4.00+)” like this:

desc.ass
[Script Info]
PlayResY: 600
WrapStyle: 1

[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: Code, monospace,20,&H00B0B0B0,&H00B0B0B0,&H00303030,&H80000008,-1,0,0,0,100,100,0.00,0.00,1,1.00,2.00, 7 ,30,10,30,0
Style: Expl, Arial,28,&H00FFB0B0,&H00B0B0B0,&H00303030,&H80000008,-1,0,0,0,100,100,0.00,0.00,1,1.00,2.00, 7 ,30,10,30,0

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,00:00:00.00,00:03:00.00,Expl, NTP,0,0,0,,{\pos(20,20)}To split audio stream into several bands, you can use `lowpass', `bandpass', `highpass', etc., but in recent ffmpeg you can also use `acrossover'.\N\NThough it is unclear how to use it due to the lack of explanation of the official document, it seems to be used like this.
Dialogue: 0,00:00:00.00,00:03:00.00,Code, NTP,0,0,0,,{\pos(40,160)}#! /bin/sh\Nifn="Air on the G String (from Orchestral Suite no. 3, BWV 1068).mp3"\Nifnb="`basename \"$\{ifn\}\" .mp3`"\Npref="`basename $0 .sh`"\N#\N"/c/Program Files/ffmpeg-4.1-win64-shared/bin/ffmpeg" -y \\N    -i "$\{ifn\}" -filter_complex "\N\N[0:a]acrossover=split='500 2000'[div1][div2][div3];\N\N[div1]asplit[div1_1][div1_2];\N[div2]asplit[div2_1][div2_2];\N[div3]asplit[div3_1][div3_2];\N\N[div1_2]showcqt=s=1920x1080[v1];\N[div2_2]showcqt=s=1920x1080[v2];\N[div3_2]showcqt=s=1920x1080[v3]" \\N    -map '[v1]' -map '[div1_1]' "$\{pref\}_$\{ifnb\}_1.mp4" \\N    -map '[v2]' -map '[div2_1]' "$\{pref\}_$\{ifnb\}_2.mp4" \\N    -map '[v3]' -map '[div3_1]' "$\{pref\}_$\{ifnb\}_3.mp4"
Dialogue: 0,00:00:00.00,00:03:00.00,Expl, NTP,0,0,0,,{\pos(20,550)}(Note: Uploaded video is of `div2'.)
[me@host: ~]$ ffmpeg -y -i input.mp4 -vf "subtitles=desc.ass" -c:a copy output.mp4

To use various fonts

see also

ImageFont Module (Python Pillow examples)

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, Alignment, Encoding
Style: F1, impact,70,&H30FF30,7,0
Style: F2, comic sans ms,70,&H30FF30,7,0
Style: F3, ar christy,70,&H30FF30,7,0
Style: F4, ar carter,120,&H30FF30,7,0
Style: F5, ar bonnie,72,&H30FF30,7,0
Style: F6, levenim mt,60,&H30FF30,7,0
Style: F7, segoe script,66,&H30FF30,7,0
Style: F8, segoe print,80,&H30FF30,7,0
Style: F9, segoe print bold,80,&H30FF30,7,0

[Fonts]
impact: impact.ttf
comic sans ms: comic.ttf
ar christy: ARCHRISTY.ttf
ar carter: ARCARTER.ttf
ar bonnie: ARBONNIE.ttf
levenim mt: lvnm.ttf
segoe script: segoesc.ttf
segoe print: segoepr.ttf
segoe print bold: segoeprb.ttf

[Events]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:10.00,F1,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:10.00,0:00:20.00,F2,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:20.00,0:00:30.00,F3,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:30.00,0:00:40.00,F4,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:40.00,0:00:50.00,F5,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:50.00,0:01:00.00,F6,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:01:00.00,0:01:10.00,F7,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:01:10.00,0:01:20.00,F8,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:01:20.00,0:01:30.00,F9,{\pos(260,320)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Watch on youtube.com

Alignment

In the case of V4.00+, the values of this is so-called “numpad layout”.

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, Alignment, Encoding
Style: A1, Arial,34,&H3030FF,1,0
Style: A2, Arial,34,&H3030FF,2,0
Style: A3, Arial,34,&H3030FF,3,0
Style: A4, Arial,34,&H3030FF,4,0
Style: A5, Arial,34,&H3030FF,5,0
Style: A6, Arial,34,&H3030FF,6,0
Style: A7, Arial,34,&H3030FF,7,0
Style: A8, Arial,34,&H3030FF,8,0
Style: A9, Arial,34,&H3030FF,9,0

[Events]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:10.00,A1,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:10.00,0:00:20.00,A2,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:20.00,0:00:30.00,A3,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:30.00,0:00:40.00,A4,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:40.00,0:00:50.00,A5,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:00:50.00,0:01:00.00,A6,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:01:00.00,0:01:10.00,A7,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:01:10.00,0:01:20.00,A8,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Dialogue: 0:01:20.00,0:01:30.00,A9,{\pos(600,400)}The quick brown fox jumps over a lazy dog.\NSphinx of black quartz, judge my vow.
Watch on youtube.com

BorderStyle, Outline, Shadow

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, OutlineColour, BackColour, BorderStyle, Outline, Shadow, Alignment, Encoding
Style: S01, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 0, 0, 0, 7, 0
Style: S02, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 1, 0, 7, 0
Style: S03, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 2, 0, 7, 0
Style: S04, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 3, 0, 7, 0
Style: S05, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 4, 0, 7, 0
Style: S06, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 0, 1, 7, 0
Style: S07, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 0, 2, 7, 0
Style: S08, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 0, 3, 7, 0
Style: S09, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 0, 4, 7, 0
Style: S10, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 4, 2, 7, 0
Style: S11, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 1, 2, 4, 7, 0
Style: S12, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 3, 0, 0, 7, 0
Style: S13, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 3, 1, 0, 7, 0
Style: S14, Arial, 70, &HFFFFFF, &HFF0000, &H555555, 3, 0, 1, 7, 0

[Events]
Format: Start, End, Style, Text
Dialogue: 00:00:00.00,00:00:10.00,S01,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:10.00,00:00:20.00,S02,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:20.00,00:00:30.00,S03,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:30.00,00:00:40.00,S04,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:40.00,00:00:50.00,S05,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:50.00,00:01:00.00,S06,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:00.00,00:01:10.00,S07,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:10.00,00:01:20.00,S08,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:20.00,00:01:30.00,S09,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:30.00,00:01:40.00,S10,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:40.00,00:01:50.00,S11,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:50.00,00:02:00.00,S12,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:02:00.00,00:02:10.00,S13,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:02:10.00,00:02:20.00,S14,{\pos(20,40)}The quick brown fox jumps over a lazy dog.
Watch on youtube.com

Note

The documentation doesn’t explain the behaviour of “Outline” and “Shadow” when “BorderStyle=3”. It seems that the ass engine uses “Outline” or “Shadow” as background color if you specify non-zero to these when “BorderStyle=3”.

Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle

You’ll be happier if you read style override codes first before this.

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, Bold, Italic, Underline, StrikeOut, Alignment, Encoding
Style: S1, Arial,60,&HFFB0B0,-1, 0, 0, 0, 7, 0
Style: S2, Arial,60,&HFFB0B0, 0,-1, 0, 0, 7, 0
Style: S3, Arial,60,&HFFB0B0, 0, 0,-1, 0, 7, 0
Style: S4, Arial,60,&HFFB0B0, 0, 0, 0,-1, 7, 0

[Events]
Format: Start, End, Style, Text
Dialogue: 00:00:00.00,00:00:10.00,S1,{\pos(60,100)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:10.00,00:00:20.00,S2,{\pos(60,100)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:20.00,00:00:30.00,S3,{\pos(60,100)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:30.00,00:00:40.00,S4,{\pos(60,100)}The quick brown fox jumps over a lazy dog.
[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, ScaleX, ScaleY, Spacing, Angle, Alignment, Encoding
Style: S1, Arial,60,&HFFB0B0,  150,  100,  0.00,  0.00, 7, 0
Style: S2, Arial,60,&HFFB0B0,  100,  150,  0.00,  0.00, 7, 0
Style: S3, Arial,60,&HFFB0B0,  100,  100,  4.00,  0.00, 7, 0
Style: S4, Arial,60,&HFFB0B0,  100,  100,  0.00, -5.00, 7, 0

[Events]
Format: Start, End, Style, Text
Dialogue: 00:00:00.00,00:00:10.00,S1,{\pos(50,100)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:10.00,00:00:20.00,S2,{\pos(50,100)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:20.00,00:00:30.00,S3,{\pos(50,100)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:30.00,00:00:40.00,S4,{\pos(50,100)}The quick brown fox jumps over a lazy dog.
Watch on youtube.com

style override codes

Apart from the global style that you can describe in [V4+ Styles] section, you can use `style override code’ in each `Dialogue’ event:

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Alignment, Encoding
Style: S1, Arial,60,&HFFB0B0,&HFFFF00,&H998877,&H773030,7,0

[Events]
Format: Start, End, Style, Text
Dialogue: 00:00:00.00,00:00:10.00,S1,{\pos(60,100)}The quick {\b1}brown{\b0} fox jumps over a lazy dog.
Dialogue: 00:00:10.00,00:00:20.00,S1,{\pos(60,100)}The quick {\i1}brown{\i0} fox jumps over a lazy dog.
Dialogue: 00:00:20.00,00:00:30.00,S1,{\pos(60,100)}The quick {\u1}brown{\u0} fox jumps over a lazy dog.
Dialogue: 00:00:30.00,00:00:40.00,S1,{\pos(60,100)}The quick {\s1}brown{\s0} fox jumps over a lazy dog.
Dialogue: 00:00:40.00,00:00:50.00,S1,{\pos(60,100)}The quick {\s1}brown{\r} fox jumps over a lazy dog.
Dialogue: 00:00:50.00,00:01:00.00,S1,{\pos(60,100)}\bord uses {\bord3}OutlineColour{\r} in [V4+ Styles] section as a border.
Dialogue: 00:01:00.00,00:01:10.00,S1,{\pos(60,100)}\shad uses {\shad5}BackColour{\r} in [V4+ Styles] section as a shade.
Dialogue: 00:01:10.00,00:01:20.00,S1,{\pos(60,100)}The quick {\fnCourier New}brown{\r} fox jumps over a lazy dog.
Dialogue: 00:01:20.00,00:01:30.00,S1,{\pos(60,100)}{\fs80}T{\r}he quick brown fox jumps over a lazy dog.
Dialogue: 00:01:30.00,00:01:40.00,S1,{\pos(60,100)}{\fscy200}T{\r}he quick brown fox jumps over a lazy dog.
Dialogue: 00:01:40.00,00:01:50.00,S1,{\pos(60,100)}The quick brown fox jumps over a {\fscx250}lazy{\r} dog.
Dialogue: 00:01:50.00,00:02:00.00,S1,{\pos(60,100)}The quick brown fox jumps over a{\fsp20} lazy {\r}dog.
Dialogue: 00:02:00.00,00:02:10.00,S1,{\pos(60,100)}{\frx350}The quick brown fox jumps over a lazy dog.{\r}
Dialogue: 00:02:10.00,00:02:20.00,S1,{\pos(60,100)}{\fry350}The quick brown fox jumps over a lazy dog.{\r}
Dialogue: 00:02:20.00,00:02:30.00,S1,{\pos(60,100)}{\frz350}The quick brown fox jumps over a lazy dog.{\r}
Dialogue: 00:02:30.00,00:02:40.00,S1,{\pos(60,100)}The quick brown {\c&HFF0000&}fox{\r} {\c&HFF}jumps{\r} over a lazy {\c&FF00&}dog{\r}.
Dialogue: 00:02:40.00,00:02:50.00,S1,{\pos(60,100)}{\k150}\k {\k150}uses {\k300}PrimaryColour {\k100}and {\k300}SecondaryColour.
Dialogue: 00:02:50.00,00:03:00.00,S1,{\pos(60,100)}{\K150}\K {\K150}uses {\K300}PrimaryColour {\K100}and {\K300}SecondaryColour.
Watch on youtube.com

Functions:

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Alignment, Encoding
Style: S1, Arial,60,&HFFB0B0,&HFFFF00,&H998877,&H773030,7,0

[Events]
Format: Start, End, Style, Text
Dialogue: 00:00:00.00,00:00:10.00,S1,{\pos(60,100)}{\t(0,10000,0.5,\fscy200)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:10.00,00:00:20.00,S1,{\pos(60,100)}{\t(0,10000,1,\fscy200)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:20.00,00:00:30.00,S1,{\pos(60,100)}{\t(0,10000,2,\fscy200)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:30.00,00:00:40.00,S1,{\pos(60,100)}{\t(0,5000,0.5,\fscy200)}{\t(5000,10000,2,\c&HFF&)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:40.00,00:00:50.00,S1,{\move(60,100,150,250,0,5000)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:00:50.00,00:01:00.00,S1,{\move(60,100,150,250,1000,10000)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:00.00,00:01:10.00,S1,{\pos(60,100)}{\fade(255,0,255,0,4000,6000,10000)}The quick brown fox jumps over a lazy dog.
Dialogue: 00:01:10.00,00:01:20.00,S1,{\pos(60,100)}{\fad(4000,4000)}The quick brown fox jumps over a lazy dog.
Watch on youtube.com

`Effect’ field

You can specify some `Effect’ in each `Dialogue’ event. But don’t expect too much to it. I don’t think this is useful.

[Script Info]
PlayResX: 1280
PlayResY: 720
WrapStyle: 1

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, Alignment, Encoding
Style: S1, Arial,70,&HB0FFB0,1,0

[Events]
Format: Start, End, Style, Effect, Text
Dialogue: 0:00:00.00,0:00:10.00,S1,Scroll up;300;100;0,The quick brown fox jumps over a lazy dog.
Dialogue: 0:00:10.00,0:00:20.00,S1,Scroll up;300;100;1,The quick brown fox jumps over a lazy dog.
Dialogue: 0:00:20.00,0:00:30.00,S1,Scroll up;300;100;10,The quick brown fox jumps over a lazy dog.
Dialogue: 0:00:30.00,0:00:40.00,S1,Scroll up;300;100;50,The quick brown fox jumps over a lazy dog.
Dialogue: 0:00:40.00,0:00:50.00,S1,Scroll down;100;300;0,The quick brown fox jumps over a lazy dog.
Dialogue: 0:00:50.00,0:01:00.00,S1,Scroll down;100;300;1,The quick brown fox jumps over a lazy dog.
Dialogue: 0:01:00.00,0:01:10.00,S1,Scroll down;100;300;10,The quick brown fox jumps over a lazy dog.
Dialogue: 0:01:10.00,0:01:20.00,S1,Scroll down;100;300;50,The quick brown fox jumps over a lazy dog.
Dialogue: 0:01:20.00,0:01:30.00,S1,Banner;0,The quick brown fox jumps over a lazy dog. Sphinx of black quartz, judge my vow.
Dialogue: 0:01:30.00,0:01:40.00,S1,Banner;1,The quick brown fox jumps over a lazy dog. Sphinx of black quartz, judge my vow.
Dialogue: 0:01:40.00,0:01:50.00,S1,Banner;2,The quick brown fox jumps over a lazy dog. Sphinx of black quartz, judge my vow.
Dialogue: 0:01:50.00,0:02:00.00,S1,Banner;5,The quick brown fox jumps over a lazy dog. Sphinx of black quartz, judge my vow.
Watch on youtube.com

You can’t specify x-position when you use `Scroll up/down’, and you can’t specify y-position when you use 'Banner’. At best you can only specify 'Alignment’, MarginL’, `MarginR’, and `MarginV’. If you really want to control this, do it in a way outside of the “ass” like this:

#! /bin/sh
ffmpeg -i aaa.mp4 -filter_complex "
[0:v]scale=1920:1080,setsar=1[cont];
color=black:s=1280:720,loop=-1:size=2,subtitle=aaa.ass,colorkey=black,setsar=1[st];
[cont][st]overlay=x=30:y=50:shortest=1
" out.mp4