A robust TypeScript library for parsing, manipulating, and converting TTML (Timed Text Markup Language) lyrics data, specifically designed to handle Apple Music-style TTML files.
- Robust Parsing: Handles complex TTML structures, including mixed content and various timing formats.
- Metadata Extraction: Extracts rich metadata including:
- Duration
- Language
- Leading Silence
- Songwriters / Credits
- Performing Agents (Singers/Groups)
- Timing Support: Detects and handles:
- Word-level timing (karaoke style)
- Line-level timing
- No timing (plain text)
- Conversion:
- Convert to LRC format (standard synced lyrics)
- Convert to Markdown (readable text)
- Built-in Player: Includes a
Playerclass to simulate playback and emit events for building lyric UIs. - Type-Safe: Built with TypeScript and Zod for runtime validation.
# using bun
bun add @syncfm/ttml
# using npm
npm install @syncfm/ttml
# using pnpm
pnpm add @syncfm/ttmlimport { TTML } from "@syncfm/ttml";
const xmlData = `... your TTML xml string ...`;
const ttml = TTML.fromString(xmlData);
// Access metadata
console.log("Duration:", ttml.getDuration());
console.log("Language:", ttml.getLanguage());
console.log("Credits:", ttml.getCredits());
// Check timing type
console.log("Timing Type:", ttml.getTiming()); // "word", "line", or "none"// Convert to LRC
const lrc = ttml.toLRC();
console.log(lrc);
// Output:
// [00:12.34] Line one text
// [00:15.67] Line two text
// Convert to Markdown
const md = ttml.toMarkdown();
console.log(md);
// Output:
// ### Verse 1
//
// Line one text
// Line two textThe Player class allows you to easily build a lyrics UI by emitting events as playback progresses.
const player = ttml.createPlayer({
updateInterval: 100 // Check every 100ms
});
// Listen for events
player.on("play", () => console.log("Playback started"));
player.on("pause", () => console.log("Playback paused"));
player.on("end", () => console.log("Playback finished"));
// Listen for lyric updates
player.on("line", (line) => {
console.log("Current Line:", line.text);
});
player.on("lyric", (word) => {
console.log("Current Word:", word.text);
});
// Control playback
player.play();
// player.pause();
// player.skipTo(30); // Skip to 30 secondsThis project uses Bun.
# Install dependencies
bun install
# Run tests
bun test
# Build
bun run build
# Lint
bun run lintMIT