- Why SyncWave
- Features
- Quick start
- How it works
- Security & privacy
- Build from source
- Tests
- Project status
- Limitations
- Roadmap
- FAQ
Discord's screen share is built for video, and music bots only play links. SyncWave sends what's actually playing on your PC (a Spotify playlist, a browser tab, a movie, a game's soundtrack) to your friends in a voice channel, at music quality, with no user-token tricks. It runs through a normal Discord bot that you create and own.
|
|
|
|
Important
You need a Discord bot of your own. It takes about two minutes, once.
- Install. Download
SyncWave-Setup-x.y.z.exefrom Releases and run it. It's a per-user install with no admin rights needed. - Create a bot. In the Discord Developer Portal, click New Application → Bot → Reset Token → copy it.
- Leave all Privileged Gateway Intents off.
- Turning Public Bot off is recommended, so only you can invite it.
- Connect. Paste the token into SyncWave's setup window → Save & connect.
- Invite. Click Open invite link and pick your server.
- Share. Choose a voice channel on the left and a source on the right, then press Start sharing. 🎶
Warning
Never paste your personal Discord account token. SyncWave only accepts bot tokens. Using a user token ("self-bot") is against Discord's Terms of Service.
Note
The installer is not code-signed yet, so Windows SmartScreen may warn you. Click More info → Run anyway. Each release lists the installer's SHA-256, so you can verify your download (certutil -hashfile SyncWave-Setup-1.0.0.exe SHA256).
A Discord bot can't hear your PC by itself, so SyncWave builds a real pipeline from the sound card to Discord's voice servers:
flowchart LR
A["🎧 syncwave-capture.exe<br/><sub>C++ · WASAPI loopback</sub>"] -- "PCM over<br/>stdio pipe" --> B
subgraph B["⚙️ Engine · Electron utilityProcess"]
direction TB
B1["20 ms framing<br/>gain · mute · meters"] --> B2["Opus encode<br/><sub>libopus · music mode · FEC</sub>"]
B2 --> B3["Bounded low-latency<br/>packet queue"]
B3 --> B4["@discordjs/voice"]
end
B4 -- "UDP" --> D["🔊 Discord<br/>voice channel"]
M["🖥️ Main process<br/><sub>window · tray · settings<br/>encrypted token · IPC</sub>"] <-. "validated<br/>messages" .-> B
R["🎨 React UI<br/><sub>sandboxed renderer</sub>"] <-. "contextBridge" .-> M
Why anonymous stdio pipes for the audio transport? They're private to the parent/child pair: no ports, no firewall prompts, back-pressure for free, and no coupling to Electron's native ABI. The engine also keeps latency bounded when the sound card's clock and Discord's 20 ms clock drift apart. The full design is in docs/ARCHITECTURE.md.
| 🔐 Token storage | Encrypted with Electron safeStorage (Windows DPAPI, tied to your Windows account) in %APPDATA%\SyncWave\token.bin. Settings → Bot token → Remove deletes it. |
| 🙈 Token isolation | The UI never gets the token back. It reaches the engine only over a private message port, never via command line or environment variables. |
| 🧱 Sandboxed UI | The renderer runs sandboxed with contextIsolation and no Node.js. Every IPC message is validated. |
| 🎙️ No microphone | SyncWave captures playback audio only. It never opens your microphone. |
| Sharing only starts when you press Start. Rejoining a channel never starts sharing on its own. | |
| 🚫 No DRM bypass | Protected playback and exclusive-mode audio aren't captured, by design. |
| 🧹 Clean shutdown | Stopping or quitting tears down capture, encoder and bot. No processes are left behind. |
| 📡 No telemetry | SyncWave talks only to Discord. |
Requirements
- Windows 10 2004+ / Windows 11, x64
- Node.js 22+ (tested with 24) and npm 11
- Visual Studio 2019+ Build Tools with Desktop development with C++ (MSVC + Windows SDK). Only needed to rebuild the native capture helper.
- Python 3, only to regenerate icons (
python scripts/make-icons.py)
npm install
npm run build:native # builds resources/bin/syncwave-capture.exe
npm run dev # run with hot reload
npm run dist # native + app + NSIS installer → release/Notes on native modules and environment variables
npm install runs scripts/fix-opus-binding.cjs, which makes the N-API libopus binary loadable under Electron. The allowScripts field in package.json approves the two install scripts npm 11 would otherwise block (@discordjs/opus, electron-winstaller). If libopus can't load, SyncWave falls back to opusscript and says so in Settings → Activity log.
No environment variables are needed to run the app. They're only for tests:
| Variable | Purpose |
|---|---|
SYNCWAVE_USER_DATA |
Use a throwaway profile folder (the e2e test sets this) |
SYNCWAVE_EXE |
Point the e2e test at a packaged SyncWave.exe |
SYNCWAVE_E2E_NETWORK=1 |
Let the e2e test make one login attempt with a fake token |
Project layout
native/capture/ C++ WASAPI helper (list, system/process/exclude loopback)
src/main/ Electron main: lifecycle, tray, IPC, settings, token vault, engine host
src/preload/ contextBridge API (window.syncwave)
src/engine/ utilityProcess: bot, voice, capture, processing, Opus, queue
src/shared/ types, engine protocol, validation
src/renderer/ React UI
tests/unit|native|e2e
docs/ARCHITECTURE.md
npm test # unit: validation, settings, token vault, framing, gain/mute,
# meters, Opus round-trip, latency queue, stream lifecycle
npm run test:native # real capture helper on this PC (plays a quiet 440 Hz tone ~3 s)
npm run test:e2e # builds and drives the real app UI with Playwright
npm run typecheckThe native suite includes a full pipeline test. It captures a tone-playing process with per-app capture, runs it through framing → gain → libopus → the latency queue → the real @discordjs/voice AudioPlayer, then decodes the packets the player sends and checks that they contain the tone and keep real-time pace.
SyncWave is in beta. Here's exactly what has and hasn't been tested so far.
✅ Verified on Windows 10 Pro (19045)
- System loopback, per-app loopback and "system minus Discord" capture with real audio levels, continuous 48 kHz output with silence padding, source-exit detection and clean stop.
- The full pipeline capture → Opus →
AudioPlayer, with packets decoded and checked. - UI, engine start-up, native libopus and DAVE (Discord voice encryption) loading, IPC validation, settings persistence, malformed-token rejection, Discord's rejection of an invalid token, and clean shutdown with no leftover processes. All of this in dev and in the packaged build.
🧪 Being tested now
- An end-to-end session with a real bot and real listeners: sound quality, real-world latency, reconnect after network loss, being moved or kicked.
- Running the installer through install and uninstall.
Found a problem? Please open an issue. The Activity log in Settings helps a lot.
- Per-app capture needs Windows 10 version 2004 (build 19041) or newer.
- DRM-protected playback and exclusive-mode audio can't be captured by loopback.
- If you share system audio while you're in the same channel, keep Leave Discord out of system audio on to avoid echo.
- Discord caps the effective bitrate at the channel's setting (64–96 kbps on unboosted servers).
- One voice channel at a time. If the engine crashes, it restarts and reconnects the bot, but you have to rejoin the channel.
- Code-signed installer
- Auto-update
- macOS support. Everything above the capture helper is already platform-neutral, so a port needs a helper with the same stdio protocol (ScreenCaptureKit or Core Audio process taps), an
.icnsicon and an electron-buildermactarget. - Mixing several apps into one stream
Is this against Discord's rules?
No. SyncWave uses an ordinary bot account through Discord's official API and voice protocol, the same way music bots do. It never asks for or uses your personal account token.
Why do I need my own bot?
The audio has to be sent by someone in the channel, and a bot you own means your token never leaves your PC. There's no shared server in the middle.
My friends hear an echo of themselves.
You're sharing system audio while you're in the call. Turn on Settings → Leave Discord out of system audio, or share a single app instead.
Windows says the installer is unrecognized.
This happens because the installer isn't code-signed yet. Compare the SHA-256 shown on the release page, then click More info → Run anyway. You can always build it yourself from source.
🇸🇦 بالعربية: البدء السريع
- نزّل المثبّت من Releases وشغّله.
- أنشئ بوتاً من Developer Portal، ثم من تبويب Bot اضغط Reset Token وانسخ التوكن. لا تحتاج إلى أي Intents مميزة.
- الصق التوكن في نافذة الإعداد، ثم اضغط Open invite link وأضف البوت إلى سيرفرك.
- اختر روماً صوتياً من اليسار، ومصدر الصوت من اليمين (صوت النظام أو تطبيق معيّن)، ثم اضغط Start sharing.
لا تضع توكن حسابك الشخصي أبداً، بل توكن البوت فقط. يُخزَّن التوكن مشفّراً على جهازك.
Made by Team GRIPHOX · Released under the MIT License
SyncWave is not affiliated with or endorsed by Discord Inc.


