diff --git a/.changes/fix-audio-visualizer-unpublished-track b/.changes/fix-audio-visualizer-unpublished-track new file mode 100644 index 000000000..5c97dce38 --- /dev/null +++ b/.changes/fix-audio-visualizer-unpublished-track @@ -0,0 +1 @@ +patch type="fixed" "Fix audio visualizer not working for unpublished local audio tracks" diff --git a/lib/src/hardware/hardware.dart b/lib/src/hardware/hardware.dart index 065d4f361..db9dfc62a 100644 --- a/lib/src/hardware/hardware.dart +++ b/lib/src/hardware/hardware.dart @@ -14,6 +14,8 @@ import 'dart:async'; +import 'package:flutter/foundation.dart' show kIsWeb; + import 'package:collection/collection.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; @@ -194,6 +196,31 @@ class Hardware { }); } + /// Explicitly starts the audio device module's recording pipeline. + /// + /// This is called automatically when a [LocalAudioTrack] is started, but + /// can be called manually for pre-join scenarios (e.g. audio visualization + /// before connecting to a room). + /// + /// No-ops on web. Safe to call multiple times (idempotent). + Future startLocalRecording() async { + if (!kIsWeb) { + await rtc.NativeAudioManagement.startLocalRecording(); + } + } + + /// Stops the audio device module's recording pipeline. + /// + /// Normally you don't need to call this — WebRTC manages the ADM lifecycle. + /// Use this only for explicit control (e.g. CallKit flows). + /// + /// No-ops on web. + Future stopLocalRecording() async { + if (!kIsWeb) { + await rtc.NativeAudioManagement.stopLocalRecording(); + } + } + dynamic _onDeviceChange(dynamic _) async { final devices = await enumerateDevices(); selectedAudioInput ??= devices.firstWhereOrNull((element) => element.kind == 'audioinput'); diff --git a/lib/src/track/local/audio.dart b/lib/src/track/local/audio.dart index e3675a340..8233c44da 100644 --- a/lib/src/track/local/audio.dart +++ b/lib/src/track/local/audio.dart @@ -14,6 +14,8 @@ import 'dart:async'; +import 'package:flutter/foundation.dart' show kIsWeb; + import 'package:collection/collection.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:meta/meta.dart'; @@ -110,6 +112,15 @@ class LocalAudioTrack extends LocalTrack with AudioTrack, LocalAudioManagementMi return senderStats; } + @override + Future start() async { + if (isActive) return false; + if (!kIsWeb) { + await rtc.NativeAudioManagement.startLocalRecording(); + } + return await super.start(); + } + // private constructor @internal LocalAudioTrack(