# 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)
Raw data
{
"_id": null,
"home_page": "http://github.com/chireiden/python-ass",
"name": "ass",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "ass subtitle substation alpha",
"author": "Tony Young",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/f0/20/f40eb4e64989fdddae3330468e4555f64b7234338b4e02952f3e442f3790/ass-0.5.4.tar.gz",
"platform": null,
"description": "# python-ass\n\nA library for parsing and manipulating\nAdvanced SubStation Alpha subtitle files.\n\n## Documents\n\nExample file: [**tests/test.ass**](./tests/test.ass)\n\nYou can parse the file:\n\n```py\n>>> import ass\n>>> with open(\"tests/test.ass\", encoding='utf_8_sig') as f:\n... doc = ass.parse(f)\n...\n```\n\nAccess its meta info:\n\n```py\n>>> doc.info\nScriptInfoSection('Script Info', OrderedDict([('ScriptType', 'v4.00+'), ('PlayResX', 500), ('PlayResY', 500)]))\n>>> doc.info['PlayResX']\n500\n```\n\nAccess its styles:\n\n```py\n>>> doc.styles\nStylesSection('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)])\n>>> doc.styles[0].fontname\n'Arial'\n>>> doc.styles[0].primary_color # \"color\", not \"colour\"\nColor(r=0xff, g=0xff, b=0xff, a=0x00)\n```\n\nAccess its event lines:\n\n```py\n>>> doc.events\nEventsSection('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'), ...])\n>>> doc.events[0].text\n'{\\\\3c&H0000FF}this is a test\\\\N{\\\\3c&H00FF00}this is a test\\\\N{\\\\3c&HFF0000}this is a test'\n```\n\nOr any other section data:\n\n```py\n>>> list(doc.sections.keys())\n['Script Info', 'Aegisub Project Garbage', 'Custom Section', 'V4+ Styles', 'Events', 'Aegisub Extradata']\n>>> doc.sections['Aegisub Project Garbage']['Scroll Position']\n'30'\n```\n\nYou can dump everything out into ASS format, too:\n\n```py\n>>> doc.events[0].dump()\n'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'\n```\n\nOr maybe the whole file:\n\n```py\n>>> with open(\"out.ass\", \"w\", encoding='utf_8_sig') as f:\n... doc.dump_file(f)\n...\n```\n\n\n## Tags\n\nFor parsing ASS tags, you may want to consider `ass-tag-parser`:\n<https://pypi.org/project/ass-tag-parser/>\n(on [GitHub](https://github.com/rr-/ass_tag_parser)).\n\n\n## Rendering\n\n*The following has been unmaintained for years.*\n\npython-ass can use libass for rendering.\n\nFirst you need to allocate a libass context:\n\n >>> ctx = ass.renderer.Context()\n\nThen you need to convert the `ass.document.Document` to a `ass.renderer.Track`:\n\n >>> t = ctx.make_track()\n >>> t.populate(doc)\n\nThen make a renderer to render the track:\n\n >>> r = ctx.make_renderer()\n >>> r.set_fonts(fontconfig_config=\"/usr/local/etc/fonts/fonts.conf\")\n >>> r.set_all_sizes((1280, 720))\n\nYou can render a frame at a given time:\n\n >>> imgs = r.render_frame(t, timedelta(0))\n\nExample using PIL to render to a bitmap:\n\n >>> im_out = Image.new(\"RGB\", (1280, 720))\n >>> im_data = im_out.load()\n >>> for img in imgs:\n ... r, g, b, a = img.rgba\n ... for y in range(img.h):\n ... for x in range(img.w):\n ... a_src = img[x, y] * (256 - a) // 256\n ... r_dst, g_dst, b_dst = im_data[x + img.dst_x, y + img.dst_y]\n ... r_out = ((r * a_src) + (r_dst * (256 - a_src))) // 256\n ... g_out = ((g * a_src) + (g_dst * (256 - a_src))) // 256\n ... b_out = ((b * a_src) + (b_dst * (256 - a_src))) // 256\n ... im_data[x + img.dst_x, y + img.dst_y] = (r_out, g_out, b_out)\n ...\n >>> im_out.show()\n\n### Sample Rendering (from `renderer_test.py`)\n\n![Test rendering](test.png)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A library for parsing and manipulating Advanced SubStation Alpha subtitle files.",
"version": "0.5.4",
"project_urls": {
"Homepage": "http://github.com/chireiden/python-ass"
},
"split_keywords": [
"ass",
"subtitle",
"substation",
"alpha"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "622d47532f60716fa4f76320358871f3edce28d6c2ce1ae1d1f31306270edf0e",
"md5": "8810e8ed261baae2944bbe90acd46fc4",
"sha256": "8da7d606bfed9f655a10611dc542936182b15438da5b9515205334990906e2c8"
},
"downloads": -1,
"filename": "ass-0.5.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8810e8ed261baae2944bbe90acd46fc4",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 14569,
"upload_time": "2023-07-04T00:42:03",
"upload_time_iso_8601": "2023-07-04T00:42:03.282691Z",
"url": "https://files.pythonhosted.org/packages/62/2d/47532f60716fa4f76320358871f3edce28d6c2ce1ae1d1f31306270edf0e/ass-0.5.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f020f40eb4e64989fdddae3330468e4555f64b7234338b4e02952f3e442f3790",
"md5": "7f2229cb42fe1e8213110c9279e8ce28",
"sha256": "7b3db1929d975121a3e449f38ce7747bfaa88ea4aa1202cd84c14fa85d3ba5d0"
},
"downloads": -1,
"filename": "ass-0.5.4.tar.gz",
"has_sig": false,
"md5_digest": "7f2229cb42fe1e8213110c9279e8ce28",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15223,
"upload_time": "2023-07-04T00:42:07",
"upload_time_iso_8601": "2023-07-04T00:42:07.249132Z",
"url": "https://files.pythonhosted.org/packages/f0/20/f40eb4e64989fdddae3330468e4555f64b7234338b4e02952f3e442f3790/ass-0.5.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-04 00:42:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "chireiden",
"github_project": "python-ass",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "ass"
}