Skip to content

map: ScriptProcessorNode audio fallback so listening works over plain HTTP - #14

Merged
M0LTE merged 1 commit into
mainfrom
map-audio-http-fallback
Jun 4, 2026
Merged

map: ScriptProcessorNode audio fallback so listening works over plain HTTP#14
M0LTE merged 1 commit into
mainfrom
map-audio-http-fallback

Conversation

@M0LTE

@M0LTE M0LTE commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Problem

On the live map, clicking a port's ♪ to listen threw:

TypeError: Cannot read properties of undefined (reading 'addModule') at ensureAudioCtx (map:1575)

ensureAudioCtx calls ctx.audioWorklet.addModule(...), but AudioWorklet is a secure-context-only API. When the UI is served over plain HTTP from a non-localhost host (e.g. http://packetdotnet:8090), ctx.audioWorklet is undefined, so playback never started. (The ws:// audio stream itself isn't secure-context-gated — only the worklet playback was.)

Fix

Branch the playback node in ensureAudioCtx:

  • Secure context (HTTPS / localhost): unchanged — AudioWorklet as before.
  • Insecure context (plain HTTP): fall back to a ScriptProcessorNode. Deprecated and main-thread, but not secure-context-gated and fine for monitoring one port. Same queue/drain logic as the worklet, with a ~2 s backlog cap.

ws.onmessage now routes samples through a mode-agnostic listenState.feed, so both paths share the receive/decode code. No behaviour change on HTTPS/localhost.

Not in scope (separate, environmental)

The 503 on /api/peer/chatbot/state is unrelated: the peer proxy can't resolve a chatbot container on the Docker network (lookup chatbot ... no such host), so it returns a clean 503 and the map hides that panel. Nothing to fix in code — run a container named chatbot (port 8090) on the same network if you want the panel.

Testing

  • make test green; go build of the embed OK; map.html JS passes node --check.
  • Served /map over HTTP and confirmed it carries the fallback (createScriptProcessor, the ctx.audioWorklet guard, and the feed() routing).
  • A true in-browser check over an insecure origin wasn't possible in the sandbox (host OS too new for Playwright's chromium; the chrome channel needs root). The fix targets the exact, confirmed cause with the canonical ScriptProcessorNode generator pattern — worth a 10-second manual confirm: reload the map over http://… and click ♪.

Merging publishes a fresh ghcr.io/packethacking/net-sim:main image with the fix.

…ontexts

The map's "listen" feature opened an AudioWorklet to play a port's PCM. AudioWorklet is a secure-context-only API, so on plain HTTP served from a non-localhost host (e.g. http://packetdotnet:8090) `ctx.audioWorklet` is undefined and `ensureAudioCtx` threw `TypeError: Cannot read properties of undefined (reading 'addModule')` — audio never started.

Branch the playback node in ensureAudioCtx: keep the AudioWorklet on secure contexts (HTTPS / localhost), and fall back to a ScriptProcessorNode when `ctx.audioWorklet` is absent. ScriptProcessorNode is deprecated and runs on the main thread, but it isn't secure-context-gated and is fine for monitoring one port. It uses the same queue/drain logic as the worklet (with a ~2 s backlog cap). The WebSocket onmessage now routes samples through a mode-agnostic `listenState.feed` so both paths share the receive code.

No functional change on HTTPS/localhost (still uses the worklet). Unrelated to the 503s on /api/peer/chatbot/state — those are just the peer proxy reporting no `chatbot` container is resolvable on the Docker network; the map already hides that panel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@M0LTE
M0LTE merged commit 9c24c97 into main Jun 4, 2026
1 check passed
@M0LTE
M0LTE deleted the map-audio-http-fallback branch June 4, 2026 04:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant