Skip to content

feat(audio): add AudioManager session and routing APIs#1108

Merged
hiroshihorie merged 37 commits into
mainfrom
hiroshi/audio-manager-api
Jun 18, 2026
Merged

feat(audio): add AudioManager session and routing APIs#1108
hiroshihorie merged 37 commits into
mainfrom
hiroshi/audio-manager-api

Conversation

@hiroshihorie

@hiroshihorie hiroshihorie commented Jun 12, 2026

Copy link
Copy Markdown
Member

What

Adds first-class, process-wide audio session and routing control through AudioManager on iOS and Android. LiveKit owns the platform audio session by default, while apps that need exact platform behavior can switch to manual mode and apply typed session configs.

API and behavior

  • Automatic by default: calls need no setup. LiveKit applies a managed communication policy.
  • iOS automatic mode: the native WebRTC audio-engine delegate drives AVAudioSession from engine lifecycle events. Listen-only playout uses playback; recording uses playAndRecord.
  • Android automatic mode: LiveKit uses a communication session through the new AudioSwitch-backed LKAudioSwitchManager.
  • Manual mode: setAudioSessionOptions(...) and deactivateAudioSession() switch AudioManager to manual mode. setAudioSessionManagementMode(AudioSessionManagementMode.automatic) hands lifecycle control back to LiveKit.
  • Typed options: AudioSessionOptions.communication() and AudioSessionOptions.media() pre-fill Apple and Android configs, with per-platform overrides applied verbatim in manual mode.
  • Speaker routing: AudioManager.instance.setSpeakerOutputPreferred(...) owns speaker preference and forced speaker routing. Wired and Bluetooth devices still win unless force: true.

Compatibility

  • Existing calls keep working without audio-session setup.
  • Hardware audio members and Room.setSpeakerOn(...) are deprecated forwarders to AudioManager.
  • flutter_webrtc native audio-session management is disabled so LiveKit has one owner for the session.
  • bypassVoiceProcessing now only controls WebRTC voice processing; it no longer changes the session intent.

Docs and tests

  • Adds docs/audio.md and updates the README audio sections.
  • Adds coverage for session options, automatic/manual mode transitions, Apple/Android policy resolution, routing serialization, and engine-state observation.
  • Verified locally with dart analyze, flutter test test/audio/audio_session_test.dart, and flutter test --reporter compact.

Process-wide audio session control on AudioManager: session options and
management modes (automatic/manual), Android audio session configuration
(mode/focus/routing) backed by an AudioSwitch-based manager in the native
plugin, Apple speakerphone routing, and speaker output preferences.
Platform audio sessions are global to the app process, so this lives on
AudioManager rather than Room.
Picks up the aligned audioswitch revision (flutter-webrtc#2084), which
resolves the Android build conflict on the shared classpath.
@hiroshihorie hiroshihorie marked this pull request as ready for review June 15, 2026 10:22
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

Caution

Breaking change detected without major changeset

dart-apitool detected the following breaking changes:

Preparing git repository: https://github.com/livekit/client-sdk-flutter
Using ref: main
Cloning git repository: https://github.com/livekit/client-sdk-flutter
Checking out ref: main
Successfully cloned to: /tmp/CTVIYB
Preparing package dependencies for git package https://github.com/livekit/client-sdk-flutter (forced Flutter)
Resolving dependencies...
Downloading packages...
  _fe_analyzer_shared 85.0.0 (104.0.0 available)
  analyzer 7.7.1 (14.0.0 available)
  build 2.5.4 (4.0.6 available)
  build_config 1.1.2 (1.3.0 available)
  build_resolvers 2.5.4 (3.0.4 available)
  build_runner 2.5.4 (2.15.0 available)
  build_runner_core 9.1.2 (9.3.2 available)
  built_value 8.12.4 (8.12.6 available)
  code_assets 1.0.0 (1.2.1 available)
  dart_style 3.1.1 (3.1.9 available)
  dart_webrtc 1.8.0 (1.8.1 available)
  dbus 0.7.12 (0.7.14 available)
  device_info_plus 12.3.0 (13.1.0 available)
  device_info_plus_platform_interface 7.0.3 (8.1.0 available)
  flutter_webrtc 1.5.0 (1.5.1 available)
  hooks 1.0.2 (2.0.2 available)
  json_annotation 4.9.0 (4.12.0 available)
  json_serializable 6.9.5 (6.14.0 available)
  matcher 0.12.19 (0.12.20 available)
  meta 1.18.0 (1.18.3 available)
  mockito 5.4.6 (5.7.0 available)
  native_toolchain_c 0.17.6 (0.19.1 available)
  objective_c 9.3.0 (9.4.1 available)
  package_config 2.2.0 (3.0.0 available)
  path_provider 2.1.5 (2.1.6 available)
  path_provider_android 2.2.22 (2.3.1 available)
  path_provider_platform_interface 2.1.2 (2.1.3 available)
  source_gen 2.0.0 (4.2.3 available)
  source_helper 1.3.7 (1.3.12 available)
  synchronized 3.4.0 (3.4.1 available)
  test_api 0.7.11 (0.7.12 available)
  vector_math 2.2.0 (2.4.0 available)
  vm_service 15.0.2 (15.2.0 available)
  win32 5.15.0 (6.3.0 available)
  win32_registry 2.1.0 (3.0.3 available)
  xml 6.6.1 (7.0.1 available)
Got dependencies!
36 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.
Resolving dependencies in `./example`...
Downloading packages...
Got dependencies in `./example`.
Preparing . (forced Flutter)
Copying sources from .
Preparing package dependencies for local package . (forced Flutter)
Resolving dependencies...
Downloading packages...
  _fe_analyzer_shared 85.0.0 (104.0.0 available)
  analyzer 7.7.1 (14.0.0 available)
  build 2.5.4 (4.0.6 available)
  build_config 1.1.2 (1.3.0 available)
  build_resolvers 2.5.4 (3.0.4 available)
  build_runner 2.5.4 (2.15.0 available)
  build_runner_core 9.1.2 (9.3.2 available)
  built_value 8.12.4 (8.12.6 available)
  code_assets 1.0.0 (1.2.1 available)
  dart_style 3.1.1 (3.1.9 available)
  dart_webrtc 1.8.0 (1.8.1 available)
  dbus 0.7.12 (0.7.14 available)
  device_info_plus 12.3.0 (13.1.0 available)
  device_info_plus_platform_interface 7.0.3 (8.1.0 available)
  hooks 1.0.2 (2.0.2 available)
  json_annotation 4.9.0 (4.12.0 available)
  json_serializable 6.9.5 (6.14.0 available)
  matcher 0.12.19 (0.12.20 available)
  meta 1.18.0 (1.18.3 available)
  mockito 5.4.6 (5.7.0 available)
  native_toolchain_c 0.17.6 (0.19.1 available)
  objective_c 9.3.0 (9.4.1 available)
  package_config 2.2.0 (3.0.0 available)
  path_provider 2.1.5 (2.1.6 available)
  path_provider_android 2.2.22 (2.3.1 available)
  path_provider_platform_interface 2.1.2 (2.1.3 available)
  source_gen 2.0.0 (4.2.3 available)
  source_helper 1.3.7 (1.3.12 available)
  synchronized 3.4.0 (3.4.1 available)
  test_api 0.7.11 (0.7.12 available)
  vector_math 2.2.0 (2.4.0 available)
  vm_service 15.0.2 (15.2.0 available)
  win32 5.15.0 (6.3.0 available)
  win32_registry 2.1.0 (3.0.3 available)
  xml 6.6.1 (7.0.1 available)
Got dependencies!
35 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.
Resolving dependencies in `./example`...
Downloading packages...
Got dependencies in `./example`.
Omitting pub get (package config already present)
Analyzing /tmp/CTVIYB
Omitting pub get (package config already present)
Analyzing .
Cleaning up
Cleaning up
Checking Package version
ignoring prerelease
-- Generating report using: Console Reporter --
BREAKING CHANGES
└─┬ Class AudioProcessingOptions
  └── Constructor "raw" removed (CE10)
Non-Breaking changes
├── Interface "AudioEngineState" added (CI02) (minor)
├── Interface "AudioSessionOptions" added (CI02) (minor)
├── Interface "AppleAudioSessionConfiguration" added (CI02) (minor)
├── Interface "AppleAudioCategory" added (CI02) (minor)
├── Interface "AppleAudioCategoryOption" added (CI02) (minor)
├── Interface "AppleAudioMode" added (CI02) (minor)
├── Interface "ValueOrAbsent" added (CI02) (minor)
├── Interface "AndroidAudioSessionConfiguration" added (CI02) (minor)
├── Interface "AndroidAudioMode" added (CI02) (minor)
├── Interface "AndroidAudioFocusMode" added (CI02) (minor)
├── Interface "AndroidAudioStreamType" added (CI02) (minor)
├── Interface "AndroidAudioAttributesUsageType" added (CI02) (minor)
├── Interface "AndroidAudioAttributesContentType" added (CI02) (minor)
├── Interface "AudioSessionManagementMode" added (CI02) (minor)
├── Package dependency "flutter_webrtc" version changed from "1.5.0" to "1.5.1" (CD03) (minor)
├─┬ Class AudioProcessingOptions
│ └── Constructor "noProcessing" added (CE11) (minor)
├─┬ Class RoomHardwareManagementMethods
│ └─┬ Method setSpeakerOn
│   └── Deprecated Flag changed. false -> true (CE13) (minor)
├─┬ Class Hardware
│ ├─┬ Method setAutomaticConfigurationEnabled
│ │ └── Deprecated Flag changed. false -> true (CE13) (minor)
│ └─┬ Method setSpeakerphoneOn
│   └── Deprecated Flag changed. false -> true (CE13) (minor)
└─┬ Class AudioManager
  ├── Method "resetForTest" added (CE11) (minor)
  ├── Method "setAudioSessionOptions" added (CE11) (minor)
  ├── Method "setAudioSessionManagementMode" added (CE11) (minor)
  ├── Method "deactivateAudioSession" added (CE11) (minor)
  ├── Method "setSpeakerOutputPreferred" added (CE11) (minor)
  ├── Field "options" added (CF02) (minor)
  ├── Field "managementMode" added (CF02) (minor)
  ├── Field "isSpeakerOutputPreferred" added (CF02) (minor)
  ├── Field "isSpeakerOutputForced" added (CF02) (minor)
  ├── Field "canSwitchSpeakerphone" added (CF02) (minor)
  ├── Field "audioEngineState" added (CF02) (minor)
  └── Field "audioEngineStateStream" added (CF02) (minor)
To learn more about the detected changes visit: https://github.com/bmw-tech/dart_apitool/blob/main/readme/change_codes.md
Version Check
New Version is too low!

Old version: "2.8.0"
New version: "2.8.0"
Needed version: "3.0.0"

Got "2.8.0" expected >= "3.0.0" (breaking changes)

If this is intentional, please add a changeset with major level in .changes/:

major type="changed" "Description of breaking change"

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces first-class, process-wide audio session/routing management via AudioManager, consolidating previously scattered session behavior (track-counting, Hardware, and implicit native defaults) into a single, typed API with native backends on Apple and Android.

Changes:

  • Adds typed audio-session configuration (AudioSessionOptions, per-platform overrides, and AudioSessionManagementMode) plus supporting copy/serialization helpers.
  • Updates native plugins to let LiveKit own platform audio sessions: iOS/macOS engine-lifecycle observer drives session activation; Android adds an AudioSwitch-based manager for focus/mode/routing.
  • Deprecates/rewires legacy entry points (Hardware, track audio management mixins) to forward through AudioManager, and updates examples + adds unit tests.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/audio/audio_session_test.dart Adds unit tests covering session options, copyWith semantics, and serialization.
shared_swift/LiveKitPlugin.swift Disables flutter_webrtc audio management; adds engine-lifecycle observer + new method-channel handlers for Apple session management and speaker routing.
pubspec.yaml Bumps flutter_webrtc dependency to 1.5.1.
pubspec.lock Locks flutter_webrtc to 1.5.1 with updated hash.
lib/src/track/remote/audio.dart Removes legacy remote audio management mixin usage.
lib/src/track/local/audio.dart Removes legacy local audio management mixin usage.
lib/src/track/audio_management.dart Replaces track-counting session management with AudioManager connect/apply and Android stop handling.
lib/src/support/value_or_absent.dart Adds ValueOrAbsent utility to support nullable-field copyWith APIs.
lib/src/support/native.dart Extends Apple configureNativeAudio payload + adds Android/Apple session/routing method-channel APIs and engine-state callback handling.
lib/src/support/native_audio.dart Updates NativeAudioConfiguration.copyWith to use ValueOrAbsent; removes old static presets.
lib/src/livekit.dart Initializes AudioManager defaults and passes Android init configuration when needed.
lib/src/hardware/hardware.dart Deprecates audio-related members and forwards to AudioManager.
lib/src/core/room.dart Ensures audio session start/stop is cleaned up on connect failure; routes speaker toggles via AudioManager.
lib/src/audio/audio_session.dart New public API types for session intent + per-platform configuration.
lib/src/audio/audio_manager.dart Implements the new process-wide audio session manager, including engine-state stream and platform apply logic.
lib/src/audio/android_audio_session_adapter.dart Serializes Android session configuration to method-channel wire format and applies it via native.
lib/livekit_client.dart Exports the new audio session API.
example/lib/widgets/controls.dart Updates example UI to read speaker state from AudioManager.
example/lib/pages/room.dart Updates example to toggle speaker via AudioManager.
android/src/main/kotlin/io/livekit/plugin/LKAudioSwitchManager.kt Adds AudioSwitch-based Android session/focus/mode/routing manager.
android/src/main/kotlin/io/livekit/plugin/LiveKitPlugin.kt Disables flutter_webrtc audio management; wires method-channel handlers to LKAudioSwitchManager.
android/build.gradle Adds JitPack repository and AudioSwitch dependency.
.changes/audio-manager-api Adds a changeset entry documenting the new API.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread android/build.gradle
Comment on lines 17 to +21
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging this. A quick bit of context here. flutter_webrtc, which is a direct dependency of this plugin, already declares the JitPack repository at rootProject.allprojects scope, so every consuming app already gets it applied app wide. This block uses plain allprojects with no rootProject. prefix, which is actually a narrower scope, so it does not add anything the host app was not already getting transitively through flutter_webrtc.

We also pin the same audioswitch commit that flutter_webrtc and the LiveKit Android SDK use, so dependency resolution stays consistent across the whole stack. Keeping our own declaration here just makes the plugin self sufficient rather than relying on the transitive one.

Comment thread android/build.gradle
Comment on lines +65 to +67
// Audio device/focus/mode routing. Pinned to the same revision used by
// the LiveKit Android SDK (AudioSwitchHandler).
implementation 'com.github.davidliu:audioswitch:039a35aefab7747c557242fa216c9ea11743b604'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. This one is a deliberate tradeoff, and it matches the rest of the LiveKit stack. The same audioswitch commit is pinned by both flutter_webrtc and the LiveKit Android SDK, so dependency resolution stays consistent end to end. A JitPack artifact is immutable per commit, so the pin is reproducible in practice, and the main residual risk is JitPack availability rather than the artifact changing under us.

The fork is needed for its CommDeviceAudioSwitch, which provides the API 31 setCommunicationDevice routing path, and that class has no tagged release or MavenCentral coordinate to point at yet. If upstream publishes a release that carries it, we would happily switch over.

Comment on lines +359 to +365
"configureAndroidAudioSession" -> {
@Suppress("UNCHECKED_CAST")
val configuration = call.arguments as? Map<String, Any?> ?: emptyMap()
audioSwitchManager?.configure(configuration)
audioSwitchManager?.start()
result.success(null)
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good observation. The coupling here is intentional on Android. Unlike iOS, the Android side has no audio engine lifecycle observer to defer activation to, so the session is activated when LiveKit applies its options (at connect, or on an explicit apply) and released on stop or disconnect. That keeps focus and mode ownership tied to a clear start and stop, which is the standard call session pattern.

Separating configure from activate, or adding an activate flag, is a reasonable future enhancement for finer grained manual mode control, and we can revisit it if a concrete need shows up. For this change the current behavior is the intended one, so we will keep it as is for now.

Comment thread shared_swift/LiveKitPlugin.swift Outdated
Comment on lines +798 to +801
// Leave sessionActive untrue so cached state still reflects the
// live session. Flipping it to false here would make a later
// configureNativeAudio(automatic:) cache-only while the session
// is in fact still active.
Relocate AppleAudioCategory / AppleAudioCategoryOption / AppleAudioMode from
the internal wire file (support/native_audio.dart) into audio_session.dart,
where the public AppleAudioSessionConfiguration already lives. native_audio.dart
keeps only the internal NativeAudioConfiguration wire type and its toStringValue
serialization, importing the enums from the audio layer. Removes the
import-plus-export of native_audio from audio_session.dart. Public API and
behavior are unchanged.
The automatic-mode session expressed the speaker preference twice: through
the audio mode (videoChat for speaker, voiceChat for receiver) and again
through overrideOutputAudioPort. The override hard-routes to the speaker even
over a connected headset, so a plain setSpeakerphoneOn(true) ignored the
documented headset priority and behaved like a forced speaker.

Gate the speaker override on the forced case only (carried as the
defaultToSpeaker category option) and otherwise clear it, letting the audio
mode and connected devices decide. This matches the Swift SDK, which selects
playAndRecordSpeaker/playAndRecordReceiver by mode and never overrides the
output port. Removes the now-unused preferSpeakerOutput plumbing from the
native observer and apply path. Manual mode keeps its direct route override.
Rename the new (unreleased) AudioManager speaker surface for clarity and to
match the Swift SDK vocabulary:
  setSpeakerphoneOn(enable, {forceSpeakerOutput})  -> setSpeakerOutputPreferred(preferred, {force})
  get preferSpeakerOutput                          -> get isSpeakerOutputPreferred
  get forceSpeakerOutput                           -> get isSpeakerOutputForced
Drop the duplicate speakerphoneOn getter (was identical to preferSpeakerOutput).
Update the deprecated Hardware forwards, Room.setSpeakerOn, the example app,
the audio guide, and the tests. AudioSessionOptions.preferSpeakerOutput and the
per-platform config fields keep their names. No behavior change.
The headset-priority fix made the native side ignore the preferSpeakerOutput
wire field (the speaker preference now lives entirely in the audio mode). Remove
the now-dead field from NativeAudioConfiguration (field, toMap, copyWith) and stop
sending it from the resolved Apple policy. The wire-format test now pins its
absence.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

Comment thread lib/src/audio/audio_manager.dart Outdated
Comment on lines +291 to +292
await setAndroidAudioSessionConfiguration(config);
await Native.setAndroidSpeakerphoneOn(policy.preferSpeakerOutput);
Comment on lines +125 to +132
val device = if (enable) {
switch.availableAudioDevices.firstOrNull { it is AudioDevice.Speakerphone }
} else {
switch.availableAudioDevices.firstOrNull {
it is AudioDevice.BluetoothHeadset || it is AudioDevice.WiredHeadset || it is AudioDevice.Earpiece
}
}
switch.selectDevice(device)
setSpeakerphoneOn(true) explicitly selected the speaker device even when a
wired/Bluetooth headset was connected, forcing the speaker and ignoring the
documented headset priority. Select a connected headset first and fall back to
the speaker only when none is present (earpiece when the speaker is not
preferred). This mirrors the iOS fix and removes the forced-speaker routing the
media preset would otherwise apply on every options change.
@hiroshihorie hiroshihorie requested a review from Copilot June 16, 2026 13:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.

Comment thread docs/audio.md Outdated

## Per platform overrides

When the presets are not enough you can pin exact platform values. Anything you do not set falls back to the preset behavior.
…erence

Remove the redundant Room-level speaker persistence. The deprecated
Room.setSpeakerOn forwards straight to
AudioManager.instance.setSpeakerOutputPreferred without writing to
roomOptions, the Room.speakerOn getter reports the process-wide AudioManager
state, and the publish/unpublish replay is removed because the iOS engine
observer and the Android audioswitch handler already re-assert the cached
prefer and force values, neither of which is reset by track publish. A
construction-time RoomOptions speakerOn is bridged into AudioManager once at
connect so that default still applies.
The README Android audio-modes section still told users to configure audio
through flutter_webrtc, which LiveKit now disables. Replace it with the
AudioManager media-mode equivalent. Reword the per-platform override note in
docs/audio.md so it no longer implies unset override fields merge with the
preset. Drop two semicolons from prose comments.
AudioSwitch applies the audio mode, focus, and attributes at activate()
time, so changing them on an already active switch (for example switching
from communication to media mid session) did not take effect until the next
restart. configure() now detects activate-time config changes and, when the
session is active, cycles deactivate() and activate() to apply them, then
reasserts speaker routing.
The construction-time RoomOptions speakerOn was re-applied to AudioManager
on every Room.connect(), so reusing a Room across a manual disconnect and
connect after a runtime speaker change would revert it. Bridge it only on the
first connect so the runtime preference owned by AudioManager wins.
…undary

Add an Audio processing section explaining how AudioManager spans both the
audio session (this PR) and the runtime audio processing options (per-track
DSP plus engine-wide state read-back), and how the communication and media
intents pair with AudioProcessingOptions. Note in the iOS platform notes that
receiver routing and forced speaker both require the playAndRecord category.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 2 comments.

Comment on lines +164 to +170
Future<void> setAudioSessionOptions(AudioSessionOptions options) async {
_hasExplicitRuntimeOptions = true;
_syncSpeakerPreferenceFromOptions(options);
_forceSpeakerOutput = false;
_options = options;
await applyCurrentAudioSessionOptions();
}
Comment thread lib/src/audio/audio_manager.dart Outdated
Comment on lines +340 to +341
bool _speakerPreferenceForOptions(AudioSessionOptions options) =>
options.apple?.preferSpeakerOutput ?? options.preferSpeakerOutput;

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 1 comment.

Comment on lines +182 to +203
private fun applyConfiguration(switch: AbstractAudioSwitch) {
switch.manageAudioFocus = manageAudioFocus
switch.audioMode = audioMode
switch.focusMode = focusMode
switch.audioStreamType = audioStreamType
switch.audioAttributeUsageType = audioAttributeUsageType
switch.audioAttributeContentType = audioAttributeContentType
switch.forceHandleAudioRouting = forceHandleAudioRouting
}

private fun applySpeakerRouting(switch: AbstractAudioSwitch) {
switch.setPreferredDeviceList(preferredDeviceList)
val forcedSpeaker = if (speakerOutputForced) {
switch.availableAudioDevices.firstOrNull { it is AudioDevice.Speakerphone }
} else {
null
}
// AudioSwitch selections are sticky. Use them only for forced speaker output.
// Clearing the selection lets the preferred-device list handle normal routing
// and headset hot-plug priority.
switch.selectDevice(forcedSpeaker)
}
@hiroshihorie hiroshihorie changed the title feat(audio): AudioManager audio session management feat(audio): add AudioManager session and routing APIs Jun 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated 2 comments.

Comment thread shared_swift/LiveKitPlugin.swift Outdated
Comment thread shared_swift/LiveKitPlugin.swift Outdated
@hiroshihorie hiroshihorie merged commit 55af814 into main Jun 18, 2026
16 of 17 checks passed
@hiroshihorie hiroshihorie deleted the hiroshi/audio-manager-api branch June 18, 2026 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants