Skip to content

Conversation

chenosaurus
Copy link
Contributor

@chenosaurus chenosaurus commented Sep 9, 2025

  • Add a new class MediaDevices that provides centralized access to local audio input/outputs.
  • Enables AEC loop when using both mic & speaker.
  • Add examples for publishing local mic & full duplex audio.

@chenosaurus chenosaurus marked this pull request as ready for review September 24, 2025 22:18
Copy link
Member

@theomonnom theomonnom left a comment

Choose a reason for hiding this comment

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

Nice!!

except StopAsyncIteration:
exhausted = True
break
# AudioStream may yield either AudioFrame or AudioFrameEvent; unwrap if needed
Copy link
Member

Choose a reason for hiding this comment

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

The correct typing should be:

self, stream: AsyncIterator[AudioFrame | AudioFrameEvent], buf: np.ndarray

stream_kwargs["mapping"] = mapping
elif mapping is not None:
logging.getLogger(__name__).warning(
"sounddevice.InputStream does not support 'mapping' in this version; "
Copy link
Member

Choose a reason for hiding this comment

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

Do we have to support that? or only latest?

input_channel_index,
)

input_stream = sd.InputStream(**stream_kwargs)
Copy link
Member

Choose a reason for hiding this comment

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

nit: Ideally we keep the typed args (no dict)

participant: rtc.RemoteParticipant,
):
if track.kind == rtc.TrackKind.KIND_AUDIO:
stream = rtc.AudioStream(track, sample_rate=48000, num_channels=1)
Copy link
Member

Choose a reason for hiding this comment

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

I think we should abstract further down, and directly allow to add a AudioTrack

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do you mean we should add a add_track and remove_track method to the AudioMixer class?

def open_output(
self,
*,
apm_for_reverse: Optional[AudioProcessingModule] = None,
Copy link
Member

Choose a reason for hiding this comment

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

This should be exposed to the user. Let's make this an internal detail

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do you mean should not?

Copy link
Member

Choose a reason for hiding this comment

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

Yes sry, it shouldn't

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.

2 participants