Skip to content

Recreate audio source and republish track on sample-rate change#312

Open
MaxHeimbrock wants to merge 1 commit into
max/mic-restart-on-device-changefrom
max/mic-rate-change-republish
Open

Recreate audio source and republish track on sample-rate change#312
MaxHeimbrock wants to merge 1 commit into
max/mic-restart-on-device-changefrom
max/mic-rate-change-republish

Conversation

@MaxHeimbrock

Copy link
Copy Markdown
Contributor

Stacked on #311 — review/merge that first. This PR's diff is one commit on top of it.

Problem

#311 restarts capture on a device change, but the native audio source's rate is fixed at construction. If the new device has a different sample rate, RtcAudioSource silently drops every captured frame (it rejects frames whose rate/channels don't match the source) — so audio stays dead.

The FFI exposes no in-place source reconfigure (only NewAudioSource), so recovery requires a fresh native source and a re-bound track.

Change

  • Add RtcAudioSource.Reconfigure(sampleRate, channels): disposes the old native handle, rebuilds the source at the new format, and raises a new FormatChanged event. The native source stays alive via the track's reference until the track is dropped, so disposing the handle before the old track is unpublished is safe.
  • MicrophoneSource detects the format change via ResolveDeviceFormat in its config-changed handler and calls Reconfigure inside the restart while capture is paused (no AudioRead callbacks in flight), replacing the warning from Restart microphone capture on audio device change #311.
  • MeetManager subscribes to FormatChanged and republishes the local audio track against the source's new handle (unsubscribing on unpublish/cleanup).

Note

Republishing yields a new track SID, so remote peers resubscribe on a rate change — acceptable but observable.

Testing

  • Scripts~/run_unity.sh build macos → Build SUCCEEDED.
  • Manual runtime verification (device swap that actually changes the DSP rate → audio recovers with a republish log line) still recommended on a real device.

🤖 Generated with Claude Code

@MaxHeimbrock MaxHeimbrock force-pushed the max/mic-restart-on-device-change branch from 37725a6 to d19145d Compare June 15, 2026 14:26
Commit 1 restarts capture on a device change but the native source's
rate stays fixed at construction, so a device whose rate differs from
the original silently has every frame dropped.

Add RtcAudioSource.Reconfigure(sampleRate, channels): it disposes the
old native handle, rebuilds the source at the new format, and raises a
new FormatChanged event. The native source stays alive via the track's
reference until the track is dropped, so disposing the handle before the
old track is unpublished is safe. The FFI exposes no in-place source
reconfigure, so a fresh source (and re-bound track) is required.

MicrophoneSource detects the format change via ResolveDeviceFormat in
its config-changed handler and calls Reconfigure inside the restart
while capture is paused (no AudioRead callbacks in flight). MeetManager
subscribes to FormatChanged and republishes the local audio track
against the source's new handle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MaxHeimbrock MaxHeimbrock force-pushed the max/mic-rate-change-republish branch from 9de6396 to 817b1a6 Compare June 15, 2026 14:27
if (sampleRate == 0 || channels == 0) return false;
if (sampleRate == _expectedSampleRate && channels == _expectedChannels) return false;

Utils.Debug($"{DebugTag} reconfigure {_expectedSampleRate}/{_expectedChannels} -> {sampleRate}/{channels}");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Without this change, we can have:

LiveKit: MicrophoneSource: audio device change moved the DSP output rate to 44100Hz, but the native source is fixed at 48000Hz. Captured frames will be dropped until the track is recreated at the new rate.
UnityEngine.Logger:LogWarning (string,object)
LiveKit.Internal.Utils:Warning (object) (at /Users/maxheimbrock/dev/unity/client-sdk-unity/Runtime/Scripts/Internal/Utils.cs:41)
LiveKit.MicrophoneSource:OnAudioConfigurationChanged (bool) (at /Users/maxheimbrock/dev/unity/client-sdk-unity/Runtime/Scripts/MicrophoneSource.cs:248)
UnityEngine.AudioSettings:InvokeOnAudioConfigurationChanged (bool) (at /Users/bokken/build/output/unity/unity/Modules/Audio/Public/ScriptBindings/Audio.bindings.cs:413)

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.

1 participant