The server
The server hosts the web app and your media files, and can run on pretty much anything including a Raspberry Pi, NAS or Windows/Mac/Linux desktop. Since the player is fully browser-based, it doesn’t need to run on the same system as the server, but it can.
Installation
KaraokeArcade Server is installed from source.
From source
-
Install Node.js v24 or later and Bun if they’re not already installed.
-
Clone the repository and install dependencies:
git clone https://github.com/matt-antone/KaraokeArcade.git
cd KaraokeArcade
bun install- Build and start the server:
npm run build
npm run serve- Look for “Web server running at…” and browse to that server URL.
See Getting Started if you’re new to KaraokeArcade.
Media Files
The following file types are supported:
- MP3+G (including zipped; also supports .m4a instead of .mp3)
- MP4 video (codec support can vary depending on the browser running the player)
A loose .mp3/.m4a file needs a same-name .cdg file next to it (case-insensitive); a .zip needs its .cdg file at the root of the archive.
KaraokeArcade Server expects your media files to be named in “Artist - Title” format by default (you can configure this). Media with filenames that couldn’t be parsed won’t appear in the library, so check the scanner log or console output for these. A trailing [Tag, Tag] group in the filename becomes song tags (tags containing “karaoke” or “vocal” are ignored).
Metadata Parser
You can customize the metadata parser by creating a file named _kes.v2.json in a media folder. It will apply to all media files in the folder, including subfolders. If any subfolders contain their own _kes.v2.json file, that will take precedence instead. These files can be in JSON or JSON5 format - JSON5 is used in the examples below since it’s friendlier for humans.
Basic Configuration
At the most basic, your _kes.v2.json file can alter some or all of the parser’s default configuration, which is:
{
// used to normalize artist/title; set false to disable
articles: ['A', 'An', 'The'],
// assumes filenames are in "Artist - Title" format
artistOnLeft: true,
// assumes a hyphen separates the artist and title
delimiter: '-',
}For example, if you had a folder with filenames in the format “Title - Artist” instead, you could create this _kes.v2.json file in it:
{
artistOnLeft: false, // override default
}If a filename contains " in the style of " (case-insensitive), that phrase is used as the delimiter automatically and the artist is assumed to be on the right, e.g. “Some Song in the style of Some Artist”.
Advanced Templating
If changing the parser’s default configuration doesn’t yield the desired results, you can also define your own “template” to override the result for one or more of these fields:
artist(string) artist’s name as it will be shown in the libraryartistNorm(string) normalized version of the artist’s name; used for matching and sorting (artistif not set)title(string) song’s title as it will be shown in the librarytitleNorm(string) normalized version of the song’s title; used for matching and sorting (titleif not set)
For each media file encountered, KaraokeArcade makes a “context” available to your field template(s). This context includes the fields above (that is, the results from the built-in parser) in addition to:
name(string) media filename (without extension)meta(object) media file’s metadata fieldsdir(string) full path of the containing folderdirSep(string) path separator used by the current OS (/or\)
Field templates are defined using JSON-e syntax. In addition to JSON-e’s built-in methods, a replace method is also provided for simple text replacement. Here are a few examples of how one might use field templates in their _kes.v2.json file:
// explicitly set the artist field
{
artist: "My Artist's Name",
}// remove "junk" from anywhere in the parsed artist field
{
artist: {
$eval: 'replace(artist, "junk", "")'
},
}// remove "junk" case-insensitively from the start of the parsed artist field (regex syntax)
// note: double backslash escapes to a single backslash
{
artist: {
$eval: 'replace(artist, "^junk\\s", "i", "")'
},
}// set artist and title using the media file's metadata tags
{
artist: '${meta.artist}',
title: '${meta.title}',
}CLI & ENV
KaraokeArcade Server supports the following CLI options and environment variables. The numeric values used for log/console levels are: 0=off, 1=error, 2=warn, 3=info, 4=verbose, 5=debug.
| Option | ENV | Description | Default |
|---|---|---|---|
--data <string> |
KES_PATH_DATA |
Absolute path of folder for database files | |
-p, --port <number> |
KES_PORT |
Web server port | auto |
--rotateKey |
KES_ROTATE_KEY |
Rotate the session key at startup | |
--scan |
KES_SCAN |
Run the media scanner at startup. Accepts a comma-separated list of pathIds, or “all” | |
--scannerConsoleLevel <number> |
KES_SCANNER_CONSOLE_LEVEL |
Media scanner console output level (default=4) | 4 |
--scannerLogLevel <number> |
KES_SCANNER_LOG_LEVEL |
Media scanner log file level | 3 |
--serverConsoleLevel <number> |
KES_SERVER_CONSOLE_LEVEL |
Web server console output level | 4 |
--serverLogLevel <number> |
KES_SERVER_LOG_LEVEL |
Web server log file level | 3 |
--serverUrl <string> |
KES_SERVER_URL |
Absolute http(s) URL guests reach the server at, used for join QR codes. See Stable addresses |
current LAN IP |
--urlPath <string> |
KES_URL_PATH |
Web server base URL path (must begin with a forward slash) | / |
KES_CONSOLE_COLORS |
Set to 0 or false to disable colors in console output |
enabled | |
PUID |
User ID to run as | ||
PGID |
Group ID to run as | ||
-v, --version |
Show version and exit | ||
-h, --help |
Show help and exit |
Stable addresses
By default the join QR encodes the server’s current LAN IP. That works for a one-off party, but an IP is an address rather than an identity: it changes when you take the server to a different venue, and it can change at the same venue when the DHCP lease renews.
This matters if guests add the app to their home screen. An install freezes whatever URL it was added from, and a standalone window has no address bar to correct it, so a changed IP leaves a dead icon. Worse, private ranges are heavily reused, so the old address may reach some unrelated device on the new network.
Set --serverUrl to a name that follows the server between networks and the QR, the install and the icon all agree:
npm run serve -- --serverUrl http://karaokearcade.local:8080
A Bonjour .local name is the simplest option, and iOS and macOS resolve it with no setup on the guest’s phone. macOS hosts already answer <computer-name>.local; on Linux this needs Avahi, and on Windows the Bonjour service. A tunnel or reverse proxy hostname works too, and an https one additionally unlocks the browser features that require a secure context.
The value is normalized rather than used verbatim, so include the port and any base path. It is ignored (with a warning, falling back to the LAN IP) unless it parses as an http or https URL — note that karaokearcade.local:8080 is not one, since it has no scheme.
The home-screen install hint (iOS Safari only) shows when a guest reaches the server by hostname or a private LAN IP, and is suppressed for a public IP or an IPv6 literal — guests in the suppressed case are left on the QR-and-browser flow, which keeps working no matter how the address moves.
File Locations
The default locations for the database (database.sqlite3), web server log (server.log) and media scanner log (scanner.log) are as follows:
These folders keep the pre-rebrand Karaoke Eternal Server name so existing installs keep their database. Set --data or KES_PATH_DATA to put the database somewhere else.
Windows
- Database:
%APPDATA%\Karaoke Eternal Server(usually%USERPROFILE%\AppData\Roaming\Karaoke Eternal Server) - Logs:
%USERPROFILE%\AppData\Roaming\Karaoke Eternal Server\logs
macOS
- Database:
~/Library/Application Support/Karaoke Eternal Server - Logs:
~/Library/Logs/Karaoke Eternal Server
Linux
- Database:
$XDG_CONFIG_HOME/Karaoke Eternal ServerifXDG_CONFIG_HOMEis set, otherwise~/.config/Karaoke Eternal Server - Logs:
~/.config/Karaoke Eternal Server/logs
Older versions put database.sqlite3 directly in %APPDATA% or $XDG_CONFIG_HOME when those were set, without the Karaoke Eternal Server folder. If a database is still there and none is in the new folder, the server keeps using the old one. To switch, stop the server and move database.sqlite3 (and any database.sqlite3-wal / -shm files next to it) into the new folder.