Web UI for discovering and viewing Lab Streaming Layer (LSL) streams on your local network.
Because browsers cannot speak the LSL protocol directly (UDP multicast discovery + data transport), this repo includes a small backend relay that uses pylsl to read streams and forward samples to the browser via WebSocket.
Run the webpage and backend with this command:
curl -sSL https://raw.githubusercontent.com/onecalfman/lsl-view/main/docker-compose-release.yml | docker compose -f - up -dIt will launch on localhost:4321
- Discover streams on your LAN (
/api/streams) - Stream metadata inspector (including channel labels and raw XML)
- Real-time time-series chart (Canvas, stacked/overlay, per-channel toggles)
- Event marker timeline for string streams
- Downsampling for high-rate streams
- Frontend (nginx serving built Astro):
http://localhost:4321 - Backend (FastAPI):
http://localhost:8765
LSL discovery relies on UDP multicast. For this to work, the backend must run on the same network as the LSL sources.
On Linux, the backend runs with host networking so multicast discovery works:
docker compose up --buildOpen http://localhost:4321, click "Scan Network", then select a stream.
Docker Desktop does not reliably support the host-network + multicast setup needed for LSL discovery.
Run the backend natively, and use either the frontend container or pnpm dev.
Backend (requires Python + uv):
cd backend
uv run python server.pyOr from the repo root:
pnpm dev:backendFrontend (Docker):
docker compose up frontend --buildOr frontend (local dev):
pnpm devIn a separate terminal:
cd backend
uv run python mock_streams.pyOr from the repo root:
pnpm dev:mock-streamsStandalone mock stream project:
pnpm dev:mockThis publishes:
MockEEG(4ch @ 256 Hz)MockAccel(3ch @ 50 Hz)MockMarkers(string markers)
Then open the UI and scan.
- If "Scan Network" finds nothing: check firewall rules, that LSL sources are on the same LAN/VLAN, and that you are not trying to discover streams from inside a bridged Docker network.
- If you run the backend in Docker on Linux: verify
network_mode: hostis active. - Backend health endpoint:
GET /api/health.
When connected to a stream, you can start a recording from the sidebar. The backend writes:
recordings/<timestamp>_<stream>_<id>/metadata.json– stream + backend metadatarecordings/<timestamp>_<stream>_<id>/samples.ndjson– one JSON object per sample:{ "t": <lsl_timestamp>, "d": [...] }recordings/<timestamp>_<stream>_<id>/recording.zip– convenience archive for download
src/Astro + React UIbackend/FastAPI + pylsl relaydocker-compose.ymlproduction-ish setupdocker-compose.dev.ymldev setup (hot reload)