Noise control for Sony headphones, in your browser.
No app, no account, no server: a static web page that talks to your headphones over Bluetooth.
Open WebMDR · Status · Known issues · Contributing
Independent project; not affiliated with or endorsed by Sony. "WebMDR" is a working name, not a claim of trademark clearance.
- Switch between Noise cancelling, Ambient sound and Off.
- Set the Ambient level (live while you drag) and Voice passthrough.
- Follow changes you make with the headphone buttons.
- Show the firmware version the headphones report.
Every change is confirmed by reading the setting back from the headphones. If that can't be confirmed, the page says so instead of pretending it worked.
- Pair the headphones with your computer in the system Bluetooth settings.
- Open https://abnormal749.github.io/WebMDR/ in desktop Chrome. Other Chromium browsers such as Edge may work but are untested.
- Click Connect and pick your headphones.
Turn on Advanced (top right) for connection details, read-only/passive session modes and the protocol log. The log stays in the page: nothing is uploaded or stored.
The page only works while it is open; closing it disconnects.
The protocol is chosen from the Bluetooth service the headphones expose, never from their name.
| Protocol | Tested in WebMDR | Expected to work (listed by upstream, untested here) |
|---|---|---|
| Sony V2 | WH-1000XM5 (firmware 2.5.1) | WH-1000XM6, WF-1000XM4, WF-1000XM5, WF-1000XM6, WH-CH720N, ULT WEAR, LinkBuds S, newer WH-1000XM4 units |
| Sony V1 | none | WH-1000XM3, older WH-1000XM4 units |
On V1 headphones the page asks you to enable the untested controls explicitly. If your model isn't in the tested column, a hardware report is the most useful contribution you can make.
Last updated 2026-09-28.
| Milestone | State | Evidence |
|---|---|---|
| Frame codec, session, noise-control logic | Done | Unit tests with a fake transport and fake time |
| Connect, initialize, read state | Done on XM5 | H-003, replayed in CI |
| Change settings, confirmed by read-back | Done on XM5 | NC / Ambient / Off, levels 1–20, voice passthrough (H-003, H-004) |
| Adopt headphone-button changes; handle power-off | Done on XM5 | H-005 |
| Published site | Done | Tested from the GitHub Pages origin (H-005, H-006) |
| V1 protocol and other V2 models | Code done | Needs hardware reports |
| Firmware version display | Done on XM5 | Firmware 2.5.1 read in H-007/H-008 |
Hardware results are recorded in the evidence record. Unit tests are never counted as hardware validation.
- Reconnecting after a headphone power cycle can fail on macOS with Chrome 154. Page cleanup works, but an orphaned native RFCOMM channel can block the next open. Bluetooth disconnect/reconnect alone was unreliable. The optional local mode below recovered without restarting Chrome; the static website cannot perform this native handoff. Exact test results and limits.
- The model can't be detected. Web Serial hides the Bluetooth name, and no reviewed Sony command returns the model, so the page shows the protocol and firmware instead.
- Only one headset model has been tested. Some V2 models may use a different noise-control code; on those, the page stops at "not ready" without changing anything.
- Browsers: desktop Chrome on macOS is tested. Windows, Linux and Android Chrome 138+ have the API but are untested. Safari and Firefox have no Web Serial.
- Not tested: audio playback during a session, multipoint connections, sleep.
- No background control: closing the page ends the control session. The optional recovery companion only assists failed connections.
The local companion enables refresh recovery for the tested Chrome/XM5 issue. It requires Node 24 and Xcode Command Line Tools:
npm ci
npm run build
npm run local:recovery -- --device "WH-1000XM5"Open http://127.0.0.1:5173/WebMDR/ directly in Chrome and authorize the configured headset. Keep the terminal running. After a headset restart, wait for it to reconnect to the Mac, then refresh the page. The page reconnects and reads current state without replaying settings.
- Recovery took 21–27 seconds in local tests. It briefly interrupts audio and pauses Chrome, with an independent 20-second resume watchdog.
- If multiple Chrome processes are running, add
--chrome-pid PIDfor the intended main browser process. Use only one authorized headset for local mode. - A failed recovery stops after one attempt. Check the terminal before pressing Reconnect again. Ctrl-C stops the companion.
The companion binds only to loopback, accepts authenticated same-origin requests, and installs no background service. This workaround is available only in local mode; it does not change Chrome or Bluetooth pairing. See H-008 for evidence and limits.
Contributions are welcome, especially hardware reports for models other than the WH-1000XM5. See CONTRIBUTING.md for setup, the rules protocol code follows, and how to test with real headphones.
npm ci
npm run dev # local server at http://localhost:5173
npm run verify # type-check, tests, production build, dist checks (same as CI)Static HTTPS page → Web Serial → Bluetooth RFCOMM → Sony control service
src/ui/ page and DOM (the only code that touches the DOM)
src/app/ controller: connection phases, one in-flight change, confirmation
src/features/ noise-control state, merging edits
src/protocol/ frame codec, session (ACKs, sequencing, timeouts), V1/V2 layouts, profiles
src/transport/ Web Serial port selection, open/close
test/ unit tests, fake transport, captured sessions replayed in CI
A browser write, a protocol ACK and a confirmed setting are treated as three different outcomes. The session runs one transaction at a time and lets ACKs bypass the queue. An ambiguous timeout is reported as "unknown" and never retried blindly. The technical review explains why.
| Document | Contents |
|---|---|
| CONTRIBUTING.md | Setup, workflow, pull-request checklist |
| CHANGELOG.md | Changes in each release |
| AGENTS.md | Protocol and architecture contract (for humans and coding agents) |
| docs/hardware-test.md | Step-by-step test with real headphones |
| docs/device-matrix.md | Hardware evidence records H-001 to H-008 |
| docs/technical-review.md | Frame format, session design, reasons for each rule |
| docs/sources.md | Sources reviewed and what each supports |
| docs/reuse-manifest.md | Every file adapted from third-party code |
The page has no backend and loads no third-party scripts; a strict content-security policy is applied to the build. Protocol data stays in the page. The protocol log is kept in memory only and shown only under Advanced.
WebMDR is released under the MIT License.
The frame format and command layouts are adapted from Sony Device Center (MIT) at commit dea38969b501a4a167f330dff104414531e80eae. Its notice ships in THIRD_PARTY_NOTICES.txt and in the deployed site, and every adapted file is listed in the reuse manifest. No Gadgetbridge (AGPLv3) code is used; it was read for protocol facts only.