From 31ec6b09ccb5cd40cb0bb174ccdf25bd8d021a5d Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:19:24 +0900 Subject: [PATCH] Fix audio visualizer exception (#1008) Fix `MissingPluginException` when stopping audio visualizer. --- .changes/fix-audio-visualizer-missing-plugin-exception | 1 + lib/src/track/audio_visualizer_native.dart | 6 ++++-- shared_swift/LiveKitPlugin.swift | 1 + shared_swift/Visualizer.swift | 7 ++++++- 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 .changes/fix-audio-visualizer-missing-plugin-exception diff --git a/.changes/fix-audio-visualizer-missing-plugin-exception b/.changes/fix-audio-visualizer-missing-plugin-exception new file mode 100644 index 0000000..d0e10a5 --- /dev/null +++ b/.changes/fix-audio-visualizer-missing-plugin-exception @@ -0,0 +1 @@ +patch type="fixed" "MissingPluginException when stopping audio visualizer on Android/iOS" diff --git a/lib/src/track/audio_visualizer_native.dart b/lib/src/track/audio_visualizer_native.dart index a7ed376..926049c 100644 --- a/lib/src/track/audio_visualizer_native.dart +++ b/lib/src/track/audio_visualizer_native.dart @@ -53,11 +53,13 @@ class AudioVisualizerNative extends AudioVisualizer { return; } - await Native.stopVisualizer(mediaStreamTrack.id!, visualizerId: visualizerId); - + // Cancel subscription before native stop, otherwise the native + // StreamHandler is already removed and cancel throws MissingPluginException. await _streamSubscription?.cancel(); _streamSubscription = null; _eventChannel = null; + + await Native.stopVisualizer(mediaStreamTrack.id!, visualizerId: visualizerId); } } diff --git a/shared_swift/LiveKitPlugin.swift b/shared_swift/LiveKitPlugin.swift index 8d11d9e..a2d8d86 100644 --- a/shared_swift/LiveKitPlugin.swift +++ b/shared_swift/LiveKitPlugin.swift @@ -201,6 +201,7 @@ public class LiveKitPlugin: NSObject, FlutterPlugin { } for processors in audioProcessors.values { + processors.visualizers[visualizerId]?.stop() processors.visualizers.removeValue(forKey: visualizerId) } diff --git a/shared_swift/Visualizer.swift b/shared_swift/Visualizer.swift index c856ec5..19c6bd9 100644 --- a/shared_swift/Visualizer.swift +++ b/shared_swift/Visualizer.swift @@ -69,8 +69,13 @@ public class Visualizer: NSObject, RTCAudioRenderer, FlutterStreamHandler { channel?.setStreamHandler(self) } - deinit { + public func stop() { _track?.remove(audioRenderer: self) + channel?.setStreamHandler(nil) + } + + deinit { + stop() } public func render(pcmBuffer: AVAudioPCMBuffer) {