Skip to content

Repository files navigation

lyric-kit

A TypeScript library for parsing, serializing, and synchronizing lyrics across formats (LRC, TTML, QRC, KRC, YRC, LyS, SRT, ASS).

License TypeScript Zero Dependency

English | 简体中文

Installation

pnpm add lyric-kit
# or
npm install lyric-kit

Quick Start

Parse Lyrics

parseLyric accepts raw lyric text or an object payload with optional translations/romanizations.

import { parseLyric } from "lyric-kit";

// 1. Parse string (format auto-detected)
const { lines, metadata } = parseLyric(`
[ti:Song Title]
[ar:Artist Name]
[00:01.00]First line
[00:03.00]Second line
`);

// 2. Parse with translation & romanization alignment
const result = parseLyric({
  content: "[00:01.00]Hello\n[00:03.00]Goodbye",
  translation: "[00:01.00]你好\n[00:03.00]再见",
  romaji: "[00:01.00]haro\n[00:03.00]gubbai",
});

Serialize Lyrics

Export via dedicated serializer functions or the unified serializeLyric entry:

import { toEnhancedLRC, toLRC, toSRT, toTTML } from "lyric-kit";

// Standard line-by-line LRC
const lrc = toLRC(lines);

// Word-by-word enhanced LRC
const elrc = toEnhancedLRC(lines);

// Apple Music TTML XML (accepts lines array or LyricResult with metadata)
const ttml = toTTML(result);

// SubRip subtitle
const srt = toSRT(lines);

// Or via unified serializeLyric entry:
import { serializeLyric } from "lyric-kit";
const output = serializeLyric(lines, "ttml");

Clean Metadata Headers

Strip credit headers/footers (lyricist, composer, arranger, copyright notices):

import { stripLyricMetadata } from "lyric-kit";

const cleanedLines = stripLyricMetadata(lines, {
  matchMetadata: {
    title: "Song Title",
    artists: ["Artist Name"],
  },
});

Playback Synchronization

import { findLyricIndex, getWordSweepProgress } from "lyric-kit";

// Find current active line by playback time (ms)
const currentMs = 1500;
const lineIndex = findLyricIndex(lines, currentMs);

if (lineIndex !== -1) {
  const activeLine = lines[lineIndex];

  // Calculate karaoke highlight progress [0, 1] per syllable/word
  for (const word of activeLine.words) {
    const progress = getWordSweepProgress(word, activeLine.startTime, currentMs);
  }
}

API Reference

parseLyric(input, options?)

Parses lyrics and returns a LyricResult.

  • input: string | LyricInput
    • content: Primary lyric string.
    • format?: Optional format override.
    • translation?: Optional translation string.
    • translationFormat?: Optional translation format override.
    • romaji?: Optional romanization string. When word-timed (QRC / KRC / TTML), automatically aligns syllables to word.romanWord.
    • romajiFormat?: Optional romanization format override.
    • kana?: Optional standalone furigana kana string (used if not embedded via [kana: ...]).
  • options: ParseOptions (optional)

ParseOptions

Option Type Default Description
format LyricFormat auto Explicit format override (lrc, ttml, qrc, krc, yrc, lys, srt, ass).
detectBackground boolean false Detect and split parenthesized background/harmony vocals.
extractMetadata boolean false Extract song metadata (title, artist, album, creators, offset).
cleanKangxi boolean false Normalize KangXi radicals and CJK compatibility ideographs to standard characters.
applyOffset boolean false Automatically apply metadata.offset ms to all lines and words (newTime = originalTime + offset).
keepEmptyLines boolean false Keep empty lines (interlude markers). Defaults to false (strips empty lines after clamping previous line); true preserves them for player interlude handling.
multiLineMode "join" | "bilingual" "join" SRT multi-line parsing mode. join joins lines with space; bilingual maps lines to primary, translation, romanization.
preferredLang string "" Preferred translation language code for multi-track TTML (e.g. "zh-CN").
domParser DOMParserLike auto Custom DOMParser instance/constructor (required in non-browser/Node.js environments when parsing TTML or QRC XML).

Format Parsers & Serializers

Dedicated parsers and serializers for each format can be called directly (unified uppercase standard naming):

import {
  parseLRC,
  parseTTML,
  parseQRC,
  parseKRC,
  parseYRC,
  parseLyS,
  parseSRT,
  parseASS,
  toLRC,
  toEnhancedLRC,
  toTTML,
  toSRT,
} from "lyric-kit";

// Parsing
const result = parseLRC(lrcText, { cleanKangxi: true });

// Serialization
const ttmlXml = toTTML(result);
const lrcText = toLRC(result.lines);

detectFormat(text)

Inspects raw text patterns and returns the detected format: "lrc" | "ttml" | "qrc" | "krc" | "yrc" | "lys" | "srt" | "ass".

Data Models

interface LyricResult {
  lines: LyricLine[];
  metadata: LyricMetadata;
}

interface LyricLine {
  id?: string;
  language?: "ja" | "ko" | "zh-CN" | "und-Latn";
  words: LyricWord[];
  translatedLyric: string;
  romanLyric: string;
  startTime: number; // ms
  endTime: number;   // ms
  isBG: boolean;
  isDuet: boolean;
  agentId?: string;
  songPart?: string;
  blockIndex?: number;
}

interface LyricWord {
  word: string;
  startTime: number; // ms
  endTime: number;   // ms
  romanWord?: string; // Per-word romanization/pinyin syllable (e.g. "kai", "zeoi")
  ruby?: LyricSpan[]; // Furigana/ruby spans (e.g. Japanese kana "かい")
  obscene?: boolean;
  endsWithSpace?: boolean;
  emptyBeat?: number;
}

License

AGPL-3.0

About

A lightweight, zero-dependency toolkit for parsing, serializing, and processing lyrics across multiple formats.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages