Skip to content

Web Access

Score2 edited this page Aug 15, 2026 · 1 revision

Web Access

AudioHub can serve the same interface on a separate port, so you can drive it from a browser on this machine with nothing installed.

Reaching it from a phone, a tablet or another computer is not possible in this release. The port is bound to 127.0.0.1 unconditionally — the switch that would change that is present but locked, and a configuration file that says otherwise is overridden. That is not an oversight; the reason is below.

It is off by default.


What it is

Default port 47800/TCP, changeable, range 1024–65535
Where to open it http://127.0.0.1:<port>/ — the exact link is shown in Settings under the switch once the listener is up. No other address works while the port is locked to local only.
Served by the app, not the audio service
Relationship to audio none — this port carries no media and is not the control port
Lifetime tied to the app window process. "Quit App (Audio Stays On)" from the tray closes this port and leaves audio running.
Contents the identical UI bundle the desktop window renders
Methods served GET and HEAD. Anything else gets 405.

AudioHub never puts credentials in the URL. Once the page has loaded it asks the app for connection parameters over a same-origin GET /ipc-endpoint, so nothing lands in your address bar, your history, or the referrer header of anything you click. (The page will honour a ?port=…&token=… query string if something hands it one, ahead of every other source — that path exists for test tooling, and pasting such a URL would give away the property just described.)

What does not work from a browser tab

Three settings become read-only: the enable switch, the port, and Local only. Otherwise a single misclick from the browser would close the very door you are standing in. The page says so, under the note Browser view · Change the three settings above in the app to avoid closing this page.

Two other things also differ:

  • The Install / Update / Repair Driver button on the Mode card is not read-only, it is absent. It needs the desktop app. Someone following the Mode B setup steps from a browser tab will look for a button that is not there.
  • The ? help links may end up copied to your clipboard instead of opening, since the tab has no way to hand a URL to your system browser.

Why "local only" is locked

Local only means the port is bound to 127.0.0.1. Not "bound everywhere and filtered by source" — actually not listening on any outward-facing address, so nothing on the LAN can reach it at all.

The switch that would turn this off is present but disabled, and the honest reason is not "not implemented yet". It is that turning it off does not produce a working remote interface, so the only thing it would accomplish is the harm.

Measured, machine to machine on one LAN:

  1. The remote browser does fetch the page. Fine so far.
  2. The remote browser does obtain the service's IPC token from /ipc-endpoint. Already bad, and we will come back to it.
  3. The remote browser cannot connect to the audio service. The service's IPC listener is bound to loopback and nothing else. From another machine it is simply not there.
  4. Opening the LAN address from the local machine does not rescue it either: browsers apply Private Network Access rules and block a page served from a LAN address when it tries to open a connection to loopback.

So the net effect of unlocking the switch, today, is step 2 and nothing else: the token goes out in the clear, and the interface still does not work.

The lock lives at the line that actually binds the socket, not merely on the UI switch, because webui.json is a plain file anyone can edit. A stored local_only: false still binds loopback.

What it would take to unlock it

The app would have to provide a second path that forwards IPC outward. That is a real feature and it is not off the table — but the moment it exists, "no authentication for now" stops being tenable. Remote control and no authentication cannot both be true. Whichever way that is resolved, it is a decision to make deliberately, not one to arrive at by flipping a switch whose label says nothing about it.

Your stored value is left alone rather than rewritten, and the app writes one line to its log the first time it starts the listener with that configuration, so the override is visible rather than silent. The log is app.log in the config folder. It is only written when web access is actually on, because that is when the listener starts — grepping the audio service's log, or looking with the feature switched off, will find nothing.


What turning it off would expose

Stated plainly, because if the lock is ever lifted this is what the warning in the UI is compressing:

  • Anyone on the same network who knows the IP and port can open the interface.
  • /ipc-endpoint hands them the audio service's IPC token in plain text. There is no authentication in front of it.
  • That token is full control of the local audio service, for anyone holding it who can also reach loopback — another login session on the machine, or any program on it that can make an HTTP request. Pair, unpair, open and close audio paths, change settings.

It is not a read-only status page. Treat the token as a password, because that is what it is.


Practical notes

Use 127.0.0.1 or localhost, nothing else. While the port is loopback-only the server refuses any other Host header with 421 Misdirected Request — including a friendly name you pointed at 127.0.0.1 yourself in your hosts file, and including this machine's own .local name. This is deliberate: without it, any web site could resolve a domain it controls to your loopback address, and the page it served would then be same-origin with this one and could read /ipc-endpoint.

The page and the audio service fail independently. If the audio service is not running, the page still loads — it is served by the app — but the interface never connects: /ipc-endpoint answers 503 with {"error":"daemon not running"}. A loaded-but-dead page means the service, not the web feature. Check the status indicator in the app window; a browser tab cannot start the service.

The server's error pages are Chinese-only, whatever language you have set. The interface itself is fully translated, but the handful of raw HTTP errors the web server produces itself — 400 for a malformed request or a rejected path, 403 for a non-loopback client, 404, 405, 421, and 503 when more than 32 connections are already in flight — are hard-coded Chinese strings. This is a known gap, not a broken page.

The port is not the audio port. Changing it cannot break a call. If binding fails the interface says so and the switch stays off — the usual cause is another program already on that port. The number you typed is saved even when the bind fails, deliberately, so your intent is not lost; that also means a restart will retry the same busy port. Pick a different one and press Apply.

Two sources for the page. Under the switch, Settings prints either Page files are embedded in the app and match the in-app interface or Page files are served from <path>. The second appears in development builds, and in any build if AUDIOHUB_WEBUI_ROOT points at a directory containing an index.html. It is the answer to "why does the browser look older than the window".

Keyboard shortcuts do not travel. They live in the browser storage of whichever origin you opened, so the desktop window and a browser tab keep separate sets. The same is true of the language and theme menus. See Settings Reference.

Clone this wiki locally