{"id":30113735,"url":"https://github.com/luxluth/ass-html5","last_synced_at":"2026-04-01T22:14:53.287Z","repository":{"id":180082553,"uuid":"664556941","full_name":"luxluth/ass-html5","owner":"luxluth","description":"Display ASS/SSA subtitles for html video","archived":false,"fork":false,"pushed_at":"2026-03-21T20:59:55.000Z","size":705,"stargazers_count":19,"open_issues_count":5,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-22T09:38:07.488Z","etag":null,"topics":["aegisub","ass-subtitles","html-canvas","html5","javascript","libass","ssa-subtitles","subtitles","typescript"],"latest_commit_sha":null,"homepage":"https://asshtml5.luxluth.dev/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luxluth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-10T08:39:57.000Z","updated_at":"2026-03-21T20:59:09.000Z","dependencies_parsed_at":"2025-12-29T13:03:36.931Z","dependency_job_id":null,"html_url":"https://github.com/luxluth/ass-html5","commit_stats":null,"previous_names":["luxluth/ass-html5"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/luxluth/ass-html5","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxluth%2Fass-html5","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxluth%2Fass-html5/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxluth%2Fass-html5/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxluth%2Fass-html5/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luxluth","download_url":"https://codeload.github.com/luxluth/ass-html5/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxluth%2Fass-html5/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aegisub","ass-subtitles","html-canvas","html5","javascript","libass","ssa-subtitles","subtitles","typescript"],"created_at":"2025-08-10T07:27:47.433Z","updated_at":"2026-04-01T22:14:53.264Z","avatar_url":"https://github.com/luxluth.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# ass-html5\n\nDisplay ASS/SSA subtitles on html5 videos\n\n![CI workflow](https://github.com/luxluth/ass-html5/actions/workflows/main.yml/badge.svg)\n![Publish workflow](https://github.com/luxluth/ass-html5/actions/workflows/publish.yml/badge.svg)\n![License](https://img.shields.io/github/license/luxluth/ass-html5?color=blue)\n![npm bundle size](https://img.shields.io/bundlephobia/min/ass-html5)\n![npm](https://img.shields.io/npm/v/ass-html5?logo=npm\u0026color=white\u0026link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fass-html5)\n\n\u003c/div\u003e\n\n## Table of Contents\n\n- [ass-html5](#ass-html5)\n  - [Table of Contents](#table-of-contents)\n  - [Installation](#installation)\n  - [Features](#features)\n  - [Usage](#usage)\n    - [Options](#options)\n    - [Simple HTML](#simple-html)\n    - [Svelte and Plry](#svelte-and-plry)\n    - [videojs](#videojs)\n- [Credits](#credits)\n\n## Installation\n\n```bash\npnpm add ass-html5\n```\n\n## Features\n\n- **Karaoke Support**: Full support for `\\k`, `\\kf`, `\\ko`, and `\\K` tags.\n- **Vector Drawings**: High-performance rendering of ASS vector paths (`\\p`) using `Path2D`.\n- **Clipping**: Support for rectangular and vector clipping/masking (`\\clip`, `\\iclip`).\n- **Advanced Transformations**:\n  - Rotation around all axes (`\\frz`, `\\frx`, `\\fry`).\n  - Scaling (`\\fscx`, `\\fscy`) and Shearing (`\\fax`, `\\fay`).\n  - Custom rotation origin (`\\org`).\n- **Smart Wrapping**: Implementation of `\\q` styles for optimal line breaking.\n- **Collision Handling**: Automatic vertical shifting to prevent overlapping subtitles.\n- **Blur Effects**: Edge blur (`\\be`) and Gaussian blur (`\\blur`) using Canvas filters.\n- **Performance Optimized**: Built-in layer caching to minimize redundant redraws.\n\n## Usage\n\n### Options\n\n| option  |                                                 description                                                 | required |             type              |        default        |\n| :-----: | :---------------------------------------------------------------------------------------------------------: | :------: | :---------------------------: | :-------------------: |\n| assText |                                             The ass text string                                             |    🚫    |           `string`            |      `undefined`      |\n| subUrl  |                                      URL to fetch the ASS content from                                      |    🚫    |           `string`            |      `undefined`      |\n|  video  | The video to display the subtile on. Can be either an `HTMLVideoElement` or `string` (html query selector ) |    ✅    | `HTMLVideoElement` / `string` |      `undefined`      |\n|  fonts  |                                            Custom fonts to load                                             |    🚫    |  [`Font[]`](src/ass.ts#L78)   |      `undefined`      |\n| zIndex  |                                        zIndex of the rendering frame                                        |    🚫    |           `number`            | Drawn after the video |\n| onReady |              A Callback that is invoked when the preprocess of the ass text by render is done               |    🚫    |         `() =\u003e void`          |      `undefined`      |\n| logging |                                               Type of logging                                               |    🚫    |  [`LOGTYPE`](src/ass.ts#L50)  |   `LOGTYPE.DISABLE`   |\n\n\u003e One of `assText` or `subUrl` is required.\n\n### Simple HTML\n\n\u003e [!NOTE]\n\u003e The simple `video` tag element, in fullscreen mode, the position of the video is absolutely on top of any element.\n\u003e No other element can go on top of it.\n\u003e\n\u003e It's therefore recommended to use a third party player rather than the native one. You can see an example with [plry](https://github.com/sampotts/plyr) [here](#svelte-and-plry).\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/ass-html5@0.6.0/dist/ass.min.js\"\u003e\u003c/script\u003e\n```\n\n```html\n\u003cvideo src=\"/assets/video.mp4\" id=\"video\" controls\u003e\u003c/video\u003e\n```\n\n```html\n\u003cscript\u003e\n  document.addEventListener('DOMContentLoaded', async () =\u003e {\n    // Using subUrl to fetch subtitle automatically\n    const ass = new ASS.default({\n      subUrl: '/assets/video.ass',\n      video: document.getElementById('video')\n    });\n    await ass.render();\n\n    // You can switch subtitles dynamically:\n    // await ass.setSubUrl('/assets/other.ass');\n    // OR\n    // await ass.setAssText('[Script Info]...');\n  });\n\u003c/script\u003e\n```\n\n### [Svelte](https://github.com/sveltejs/svelte) and [Plry](https://github.com/sampotts/plyr)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n    import video from '$lib/assets/video.mp4'\n    import cc from '$lib/assets/cc.ass?url'\n    import ASS from 'ass-html5'\n    import { onMount } from 'svelte';\n    import Plyr from 'plyr'\n\n    const ass = new ASS({\n        subUrl: cc,\n        video: \"#video-test\"\n    })\n\n    let vidElement: HTMLVideoElement\n    let player: Plyr\n    onMount(async () =\u003e {\n        player = new Plyr(vidElement)\n        await ass.render()\n    })\n\n\u003c/script\u003e\n\n\u003cdiv class=\"video-container\"\u003e\n    \u003c!-- svelte-ignore a11y-media-has-caption --\u003e\n    \u003cvideo\n        preload=\"metadata\"\n        src=\"{video}\"\n        id=\"video-test\"\n        controls\n        autoplay\n        class=\"vid\"\n        bind:this={vidElement}\n    \u003e\u003c/video\u003e\n\u003c/div\u003e\n```\n\n### [videojs](https://github.com/videojs/video.js)\n\nIn the `head` :\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/ass-html5@0.6.2/dist/ass.min.js\" defer\u003e\u003c/script\u003e\n\u003cscript src=\"https://vjs.zencdn.net/8.3.0/video.min.js\" defer\u003e\u003c/script\u003e\n\u003clink href=\"https://vjs.zencdn.net/8.3.0/video-js.css\" rel=\"stylesheet\" /\u003e\n```\n\nIn the `body` :\n\n```html\n\u003cvideo\n  id=\"my-video\"\n  class=\"video-js\"\n  controls\n  preload=\"auto\"\n  width=\"1280\"\n  height=\"720\"\n  data-setup=\"{}\"\n\u003e\n  \u003csource src=\"assets/video.mp4\" type=\"video/mp4\" /\u003e\n\u003c/video\u003e\n```\n\nIn the `script` tag :\n\n```html\n\u003cscript\u003e\n  document.addEventListener('DOMContentLoaded', async () =\u003e {\n    let res = await fetch('/assets/video.ass');\n    let assSubs = await res.text();\n\n    var player = videojs('my-video');\n\n    player.ready(async () =\u003e {\n      // Get the video element from the player\n      var videoElement = player.el().getElementsByTagName('video')[0];\n      const ass = new ASS.default({\n        assText: assSubs,\n        video: videoElement\n      });\n      await ass.render();\n    });\n  });\n\u003c/script\u003e\n```\n\n---\n\n# Credits\n\nThanks to the [ass-compiler](https://github.com/weizhenye/ass-compiler/) by weizhenye.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluxluth%2Fass-html5","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluxluth%2Fass-html5","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluxluth%2Fass-html5/lists"}