pnpm add ass-html5- Karaoke Support: Full support for
\k,\kf,\ko, and\Ktags. - Vector Drawings: High-performance rendering of ASS vector paths (
\p) usingPath2D. - Clipping: Support for rectangular and vector clipping/masking (
\clip,\iclip). - Advanced Transformations:
- Rotation around all axes (
\frz,\frx,\fry). - Scaling (
\fscx,\fscy) and Shearing (\fax,\fay). - Custom rotation origin (
\org).
- Rotation around all axes (
- Smart Wrapping: Implementation of
\qstyles for optimal line breaking. - Collision Handling: Automatic vertical shifting to prevent overlapping subtitles.
- Blur Effects: Edge blur (
\be) and Gaussian blur (\blur) using Canvas filters. - Performance Optimized: Built-in layer caching to minimize redundant redraws.
| option | description | required | type | default |
|---|---|---|---|---|
| assText | The ass text string | 🚫 | string |
undefined |
| subUrl | URL to fetch the ASS content from | 🚫 | string |
undefined |
| video | The video to display the subtile on. Can be either an HTMLVideoElement or string (html query selector ) |
✅ | HTMLVideoElement / string |
undefined |
| font_urls | Custom fonts url load | 🚫 | string[] |
undefined |
| zIndex | zIndex of the rendering frame | 🚫 | number |
Drawn after the video |
| onReady | A Callback that is invoked when the preprocess of the ass text by render is done | 🚫 | () => void |
undefined |
| logging | Type of logging | 🚫 | LOGTYPE |
LOGTYPE.DISABLE |
One of
assTextorsubUrlis required.
Note
In fullscreen, the browser only shows the video element and its controls, so the subtitles move to the top layer with the Popover API. That needs Chrome 114+, Firefox 125+ or Safari 17+. On iPhone the video uses its own fullscreen player, so subtitles are not shown there.
Subtitles that reach the bottom of the frame are drawn over the native control bar. Players with their own controls, like video.js or plyr (example), keep the controls above the subtitles.
<script src="https://cdn.jsdelivr.net/npm/ass-html5@latest/dist/ass.min.js"></script><video src="/assets/video.mp4" id="video" controls></video><script>
document.addEventListener('DOMContentLoaded', async () => {
// Using subUrl to fetch subtitle automatically
const ass = new ASS.default({
subUrl: '/assets/video.ass',
video: document.getElementById('video')
});
await ass.render();
// You can switch subtitles dynamically:
// await ass.setSubUrl('/assets/other.ass');
// OR
// await ass.setAssText('[Script Info]...');
});
</script><script lang="ts">
import video from '$lib/assets/video.mp4'
import cc from '$lib/assets/cc.ass?url'
import ASS from 'ass-html5'
import { onMount } from 'svelte';
import Plyr from 'plyr'
const ass = new ASS({
subUrl: cc,
video: "#video-test"
})
let vidElement: HTMLVideoElement
let player: Plyr
onMount(async () => {
player = new Plyr(vidElement)
await ass.render()
})
</script>
<div class="video-container">
<!-- svelte-ignore a11y-media-has-caption -->
<video
preload="metadata"
src="{video}"
id="video-test"
controls
autoplay
class="vid"
bind:this={vidElement}
></video>
</div>In the head :
<script src="https://cdn.jsdelivr.net/npm/ass-html5@latest/dist/ass.min.js" defer></script>
<script src="https://vjs.zencdn.net/8.3.0/video.min.js" defer></script>
<link href="https://vjs.zencdn.net/8.3.0/video-js.css" rel="stylesheet" />In the body :
<video
id="my-video"
class="video-js"
controls
preload="auto"
width="1280"
height="720"
data-setup="{}"
>
<source src="assets/video.mp4" type="video/mp4" />
</video>In the script tag :
<script>
document.addEventListener('DOMContentLoaded', async () => {
let res = await fetch('/assets/video.ass');
let assSubs = await res.text();
var player = videojs('my-video');
player.ready(async () => {
// Get the video element from the player
var videoElement = player.el().getElementsByTagName('video')[0];
const ass = new ASS.default({
assText: assSubs,
video: videoElement
});
await ass.render();
});
});
</script>Thanks to the ass-compiler by weizhenye.