A MagicMirror² module that displays a grid of numbered buttons for your audio tracks and lets you play them individually or in a randomized loop. Supports local files stored on the SD card, USB paths (securely streamed via the backend), and URL sources. Includes pagination, hover/active styling, volume control, and an optional autostart random loop. Number of buttons on the grid will automatically match the number of sound files
- Version: 1.1.0
- Author: gitgitaway
- MagicMirror² Compatibility: Tested with current MM² versions
- Files:
MMM-JukeBox.js,node_helper.js,MMM-JukeBox.css - Changelog: See CHANGELOG.md for version history
- Auto-scan of audio files from a local
soundFilesfolder or a configured USB folder - Volume Control with persistent storage (slider UI with localStorage + backend persistence)
- Dual Control Modes: Traditional buttons or modern symbol-based control bar (◀ ⏸ ▷ ✖ ▶)
- Random Play with continuous looping and shuffle functionality
- Playback State Persistence: Remembers active track, random mode, and volume across reloads
- Pagination to handle large libraries (configurable page size)
- USB file streaming via secure Express route with path traversal protection
- Optional USB→Local Sync: when
source: "USB"andsyncUsbToLocal: true, files are copied fromusbPathto./soundFilesand played locally (UI shows syncing with spinner and results) - Backup functionality: Optionally backup local files before USB sync operations
- USB path probing with automatic retry for reliability
- Autostart Random Loop on startup (optional)
- Continue playing on HIDE (optional)
- Marquee scrolling for long "Now Playing" text
- Hide/Show Toggle: Optional on-screen toggle button to collapse/expand the module while keeping playback functional
- Theme customization: Dark/light mode, color overrides, opacity controls
- Allowed extensions filter (front-end configurable and enforced in the backend)
- Accessibility features: Focus-visible styles, keyboard navigation support
- Navigate to your MagicMirror modules directory:
cd ~/MagicMirror/modules
- Clone or copy this module into
MMM-JukeBox/.
git clone https://github.com/gitgitaway/MMM-JukeBox.git- Place your audio files in:
- Local mode (default):
MMM-JukeBox/soundFiles/ - USB mode: your USB directory (e.g.,
D:/soundFiles) and setsource: "USB"in config
- Local mode (default):
Add the module to your config/config.js:
{
module: "MMM-JukeBox",
position: "top_left", // Explanation: choose any MagicMirror position
config: {
source: "file", // "file" | "USB" | "URL"
usbPath: "D:/soundFiles", // Explanation: only used when source === "USB"
allowedExtensions: [".mp3", ".wav", ".ogg", ".m4a"],
pageSize: 40, // Explanation: number of buttons per page
showControlBar: true, // NEW: use symbol bar; hides legacy Random button
randomButtonText: "Random Play", // Explanation: label for the legacy random button (when control bar is off)
stopButtonText: "Stop", // Explanation: label for the stop button
infoText: "Select a number or use Random Play.",
continueOnHide: true, // Explanation: true = audio continues when module hides
syncUsbToLocal: false, // Explanation: optional backend copy from USB to ./soundFiles
autostartRandomLoop: false // Explanation: true = auto start random loop on startup
}
},| Option | Type | Default | Description |
|---|---|---|---|
source |
string | "file" |
Audio source. "file" uses the module's soundFiles directory. "USB" streams via backend from usbPath and, if syncUsbToLocal: true, will first copy to ./soundFiles and then play locally. "URL" expects you to provide url values for tracks. |
usbPath |
string | "D:/soundFiles" |
Path to your USB music folder when source === "USB". Example for Windows shown. |
allowedExtensions |
string[] | [".mp3", ".wav", ".ogg", ".m4a"] |
File extensions included during scanning. Case-insensitive. |
pageSize |
number | 40 |
Number of track buttons per page. Must be ≥ 1. |
randomButtonText |
string | "Random Play" |
Label of the Random Play button. |
stopButtonText |
string | "Stop" |
Label of the Stop button. |
infoText |
string | "Select a number or use Random Play." |
Info text shown above the grid. |
continueOnHide |
boolean | true |
If true, audio keeps playing when the module receives HIDE. Otherwise it stops on HIDE/SUSPEND/STOP. |
syncUsbToLocal |
boolean | false |
If true, backend can copy from usbPath into the module's soundFiles directory (see Notifications). |
autostartRandomLoop |
boolean | false |
Start randomized playback automatically after the scan completes (once at startup). |
showHideToggle |
boolean | true |
If true, displays a toggle button to hide/show the module grid while keeping playback functional. |
tracks |
array | [] |
Populated automatically by the scan. For URL source, you can provide objects with { url, title, artist }. |
backupLocal |
boolean | false |
If true and source: "USB", copy the current ./soundFiles into ./backupFiles once before the first USB scan/sync. |
darkMode |
boolean/null | null |
Theme control: null = auto (default CSS), true = force dark mode, false = force light mode. |
fontColorOverride |
string/null | null |
Override all font colors with a specific color (e.g., "#FFFFFF" for white). Set to null to use default CSS colors. |
opacityOverride |
number/null | null |
Override all opacity values (e.g., 1.0 for full opacity). Set to null to use default CSS opacity values. |
- On start, the module sends
SCAN_SONGSwith the resolved scan path and allowed extensions. - When the backend replies with
SONG_LIST, a button grid is rendered with pagination. - Clicking a button plays that track; clicking Random Play starts a continuous random loop.
- The Now Playing area shows title/artist and (once known) duration.
- For
USBsource, audio is streamed via/MMM-JukeBox/usb?base=...&file=...to avoid browserfile:///restrictions.
- Scans the given directory (non-recursive) and filters by
allowedExtensions. - Normalizes titles from filenames (removes prefix numbers like
01 -, replaces underscores with spaces). - Provides a secure Express route for USB streaming that prevents path traversal and sets basic
Content-Type.
GET /MMM-JukeBox/usb?base=<encodedPath>&file=<encodedFilename>
# Explanation: Streams the requested audio file if it exists within <base>.
# - base: URL-encoded absolute directory path (e.g., D:/soundFiles)
# - file: URL-encoded filename within that base (e.g., 01 - Song.mp3)
SCAN_SONGS- Payload:
{ path, source, extensions } - Explanation: Request the backend to scan for audio files.
- Payload:
SYNC_USB_TO_LOCAL(optional)- Payload:
{ usbBase, extensions } - Explanation: Copy matching audio files from
usbBaseto the module's./soundFilesdirectory.
- Payload:
SONG_LIST- Payload:
[{ file, title, artist }] - Explanation: Result of the scan, used to build the grid and play audio.
- Payload:
SYNC_DONE- Payload:
{ ok: boolean, copied?: number, skipped?: number, dest?: string, error?: string } - Explanation: Outcome of a sync request.
- Payload:
Key classes from MMM-JukeBox.css you can theme in your custom CSS:
.jukebox-wrapper: Outer container.jukebox-info: Info text above the grid.jukebox-grid: Grid container for numbered buttons.jukebox-btn: Individual track buttons (use.activefor the playing state).jukebox-random-btn,.jukebox-stop-btn: Action buttons.jukebox-nowplaying: Now playing footer area.jukebox-pager,.jukebox-pager-btn,.jukebox-page-info: Pagination controls
- No tracks appear
- Explanation: Ensure your files are in the correct folder for your chosen
sourceand that their extensions matchallowedExtensions.
- Explanation: Ensure your files are in the correct folder for your chosen
- USB files don't play
- Explanation: Verify
source: "USB"and thatusbPathpoints to a valid directory accessible by the MagicMirror process.
- Explanation: Verify
- Browser cannot play certain formats
- Explanation: Not all browsers support every codec/container. Convert problematic files to widely supported formats (e.g., MP3).
- Large libraries
- Explanation: Increase
pageSizeor curate files in subfolders (module scans non-recursively by design).
- Explanation: Increase
- Scanning is non-recursive for simplicity and performance.
- For
URLsource, providetrackswith{ url, title, artist }and setsource: "URL"(the scan will return an empty list by design). - The backend title formatter strips numeric prefixes and underscores to create cleaner display titles.
This is the 4th module in my Celtic themed man cave magicmirror.
The other modules can be found here:-
- Module 1: https://github.com/gitgitaway/MMM-MyTeams-Clock
- Module 2: https://github.com/gitgitaway/MMM-MyTeams-LeaugeTable
- Module 3: https://github.com/gitgitaway/MMM-MyTeams-Fixtures
- Module 5: https://github.com/gitgitaway/MMM-Celtic-OnThisDay
Thanks to the MagicMirror community for inspiration and guidance! Special thanks to @jasonacox for his work on MMM-MusicPlayer which served as a starting point.
- All tracks are the property of their respective owners; included tracks are for demonstration purposes only and should be replaced with your own
MIT


