ass-html5
v0.6.3
Published
Display ASS/SSA subtitles on html5 videos
Maintainers
Readme
ass-html5
Display ASS/SSA subtitles on html5 videos
Table of Contents
Installation
pnpm add ass-html5Features
- 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.
Usage
Options
| 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 |
| fonts | Custom fonts to load | 🚫 | Font[] | 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.
Simple HTML
[!NOTE] In fullscreen, the browser only shows the
videoelement 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/[email protected]/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>Svelte and Plry
<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>videojs
In the head :
<script src="https://cdn.jsdelivr.net/npm/[email protected]/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>Credits
Thanks to the ass-compiler by weizhenye.
