Speech-to-text mic (bottom-right button) did not work in the Linux AppImage. It was a chain of separate problems, each hidden behind the previous one. The surfaced error, OverconstrainedError: Invalid constraint, was only a symptom of WebKitGTK seeing 0 capture devices.
Changes
GStreamer plugins: the AppImage bundled GStreamer libs but no plugins (appsink not found, 0 devices). Enable bundle.linux.appimage.bundleMediaFramework and install the gst plugin packages on the CI runners (both app workflows).
libpipewire: the bundled copy has the builder's SPA plugin paths compiled in and failed on other layouts (pw_loop_new: can't make support.system handle). finalize-appimage.sh now removes it so the host's is used, as already done for libwayland-client, and asserts it is gone.
WebKitGTK permission (new linux_media.rs, Linux only): wry neither enables media streams nor answers permission-request, giving NotAllowedError. The main window now enables media streams and grants audio-only requests; camera, mixed, and all other permission types are denied. Other windows get nothing.
getUserMedia ladder (get-microphone.ts): saved device, then default device, then bare audio: true on OverconstrainedError/NotFoundError. Permission errors still surface. STT error now includes the DOMException name.
Testing
Frontend: tsc clean, 1173 vitest tests pass. Rust: unit tests for the grant rule pass.
Manually verified on CachyOS with a built AppImage: media permission request allowed, recording and transcription work.
CI changes are unverified until this PR's preview build runs.
Notes
AppImage grows from ~89 MB to ~100 MB.
GStreamer-CRITICAL ... GstIntRange lines still print from WebKit; mic works regardless.
The Microphone settings picker remains hidden (c023d80).
Speech-to-text mic (bottom-right button) did not work in the Linux AppImage. It was a chain of separate problems, each hidden behind the previous one. The surfaced error, `OverconstrainedError: Invalid constraint`, was only a symptom of WebKitGTK seeing 0 capture devices.
## Changes
- **GStreamer plugins**: the AppImage bundled GStreamer libs but no plugins (`appsink not found`, `0 devices`). Enable `bundle.linux.appimage.bundleMediaFramework` and install the gst plugin packages on the CI runners (both app workflows).
- **libpipewire**: the bundled copy has the builder's SPA plugin paths compiled in and failed on other layouts (`pw_loop_new: can't make support.system handle`). `finalize-appimage.sh` now removes it so the host's is used, as already done for libwayland-client, and asserts it is gone.
- **WebKitGTK permission** (new `linux_media.rs`, Linux only): wry neither enables media streams nor answers `permission-request`, giving `NotAllowedError`. The main window now enables media streams and grants audio-only requests; camera, mixed, and all other permission types are denied. Other windows get nothing.
- **getUserMedia ladder** (`get-microphone.ts`): saved device, then default device, then bare `audio: true` on `OverconstrainedError`/`NotFoundError`. Permission errors still surface. STT error now includes the DOMException name.
## Testing
- Frontend: tsc clean, 1173 vitest tests pass. Rust: unit tests for the grant rule pass.
- Manually verified on CachyOS with a built AppImage: `media permission request allowed`, recording and transcription work.
- **CI changes are unverified until this PR's preview build runs.**
## Notes
- AppImage grows from ~89 MB to ~100 MB.
- `GStreamer-CRITICAL ... GstIntRange` lines still print from WebKit; mic works regardless.
- The Microphone settings picker remains hidden (c023d80).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The mic button failed on Linux with a chain of distinct problems, each
hidden behind the previous one:
- The AppImage bundled GStreamer libraries but no plugins, so WebKitGTK
found 0 capture devices. Enable bundleMediaFramework and install the
GStreamer plugin packages on the CI runners.
- The bundled libpipewire had the builder's SPA plugin paths compiled in
and failed on hosts with a different layout. finalize-appimage.sh now
drops it so the host's is used (host-coupled, like libwayland-client).
- WebKitGTK denies getUserMedia until the embedder enables media streams
and answers the permission request; wry does neither. Add a Linux-only
handler for the main window that grants audio-only requests and denies
everything else.
- getUserMedia now steps down from the saved device to the default device
to bare audio:true on OverconstrainedError/NotFoundError, and the STT
error shows the DOMException name.
Verified on CachyOS: permission request allowed, recording works.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
jknapp
merged commit d4a14d2ded into main2026-11-05 14:42:33 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Speech-to-text mic (bottom-right button) did not work in the Linux AppImage. It was a chain of separate problems, each hidden behind the previous one. The surfaced error,
OverconstrainedError: Invalid constraint, was only a symptom of WebKitGTK seeing 0 capture devices.Changes
appsink not found,0 devices). Enablebundle.linux.appimage.bundleMediaFrameworkand install the gst plugin packages on the CI runners (both app workflows).pw_loop_new: can't make support.system handle).finalize-appimage.shnow removes it so the host's is used, as already done for libwayland-client, and asserts it is gone.linux_media.rs, Linux only): wry neither enables media streams nor answerspermission-request, givingNotAllowedError. The main window now enables media streams and grants audio-only requests; camera, mixed, and all other permission types are denied. Other windows get nothing.get-microphone.ts): saved device, then default device, then bareaudio: trueonOverconstrainedError/NotFoundError. Permission errors still surface. STT error now includes the DOMException name.Testing
media permission request allowed, recording and transcription work.Notes
GStreamer-CRITICAL ... GstIntRangelines still print from WebKit; mic works regardless.c023d80).🤖 Generated with Claude Code