@rapidaai/react 1.1.50 → 1.1.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27337,6 +27337,9 @@ var import_moment = __toESM(require("moment"));
27337
27337
  function isSafari() {
27338
27338
  return getBrowser()?.name === "Safari";
27339
27339
  }
27340
+ function isChrome() {
27341
+ return getBrowser()?.name === "Chrome";
27342
+ }
27340
27343
  function toDate(timestamp) {
27341
27344
  const seconds = timestamp.getSeconds();
27342
27345
  const nanos = timestamp.getNanos();
@@ -28293,6 +28296,24 @@ registerProcessor("raw-audio-processor", RawAudioProcessor);
28293
28296
 
28294
28297
  // src/audio/input.ts
28295
28298
  var LIBSAMPLERATE_JS = "https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js";
28299
+ function getAudioConstraints(sampleRate) {
28300
+ if (isChrome()) {
28301
+ return {
28302
+ sampleRate: { ideal: sampleRate },
28303
+ echoCancellation: true,
28304
+ noiseSuppression: true,
28305
+ autoGainControl: true,
28306
+ // Chrome-specific: helps with consistent audio quality
28307
+ channelCount: { ideal: 1 }
28308
+ };
28309
+ }
28310
+ return {
28311
+ sampleRate: { ideal: sampleRate },
28312
+ echoCancellation: { ideal: true },
28313
+ noiseSuppression: { ideal: true },
28314
+ autoGainControl: { ideal: true }
28315
+ };
28316
+ }
28296
28317
  var Input = class _Input {
28297
28318
  constructor(context, analyser, worklet, inputStream) {
28298
28319
  this.context = context;
@@ -28300,18 +28321,10 @@ var Input = class _Input {
28300
28321
  this.worklet = worklet;
28301
28322
  this.inputStream = inputStream;
28302
28323
  }
28303
- static async create({
28304
- sampleRate,
28305
- format
28306
- }) {
28324
+ static async create({ sampleRate, format }, existingStream) {
28307
28325
  let context = null;
28308
28326
  let inputStream = null;
28309
28327
  try {
28310
- const options = {
28311
- sampleRate: { ideal: sampleRate },
28312
- echoCancellation: { ideal: true },
28313
- noiseSuppression: { ideal: true }
28314
- };
28315
28328
  const supportsSampleRateConstraint = navigator.mediaDevices.getSupportedConstraints().sampleRate;
28316
28329
  context = new window.AudioContext(
28317
28330
  supportsSampleRateConstraint ? { sampleRate } : {}
@@ -28321,9 +28334,14 @@ var Input = class _Input {
28321
28334
  await context.audioWorklet.addModule(LIBSAMPLERATE_JS);
28322
28335
  }
28323
28336
  await loadRawAudioProcessor(context.audioWorklet);
28324
- inputStream = await navigator.mediaDevices.getUserMedia({
28325
- audio: options
28326
- });
28337
+ if (existingStream) {
28338
+ inputStream = existingStream;
28339
+ } else {
28340
+ const options = getAudioConstraints(sampleRate);
28341
+ inputStream = await navigator.mediaDevices.getUserMedia({
28342
+ audio: options
28343
+ });
28344
+ }
28327
28345
  const source = context.createMediaStreamSource(inputStream);
28328
28346
  const worklet = new AudioWorkletNode(context, "raw-audio-processor");
28329
28347
  worklet.port.postMessage({ type: "setFormat", format, sampleRate });
@@ -28576,13 +28594,14 @@ var VoiceAgent = class extends Agent {
28576
28594
  connectDevice = async () => {
28577
28595
  try {
28578
28596
  this.preliminaryInputStream = await this.waitForUserMediaPermission();
28579
- [this.input, this.output] = await Promise.all([
28580
- Input.create(this.agentConfig.inputOptions.recorderOption),
28581
- Output.create(this.agentConfig.outputOptions.playerOption)
28582
- ]);
28597
+ this.output = await Output.create(this.agentConfig.outputOptions.playerOption);
28598
+ this.input = await Input.create(
28599
+ this.agentConfig.inputOptions.recorderOption,
28600
+ this.preliminaryInputStream
28601
+ // Reuse the same MediaStream
28602
+ );
28583
28603
  this.input.worklet.port.onmessage = this.onInputWorkletMessage;
28584
28604
  this.output.worklet.port.onmessage = this.onOutputWorkletMessage;
28585
- this.preliminaryInputStream?.getTracks().forEach((track) => track.stop());
28586
28605
  this.preliminaryInputStream = null;
28587
28606
  } catch (error) {
28588
28607
  await this.disconnectAudio();
@@ -28592,7 +28611,20 @@ var VoiceAgent = class extends Agent {
28592
28611
  // Helper method to handle media permissions:
28593
28612
  waitForUserMediaPermission = async () => {
28594
28613
  try {
28595
- return await navigator.mediaDevices.getUserMedia({ audio: true });
28614
+ const sampleRate = this.agentConfig.inputOptions.recorderOption.sampleRate;
28615
+ const options = isChrome() ? {
28616
+ sampleRate: { ideal: sampleRate },
28617
+ echoCancellation: true,
28618
+ noiseSuppression: true,
28619
+ autoGainControl: true,
28620
+ channelCount: { ideal: 1 }
28621
+ } : {
28622
+ sampleRate: { ideal: sampleRate },
28623
+ echoCancellation: { ideal: true },
28624
+ noiseSuppression: { ideal: true },
28625
+ autoGainControl: { ideal: true }
28626
+ };
28627
+ return await navigator.mediaDevices.getUserMedia({ audio: options });
28596
28628
  } catch (error) {
28597
28629
  console.error(
28598
28630
  "Permission denied or error while requesting microphone access:",
@@ -28864,6 +28896,7 @@ var VoiceAgent = class extends Agent {
28864
28896
  const audioData = content.getContent_asU8();
28865
28897
  this.addAudioChunk(new Uint8Array(audioData).buffer);
28866
28898
  }
28899
+ break;
28867
28900
  case import_common_pb8.AssistantConversationAssistantMessage.MessageCase.TEXT:
28868
28901
  const systemTranscript = systemContent.getText()?.getContent();
28869
28902
  if (systemTranscript) {