# python-ass

A library for parsing and manipulating
Advanced SubStation Alpha subtitle files.

## Documents

Example file: [**tests/test.ass**](./tests/test.ass)

You can parse the file:

```py
>>> import ass
>>> with open("tests/test.ass", encoding='utf_8_sig') as f:
...     doc = ass.parse(f)
...
```

Access its meta info:

```py
>>> doc.info
ScriptInfoSection('Script Info', OrderedDict([('ScriptType', 'v4.00+'), ('PlayResX', 500), ('PlayResY', 500)]))
>>> doc.info['PlayResX']
500
```

Access its styles:

```py
>>> doc.styles
StylesSection('V4+ Styles', [Style(name='Default', fontname='Arial', fontsize=20.0, primary_color=Color(r=0xff, g=0xff, b=0xff, a=0x00), secondary_color=Color(r=0xff, g=0x00, b=0x00, a=0x00), outline_color=Color(r=0x00, g=0x00, b=0x00, a=0x00), back_color=Color(r=0x00, g=0x00, b=0x00, a=0x00), bold=False, italic=False, underline=False, strike_out=False, scale_x=100.0, scale_y=100.0, spacing=0.0, angle=0.0, border_style=1, outline=1.0, shadow=2.0, alignment=5, margin_l=10, margin_r=10, margin_v=10, encoding=1)])
>>> doc.styles[0].fontname
'Arial'
>>> doc.styles[0].primary_color  # "color", not "colour"
Color(r=0xff, g=0xff, b=0xff, a=0x00)
```

Access its event lines:

```py
>>> doc.events
EventsSection('Events', [Dialogue(layer=0, start=datetime.timedelta(0), end=datetime.timedelta(seconds=5), style='Default', name='', margin_l=0, margin_r=0, margin_v=0, effect='', text='{\\3c&H0000FF}this is a test\\N{\\3c&H00FF00}this is a test\\N{\\3c&HFF0000}this is a test'), ...])
>>> doc.events[0].text
'{\\3c&H0000FF}this is a test\\N{\\3c&H00FF00}this is a test\\N{\\3c&HFF0000}this is a test'
```

Or any other section data:

```py
>>> list(doc.sections.keys())
['Script Info', 'Aegisub Project Garbage', 'Custom Section', 'V4+ Styles', 'Events', 'Aegisub Extradata']
>>> doc.sections['Aegisub Project Garbage']['Scroll Position']
'30'
```

You can dump everything out into ASS format, too:

```py
>>> doc.events[0].dump()
'0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\\3c&H0000FF}this is a test\\N{\\3c&H00FF00}this is a test\\N{\\3c&HFF0000}this is a test'
```

Or maybe the whole file:

```py
>>> with open("out.ass", "w", encoding='utf_8_sig') as f:
...     doc.dump_file(f)
...
```


## Tags

For parsing ASS tags, you may want to consider `ass-tag-parser`:
<https://pypi.org/project/ass-tag-parser/>
(on [GitHub](https://github.com/rr-/ass_tag_parser)).


## Rendering

*The following has been unmaintained for years.*

python-ass can use libass for rendering.

First you need to allocate a libass context:

    >>> ctx = ass.renderer.Context()

Then you need to convert the `ass.document.Document` to a `ass.renderer.Track`:

    >>> t = ctx.make_track()
    >>> t.populate(doc)

Then make a renderer to render the track:

    >>> r = ctx.make_renderer()
    >>> r.set_fonts(fontconfig_config="/usr/local/etc/fonts/fonts.conf")
    >>> r.set_all_sizes((1280, 720))

You can render a frame at a given time:

    >>> imgs = r.render_frame(t, timedelta(0))

Example using PIL to render to a bitmap:

    >>> im_out = Image.new("RGB", (1280, 720))
    >>> im_data = im_out.load()
    >>> for img in imgs:
    ...     r, g, b, a = img.rgba
    ...     for y in range(img.h):
    ...         for x in range(img.w):
    ...             a_src = img[x, y] * (256 - a) // 256
    ...             r_dst, g_dst, b_dst = im_data[x + img.dst_x, y + img.dst_y]
    ...             r_out = ((r * a_src) + (r_dst * (256 - a_src))) // 256
    ...             g_out = ((g * a_src) + (g_dst * (256 - a_src))) // 256
    ...             b_out = ((b * a_src) + (b_dst * (256 - a_src))) // 256
    ...             im_data[x + img.dst_x, y + img.dst_y] = (r_out, g_out, b_out)
    ...
    >>> im_out.show()

### Sample Rendering (from `renderer_test.py`)

![Test rendering](test.png)
