Skip to content

MrBlindMouse/Roomz

Repository files navigation

Roomz (Name change pending)

LAN-synchronized single-stream audio playback: one global stream, all devices in sync. Like an old school radio!

  • Single global stream — no rooms, no codes. One playlist and one playback state for the entire LAN.
  • Sub-10 ms sync on LAN using NTP-style clock sync and Web Audio API.
  • Per-device delay (0–500 ms) to compensate for speaker placement.
  • Multiple library folders — add paths from the UI (under an allowed base); scan recursively. Upload to a chosen folder.
  • Upload or scan, collaborative playlist, simple chat.

The Why

I created Roomz because I was annoyed that I cannot connect more than 1 BT Speaker to my phone for wider 'covarage'.

Now I can play music throughout my house from multiple devices.

I'm pretty sure something else already exists for this. . . but so-what.

Future plans:

  • Add a centralized control, for managing per device delays and volume from one client.
  • Create a client for rpi or headless devices.
  • Maybe add a 'Announcement' function to the 'Main' client, to broadcast voice over the stream.

Warning

Roomz is meant to be run on a private LAN/Home network. There is no security built in, and anybody connected to the network has full access. If enough interest is shown for it, then security might be added at a later date.

Run

Copy .env.example to .env and adjust if needed (e.g. ROOMZ_LIBRARY_BASE). The app loads .env automatically at startup.

uv sync
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000

Then open http://<this-machine-ip>:8000 in a browser.

Development

Install with dev dependencies (pytest, ruff, black), then run tests and lint:

uv sync --extra dev
uv run pytest
uv run ruff check .
uv run black --check .   # optional

Multi-device sync test

  1. Run the server on a machine on your LAN (e.g. 192.168.1.10).
  2. On multiple devices (phones, laptops, same LAN), open http://192.168.1.10:8000.
  3. Add or scan music, press play. All clients should play the same track at the same position.
  4. Use Speaker delay (ms) on each device to align with physical speaker placement (e.g. farther speakers get more delay).

Adding music

  • Library folders: In Library folders, add a path (and optional name). Paths must be under the allowed base (default: project data/; set ROOMZ_LIBRARY_BASE to allow e.g. /home/you/Music). Remove a folder only when it has no tracks.
  • Upload: Choose a destination folder in the Upload to dropdown, then Upload and select MP3/WAV/OGG/M4A/FLAC files. They are saved under that folder and added to the playlist.
  • Scan: Scan all scans every library folder recursively; or click Scan next to a folder to scan only that one. New files are added to the DB and playlist.

Per-device delay

Use the Speaker delay compensation (ms) slider (0–500) in the header to fine-tune each device. No server round-trip; applies instantly to the sync position so playback stays aligned with others.

Sync accuracy

On a typical LAN, sync within <10 ms is achievable with Web Audio API and clock sync. Browser and device output latency can add a constant offset; use the delay slider to compensate so all speakers sound in phase.

Project structure

Roomz/
├── pyproject.toml
├── uv.lock
├── tests/
│   ├── conftest.py
│   └── test_app.py
├── app/
│   ├── main.py          # FastAPI app, /music/track/{id}, /ws, static mount
│   ├── config.py        # LIBRARY_BASE, validate_library_path
│   ├── models.py
│   ├── schemas.py
│   ├── crud.py
│   ├── db.py
│   ├── ws_manager.py
│   ├── clock_sync.py
│   ├── audio_utils.py
│   └── routers/
│       └── api.py       # upload, scan, playlist CRUD
├── data/
│   ├── music/           # audio files
│   └── app.db           # SQLite
├── frontend/
│   ├── index.html
│   └── static/          # CSS and JS assets
│       ├── app.js
│       ├── colors.css
│       ├── _reset.css
│       ├── base.css
│       ├── layout.css
│       └── components.css
└── alembic/

Tech stack

  • Backend: FastAPI, Uvicorn, SQLAlchemy 2.0 (async), Alembic, SQLite, mutagen, aiofiles. Managed with uv.
  • Frontend: Vanilla HTML/CSS/JS, layered vanilla CSS (reset, base, colors, layout, components), Web Audio API (with <audio> fallback).

No auth (LAN-only). Production run: uv run uvicorn app.main:app --host 0.0.0.0 --port 8000.

About

Syncronized Music streaming server

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors