# ASS.js (v2 by Shahzad)

[![GitHub Action](https://img.shields.io/github/actions/workflow/status/code-with-shahzad/assjs/ci.yml?logo=github)](https://github.com/code-with-shahzad/assjs/actions)
[![Codecov](https://img.shields.io/codecov/c/gh/code-with-shahzad/assjs?logo=codecov)](https://codecov.io/gh/code-with-shahzad/assjs)
[![License](https://img.shields.io/npm/l/assjs-v2)](https://github.com/code-with-shahzad/assjs/blob/master/LICENSE)
[![File size](https://img.shields.io/bundlephobia/minzip/assjs-v2)](https://bundlephobia.com/result?p=assjs-v2)

<span>・</span>
<a href="https://ass.js.org/">Online Demo</a>
<span>・</span>
<a href="https://github.com/weizhenye/ASS/wiki/ASS-%E5%AD%97%E5%B9%95%E6%A0%BC%E5%BC%8F%E8%A7%84%E8%8C%83">ASS Specs (zh-Hans)</a>
<span>・</span>
<a href="https://github.com/weizhenye/ass-compiler">ass-compiler</a>

---

**ASS.js** renders ASS subtitles on HTML5 videos using DOM elements with [almost full ASS feature support](https://github.com/weizhenye/ASS/wiki/Differences-with-Specs).

It’s **lightweight**, **accurate**, and **ideal for the web**, being around **60× smaller** than WebAssembly-based solutions:

| | Solution | Size |
| - | - | - |
| ASS.js | DOM | ![](https://img.shields.io/github/size/code-with-shahzad/assjs/dist%2Fass.min.js?label=main) |
| [JavascriptSubtitlesOctopus](https://github.com/libass/JavascriptSubtitlesOctopus) | WebAssembly | ![](https://img.shields.io/github/size/libass/JavascriptSubtitlesOctopus/assets%2Fjs%2Fsubtitles-octopus.js?branch=gh-pages&label=main) ![](https://img.shields.io/github/size/libass/JavascriptSubtitlesOctopus/assets%2Fjs%2Fsubtitles-octopus-worker.js?branch=gh-pages&label=worker) ![](https://img.shields.io/github/size/libass/JavascriptSubtitlesOctopus/assets%2Fjs%2Fsubtitles-octopus-worker.wasm?branch=gh-pages&label=wasm) |
| [JASSUB](https://github.com/ThaUnknown/jassub) | WebAssembly | ![](https://img.shields.io/github/size/ThaUnknown/jassub/dist%2Fjassub.umd.js?label=main) ![](https://img.shields.io/github/size/ThaUnknown/jassub/dist%2Fjassub-worker.js?label=worker) ![](https://img.shields.io/github/size/ThaUnknown/jassub/dist%2Fjassub-worker.wasm?label=wasm) |

WebAssembly solutions often require large fallback fonts to prevent CJK text from rendering as tofu.  
ASS.js uses the browser’s built-in font fallback, so **it works out of the box**.

---

## 📦 Installation

[![NPM Version](https://img.shields.io/npm/v/assjs-v2?logo=npm)](https://www.npmjs.com/package/assjs-v2)
[![jsDelivr](https://img.shields.io/jsdelivr/npm/hm/assjs-v2?logo=jsdelivr)](https://www.jsdelivr.com/package/npm/assjs-v2)
[![unpkg](https://img.shields.io/badge/unpkg-555?logo=unpkg)](https://unpkg.com/assjs-v2/)

```bash
npm install assjs-v2
````

### Importing

```html
<script type="module">
  import ASS from '/path/to/assjs-v2/dist/ass.min.js';
</script>
```

or via global script:

```html
<script src="/path/to/assjs-v2/dist/ass.global.min.js"></script>
<script>
  console.log(window.ASS);
</script>
```

---

## 🧩 Usage

```html
<div id="player">
  <video id="video" src="./example.mp4"></video>
  <div id="ass-container"></div>
</div>
```

```js
import ASS from 'assjs-v2';

const content = await fetch('/path/to/example.ass').then(res => res.text());

const ass = new ASS(content, document.querySelector('#video'), {
  container: document.querySelector('#ass-container'),
});
```

When initialized, `ASS` appends subtitle elements inside the container and automatically syncs the rendering area with the video.

Make sure your container overlaps the video properly:

```html
<div id="player" style="position: relative;">
  <video id="video" src="./example.mp4" style="position: absolute; top: 0; left: 0;"></video>
  <div id="ass-container" style="position: absolute; top: 0; left: 0;"></div>
</div>
```

If using the **native fullscreen button**, only the `<video>` goes fullscreen, hiding subtitles.
Instead, call:

```js
document.querySelector('#player').requestFullscreen();
```

---

## ⚙️ API Reference

### Initialization

```js
const ass = new ASS(content, video, {
  // Subtitles display inside this container
  container: document.getElementById('my-container'),

  // Controls how subtitle scaling is calculated
  resampling: 'video_width',
});
```

---

### Methods

```js
ass.show();     // Show subtitles
ass.hide();     // Hide subtitles
ass.destroy();  // Destroy instance
```

---

### Delay

```js
ass.delay = 5;   // Subtitles appear 5s later
ass.delay = -3;  // Subtitles appear 3s earlier
```

---

## 📐 Resampling

When the **ASS script resolution (PlayResX / PlayResY)** does not match the **video resolution**,
the `resampling` option controls how scaling behaves.

> Drawings and clips always follow the original script resolution.

| Value                      | Description                                                                                                                           |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `video_width`              | Scale based on video width. Example: 640×480 → scaled to 640×360, scale = 1280 / 640 = 2.                                             |
| `video_height` *(default)* | Scale based on video height. Example: 640×480 → scaled to 853×480, scale = 720 / 480 = 1.5.                                           |
| `script_width`             | Keep script resolution but scale using script width. May cause vertical cropping.                                                     |
| `script_height`            | Keep script resolution but scale using script height. Centered vertically.                                                            |
| `container`                | 🆕 **(New in v2)** — Script resolution automatically matches the **container size**. Ideal for responsive overlays or custom players. |

```js
ass.resampling = 'container';
```

---

## 🌐 Browser Compatibility

| Feature                     | Web API                                                                                                       | Chrome | Firefox | Safari |
| --------------------------- | ------------------------------------------------------------------------------------------------------------- | ------ | ------- | ------ |
| Auto resize                 | [ResizeObserver](https://caniuse.com/resizeobserver)                                                          | 64     | 69      | 13.1   |
| `\[i]clip`                  | [clip-path](https://caniuse.com/css-clip-path) / [path()](https://caniuse.com/mdn-css_types_basic-shape_path) | 88     | 97      | 13.1   |
| Animations (`\t`)           | [registerProperty()](https://caniuse.com/mdn-api_css_registerproperty_static)                                 | 78     | 128     | 16.4   |
| accel in `\t`               | [linear()](https://caniuse.com/mdn-css_types_easing-function_linear-function)                                 | 113    | 112     | 17.2   |
| `\q0`                       | [text-wrap: balance](https://caniuse.com/css-text-wrap-balance)                                               | 114    | 121     | 17.5   |
| BorderStyle=3 with `\bord0` | [@container](https://caniuse.com/mdn-css_at-rules_container_style_queries_for_custom_properties)              | 111    | -       | 18.0   |
| `\blur` with `\bord0`       | [round()](https://caniuse.com/mdn-css_types_round)                                                            | 125    | 118     | 15.4   |

---

## 🧠 Notes

* `assjs-v2` introduces the new **`container` resampling mode** for responsive, container-based rendering.
* Original library by [@weizhenye](https://github.com/weizhenye/ASS)
* Maintained and improved by [@code-with-shahzad](https://github.com/code-with-shahzad)

---

---

## 💼 Connect with Me

I’m always open to collaborations and discussions about open-source projects, AI, and frontend innovation.

[![LinkedIn](https://img.shields.io/badge/LinkedIn-0A66C2?logo=linkedin&logoColor=white)](https://www.linkedin.com/in/shahzadsiddique1)
[![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/code-with-shahzad)
[![Email](https://img.shields.io/badge/Email-mshahzadsiddique5%40gmail.com-red?logo=gmail&logoColor=white)](mailto:mshahzadsiddique5@gmail.com)

---

## 🪪 License

MIT © [Shahzad Siddique](https://github.com/code-with-shahzad)

```
