Hi Darryn! Thank you for the reply and thank you for any assistance you can offer.
I’m currently unable to reproduce in the example project, it seems to just work as expected; I can see the processor when calling setProcessor however in my app I’m getting the ‘Reply already submitted’ exception. I tried both in-line room options processor like the livekit_noise_filter shows as well as setting it after while using FastConnectOptions like the example code.
I must be missing something obvious… When I remove the processor in room options I’m able to connect and everything works.
For note, I’m on Flutter 3.38.7 and livekit_client: 2.7.0
Here is the exception I’m looking at:
E/MethodChannel#livekit_krisp_noise_filter(29712): Failed to handle method call
E/MethodChannel#livekit_krisp_noise_filter(29712): java.lang.IllegalStateException: Reply already submitted
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:431)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:272)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.livekit.livekit_noise_filter.LiveKitKrispNoiseFilterPlugin.init(LiveKitKrispNoiseFilterPlugin.kt:41)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.livekit.livekit_noise_filter.LiveKitKrispNoiseFilterPlugin.onMethodCall(LiveKitKrispNoiseFilterPlugin.kt:56)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/MethodChannel#livekit_krisp_noise_filter(29712): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
E/MethodChannel#livekit_krisp_noise_filter(29712): at android.os.Handler.handleCallback(Handler.java:1070)
E/MethodChannel#livekit_krisp_noise_filter(29712): at android.os.Handler.dispatchMessage(Handler.java:125)
E/MethodChannel#livekit_krisp_noise_filter(29712): at android.os.Looper.dispatchMessage(Looper.java:333)
E/MethodChannel#livekit_krisp_noise_filter(29712): at android.os.Looper.loopOnce(Looper.java:263)
E/MethodChannel#livekit_krisp_noise_filter(29712): at android.os.Looper.loop(Looper.java:367)
E/MethodChannel#livekit_krisp_noise_filter(29712): at android.app.ActivityThread.main(ActivityThread.java:9287)
E/MethodChannel#livekit_krisp_noise_filter(29712): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#livekit_krisp_noise_filter(29712): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:566)
E/MethodChannel#livekit_krisp_noise_filter(29712): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
E/DartMessenger(29712): Uncaught exception in binary message listener
E/DartMessenger(29712): java.lang.IllegalStateException: Reply already submitted
E/DartMessenger(29712): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:431)
E/DartMessenger(29712): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:287)
E/DartMessenger(29712): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
E/DartMessenger(29712): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/DartMessenger(29712): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
E/DartMessenger(29712): at android.os.Handler.handleCallback(Handler.java:1070)
E/DartMessenger(29712): at android.os.Handler.dispatchMessage(Handler.java:125)
E/DartMessenger(29712): at android.os.Looper.dispatchMessage(Looper.java:333)
E/DartMessenger(29712): at android.os.Looper.loopOnce(Looper.java:263)
E/DartMessenger(29712): at android.os.Looper.loop(Looper.java:367)
E/DartMessenger(29712): at android.app.ActivityThread.main(ActivityThread.java:9287)
E/DartMessenger(29712): at java.lang.reflect.Method.invoke(Native Method)
E/DartMessenger(29712): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:566)
E/DartMessenger(29712): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
Which appears when I try to set the processor on the audio track, here is the code snippet, this throws at the last line.
_noiseFilter = LiveKitNoiseFilter();
final room = Room(
roomOptions: RoomOptions(
defaultAudioCaptureOptions: AudioCaptureOptions(
processor: _noiseFilter,
),
defaultAudioPublishOptions: const AudioPublishOptions(
name: 'microphone',
),
),
);
_registerRoomListeners(room);
try {
await room.connect(
wsUrl,
token,
connectOptions: const ConnectOptions(autoSubscribe: false),
);
} catch (e) {
setIsConnecting(false);
FirebaseCrashlytics.instance
.recordError(e, StackTrace.current, reason: 'LiveKit connect failed');
return 'Failed to connect to voice channel';
}
await room.localParticipant?.setMicrophoneEnabled(true);
I also noticed the example uses FastConnectOptions so I tried with that and get the same error when calling await _audioTrack?.setProcessor(_noiseFilter); Here is that stack track:
E/MethodChannel#livekit_krisp_noise_filter(32549): Failed to handle method call
E/MethodChannel#livekit_krisp_noise_filter(32549): java.lang.IllegalStateException: Reply already submitted
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:431)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:272)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.livekit.livekit_noise_filter.LiveKitKrispNoiseFilterPlugin.init(LiveKitKrispNoiseFilterPlugin.kt:41)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.livekit.livekit_noise_filter.LiveKitKrispNoiseFilterPlugin.onMethodCall(LiveKitKrispNoiseFilterPlugin.kt:56)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/MethodChannel#livekit_krisp_noise_filter(32549): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
E/MethodChannel#livekit_krisp_noise_filter(32549): at android.os.Handler.handleCallback(Handler.java:1070)
E/MethodChannel#livekit_krisp_noise_filter(32549): at android.os.Handler.dispatchMessage(Handler.java:125)
E/MethodChannel#livekit_krisp_noise_filter(32549): at android.os.Looper.dispatchMessage(Looper.java:333)
E/MethodChannel#livekit_krisp_noise_filter(32549): at android.os.Looper.loopOnce(Looper.java:263)
E/MethodChannel#livekit_krisp_noise_filter(32549): at android.os.Looper.loop(Looper.java:367)
E/MethodChannel#livekit_krisp_noise_filter(32549): at android.app.ActivityThread.main(ActivityThread.java:9287)
E/MethodChannel#livekit_krisp_noise_filter(32549): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#livekit_krisp_noise_filter(32549): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:566)
E/MethodChannel#livekit_krisp_noise_filter(32549): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
E/DartMessenger(32549): Uncaught exception in binary message listener
E/DartMessenger(32549): java.lang.IllegalStateException: Reply already submitted
E/DartMessenger(32549): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:431)
E/DartMessenger(32549): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:287)
E/DartMessenger(32549): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
E/DartMessenger(32549): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/DartMessenger(32549): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
E/DartMessenger(32549): at android.os.Handler.handleCallback(Handler.java:1070)
E/DartMessenger(32549): at android.os.Handler.dispatchMessage(Handler.java:125)
E/DartMessenger(32549): at android.os.Looper.dispatchMessage(Looper.java:333)
E/DartMessenger(32549): at android.os.Looper.loopOnce(Looper.java:263)
E/DartMessenger(32549): at android.os.Looper.loop(Looper.java:367)
E/DartMessenger(32549): at android.app.ActivityThread.main(ActivityThread.java:9287)
E/DartMessenger(32549): at java.lang.reflect.Method.invoke(Native Method)
E/DartMessenger(32549): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:566)
E/DartMessenger(32549): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
I/flutter (32549): ----------------FIREBASE CRASHLYTICS----------------
I/flutter (32549): PlatformException(INVALID_ARGUMENT, track is not LocalAudioTrack, null, null)
I/flutter (32549): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653:7)
I/flutter (32549): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:367:18)
I/flutter (32549): <asynchronous suspension>
I/flutter (32549): #2 LiveKitNoiseFilter.init (package:livekit_noise_filter/src/livekit_noise_filter_native.dart:24:5)
I/flutter (32549): <asynchronous suspension>
I/flutter (32549): #3 LocalTrack.setProcessor (package:livekit_client/src/track/local/local.dart:261:5)
And that piece of code:
final room = Room(
roomOptions: RoomOptions(
adaptiveStream: true,
dynacast: true,
defaultAudioCaptureOptions: AudioCaptureOptions(
processor: _noiseFilter,
),
defaultAudioPublishOptions: const AudioPublishOptions(
name: 'microphone',
),
),
);
_registerRoomListeners(room);
try {
await room.prepareConnection(wsUrl, token);
await room.connect(
wsUrl,
token,
connectOptions: const ConnectOptions(autoSubscribe: false),
fastConnectOptions: FastConnectOptions(
microphone: TrackOption(track: _audioTrack),
),
);
} catch (e) {
await _audioTrack?.stop();
_audioTrack = null;
setIsConnecting(false);
FirebaseCrashlytics.instance
.recordError(e, StackTrace.current, reason: 'LiveKit connect failed');
return 'Failed to connect to voice channel';
}
await room.localParticipant?.setMicrophoneEnabled(willPublishMic);
if (_audioTrack != null) {
await _audioTrack!.setProcessor(_noiseFilter!);
}
