ASS Compiler

raw JSON →
0.1.16 verified Fri May 01 auth: no javascript

Parses and compiles ASS/SSA subtitle format into an easy-to-use data structure. Current stable version: 0.1.16. Released as needed with minor fixes and enhancements. Key differentiators: provides both low-level parse/stringify and high-level compile/decompile with validation, tag merging, drawing transformation, and default style support. Ships TypeScript types. Alternatives require more manual parsing or lack validation.

error TypeError: Cannot read properties of undefined (reading 'Fontname')
cause Default style not defined in ASS file and no defaultStyle option provided.
fix
Provide a defaultStyle option including Fontname, or add a 'Default' style in the ASS file.
error SyntaxError: Invalid or unexpected token
cause ASS text contains mismatched brackets (e.g., unclosed { or }).
fix
Ensure all brackets are balanced; update to v0.1.15+ which better handles mismatched brackets.
error ERR_REQUIRE_ESM
cause Trying to require() the package with CommonJS after v0.1.13.
fix
Switch to ESM imports (import { parse } from 'ass-compiler') or downgrade to v0.1.12.
breaking ESM-only since v0.1.13; CommonJS require will not work.
fix Use ESM imports: import { parse } from 'ass-compiler'.
gotcha The first \r tag must be before other override tags; otherwise it can cause incorrect style resolution.
fix Ensure \r appears at the start of override tags in Dialogue text.
gotcha When multiple \pos or \move tags exist, only the first one is used; later ones are ignored.
fix Remove duplicate \pos/\move tags; keep only the first.
gotcha Timestamps with rounding precision issues may cause slight time shifts; force rounding not applied.
fix Upgrade to v0.1.11+ which fixes rounding via #16.
npm install ass-compiler
yarn add ass-compiler
pnpm add ass-compiler

Demonstrates parsing, compiling with options, and round-tripping ASS text using parse, compile, stringify, and decompile.

import { parse, compile, stringify, decompile } from 'ass-compiler';

const assText = `[Script Info]
ScriptType: v4.00+
PlayResX: 384
PlayResY: 288

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:01.00,0:00:04.00,Default,,0,0,0,,Hello world!
`;

const parsed = parse(assText);
console.log(parsed);

const compiled = compile(assText, {
  defaultInfo: { PlayResX: 384, PlayResY: 288 },
  defaultStyle: {
    Name: 'Default',
    Fontname: 'Arial',
    Fontsize: '20',
    PrimaryColour: '&H00FFFFFF&',
    SecondaryColour: '&H000000FF&',
    OutlineColour: '&H00000000&',
    BackColour: '&H00000000&',
    Bold: '0',
    Italic: '0',
    Underline: '0',
    StrikeOut: '0',
    ScaleX: '100',
    ScaleY: '100',
    Spacing: '0',
    Angle: '0',
    BorderStyle: '1',
    Outline: '2',
    Shadow: '2',
    Alignment: '2',
    MarginL: '10',
    MarginR: '10',
    MarginV: '10',
    Encoding: '1'
  }
});
console.log(compiled);

const backToText = stringify(parsed);
const decompiledText = decompile(compiled);
console.log(backToText === decompiledText);