fix: Mikrofon hängt — PipeWire-Fallback + getUserMedia Timeout [appimage]
All checks were successful
Build AppImage / build (push) Successful in 8m22s
All checks were successful
Build AppImage / build (push) Successful in 8m22s
Wenn PipeWire nicht läuft (z.B. PulseAudio/xRDP), wird pipewiresrc auf Rank 0 gesetzt damit WebKitGTK auf pulsesrc zurückfällt. getUserMedia bekommt 5s Timeout statt endlos zu hängen. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a01959a55c
commit
6e1a3c41f2
2 changed files with 38 additions and 6 deletions
|
|
@ -120,6 +120,12 @@ pkgs.stdenv.mkDerivation {
|
|||
fi
|
||||
fi
|
||||
|
||||
# GStreamer/PipeWire: Wenn PipeWire NICHT laeuft, pipewiresrc runterranken
|
||||
# damit WebKitGTK auf pulsesrc zurueckfaellt (sonst haengt getUserMedia endlos)
|
||||
if ! pgrep -x pipewire >/dev/null 2>&1; then
|
||||
export GST_PLUGIN_FEATURE_RANK="pipewiresrc:0,pipewiresink:0"
|
||||
fi
|
||||
|
||||
exec "$BIN" "$@"
|
||||
LAUNCHER
|
||||
chmod +x $out/bin/claude-desktop
|
||||
|
|
|
|||
|
|
@ -366,15 +366,39 @@
|
|||
|
||||
// ============ Voice Interface ============
|
||||
|
||||
// getUserMedia mit Timeout — WebKitGTK hängt manchmal endlos statt zu fehlern
|
||||
function getUserMediaWithTimeout(constraints: MediaStreamConstraints, timeoutMs = 5000): Promise<MediaStream> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new Error(`getUserMedia Timeout nach ${timeoutMs}ms — GStreamer-Pipeline hängt`));
|
||||
}, timeoutMs);
|
||||
|
||||
navigator.mediaDevices.getUserMedia(constraints)
|
||||
.then((stream) => {
|
||||
clearTimeout(timer);
|
||||
resolve(stream);
|
||||
})
|
||||
.catch((err) => {
|
||||
clearTimeout(timer);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function startRecording() {
|
||||
try {
|
||||
let stream: MediaStream;
|
||||
|
||||
// Prüfe zuerst ob mediaDevices überhaupt verfügbar ist
|
||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||
throw new Error('MediaDevices API nicht verfügbar — WebKitGTK braucht GStreamer + PipeWire');
|
||||
}
|
||||
|
||||
try {
|
||||
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
stream = await getUserMediaWithTimeout({ audio: true });
|
||||
} catch (initialErr) {
|
||||
// WebKitGTK wirft verschiedene Fehler: OverconstrainedError, NotFoundError,
|
||||
// TypeError("Invalid constraint"), etc. Bei JEDEM Fehler Fallback versuchen.
|
||||
// TypeError("Invalid constraint"), Timeout. Bei JEDEM Fehler Fallback versuchen.
|
||||
console.warn('getUserMedia({audio:true}) fehlgeschlagen, versuche Fallback:', initialErr);
|
||||
|
||||
try {
|
||||
|
|
@ -383,17 +407,19 @@
|
|||
|
||||
if (audioInput) {
|
||||
console.log('Audio-Device gefunden:', audioInput.label || audioInput.deviceId);
|
||||
stream = await navigator.mediaDevices.getUserMedia({
|
||||
stream = await getUserMediaWithTimeout({
|
||||
audio: { deviceId: { exact: audioInput.deviceId } }
|
||||
});
|
||||
} else {
|
||||
// Letzter Versuch: komplett ohne Constraints
|
||||
stream = await navigator.mediaDevices.getUserMedia({ audio: {} });
|
||||
stream = await getUserMediaWithTimeout({ audio: {} });
|
||||
}
|
||||
} catch (fallbackErr) {
|
||||
throw new Error(
|
||||
'Kein Mikrofon verfügbar. Unter WebKitGTK (Tauri/Linux) wird ' +
|
||||
'PipeWire oder PulseAudio mit gst-plugin-pipewire benötigt. ' +
|
||||
'Mikrofon-Zugriff fehlgeschlagen. Mögliche Ursachen:\n' +
|
||||
'• GStreamer-Plugins fehlen (gst-plugin-pipewire)\n' +
|
||||
'• PipeWire läuft nicht\n' +
|
||||
'• App wurde nicht über den Nix-Wrapper gestartet\n' +
|
||||
`Original: ${initialErr instanceof Error ? initialErr.message : initialErr}`
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue