Live Gemini could not use an external speaker or headset. An AudioContext
is bound to whichever output was default when it was created, and
getUserMedia({audio:true}) takes the system default input, so plugging a
device in afterwards left audio going to the old one — silently, with no
error to explain it.
* Explicit Mic and Speaker pickers. Capture opens the chosen deviceId
exactly and can be switched mid-session; playback is routed through a
MediaStreamAudioDestinationNode into a hidden <audio> element so
setSinkId() can move it to the chosen sink. Both lists refresh on
devicechange and are remembered in localStorage.
* Windows reports each device three times (default, communications, and
the real one), so an Anker would have appeared three times with no way
to tell them apart. The pseudo-devices are now collapsed.
* Capture moved to an AudioWorklet (Blob-built, no extra file served)
with the ScriptProcessor kept as a fallback.
* A compatibility line reports what the browser actually supports, and
the diagnostics line now shows the output sink and capture kind — the
difference between "not listening" and "not speaking" without a
debugger.
Verified in both engines with Playwright (chromium PASS, firefox PASS: no
page errors, personas and device lists populated, test tone plays) and
against real hardware, where setSinkId matched the selection and a named
microphone opened by deviceId. Two engine-specific bugs fell out of that
run and are fixed here: reading AudioContext.prototype.audioWorklet invokes
the getter and throws in both browsers, which aborted init and left the tab
empty, and the init steps are now isolated so one failure cannot take the
rest down.
Also in this commit:
* README rewritten against what the code does today — the voice-fidelity
rationale and its three gates, why words used to cut off, the Live tab
and why the browser talks to Google directly, personas, device
selection, recordings search/filter, sign-in history, a current API
list, the cPanel production setup, and the known limits.
* shell_scripts/start_cpanel.sh — the launcher that actually keeps the
site up (HTTP health check, not a TCP probe) was only on the host.
* data/live_personas.json — the persona library (G1, R1, Agibot, T800)
existed only on the server; it is user-written content worth keeping.
* .gitignore covers runtime state (logins, generated WAVs, .env, backups).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
14 lines
122 B
Plaintext
14 lines
122 B
Plaintext
__pycache__/
|
|
*.pyc
|
|
Logs/
|
|
logs/
|
|
*.log
|
|
|
|
# runtime state, not source
|
|
data/logins.json
|
|
data/audio/*.wav
|
|
|
|
# local
|
|
.env
|
|
*.bak.*
|