ncn-to-kar
v1.2.0
Published
Convert NCN karaoke files (.mid + .lyr + .cur) to KAR format and play KAR files with lyrics display
Maintainers
Readme
ncn-to-kar
Convert NCN karaoke files (.mid + .lyr + .cur) to KAR format (MIDI with embedded karaoke tracks).
Features
- Converts NCN-style karaoke files to standard KAR format
- Supports TIS-620 encoded lyric files (Thai encoding)
- Preserves timing information from cursor files
- Creates karaoke tracks with proper grapheme cluster handling
- Generates compatible KAR files for karaoke software
- KAR Player: Play and display lyrics from KAR files with timing
Installation
npm install ncn-to-karUsage
Command Line
ncn-to-kar <midi-file> <lyric-file> <cursor-file> <output-kar-file>Example:
ncn-to-kar song.mid song.lyr song.cur song.karProgrammatic API
const { convertNcnToKar } = require('ncn-to-kar');
const result = convertNcnToKar({
midiFile: 'song.mid',
lyricFile: 'song.lyr', // TIS-620 encoded
cursorFile: 'song.cur',
outputFile: 'song.kar'
}, {
onWarn: (msg) => console.warn(msg)
});
console.log('Converted:', result.outputFile);
console.log('Title:', result.songTitle);
console.log('Artist:', result.artistName);KAR Player
Play and display lyrics from KAR files:
const { KarPlayer } = require('ncn-to-kar');
const player = new KarPlayer('song.kar');
// Load the file
const data = player.load();
console.log('Title:', data.songTitle);
console.log('Artist:', data.artistName);
// Set up callbacks
player
.onTitleChange((title) => {
console.log('Title:', title);
})
.onArtistChange((artist) => {
console.log('Artist:', artist);
})
.onLyricChange((text, time, index) => {
// Display lyrics as they come
process.stdout.write(text);
});
// Start playing
player.play();
// Get metadata
const metadata = player.getMetadata();
console.log('Duration:', metadata.duration, 'seconds');File Format
Input Files
MIDI file (.mid): Standard MIDI file with music data
- Must use ticks-per-beat timing (SMPTE timing not supported)
Lyric file (.lyr): Text file with lyrics in TIS-620 encoding
- Line 1: Song title
- Line 2: Artist name
- Line 3: Musical key (discarded)
- Line 4: Blank (discarded)
- Line 5+: Lyrics (one line per lyric line)
Cursor file (.cur): Binary file with timing information
- 2-byte little-endian values for each character
- Terminated with 0xFF
Output File
- KAR file (.kar): Standard MIDI file with embedded karaoke tracks
- Track 0: Original MIDI tracks
- Track 1: "Words" - Karaoke timing and text
- Track 2: "Lyric" - Full lyrics
- Track 3: "Artist" - Artist name
- Track 4: "SongTitle" - Song title
API Reference
convertNcnToKar(options, callbacks)
Converts NCN files to KAR format.
Parameters:
options(Object):midiFile(string): Path to MIDI filelyricFile(string): Path to lyric file (TIS-620 encoded)cursorFile(string): Path to cursor fileoutputFile(string): Path to output KAR file
callbacks(Object, optional):onWarn(Function): Callback for warning messages
Returns:
Object:outputFile(string): Path to created KAR filesongTitle(string): Extracted song titleartistName(string): Extracted artist name
Throws:
Error: If conversion fails (file not found, invalid format, etc.)
KarPlayer
Plays KAR files and displays lyrics with timing.
Constructor:
new KarPlayer(karFilePath)- Create a new player instance
Methods:
load()- Load and parse the KAR fileplay()- Start playing (triggers lyric callbacks)stop()- Stop playingpause()- Pause playingresume()- Resume playingonLyricChange(callback)- Set callback for lyric events:(text, timeInSeconds, index) => voidonTitleChange(callback)- Set callback for title:(title) => voidonArtistChange(callback)- Set callback for artist:(artist) => voidgetLyricsAtTime(timeInSeconds)- Get all lyrics up to a specific timegetAllLyrics()- Get all lyrics with timinggetMetadata()- Get song metadata (title, artist, duration, etc.)
Example:
const player = new KarPlayer('song.kar');
player.load();
player.onLyricChange((text, time, index) => {
console.log(`[${time.toFixed(2)}s] ${text}`);
});
player.play();parseKarFile(karFilePath)
Parse a KAR file and extract karaoke information.
Returns:
Object:midi- Parsed MIDI dataticksPerBeat- MIDI ticks per beatsongTitle- Song titleartistName- Artist namelyrics- Array of lyric events with timingwordsTrack,lyricTrack,artistTrack,titleTrack- Track references
CDN Configuration
Get CDN URLs for SpessaSynth libraries from .env file:
const { getCdnUrls, getCdnUrl } = require('ncn-to-kar');
// Get all CDN URLs
const urls = getCdnUrls();
console.log(urls.spessasynth_lib);
console.log(urls.spessasynth_core);
// Get specific URL
const libUrl = getCdnUrl('spessasynth_lib');The .env file should contain:
SPESSASYNTH_LIB_URL=https://cdn.jsdelivr.net/npm/spessasynth_lib@latest/dist/index.js
SPESSASYNTH_CORE_URL=https://cdn.jsdelivr.net/npm/spessasynth_core@latest/dist/index.jsRequirements
- Node.js >= 12.0.0
Dependencies
grapheme-splitter: For proper grapheme cluster handlingiconv-lite: For TIS-620 encoding/decodingmidi-file: For MIDI file parsing and writing
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
