Beatsync: multi-device audio playback in the browser, synchronized with NTP-style clock math
🔊 High-precision web player for multi-device audio playback and spatial audio.
At a glance
- What is it?
- Beatsync is a self-hostable web player that keeps audio aligned across several devices at once, using NTP-inspired time synchronization and a Bun WebSocket server. It is early-stage software, and the README says so.
- Who is it for?
- Adopt Beatsync if you want a browser-based, self-hosted way to play the same audio on several devices at once and you are comfortable running a Bun workspace. Do not adopt it if you need a stable consumer product for phones, or if your playback depends on a source format the project does not handle.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 120 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 10, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Beatsync solves, and who it is actually for
Getting two speakers in the same room to play the same track at the same instant is a timing problem, not an audio problem. Browsers give you the Web Audio API and a clock, but they do not give you agreement between machines about what time it is. Beatsync exists to close that gap in a web page. The README describes it as a "high-precision web audio player built for multi-device playback" and lists "millisecond-accurate synchronization" as the first feature, implemented by abstracting NTP-inspired time synchronization primitives.
The audience is narrow but real. You are a developer or a technically comfortable host who wants several browsers (laptops, desktops, a tablet) playing in lockstep, and you are willing to run your own server. The README points to beatsync.gg as the official app, so a hosted option exists, while the self-hostable claim means the same code can run on your own machine. The project also offers spatial audio, described as controlling device volumes through a virtual listening source, which turns a set of synchronized devices into something closer to a room-scale speaker layout than a single stereo output. If you only need one device to play a file, this is more machinery than the job requires.
How the synchronization mechanism is structured
The repository is a Turborepo monorepo with three workspaces that map onto the data flow. apps/server is a Bun HTTP plus WebSocket server. apps/client is a Next.js frontend using Tailwind and Shadcn/ui. packages/shared holds "type-safe schemas and functions shared between client & server". That shared package is the interesting part: the clock-synchronization primitives are not duplicated on each side, they are defined once and imported by both, which is what keeps the client and server agreeing on message shapes and timing math.
The runtime path is straightforward. A client opens a WebSocket to the server, exchanges timing messages, and derives an offset it can apply to scheduled playback. The server's job is to be a common reference and to relay state between clients in the same session. The Dockerfile confirms the server is a self-contained bundle: the build stage runs bun run build inside apps/server, and the runner stage copies only apps/server/dist and starts it with bun dist/index.js. No node_modules ship in the final image.
One design consequence worth naming: because synchronization depends on a live WebSocket connection to a server, the accuracy you get is bounded by the network path between each device and that server. The README does not document any offline or peer-to-peer fallback, so a dropped connection is a correctness problem, not just a convenience one.
Self-hosting Beatsync: install and first run
The README's quickstart assumes Bun and Turborepo. Before starting anything, you fill in the .env file in apps/client with the API and WebSocket URLs. The README gives these two keys and values:
NEXT_PUBLIC_API_URL=http://localhost:8080
NEXT_PUBLIC_WS_URL=ws://localhost:8080/wsThose values point at a local server on port 8080. Then install once for all workspaces and start both processes:
bun install
bun devThe README states that bun dev starts the client on port 3000 and the server on port 8080. If you prefer containers, the package.json exposes a Docker path that builds an image tagged beatsync and runs it as a container named beatsync-server, publishing port 8080 and reading environment variables from apps/server/.env:
bun run docker:prodThat script is a composition of docker:build and docker:run, so it builds first and then replaces any existing container with that name. For a long-running deployment, pm2:start runs pm2.config.js and pm2:logs follows the output. The first real use is the same in every case: open the client in a browser, and open it again on a second device pointed at the same server, then check whether the two are aligned. The README does not describe a step-by-step room-creation flow, so the UI itself is the place to look for how sessions are joined.
Where Beatsync breaks down or is the wrong tool
The README carries an explicit warning: "Beatsync is in early development. Mobile support is working, but experimental." That sentence should govern deployment decisions. If your use case is phones and tablets in a casual setting, you are on the experimental path, and the project itself asks for issues or pull requests when problems appear. There is no release history in the repository listing, so there is no versioned compatibility story to lean on.
The browser requirement is the second constraint. The README says it works on any device with a modern browser and recommends Chrome for best performance, which is a soft way of saying that behavior varies by engine. Timing precision is exactly the kind of thing that varies. The third constraint is the server dependency described above: every participating device needs a reachable WebSocket endpoint, so a venue with locked-down networking or no route to your server is out.
Finally, consider what Beatsync is not. It is a player with a synchronization layer, not a DJ application. It has no documented beatmatching, tempo detection or track-analysis features, so if that is what you mean by beat sync, this project does not do it. The search questions around Canva, Rekordbox, CapCut and DDJ controllers describe software from other vendors entirely.
Beatsync against Snapcast and other synchronized players
The closest well-known comparison is Snapcast, the multiroom audio server that pairs with MPD or similar players. The difference in approach is architectural. Snapcast runs as a native server with native clients, usually on a local network, and it streams audio to those clients. Beatsync runs in the browser: the server is a Bun HTTP and WebSocket process, the client is a Next.js app, and the synchronization is about coordinating playback rather than pushing an audio stream to dedicated endpoints. That makes Beatsync easier to stand up on machines that already have a browser and harder to use where you would want a headless hardware player.
A second comparison is simply using one browser tab and casting or mirroring it to several outputs. That avoids the clock problem by having a single source, but it also removes per-device volume control, which is what Beatsync's spatial audio feature is for. If you need independent volume per device positioned around a virtual listening source, the single-source approach cannot express it.
The trade-off is real in both directions. Snapcast gives you a mature native pipeline and no browser dependency; Beatsync gives you a cross-platform client that runs anywhere a modern browser runs, at the cost of being early software with experimental mobile support.
Licence, maintenance and upgrade cost
Beatsync is MIT licensed, which is permissive: you can run it, modify it and redistribute it, provided the licence and copyright notice are preserved. That is the whole of what the repository states, and it is not legal advice; if you are embedding it in a commercial product, read the LICENSE file in the repository root yourself.
The last push to the default branch was on 2026-06-12, and the repository is not archived. That is roughly three and a half months before the date of writing, which is recent enough that the project has not gone quiet, but there are no retrieved releases to anchor an upgrade path. Upgrades therefore track the main branch, and the practical cost is the usual monorepo cost: bun install at the root, then rebuild. The Docker path makes this cheap because the runner image contains only the bundled dist directory, so a redeploy is a rebuild and a container replacement rather than a dependency reconciliation. The pm2 path is similar; pm2:restart beatsync-server is the documented command. The MIGRATION.md file in the repository root suggests the project anticipates breaking changes and documents them, which is the right instinct for software this young.
Editorial conclusion
Adopt Beatsync if you want a browser-based, self-hosted way to play the same audio on several devices at once and you are comfortable running a Bun workspace. Do not adopt it if you need a stable consumer product for phones, or if your playback depends on a source format the project does not handle. Before deploying, verify that the .env values in apps/client point at your own server rather than localhost, and confirm the server's port 8080 is reachable from every device you intend to sync.
Frequently asked questions
What does Beatsync do?
It is a high-precision web audio player built for multi-device playback, synchronizing audio across devices with NTP-inspired time synchronization primitives. It also offers spatial audio, which controls device volumes through a virtual listening source.
Is Beatsync free?
The source is MIT licensed and the README describes the project as self-hostable, so you can run your own instance. The README also points to beatsync.gg as the official app, but it does not state any pricing for that hosted service.
How to use Beatsync?
Fill in the .env file in apps/client with NEXT_PUBLIC_API_URL and NEXT_PUBLIC_WS_URL, then run bun install and bun dev, which starts the client on port 3000 and the server on port 8080. Alternatively, bun run docker:prod builds and runs the server container on port 8080.
What is Beatsync?
Beatsync is a TypeScript project from the freeman-jiang/beatsync repository, organized as a Turborepo monorepo with a Bun HTTP and WebSocket server, a Next.js client, and a shared package of type-safe schemas.
How to use Beatsync gg?
The README identifies beatsync.gg as the official app, while the self-hosted route runs the same code locally through bun dev or the Docker scripts. The README does not document a separate workflow for the hosted site.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/freeman-jiang-beatsync)