feat: Windows-Audiogeraete-Erkennung reparieren - Dummy-PeerConnection weckt das Audio-Device-Modul (M3)
This commit is contained in:
@@ -35,12 +35,30 @@ class _VoiceSectionState extends ConsumerState<_VoiceSection> {
|
||||
} catch (_) {
|
||||
devices = [];
|
||||
}
|
||||
// Windows (und teils Android) liefert eine LEERE Liste ohne Fehler,
|
||||
// solange in diesem Prozess noch nie ein Media-Stream geöffnet wurde.
|
||||
// Deshalb nicht nur bei Exception, sondern auch bei leerer Liste einmal
|
||||
// kurz getUserMedia anfordern und erneut enumerieren — und zwar SOLANGE
|
||||
// der Stream noch offen ist (nach stop() melden manche Systeme wieder 0).
|
||||
final hasAudioInput =
|
||||
// Windows: die Geräteliste kommt aus dem Audio-Device-Module der
|
||||
// libwebrtc.dll, und das wird erst initialisiert, wenn irgendeine
|
||||
// PeerConnection existiert (webrtc-sdk/libwebrtc Issue #141, Fix #142
|
||||
// noch in keinem Binary-Release – Diagnose siehe tool/device_probe.dart).
|
||||
// Ohne laufenden Call ist die Liste deshalb IMMER leer. Workaround:
|
||||
// kurz eine Dummy-PeerConnection anlegen (kein Mikrofonzugriff nötig),
|
||||
// enumerieren, wieder schließen.
|
||||
var hasAudioInput =
|
||||
devices.any((d) => d.kind?.toLowerCase() == 'audioinput');
|
||||
if (devices.isEmpty || !hasAudioInput) {
|
||||
RTCPeerConnection? admWakeup;
|
||||
try {
|
||||
admWakeup = await createPeerConnection({});
|
||||
devices = await navigator.mediaDevices.enumerateDevices();
|
||||
} catch (_) {
|
||||
// Fallback unten übernimmt.
|
||||
} finally {
|
||||
await admWakeup?.close();
|
||||
}
|
||||
}
|
||||
// Zweite Stufe (andere Systeme, z. B. teils Android): einmal kurz
|
||||
// getUserMedia anfordern und erneut enumerieren, SOLANGE der Stream
|
||||
// offen ist (nach stop() melden manche Systeme wieder 0).
|
||||
hasAudioInput =
|
||||
devices.any((d) => d.kind?.toLowerCase() == 'audioinput');
|
||||
if (devices.isEmpty || !hasAudioInput) {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Diagnose-Sonde für die Windows-Audiogeräte-Erkennung (ROADMAP M3).
|
||||
//
|
||||
// BEFUND (2026-07-07, PC-Diagnose): enumerateDevices()/getSources liefert auf
|
||||
// Windows IMMER eine leere Liste, solange keine RTCPeerConnection existiert.
|
||||
// Ursache: flutter_webrtc holt die Geräteliste über das Audio-Device-Module
|
||||
// der libwebrtc.dll (`GetAudioDevice()`), und dieses ADM bekommt sein Init()
|
||||
// erst, wenn die Voice-Engine anläuft – sprich: wenn irgendeine
|
||||
// PeerConnection existiert. Ohne Init() liefern RecordingDevices()/
|
||||
// PlayoutDevices() -1 (per Plugin-Instrumentierung verifiziert), die
|
||||
// Geräteliste bleibt leer, obwohl die MMDevice-API des Systems 23 Endpunkte
|
||||
// meldet. Upstream-Fix: webrtc-sdk/libwebrtc #142 (2026-06-24, „fix: audio
|
||||
// devices init issue"), aber noch in KEINEM libwebrtc-Binary-Release
|
||||
// (Stand 2026-07-07: neuestes ist m144.7559.09 vom 2026-06-11) und damit in
|
||||
// keiner flutter_webrtc-Version (geprüft: 1.4.1 und 1.5.2 identisch kaputt).
|
||||
// Workaround in der App: vor dem Enumerieren eine Dummy-PeerConnection
|
||||
// anlegen (siehe settings_voice.dart) – kein getUserMedia/Mikrofonzugriff
|
||||
// nötig.
|
||||
//
|
||||
// Diese Sonde belegt das stufenweise. Lauf:
|
||||
// flutter build windows --release -t tool/device_probe.dart
|
||||
// build\windows\x64\runner\Release\pyramid.exe
|
||||
// Ergebnis landet in %TEMP%\pyramid_device_probe.txt
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final out = StringBuffer();
|
||||
void log(String s) {
|
||||
out.writeln(s);
|
||||
debugPrint('[probe] $s');
|
||||
}
|
||||
|
||||
log('device_probe ${DateTime.now().toIso8601String()}');
|
||||
|
||||
Future<int> countDevices(String phase) async {
|
||||
try {
|
||||
final devices = await rtc.navigator.mediaDevices.enumerateDevices();
|
||||
log('$phase: ${devices.length} Geräte');
|
||||
for (final d in devices.take(30)) {
|
||||
log(' kind=${d.kind} label="${d.label}"');
|
||||
}
|
||||
return devices.length;
|
||||
} catch (e) {
|
||||
log('$phase: FEHLER $e');
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
await countDevices('0-kalt');
|
||||
|
||||
// Stufe A: nur PeerConnection anlegen – das allein initialisiert das ADM.
|
||||
final pc = await rtc.createPeerConnection({});
|
||||
await countDevices('A-pc-angelegt');
|
||||
|
||||
// Nachkontrolle: nach close() fällt die Liste wieder auf 0 zurück.
|
||||
await pc.close();
|
||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
await countDevices('B-nach-close');
|
||||
|
||||
final f = File(
|
||||
'${Platform.environment['TEMP'] ?? '.'}\\pyramid_device_probe.txt');
|
||||
await f.writeAsString(out.toString());
|
||||
debugPrint('[probe] geschrieben: ${f.path}');
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user