@pipecat-ai/daily-transport 1.6.8 → 1.7.0
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.
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1206 -118
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +1206 -118
- package/dist/index.module.js.map +1 -1
- package/package.json +17 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
var $
|
|
2
|
-
var $
|
|
1
|
+
var $1clrS$dailycodailyjs = require("@daily-co/daily-js");
|
|
2
|
+
var $1clrS$pipecataiclientjs = require("@pipecat-ai/client-js");
|
|
3
|
+
var $1clrS$events = require("events");
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
function $parcel$exportWildcard(dest, source) {
|
|
@@ -26,13 +27,49 @@ function $parcel$interopDefault(a) {
|
|
|
26
27
|
function $parcel$export(e, n, v, s) {
|
|
27
28
|
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
|
|
28
29
|
}
|
|
29
|
-
var $
|
|
30
|
+
var $1c83796b12dd4e49$exports = {};
|
|
30
31
|
|
|
31
|
-
$parcel$export($
|
|
32
|
-
$parcel$export($
|
|
32
|
+
$parcel$export($1c83796b12dd4e49$exports, "DailyRTVIMessageType", () => $1c83796b12dd4e49$export$ef180de88fd317cc);
|
|
33
|
+
$parcel$export($1c83796b12dd4e49$exports, "DailyTransport", () => $1c83796b12dd4e49$export$b1ca982aa1e488c1);
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
/**
|
|
37
|
+
* Whether this browser can share a screen. Most mobile browsers, including
|
|
38
|
+
* iOS Safari, have no `getDisplayMedia`.
|
|
39
|
+
*/ function $15398512372f76d1$export$7f8f33b9b54c8307() {
|
|
40
|
+
return typeof navigator?.mediaDevices?.getDisplayMedia === "function";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/*!
|
|
45
|
+
* wavtools is adapted from openai-realtime-console
|
|
46
|
+
* (https://github.com/openai/openai-realtime-console) and modified by Daily.
|
|
47
|
+
*
|
|
48
|
+
* @license MIT
|
|
49
|
+
*
|
|
50
|
+
* Copyright (c) 2024 OpenAI
|
|
51
|
+
*
|
|
52
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
53
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
54
|
+
* in the Software without restriction, including without limitation the rights
|
|
55
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
56
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
57
|
+
* furnished to do so, subject to the following conditions:
|
|
58
|
+
*
|
|
59
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
60
|
+
* copies or substantial portions of the Software.
|
|
61
|
+
*
|
|
62
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
63
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
64
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
65
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
66
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
67
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
68
|
+
* SOFTWARE.
|
|
69
|
+
*/ /*!
|
|
70
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
71
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
72
|
+
*/ /**
|
|
36
73
|
* Raw wav audio file contents
|
|
37
74
|
* @typedef {Object} WavPackerAudioType
|
|
38
75
|
* @property {Blob} blob
|
|
@@ -43,7 +80,7 @@ $parcel$export($28bdeb35415d61e8$exports, "DailyTransport", () => $28bdeb35415d6
|
|
|
43
80
|
*/ /**
|
|
44
81
|
* Utility class for assembling PCM16 "audio/wav" data
|
|
45
82
|
* @class
|
|
46
|
-
*/ class $
|
|
83
|
+
*/ class $45766326c6faa3c4$export$13afda237b1c9846 {
|
|
47
84
|
/**
|
|
48
85
|
* Converts Float32Array of amplitude data to ArrayBuffer in Int16Array format
|
|
49
86
|
* @param {Float32Array} float32Array
|
|
@@ -131,16 +168,22 @@ $parcel$export($28bdeb35415d61e8$exports, "DailyTransport", () => $28bdeb35415d6
|
|
|
131
168
|
};
|
|
132
169
|
}
|
|
133
170
|
}
|
|
134
|
-
globalThis.WavPacker = $
|
|
171
|
+
globalThis.WavPacker = $45766326c6faa3c4$export$13afda237b1c9846;
|
|
135
172
|
|
|
136
173
|
|
|
137
|
-
|
|
174
|
+
/*!
|
|
175
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
176
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
177
|
+
*/ /*!
|
|
178
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
179
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
180
|
+
*/ /**
|
|
138
181
|
* Constants for help with visualization
|
|
139
182
|
* Helps map frequency ranges from Fast Fourier Transform
|
|
140
183
|
* to human-interpretable ranges, notably music ranges and
|
|
141
184
|
* human vocal ranges.
|
|
142
185
|
*/ // Eighth octave frequencies
|
|
143
|
-
const $
|
|
186
|
+
const $550c0e438054ce18$var$octave8Frequencies = [
|
|
144
187
|
4186.01,
|
|
145
188
|
4434.92,
|
|
146
189
|
4698.63,
|
|
@@ -155,7 +198,7 @@ const $e10a9de47f58e137$var$octave8Frequencies = [
|
|
|
155
198
|
7902.13
|
|
156
199
|
];
|
|
157
200
|
// Labels for each of the above frequencies
|
|
158
|
-
const $
|
|
201
|
+
const $550c0e438054ce18$var$octave8FrequencyLabels = [
|
|
159
202
|
"C",
|
|
160
203
|
"C#",
|
|
161
204
|
"D",
|
|
@@ -169,29 +212,29 @@ const $e10a9de47f58e137$var$octave8FrequencyLabels = [
|
|
|
169
212
|
"A#",
|
|
170
213
|
"B"
|
|
171
214
|
];
|
|
172
|
-
const $
|
|
173
|
-
const $
|
|
174
|
-
for(let i = 1; i <= 8; i++)for(let f = 0; f < $
|
|
175
|
-
const freq = $
|
|
176
|
-
$
|
|
177
|
-
$
|
|
215
|
+
const $550c0e438054ce18$export$776c63898ae5b636 = [];
|
|
216
|
+
const $550c0e438054ce18$export$facd167cc27ea9b0 = [];
|
|
217
|
+
for(let i = 1; i <= 8; i++)for(let f = 0; f < $550c0e438054ce18$var$octave8Frequencies.length; f++){
|
|
218
|
+
const freq = $550c0e438054ce18$var$octave8Frequencies[f];
|
|
219
|
+
$550c0e438054ce18$export$776c63898ae5b636.push(freq / Math.pow(2, 8 - i));
|
|
220
|
+
$550c0e438054ce18$export$facd167cc27ea9b0.push($550c0e438054ce18$var$octave8FrequencyLabels[f] + i);
|
|
178
221
|
}
|
|
179
222
|
/**
|
|
180
223
|
* Subset of the note frequencies between 32 and 2000 Hz
|
|
181
224
|
* 6 octave range: C1 to B6
|
|
182
|
-
*/ const $
|
|
225
|
+
*/ const $550c0e438054ce18$var$voiceFrequencyRange = [
|
|
183
226
|
32.0,
|
|
184
227
|
2000.0
|
|
185
228
|
];
|
|
186
|
-
const $
|
|
187
|
-
return $
|
|
229
|
+
const $550c0e438054ce18$export$dbc1581ed2cfa183 = $550c0e438054ce18$export$776c63898ae5b636.filter((_, i)=>{
|
|
230
|
+
return $550c0e438054ce18$export$776c63898ae5b636[i] > $550c0e438054ce18$var$voiceFrequencyRange[0] && $550c0e438054ce18$export$776c63898ae5b636[i] < $550c0e438054ce18$var$voiceFrequencyRange[1];
|
|
188
231
|
});
|
|
189
|
-
const $
|
|
190
|
-
return $
|
|
232
|
+
const $550c0e438054ce18$export$30a6f2881311088f = $550c0e438054ce18$export$facd167cc27ea9b0.filter((_, i)=>{
|
|
233
|
+
return $550c0e438054ce18$export$776c63898ae5b636[i] > $550c0e438054ce18$var$voiceFrequencyRange[0] && $550c0e438054ce18$export$776c63898ae5b636[i] < $550c0e438054ce18$var$voiceFrequencyRange[1];
|
|
191
234
|
});
|
|
192
235
|
|
|
193
236
|
|
|
194
|
-
class $
|
|
237
|
+
class $3f7a723e434a4b86$export$2c3136da0bf130f9 {
|
|
195
238
|
/**
|
|
196
239
|
* Retrieves frequency domain data from an AnalyserNode adjusted to a decibel range
|
|
197
240
|
* returns human-readable formatting and labels
|
|
@@ -213,7 +256,7 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
213
256
|
let frequencies;
|
|
214
257
|
let labels;
|
|
215
258
|
if (analysisType === "music" || analysisType === "voice") {
|
|
216
|
-
const useFrequencies = analysisType === "voice" ? (0, $
|
|
259
|
+
const useFrequencies = analysisType === "voice" ? (0, $550c0e438054ce18$export$dbc1581ed2cfa183) : (0, $550c0e438054ce18$export$776c63898ae5b636);
|
|
217
260
|
const aggregateOutput = Array(useFrequencies.length).fill(minDecibels);
|
|
218
261
|
for(let i = 0; i < fftResult.length; i++){
|
|
219
262
|
const frequency = i * frequencyStep;
|
|
@@ -224,8 +267,8 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
224
267
|
}
|
|
225
268
|
}
|
|
226
269
|
outputValues = aggregateOutput;
|
|
227
|
-
frequencies = analysisType === "voice" ? (0, $
|
|
228
|
-
labels = analysisType === "voice" ? (0, $
|
|
270
|
+
frequencies = analysisType === "voice" ? (0, $550c0e438054ce18$export$dbc1581ed2cfa183) : (0, $550c0e438054ce18$export$776c63898ae5b636);
|
|
271
|
+
labels = analysisType === "voice" ? (0, $550c0e438054ce18$export$30a6f2881311088f) : (0, $550c0e438054ce18$export$facd167cc27ea9b0);
|
|
229
272
|
} else {
|
|
230
273
|
outputValues = Array.from(fftResult);
|
|
231
274
|
frequencies = outputValues.map((_, i)=>frequencyStep * i);
|
|
@@ -318,7 +361,7 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
318
361
|
const index = Math.min(pct * this.fftResults.length | 0, this.fftResults.length - 1);
|
|
319
362
|
fftResult = this.fftResults[index];
|
|
320
363
|
}
|
|
321
|
-
return $
|
|
364
|
+
return $3f7a723e434a4b86$export$2c3136da0bf130f9.getFrequencies(this.analyser, this.sampleRate, fftResult, analysisType, minDecibels, maxDecibels);
|
|
322
365
|
}
|
|
323
366
|
/**
|
|
324
367
|
* Resume the internal AudioContext if it was suspended due to the lack of
|
|
@@ -329,10 +372,16 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
329
372
|
return true;
|
|
330
373
|
}
|
|
331
374
|
}
|
|
332
|
-
globalThis.AudioAnalysis = $
|
|
375
|
+
globalThis.AudioAnalysis = $3f7a723e434a4b86$export$2c3136da0bf130f9;
|
|
333
376
|
|
|
334
377
|
|
|
335
|
-
|
|
378
|
+
/*!
|
|
379
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
380
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
381
|
+
*/ /*!
|
|
382
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
383
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
384
|
+
*/ const $ff75ae50979bb4fc$export$50b76700e2b15e9 = `
|
|
336
385
|
class StreamProcessor extends AudioWorkletProcessor {
|
|
337
386
|
constructor() {
|
|
338
387
|
super();
|
|
@@ -422,23 +471,23 @@ class StreamProcessor extends AudioWorkletProcessor {
|
|
|
422
471
|
|
|
423
472
|
registerProcessor('stream_processor', StreamProcessor);
|
|
424
473
|
`;
|
|
425
|
-
const $
|
|
426
|
-
$
|
|
474
|
+
const $ff75ae50979bb4fc$var$script = new Blob([
|
|
475
|
+
$ff75ae50979bb4fc$export$50b76700e2b15e9
|
|
427
476
|
], {
|
|
428
477
|
type: "application/javascript"
|
|
429
478
|
});
|
|
430
|
-
const $
|
|
431
|
-
const $
|
|
479
|
+
const $ff75ae50979bb4fc$var$src = URL.createObjectURL($ff75ae50979bb4fc$var$script);
|
|
480
|
+
const $ff75ae50979bb4fc$export$bfa8c596114d74df = $ff75ae50979bb4fc$var$src;
|
|
432
481
|
|
|
433
482
|
|
|
434
483
|
|
|
435
|
-
class $
|
|
484
|
+
class $347522367945ce82$export$9698d62c78b8f366 {
|
|
436
485
|
/**
|
|
437
486
|
* Creates a new WavStreamPlayer instance
|
|
438
487
|
* @param {{sampleRate?: number}} options
|
|
439
488
|
* @returns {WavStreamPlayer}
|
|
440
489
|
*/ constructor({ sampleRate: sampleRate = 44100 } = {}){
|
|
441
|
-
this.scriptSrc = (0, $
|
|
490
|
+
this.scriptSrc = (0, $ff75ae50979bb4fc$export$bfa8c596114d74df);
|
|
442
491
|
this.sampleRate = sampleRate;
|
|
443
492
|
this.context = null;
|
|
444
493
|
this.stream = null;
|
|
@@ -475,7 +524,7 @@ class $1e7ce9484a3c4077$export$9698d62c78b8f366 {
|
|
|
475
524
|
* @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}
|
|
476
525
|
*/ getFrequencies(analysisType = "frequency", minDecibels = -100, maxDecibels = -30) {
|
|
477
526
|
if (!this.analyser) throw new Error("Not connected, please call .connect() first");
|
|
478
|
-
return (0, $
|
|
527
|
+
return (0, $3f7a723e434a4b86$export$2c3136da0bf130f9).getFrequencies(this.analyser, this.sampleRate, null, analysisType, minDecibels, maxDecibels);
|
|
479
528
|
}
|
|
480
529
|
/**
|
|
481
530
|
* @param {string} speaker deviceId
|
|
@@ -566,10 +615,16 @@ class $1e7ce9484a3c4077$export$9698d62c78b8f366 {
|
|
|
566
615
|
return this.getTrackSampleOffset(true);
|
|
567
616
|
}
|
|
568
617
|
}
|
|
569
|
-
globalThis.WavStreamPlayer = $
|
|
618
|
+
globalThis.WavStreamPlayer = $347522367945ce82$export$9698d62c78b8f366;
|
|
570
619
|
|
|
571
620
|
|
|
572
|
-
|
|
621
|
+
/*!
|
|
622
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
623
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
624
|
+
*/ /*!
|
|
625
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
626
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
627
|
+
*/ const $5a5c5ac16a3be24c$var$AudioProcessorWorklet = `
|
|
573
628
|
class AudioProcessor extends AudioWorkletProcessor {
|
|
574
629
|
|
|
575
630
|
constructor() {
|
|
@@ -777,25 +832,25 @@ class AudioProcessor extends AudioWorkletProcessor {
|
|
|
777
832
|
|
|
778
833
|
registerProcessor('audio_processor', AudioProcessor);
|
|
779
834
|
`;
|
|
780
|
-
const $
|
|
781
|
-
$
|
|
835
|
+
const $5a5c5ac16a3be24c$var$script = new Blob([
|
|
836
|
+
$5a5c5ac16a3be24c$var$AudioProcessorWorklet
|
|
782
837
|
], {
|
|
783
838
|
type: "application/javascript"
|
|
784
839
|
});
|
|
785
|
-
const $
|
|
786
|
-
const $
|
|
840
|
+
const $5a5c5ac16a3be24c$var$src = URL.createObjectURL($5a5c5ac16a3be24c$var$script);
|
|
841
|
+
const $5a5c5ac16a3be24c$export$1f65f50a8cbff43c = $5a5c5ac16a3be24c$var$src;
|
|
787
842
|
|
|
788
843
|
|
|
789
844
|
|
|
790
845
|
|
|
791
|
-
class $
|
|
846
|
+
class $35ad6181fc724add$export$439b217ca659a877 {
|
|
792
847
|
/**
|
|
793
848
|
* Create a new WavRecorder instance
|
|
794
849
|
* @param {{sampleRate?: number, outputToSpeakers?: boolean, debug?: boolean}} [options]
|
|
795
850
|
* @returns {WavRecorder}
|
|
796
851
|
*/ constructor({ sampleRate: sampleRate = 44100, outputToSpeakers: outputToSpeakers = false, debug: debug = false } = {}){
|
|
797
852
|
// Script source
|
|
798
|
-
this.scriptSrc = (0, $
|
|
853
|
+
this.scriptSrc = (0, $5a5c5ac16a3be24c$export$1f65f50a8cbff43c);
|
|
799
854
|
// Config
|
|
800
855
|
this.sampleRate = sampleRate;
|
|
801
856
|
this.outputToSpeakers = outputToSpeakers;
|
|
@@ -858,7 +913,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
858
913
|
else throw new Error(`"audioData" must be one of: Blob, Float32Arrray, Int16Array, ArrayBuffer, Array<number>`);
|
|
859
914
|
if (fromSampleRate === -1) throw new Error(`Must specify "fromSampleRate" when reading from Float32Array, In16Array or Array`);
|
|
860
915
|
else if (fromSampleRate < 3000) throw new Error(`Minimum "fromSampleRate" is 3000 (3kHz)`);
|
|
861
|
-
if (!data) data = (0, $
|
|
916
|
+
if (!data) data = (0, $45766326c6faa3c4$export$13afda237b1c9846).floatTo16BitPCM(float32Array);
|
|
862
917
|
const audio = {
|
|
863
918
|
bitsPerSample: 16,
|
|
864
919
|
channels: [
|
|
@@ -866,7 +921,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
866
921
|
],
|
|
867
922
|
data: data
|
|
868
923
|
};
|
|
869
|
-
const packer = new (0, $
|
|
924
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
870
925
|
const result = packer.pack(fromSampleRate, audio);
|
|
871
926
|
blob = result.blob;
|
|
872
927
|
arrayBuffer = await blob.arrayBuffer();
|
|
@@ -1088,8 +1143,8 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1088
1143
|
if (this._chunkProcessorSize) {
|
|
1089
1144
|
const buffer = this._chunkProcessorBuffer;
|
|
1090
1145
|
this._chunkProcessorBuffer = {
|
|
1091
|
-
raw: (0, $
|
|
1092
|
-
mono: (0, $
|
|
1146
|
+
raw: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.raw, data.raw),
|
|
1147
|
+
mono: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.mono, data.mono)
|
|
1093
1148
|
};
|
|
1094
1149
|
if (this._chunkProcessorBuffer.mono.byteLength >= this._chunkProcessorSize) {
|
|
1095
1150
|
this._chunkProcessor(this._chunkProcessorBuffer);
|
|
@@ -1126,7 +1181,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1126
1181
|
* @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}
|
|
1127
1182
|
*/ getFrequencies(analysisType = "frequency", minDecibels = -100, maxDecibels = -30) {
|
|
1128
1183
|
if (!this.processor) throw new Error("Session ended: please call .begin() first");
|
|
1129
|
-
return (0, $
|
|
1184
|
+
return (0, $3f7a723e434a4b86$export$2c3136da0bf130f9).getFrequencies(this.analyser, this.sampleRate, null, analysisType, minDecibels, maxDecibels);
|
|
1130
1185
|
}
|
|
1131
1186
|
/**
|
|
1132
1187
|
* Pauses the recording
|
|
@@ -1143,7 +1198,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1143
1198
|
}
|
|
1144
1199
|
/**
|
|
1145
1200
|
* Start recording stream and storing to memory from the connected audio source
|
|
1146
|
-
* @param {(data: { mono:
|
|
1201
|
+
* @param {(data: { mono: ArrayBuffer; raw: ArrayBuffer }) => any} [chunkProcessor]
|
|
1147
1202
|
* @param {number} [chunkSize] chunkProcessor will not be triggered until this size threshold met in mono audio
|
|
1148
1203
|
* @returns {Promise<true>}
|
|
1149
1204
|
*/ async record(chunkProcessor = ()=>{}, chunkSize = 8192) {
|
|
@@ -1187,7 +1242,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1187
1242
|
if (!force && this.recording) throw new Error("Currently recording: please call .pause() first, or call .save(true) to force");
|
|
1188
1243
|
this.log("Exporting ...");
|
|
1189
1244
|
const exportData = await this._event("export");
|
|
1190
|
-
const packer = new (0, $
|
|
1245
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1191
1246
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1192
1247
|
return result;
|
|
1193
1248
|
}
|
|
@@ -1212,7 +1267,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1212
1267
|
this.processor = null;
|
|
1213
1268
|
this.source = null;
|
|
1214
1269
|
this.node = null;
|
|
1215
|
-
const packer = new (0, $
|
|
1270
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1216
1271
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1217
1272
|
return result;
|
|
1218
1273
|
}
|
|
@@ -1228,10 +1283,13 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1228
1283
|
return true;
|
|
1229
1284
|
}
|
|
1230
1285
|
}
|
|
1231
|
-
globalThis.WavRecorder = $
|
|
1232
|
-
|
|
1286
|
+
globalThis.WavRecorder = $35ad6181fc724add$export$439b217ca659a877;
|
|
1233
1287
|
|
|
1234
1288
|
|
|
1289
|
+
/*!
|
|
1290
|
+
* Adapted from openai-realtime-console (https://github.com/openai/openai-realtime-console).
|
|
1291
|
+
* Copyright (c) 2024 OpenAI. Modified by Daily. MIT License; see wavtools/index.js.
|
|
1292
|
+
*/
|
|
1235
1293
|
|
|
1236
1294
|
|
|
1237
1295
|
/**
|
|
@@ -1240,7 +1298,7 @@ globalThis.WavRecorder = $0d471c38435bdab6$export$439b217ca659a877;
|
|
|
1240
1298
|
* @param {number} inputSampleRate - Sample rate of input audio
|
|
1241
1299
|
* @param {number} outputSampleRate - Desired output sample rate
|
|
1242
1300
|
* @returns {ArrayBuffer} - Resampled audio data as Int16 PCM
|
|
1243
|
-
*/ function $
|
|
1301
|
+
*/ function $ab812aec7679ec67$var$resampleAudioBuffer(inputBuffer, inputSampleRate, outputSampleRate) {
|
|
1244
1302
|
if (inputSampleRate === outputSampleRate) return inputBuffer;
|
|
1245
1303
|
const inputView = new Int16Array(inputBuffer);
|
|
1246
1304
|
const ratio = inputSampleRate / outputSampleRate;
|
|
@@ -1257,14 +1315,14 @@ globalThis.WavRecorder = $0d471c38435bdab6$export$439b217ca659a877;
|
|
|
1257
1315
|
}
|
|
1258
1316
|
return outputBuffer;
|
|
1259
1317
|
}
|
|
1260
|
-
class $
|
|
1318
|
+
class $ab812aec7679ec67$export$2934cf2d25c67a48 {
|
|
1261
1319
|
/**
|
|
1262
1320
|
* Create a new MediaStreamRecorder instance
|
|
1263
1321
|
* @param {{sampleRate?: number, outputToSpeakers?: boolean, debug?: boolean}} [options]
|
|
1264
1322
|
* @returns {MediaStreamRecorder}
|
|
1265
1323
|
*/ constructor({ sampleRate: sampleRate = 44100, outputToSpeakers: outputToSpeakers = false, debug: debug = false } = {}){
|
|
1266
1324
|
// Script source
|
|
1267
|
-
this.scriptSrc = (0, $
|
|
1325
|
+
this.scriptSrc = (0, $5a5c5ac16a3be24c$export$1f65f50a8cbff43c);
|
|
1268
1326
|
// Config
|
|
1269
1327
|
this.sampleRate = sampleRate;
|
|
1270
1328
|
this.outputToSpeakers = outputToSpeakers;
|
|
@@ -1376,14 +1434,14 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1376
1434
|
// Resample chunk data from native sample rate to target sample rate
|
|
1377
1435
|
// (no-op if rates match, i.e. for non-Firefox browsers)
|
|
1378
1436
|
const resampledData = {
|
|
1379
|
-
raw: $
|
|
1380
|
-
mono: $
|
|
1437
|
+
raw: $ab812aec7679ec67$var$resampleAudioBuffer(data.raw, contextSampleRate, this.sampleRate),
|
|
1438
|
+
mono: $ab812aec7679ec67$var$resampleAudioBuffer(data.mono, contextSampleRate, this.sampleRate)
|
|
1381
1439
|
};
|
|
1382
1440
|
if (this._chunkProcessorSize) {
|
|
1383
1441
|
const buffer = this._chunkProcessorBuffer;
|
|
1384
1442
|
this._chunkProcessorBuffer = {
|
|
1385
|
-
raw: (0, $
|
|
1386
|
-
mono: (0, $
|
|
1443
|
+
raw: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.raw, resampledData.raw),
|
|
1444
|
+
mono: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.mono, resampledData.mono)
|
|
1387
1445
|
};
|
|
1388
1446
|
if (this._chunkProcessorBuffer.mono.byteLength >= this._chunkProcessorSize) {
|
|
1389
1447
|
this._chunkProcessor(this._chunkProcessorBuffer);
|
|
@@ -1419,7 +1477,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1419
1477
|
* @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}
|
|
1420
1478
|
*/ getFrequencies(analysisType = "frequency", minDecibels = -100, maxDecibels = -30) {
|
|
1421
1479
|
if (!this.processor) throw new Error("Session ended: please call .begin() first");
|
|
1422
|
-
return (0, $
|
|
1480
|
+
return (0, $3f7a723e434a4b86$export$2c3136da0bf130f9).getFrequencies(this.analyser, this.sampleRate, null, analysisType, minDecibels, maxDecibels);
|
|
1423
1481
|
}
|
|
1424
1482
|
/**
|
|
1425
1483
|
* Pauses the recording
|
|
@@ -1436,7 +1494,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1436
1494
|
}
|
|
1437
1495
|
/**
|
|
1438
1496
|
* Start recording stream and storing to memory from the connected audio source
|
|
1439
|
-
* @param {(data: { mono:
|
|
1497
|
+
* @param {(data: { mono: ArrayBuffer; raw: ArrayBuffer }) => any} [chunkProcessor]
|
|
1440
1498
|
* @param {number} [chunkSize] chunkProcessor will not be triggered until this size threshold met in mono audio
|
|
1441
1499
|
* @returns {Promise<true>}
|
|
1442
1500
|
*/ async record(chunkProcessor = ()=>{}, chunkSize = 8192) {
|
|
@@ -1480,7 +1538,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1480
1538
|
if (!force && this.recording) throw new Error("Currently recording: please call .pause() first, or call .save(true) to force");
|
|
1481
1539
|
this.log("Exporting ...");
|
|
1482
1540
|
const exportData = await this._event("export");
|
|
1483
|
-
const packer = new (0, $
|
|
1541
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1484
1542
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1485
1543
|
return result;
|
|
1486
1544
|
}
|
|
@@ -1503,7 +1561,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1503
1561
|
this.processor = null;
|
|
1504
1562
|
this.source = null;
|
|
1505
1563
|
this.node = null;
|
|
1506
|
-
const packer = new (0, $
|
|
1564
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1507
1565
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1508
1566
|
return result;
|
|
1509
1567
|
}
|
|
@@ -1522,16 +1580,986 @@ globalThis.WavRecorder = WavRecorder;
|
|
|
1522
1580
|
|
|
1523
1581
|
|
|
1524
1582
|
|
|
1525
|
-
|
|
1526
|
-
$
|
|
1583
|
+
|
|
1584
|
+
class $48faeb169c82673e$export$4a0c46dbbe2ddb67 {
|
|
1585
|
+
constructor(){
|
|
1586
|
+
this._callbacks = {};
|
|
1587
|
+
this._micEnabled = true;
|
|
1588
|
+
this._camEnabled = false;
|
|
1589
|
+
this._supportsScreenShare = false;
|
|
1590
|
+
}
|
|
1591
|
+
setUserAudioCallback(userAudioCallback) {
|
|
1592
|
+
this._userAudioCallback = userAudioCallback;
|
|
1593
|
+
}
|
|
1594
|
+
setClientOptions(options, override = false) {
|
|
1595
|
+
if (this._options && !override) return;
|
|
1596
|
+
this._options = options;
|
|
1597
|
+
this._callbacks = options.callbacks ?? {};
|
|
1598
|
+
this._micEnabled = options.enableMic ?? true;
|
|
1599
|
+
this._camEnabled = options.enableCam ?? false;
|
|
1600
|
+
}
|
|
1601
|
+
get supportsScreenShare() {
|
|
1602
|
+
return this._supportsScreenShare;
|
|
1603
|
+
}
|
|
1604
|
+
/**
|
|
1605
|
+
* The kinds of media this media manager can capture, for the transport's
|
|
1606
|
+
* `mediaSupport`. `false` rules a kind out, and a missing key leaves it unknown.
|
|
1607
|
+
* By default only screen share can be ruled out: `screenShare` is `false` when
|
|
1608
|
+
* `supportsScreenShare` is, because this media manager or the browser can't
|
|
1609
|
+
* share the screen. Media managers that know more override this.
|
|
1610
|
+
*/ get mediaSupport() {
|
|
1611
|
+
return this._supportsScreenShare ? {} : {
|
|
1612
|
+
screenShare: false
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
class $48faeb169c82673e$export$45c5b9bfba2f6304 extends $48faeb169c82673e$export$4a0c46dbbe2ddb67 {
|
|
1617
|
+
constructor(recorderChunkSize, recorderSampleRate = 24000){
|
|
1618
|
+
super();
|
|
1619
|
+
this._initialized = false;
|
|
1620
|
+
this._recorderChunkSize = undefined;
|
|
1621
|
+
this._recorderChunkSize = recorderChunkSize;
|
|
1622
|
+
this._wavRecorder = new (0, $35ad6181fc724add$export$439b217ca659a877)({
|
|
1623
|
+
sampleRate: recorderSampleRate
|
|
1624
|
+
});
|
|
1625
|
+
this._wavStreamPlayer = new (0, $347522367945ce82$export$9698d62c78b8f366)({
|
|
1626
|
+
sampleRate: 24000
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
/** Captures the microphone only. */ get mediaSupport() {
|
|
1630
|
+
return {
|
|
1631
|
+
mic: true,
|
|
1632
|
+
cam: false,
|
|
1633
|
+
screenShare: false
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
async initialize() {
|
|
1637
|
+
try {
|
|
1638
|
+
await this._wavRecorder.begin();
|
|
1639
|
+
} catch (error) {
|
|
1640
|
+
// void. swallow the error. we still want to set up
|
|
1641
|
+
// the listeners and the player.
|
|
1642
|
+
}
|
|
1643
|
+
this._wavRecorder.listenForDeviceChange(null);
|
|
1644
|
+
this._wavRecorder.listenForDeviceChange(this._handleAvailableDevicesUpdated.bind(this));
|
|
1645
|
+
this._wavRecorder.listenForDeviceErrors(null);
|
|
1646
|
+
this._wavRecorder.listenForDeviceErrors(this._handleDeviceError.bind(this));
|
|
1647
|
+
await this._wavStreamPlayer.connect();
|
|
1648
|
+
this._initialized = true;
|
|
1649
|
+
}
|
|
1650
|
+
async connect() {
|
|
1651
|
+
if (!this._initialized) await this.initialize();
|
|
1652
|
+
const isAlreadyRecording = this._wavRecorder.getStatus() == "recording";
|
|
1653
|
+
if (this._micEnabled && !isAlreadyRecording) await this._startRecording();
|
|
1654
|
+
if (this._camEnabled) console.warn("WavMediaManager does not support video input.");
|
|
1655
|
+
}
|
|
1656
|
+
async disconnect() {
|
|
1657
|
+
if (!this._initialized) return;
|
|
1658
|
+
await this._wavRecorder.end();
|
|
1659
|
+
await this._wavStreamPlayer.interrupt();
|
|
1660
|
+
this._initialized = false;
|
|
1661
|
+
}
|
|
1662
|
+
async interruptBotAudio() {
|
|
1663
|
+
return this._wavStreamPlayer.interrupt();
|
|
1664
|
+
}
|
|
1665
|
+
bufferBotAudio(data, id) {
|
|
1666
|
+
return this._wavStreamPlayer.add16BitPCM(data, id);
|
|
1667
|
+
}
|
|
1668
|
+
getAllMics() {
|
|
1669
|
+
return this._wavRecorder.listDevices();
|
|
1670
|
+
}
|
|
1671
|
+
getAllCams() {
|
|
1672
|
+
// TODO: Video not supported yet
|
|
1673
|
+
return Promise.resolve([]);
|
|
1674
|
+
}
|
|
1675
|
+
getAllSpeakers() {
|
|
1676
|
+
// TODO: Implement speaker support
|
|
1677
|
+
return Promise.resolve([]);
|
|
1678
|
+
}
|
|
1679
|
+
async updateMic(micId) {
|
|
1680
|
+
const prevMic = this._wavRecorder.deviceSelection;
|
|
1681
|
+
if (this._wavRecorder.getStatus() !== "ended") await this._wavRecorder.end();
|
|
1682
|
+
try {
|
|
1683
|
+
await this._wavRecorder.begin(micId);
|
|
1684
|
+
if (this._micEnabled) await this._startRecording();
|
|
1685
|
+
const curMic = this._wavRecorder.deviceSelection;
|
|
1686
|
+
if (curMic && prevMic && prevMic.label !== curMic.label) this._callbacks.onMicUpdated?.(curMic);
|
|
1687
|
+
} catch (error) {
|
|
1688
|
+
// void. If begin() fails, it will have already logged and called
|
|
1689
|
+
// onDeviceError if necessary.
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
updateCam(camId) {
|
|
1693
|
+
// TODO: Video not supported yet
|
|
1694
|
+
}
|
|
1695
|
+
updateSpeaker(speakerId) {
|
|
1696
|
+
// TODO: Implement speaker support
|
|
1697
|
+
}
|
|
1698
|
+
get selectedMic() {
|
|
1699
|
+
return this._wavRecorder.deviceSelection ?? {};
|
|
1700
|
+
}
|
|
1701
|
+
get selectedCam() {
|
|
1702
|
+
// TODO: Video not supported yet
|
|
1703
|
+
return {};
|
|
1704
|
+
}
|
|
1705
|
+
get selectedSpeaker() {
|
|
1706
|
+
// TODO: Implement speaker support
|
|
1707
|
+
return {};
|
|
1708
|
+
}
|
|
1709
|
+
async enableMic(enable) {
|
|
1710
|
+
this._micEnabled = enable;
|
|
1711
|
+
if (!this._wavRecorder.stream) return;
|
|
1712
|
+
this._wavRecorder.stream.getAudioTracks().forEach((track)=>{
|
|
1713
|
+
track.enabled = enable;
|
|
1714
|
+
if (!enable) this._callbacks.onTrackStopped?.(track, $48faeb169c82673e$var$localParticipant());
|
|
1715
|
+
});
|
|
1716
|
+
if (enable) await this._startRecording();
|
|
1717
|
+
else await this._wavRecorder.pause();
|
|
1718
|
+
}
|
|
1719
|
+
enableCam(enable) {
|
|
1720
|
+
// TODO: Video not supported yet
|
|
1721
|
+
console.warn("WavMediaManager does not support video input.");
|
|
1722
|
+
}
|
|
1723
|
+
enableScreenShare(enable) {
|
|
1724
|
+
// TODO: Screensharing not supported yet
|
|
1725
|
+
console.warn("WavMediaManager does not support screen sharing.");
|
|
1726
|
+
}
|
|
1727
|
+
get isCamEnabled() {
|
|
1728
|
+
// TODO: Video not supported yet
|
|
1729
|
+
return false;
|
|
1730
|
+
}
|
|
1731
|
+
get isMicEnabled() {
|
|
1732
|
+
return this._micEnabled;
|
|
1733
|
+
}
|
|
1734
|
+
get isSharingScreen() {
|
|
1735
|
+
// TODO: Screensharing not supported yet
|
|
1736
|
+
return false;
|
|
1737
|
+
}
|
|
1738
|
+
tracks() {
|
|
1739
|
+
const tracks = this._wavRecorder.stream?.getTracks()[0];
|
|
1740
|
+
return {
|
|
1741
|
+
local: tracks ? {
|
|
1742
|
+
audio: tracks
|
|
1743
|
+
} : {}
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
async _startRecording() {
|
|
1747
|
+
await this._wavRecorder.record((data)=>{
|
|
1748
|
+
this._userAudioCallback?.(data.mono);
|
|
1749
|
+
}, this._recorderChunkSize);
|
|
1750
|
+
const track = this._wavRecorder.stream?.getAudioTracks()[0];
|
|
1751
|
+
if (track) this._callbacks.onTrackStarted?.(track, $48faeb169c82673e$var$localParticipant());
|
|
1752
|
+
}
|
|
1753
|
+
_handleAvailableDevicesUpdated(devices) {
|
|
1754
|
+
this._callbacks.onAvailableCamsUpdated?.(devices.filter((d)=>d.kind === "videoinput"));
|
|
1755
|
+
this._callbacks.onAvailableMicsUpdated?.(devices.filter((d)=>d.kind === "audioinput"));
|
|
1756
|
+
// if the current device went away or we're using the default and
|
|
1757
|
+
// the default changed, reset the mic.
|
|
1758
|
+
const defaultDevice = devices.find((d)=>d.deviceId === "default");
|
|
1759
|
+
const currentDevice = this._wavRecorder.deviceSelection;
|
|
1760
|
+
if (currentDevice && (!devices.some((d)=>d.deviceId === currentDevice.deviceId) || currentDevice.deviceId === "default" && currentDevice.label !== defaultDevice?.label)) this.updateMic("");
|
|
1761
|
+
}
|
|
1762
|
+
_handleDeviceError({ devices: devices, type: type, error: error }) {
|
|
1763
|
+
const deviceError = new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, type, error?.message, error ? {
|
|
1764
|
+
sourceError: error
|
|
1765
|
+
} : undefined);
|
|
1766
|
+
this._callbacks.onDeviceError?.(deviceError);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
const $48faeb169c82673e$var$localParticipant = ()=>{
|
|
1770
|
+
return {
|
|
1771
|
+
id: "local",
|
|
1772
|
+
name: "",
|
|
1773
|
+
local: true
|
|
1774
|
+
};
|
|
1775
|
+
};
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
|
|
1527
1781
|
|
|
1528
1782
|
|
|
1529
|
-
|
|
1783
|
+
class $00a190ef6aa79f0d$export$c95c65abc5f47125 extends (0, $48faeb169c82673e$export$4a0c46dbbe2ddb67) {
|
|
1784
|
+
constructor(enablePlayer = true, enableRecording = true, onTrackStartedCallback, onTrackStoppedCallback, recorderChunkSize, recorderSampleRate = 24000, playerSampleRate = 24000){
|
|
1785
|
+
super();
|
|
1786
|
+
this._selectedCam = {};
|
|
1787
|
+
this._selectedMic = {};
|
|
1788
|
+
this._selectedSpeaker = {};
|
|
1789
|
+
this._remoteAudioLevelInterval = null;
|
|
1790
|
+
this._recorderChunkSize = undefined;
|
|
1791
|
+
this._initialized = false;
|
|
1792
|
+
this._connected = false;
|
|
1793
|
+
this._currentAudioTrack = null;
|
|
1794
|
+
this._connectResolve = null;
|
|
1795
|
+
this.onTrackStartedCallback = onTrackStartedCallback;
|
|
1796
|
+
this.onTrackStoppedCallback = onTrackStoppedCallback;
|
|
1797
|
+
this._recorderChunkSize = recorderChunkSize;
|
|
1798
|
+
this._supportsScreenShare = (0, $15398512372f76d1$export$7f8f33b9b54c8307)();
|
|
1799
|
+
this._daily = (0, ($parcel$interopDefault($1clrS$dailycodailyjs))).getCallInstance() ?? (0, ($parcel$interopDefault($1clrS$dailycodailyjs))).createCallObject();
|
|
1800
|
+
if (enableRecording) this._mediaStreamRecorder = new (0, $ab812aec7679ec67$export$2934cf2d25c67a48)({
|
|
1801
|
+
sampleRate: recorderSampleRate
|
|
1802
|
+
});
|
|
1803
|
+
if (enablePlayer) this._wavStreamPlayer = new (0, $347522367945ce82$export$9698d62c78b8f366)({
|
|
1804
|
+
sampleRate: playerSampleRate
|
|
1805
|
+
});
|
|
1806
|
+
this._daily.on("track-started", this.handleTrackStarted.bind(this));
|
|
1807
|
+
this._daily.on("track-stopped", this.handleTrackStopped.bind(this));
|
|
1808
|
+
this._daily.on("available-devices-updated", this._handleAvailableDevicesUpdated.bind(this));
|
|
1809
|
+
this._daily.on("selected-devices-updated", this._handleSelectedDevicesUpdated.bind(this));
|
|
1810
|
+
this._daily.on("camera-error", this.handleDeviceError.bind(this));
|
|
1811
|
+
this._daily.on("local-audio-level", this._handleLocalAudioLevel.bind(this));
|
|
1812
|
+
}
|
|
1813
|
+
async initialize() {
|
|
1814
|
+
if (this._initialized) {
|
|
1815
|
+
console.warn("DailyMediaManager already initialized");
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
const infos = await this._daily.startCamera({
|
|
1819
|
+
startVideoOff: !this._camEnabled,
|
|
1820
|
+
startAudioOff: !this._micEnabled,
|
|
1821
|
+
dailyConfig: {
|
|
1822
|
+
useDevicePreferenceCookies: true
|
|
1823
|
+
}
|
|
1824
|
+
});
|
|
1825
|
+
const { devices: devices } = await this._daily.enumerateDevices();
|
|
1826
|
+
const cams = devices.filter((d)=>d.kind === "videoinput");
|
|
1827
|
+
const mics = devices.filter((d)=>d.kind === "audioinput");
|
|
1828
|
+
const speakers = devices.filter((d)=>d.kind === "audiooutput");
|
|
1829
|
+
this._callbacks.onAvailableCamsUpdated?.(cams);
|
|
1830
|
+
this._callbacks.onAvailableMicsUpdated?.(mics);
|
|
1831
|
+
this._callbacks.onAvailableSpeakersUpdated?.(speakers);
|
|
1832
|
+
this._selectedCam = infos.camera;
|
|
1833
|
+
this._callbacks.onCamUpdated?.(infos.camera);
|
|
1834
|
+
this._selectedMic = infos.mic;
|
|
1835
|
+
this._callbacks.onMicUpdated?.(infos.mic);
|
|
1836
|
+
this._selectedSpeaker = infos.speaker;
|
|
1837
|
+
this._callbacks.onSpeakerUpdated?.(infos.speaker);
|
|
1838
|
+
// Instantiate audio observers
|
|
1839
|
+
if (!this._daily.isLocalAudioLevelObserverRunning()) await this._daily.startLocalAudioLevelObserver(100);
|
|
1840
|
+
if (this._wavStreamPlayer) {
|
|
1841
|
+
await this._wavStreamPlayer.connect();
|
|
1842
|
+
if (!this._remoteAudioLevelInterval) this._remoteAudioLevelInterval = setInterval(()=>{
|
|
1843
|
+
const frequencies = this._wavStreamPlayer.getFrequencies();
|
|
1844
|
+
let aveVal = 0;
|
|
1845
|
+
if (frequencies.values?.length) aveVal = frequencies.values.reduce((a, c)=>a + c, 0) / frequencies.values.length;
|
|
1846
|
+
this._handleRemoteAudioLevel(aveVal);
|
|
1847
|
+
}, 100);
|
|
1848
|
+
}
|
|
1849
|
+
this._initialized = true;
|
|
1850
|
+
}
|
|
1851
|
+
async connect() {
|
|
1852
|
+
if (this._connected) {
|
|
1853
|
+
console.warn("DailyMediaManager already connected");
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
this._connected = true;
|
|
1857
|
+
if (!this._initialized) return new Promise((resolve)=>{
|
|
1858
|
+
(async ()=>{
|
|
1859
|
+
this._connectResolve = resolve;
|
|
1860
|
+
await this.initialize();
|
|
1861
|
+
// Without a recorder, handleTrackStarted never fires to resolve this
|
|
1862
|
+
// promise, so resolve here once initialization is complete.
|
|
1863
|
+
if (this._connectResolve && !this._mediaStreamRecorder) {
|
|
1864
|
+
this._connectResolve();
|
|
1865
|
+
this._connectResolve = null;
|
|
1866
|
+
}
|
|
1867
|
+
})();
|
|
1868
|
+
});
|
|
1869
|
+
if (this._micEnabled) this._startRecording();
|
|
1870
|
+
}
|
|
1871
|
+
async disconnect() {
|
|
1872
|
+
if (this._remoteAudioLevelInterval) clearInterval(this._remoteAudioLevelInterval);
|
|
1873
|
+
this._remoteAudioLevelInterval = null;
|
|
1874
|
+
this._daily.leave();
|
|
1875
|
+
this._currentAudioTrack = null;
|
|
1876
|
+
await this._mediaStreamRecorder?.end();
|
|
1877
|
+
this._wavStreamPlayer?.interrupt();
|
|
1878
|
+
this._initialized = false;
|
|
1879
|
+
this._connected = false;
|
|
1880
|
+
}
|
|
1881
|
+
async interruptBotAudio() {
|
|
1882
|
+
return this._wavStreamPlayer?.interrupt();
|
|
1883
|
+
}
|
|
1884
|
+
bufferBotAudio(data, id) {
|
|
1885
|
+
return this._wavStreamPlayer?.add16BitPCM(data, id);
|
|
1886
|
+
}
|
|
1887
|
+
async getAllMics() {
|
|
1888
|
+
let devices = (await this._daily.enumerateDevices()).devices;
|
|
1889
|
+
return devices.filter((device)=>device.kind === "audioinput");
|
|
1890
|
+
}
|
|
1891
|
+
async getAllCams() {
|
|
1892
|
+
let devices = (await this._daily.enumerateDevices()).devices;
|
|
1893
|
+
return devices.filter((device)=>device.kind === "videoinput");
|
|
1894
|
+
}
|
|
1895
|
+
async getAllSpeakers() {
|
|
1896
|
+
let devices = (await this._daily.enumerateDevices()).devices;
|
|
1897
|
+
return devices.filter((device)=>device.kind === "audiooutput");
|
|
1898
|
+
}
|
|
1899
|
+
updateMic(micId) {
|
|
1900
|
+
this._daily.setInputDevicesAsync({
|
|
1901
|
+
audioDeviceId: micId
|
|
1902
|
+
}).then((deviceInfo)=>{
|
|
1903
|
+
this._selectedMic = deviceInfo.mic;
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
updateCam(camId) {
|
|
1907
|
+
this._daily.setInputDevicesAsync({
|
|
1908
|
+
videoDeviceId: camId
|
|
1909
|
+
}).then((deviceInfo)=>{
|
|
1910
|
+
this._selectedCam = deviceInfo.camera;
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
async updateSpeaker(speakerId) {
|
|
1914
|
+
if (!this._wavStreamPlayer) {
|
|
1915
|
+
try {
|
|
1916
|
+
const dInfo = await this._daily.setOutputDeviceAsync({
|
|
1917
|
+
outputDeviceId: speakerId
|
|
1918
|
+
});
|
|
1919
|
+
this._selectedSpeaker = dInfo.speaker;
|
|
1920
|
+
this._callbacks.onSpeakerUpdated?.(this._selectedSpeaker);
|
|
1921
|
+
} catch (e) {
|
|
1922
|
+
console.error("Error setting output device", e);
|
|
1923
|
+
}
|
|
1924
|
+
return;
|
|
1925
|
+
}
|
|
1926
|
+
if (speakerId !== "default" && this._selectedSpeaker.deviceId === speakerId) return;
|
|
1927
|
+
let sID = speakerId;
|
|
1928
|
+
if (sID === "default") {
|
|
1929
|
+
const speakers = await this.getAllSpeakers();
|
|
1930
|
+
const defaultSpeaker = speakers.find((s)=>s.deviceId === "default");
|
|
1931
|
+
if (!defaultSpeaker) {
|
|
1932
|
+
console.warn("No default speaker found");
|
|
1933
|
+
return;
|
|
1934
|
+
}
|
|
1935
|
+
speakers.splice(speakers.indexOf(defaultSpeaker), 1);
|
|
1936
|
+
const defaultSpeakerCp = speakers.find((s)=>defaultSpeaker.label.includes(s.label));
|
|
1937
|
+
sID = defaultSpeakerCp?.deviceId ?? speakerId;
|
|
1938
|
+
}
|
|
1939
|
+
this._wavStreamPlayer?.updateSpeaker(sID).then(()=>{
|
|
1940
|
+
this._selectedSpeaker = {
|
|
1941
|
+
deviceId: speakerId
|
|
1942
|
+
};
|
|
1943
|
+
this._callbacks.onSpeakerUpdated?.(this._selectedSpeaker);
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
get selectedMic() {
|
|
1947
|
+
return this._selectedMic;
|
|
1948
|
+
}
|
|
1949
|
+
get selectedCam() {
|
|
1950
|
+
return this._selectedCam;
|
|
1951
|
+
}
|
|
1952
|
+
get selectedSpeaker() {
|
|
1953
|
+
return this._selectedSpeaker;
|
|
1954
|
+
}
|
|
1955
|
+
async enableMic(enable) {
|
|
1956
|
+
this._micEnabled = enable;
|
|
1957
|
+
if (!this._daily.participants()?.local) return;
|
|
1958
|
+
this._daily.setLocalAudio(enable);
|
|
1959
|
+
if (this._mediaStreamRecorder) {
|
|
1960
|
+
if (enable) {
|
|
1961
|
+
if (this._mediaStreamRecorder.getStatus() === "paused") this._startRecording();
|
|
1962
|
+
// else, we'll record on the track-started event
|
|
1963
|
+
} else if (this._mediaStreamRecorder.getStatus() === "recording") this._mediaStreamRecorder.pause();
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
enableCam(enable) {
|
|
1967
|
+
this._camEnabled = enable;
|
|
1968
|
+
this._daily.setLocalVideo(enable);
|
|
1969
|
+
}
|
|
1970
|
+
enableScreenShare(enable) {
|
|
1971
|
+
if (enable) this._daily.startScreenShare();
|
|
1972
|
+
else this._daily.stopScreenShare();
|
|
1973
|
+
}
|
|
1974
|
+
// NOTE: deliberately not `this._daily.localVideo()` / `localAudio()`. Daily
|
|
1975
|
+
// fires 'track-started'/'track-stopped' *before* it commits the new state
|
|
1976
|
+
// to the participant object those getters read from (see daily-js's
|
|
1977
|
+
// DAILY_EVENT_PARTICIPANT_UPDATED handling: maybeEventTrackStopped/Started
|
|
1978
|
+
// run, then `this._participants[id]` is reassigned). Callers that react to
|
|
1979
|
+
// TrackStarted/TrackStopped by reading isCamEnabled/isMicEnabled — e.g. to
|
|
1980
|
+
// resync UI state — would otherwise always observe the pre-toggle value.
|
|
1981
|
+
// _camEnabled/_micEnabled are updated synchronously in
|
|
1982
|
+
// handleTrackStarted/handleTrackStopped below, before those callbacks fire.
|
|
1983
|
+
get isCamEnabled() {
|
|
1984
|
+
return this._camEnabled;
|
|
1985
|
+
}
|
|
1986
|
+
get isMicEnabled() {
|
|
1987
|
+
return this._micEnabled;
|
|
1988
|
+
}
|
|
1989
|
+
/** Captures the microphone, the camera and, where the browser can, the screen. */ get mediaSupport() {
|
|
1990
|
+
return {
|
|
1991
|
+
mic: true,
|
|
1992
|
+
cam: true,
|
|
1993
|
+
screenShare: this._supportsScreenShare
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
get isSharingScreen() {
|
|
1997
|
+
return this._daily.localScreenAudio() || this._daily.localScreenVideo();
|
|
1998
|
+
}
|
|
1999
|
+
tracks() {
|
|
2000
|
+
const participants = this._daily.participants();
|
|
2001
|
+
return {
|
|
2002
|
+
local: {
|
|
2003
|
+
audio: participants?.local?.tracks?.audio?.persistentTrack,
|
|
2004
|
+
screenAudio: participants?.local?.tracks?.screenAudio?.persistentTrack,
|
|
2005
|
+
screenVideo: participants?.local?.tracks?.screenVideo?.persistentTrack,
|
|
2006
|
+
video: participants?.local?.tracks?.video?.persistentTrack
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
_startRecording() {
|
|
2011
|
+
if (!this._connected || !this._mediaStreamRecorder) return;
|
|
2012
|
+
try {
|
|
2013
|
+
this._mediaStreamRecorder.record((data)=>{
|
|
2014
|
+
this._userAudioCallback(data.mono);
|
|
2015
|
+
}, this._recorderChunkSize);
|
|
2016
|
+
} catch (e) {
|
|
2017
|
+
const err = e;
|
|
2018
|
+
if (!err.message.includes("Already recording")) console.error("Error starting recording", e);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
_handleAvailableDevicesUpdated(event) {
|
|
2022
|
+
this._callbacks.onAvailableCamsUpdated?.(event.availableDevices.filter((d)=>d.kind === "videoinput"));
|
|
2023
|
+
this._callbacks.onAvailableMicsUpdated?.(event.availableDevices.filter((d)=>d.kind === "audioinput"));
|
|
2024
|
+
this._callbacks.onAvailableSpeakersUpdated?.(event.availableDevices.filter((d)=>d.kind === "audiooutput"));
|
|
2025
|
+
if (this._selectedSpeaker.deviceId === "default") this.updateSpeaker("default");
|
|
2026
|
+
}
|
|
2027
|
+
_handleSelectedDevicesUpdated(event) {
|
|
2028
|
+
if (this._selectedCam?.deviceId !== event.devices.camera) {
|
|
2029
|
+
this._selectedCam = event.devices.camera;
|
|
2030
|
+
this._callbacks.onCamUpdated?.(event.devices.camera);
|
|
2031
|
+
}
|
|
2032
|
+
if (this._selectedMic?.deviceId !== event.devices.mic) {
|
|
2033
|
+
this._selectedMic = event.devices.mic;
|
|
2034
|
+
this._callbacks.onMicUpdated?.(event.devices.mic);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
handleDeviceError(ev) {
|
|
2038
|
+
const generateDeviceError = (error)=>{
|
|
2039
|
+
const devices = [];
|
|
2040
|
+
switch(error.type){
|
|
2041
|
+
case "permissions":
|
|
2042
|
+
error.blockedMedia.forEach((d)=>{
|
|
2043
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
2044
|
+
});
|
|
2045
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
2046
|
+
blockedBy: error.blockedBy
|
|
2047
|
+
});
|
|
2048
|
+
case "not-found":
|
|
2049
|
+
error.missingMedia.forEach((d)=>{
|
|
2050
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
2051
|
+
});
|
|
2052
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
2053
|
+
case "constraints":
|
|
2054
|
+
error.failedMedia.forEach((d)=>{
|
|
2055
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
2056
|
+
});
|
|
2057
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
2058
|
+
reason: error.reason
|
|
2059
|
+
});
|
|
2060
|
+
case "cam-in-use":
|
|
2061
|
+
devices.push("cam");
|
|
2062
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
2063
|
+
case "mic-in-use":
|
|
2064
|
+
devices.push("mic");
|
|
2065
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
2066
|
+
case "cam-mic-in-use":
|
|
2067
|
+
devices.push("cam");
|
|
2068
|
+
devices.push("mic");
|
|
2069
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
2070
|
+
case "undefined-mediadevices":
|
|
2071
|
+
case "unknown":
|
|
2072
|
+
default:
|
|
2073
|
+
devices.push("cam");
|
|
2074
|
+
devices.push("mic");
|
|
2075
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
2076
|
+
}
|
|
2077
|
+
};
|
|
2078
|
+
const deviceError = generateDeviceError(ev.error);
|
|
2079
|
+
// enableMic()/enableCam() set _micEnabled/_camEnabled optimistically,
|
|
2080
|
+
// but setLocalAudio()/setLocalVideo() are fire-and-forget — no promise,
|
|
2081
|
+
// no synchronous failure signal — so a failed request (blocked
|
|
2082
|
+
// permission, device in use, etc.) leaves that optimistic value wrong
|
|
2083
|
+
// with nothing to correct it: no track-started/stopped ever fires for
|
|
2084
|
+
// an operation that didn't actually take effect. This is the only
|
|
2085
|
+
// signal we get that the request failed, so resync from Daily's actual
|
|
2086
|
+
// state for whichever device(s) it implicates.
|
|
2087
|
+
if (deviceError.devices.includes("mic")) this._micEnabled = this._daily.localAudio();
|
|
2088
|
+
if (deviceError.devices.includes("cam")) this._camEnabled = this._daily.localVideo();
|
|
2089
|
+
this._callbacks.onDeviceError?.(deviceError);
|
|
2090
|
+
}
|
|
2091
|
+
_handleLocalAudioLevel(ev) {
|
|
2092
|
+
this._callbacks.onLocalAudioLevel?.(ev.audioLevel);
|
|
2093
|
+
}
|
|
2094
|
+
_handleRemoteAudioLevel(audioLevel) {
|
|
2095
|
+
this._callbacks.onRemoteAudioLevel?.(audioLevel, $00a190ef6aa79f0d$var$botParticipant());
|
|
2096
|
+
}
|
|
2097
|
+
async handleTrackStarted(event) {
|
|
2098
|
+
if (!event.participant?.local) return;
|
|
2099
|
+
if (event.track.kind === "audio") {
|
|
2100
|
+
this._micEnabled = true;
|
|
2101
|
+
if (this._mediaStreamRecorder) {
|
|
2102
|
+
const status = this._mediaStreamRecorder.getStatus();
|
|
2103
|
+
switch(status){
|
|
2104
|
+
case "ended":
|
|
2105
|
+
try {
|
|
2106
|
+
await this._mediaStreamRecorder.begin(event.track);
|
|
2107
|
+
if (this._connected) {
|
|
2108
|
+
this._startRecording();
|
|
2109
|
+
if (this._connectResolve) {
|
|
2110
|
+
this._connectResolve();
|
|
2111
|
+
this._connectResolve = null;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
} catch (e) {
|
|
2115
|
+
// void. nothing to do.
|
|
2116
|
+
}
|
|
2117
|
+
break;
|
|
2118
|
+
case "paused":
|
|
2119
|
+
this._startRecording();
|
|
2120
|
+
break;
|
|
2121
|
+
case "recording":
|
|
2122
|
+
default:
|
|
2123
|
+
if (this._currentAudioTrack !== event.track) {
|
|
2124
|
+
await this._mediaStreamRecorder.end();
|
|
2125
|
+
try {
|
|
2126
|
+
await this._mediaStreamRecorder.begin(event.track);
|
|
2127
|
+
this._startRecording();
|
|
2128
|
+
} catch (e) {
|
|
2129
|
+
// void. nothing to do.
|
|
2130
|
+
}
|
|
2131
|
+
} else console.warn("track-started event received for current track and already recording");
|
|
2132
|
+
break;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
this._currentAudioTrack = event.track;
|
|
2136
|
+
} else if (event.track.kind === "video") this._camEnabled = true;
|
|
2137
|
+
this._callbacks.onTrackStarted?.(event.track, event.participant ? $00a190ef6aa79f0d$var$dailyParticipantToParticipant(event.participant) : undefined);
|
|
2138
|
+
this.onTrackStartedCallback?.(event);
|
|
2139
|
+
}
|
|
2140
|
+
handleTrackStopped(event) {
|
|
2141
|
+
if (!event.participant?.local) return;
|
|
2142
|
+
if (event.track.kind === "audio") {
|
|
2143
|
+
this._micEnabled = false;
|
|
2144
|
+
if (this._mediaStreamRecorder && this._mediaStreamRecorder.getStatus() === "recording") this._mediaStreamRecorder.pause();
|
|
2145
|
+
} else if (event.track.kind === "video") this._camEnabled = false;
|
|
2146
|
+
this._callbacks.onTrackStopped?.(event.track, event.participant ? $00a190ef6aa79f0d$var$dailyParticipantToParticipant(event.participant) : undefined);
|
|
2147
|
+
this.onTrackStoppedCallback?.(event);
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
const $00a190ef6aa79f0d$var$dailyParticipantToParticipant = (p)=>({
|
|
2151
|
+
id: p.user_id,
|
|
2152
|
+
local: p.local,
|
|
2153
|
+
name: p.user_name
|
|
2154
|
+
});
|
|
2155
|
+
const $00a190ef6aa79f0d$var$botParticipant = ()=>({
|
|
2156
|
+
id: "bot",
|
|
2157
|
+
local: false,
|
|
2158
|
+
name: "Bot"
|
|
2159
|
+
});
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
const $7f41aaa208a19660$var$readyStates = [
|
|
2164
|
+
"CONNECTING",
|
|
2165
|
+
"OPEN",
|
|
2166
|
+
"CLOSING",
|
|
2167
|
+
"CLOSED"
|
|
2168
|
+
];
|
|
2169
|
+
const $7f41aaa208a19660$var$KEEP_ALIVE_INTERVAL = 5000;
|
|
2170
|
+
const $7f41aaa208a19660$var$KEEP_ALIVE_TIMEOUT = 15000;
|
|
2171
|
+
// client side code in soupSFU has a timeout of 15 seconds for command response
|
|
2172
|
+
// 5 seconds seems reasonable that it provides roughly 3 retry attempts
|
|
2173
|
+
const $7f41aaa208a19660$var$WEBSOCKET_CONNECTION_TIMEOUT = 150000;
|
|
2174
|
+
const $7f41aaa208a19660$var$DEFAULT_RECONNECT_ATTEMPTS = 2;
|
|
2175
|
+
const $7f41aaa208a19660$var$MAX_RECONNECT_ATTEMPTS = 10;
|
|
2176
|
+
const $7f41aaa208a19660$var$DEFAULT_RECONNECT_INTERVAL = 1000;
|
|
2177
|
+
const $7f41aaa208a19660$var$MAX_RECONNECT_INTERVAL = 30000;
|
|
2178
|
+
const $7f41aaa208a19660$var$DEFAULT_RECONNECT_DECAY = 1.5;
|
|
2179
|
+
const $7f41aaa208a19660$var$WEBSOCKET_TIMEOUT_CODE = 4100;
|
|
2180
|
+
const $7f41aaa208a19660$var$SIG_CONNECTION_CANCELED = "SIG_CONNECTION_CANCELED";
|
|
2181
|
+
const $7f41aaa208a19660$var$WEBSOCKET_ERROR = "WEBSOCKET_ERROR";
|
|
2182
|
+
var $7f41aaa208a19660$var$LOG_LEVEL;
|
|
2183
|
+
(function(LOG_LEVEL) {
|
|
2184
|
+
LOG_LEVEL[LOG_LEVEL["DEBUG"] = 0] = "DEBUG";
|
|
2185
|
+
LOG_LEVEL[LOG_LEVEL["ERROR"] = 1] = "ERROR";
|
|
2186
|
+
LOG_LEVEL[LOG_LEVEL["INFO"] = 2] = "INFO";
|
|
2187
|
+
LOG_LEVEL[LOG_LEVEL["WARN"] = 3] = "WARN";
|
|
2188
|
+
})($7f41aaa208a19660$var$LOG_LEVEL || ($7f41aaa208a19660$var$LOG_LEVEL = {}));
|
|
2189
|
+
class $7f41aaa208a19660$var$rWebSocket {
|
|
2190
|
+
constructor(url, protocols){
|
|
2191
|
+
this._closedManually = false;
|
|
2192
|
+
this._errored = false;
|
|
2193
|
+
this._rejected = false;
|
|
2194
|
+
this._timed_out = false;
|
|
2195
|
+
this._initialConnectionOk = false;
|
|
2196
|
+
this._ws = new WebSocket(url, protocols);
|
|
2197
|
+
}
|
|
2198
|
+
addEventListener(type, listener) {
|
|
2199
|
+
this._ws.addEventListener(type, listener);
|
|
2200
|
+
}
|
|
2201
|
+
// Add other WebSocket methods as needed
|
|
2202
|
+
close(code, reason) {
|
|
2203
|
+
this._ws.close(code, reason);
|
|
2204
|
+
}
|
|
2205
|
+
send(data) {
|
|
2206
|
+
this._ws.send(data);
|
|
2207
|
+
}
|
|
2208
|
+
// Add getters for WebSocket properties
|
|
2209
|
+
get url() {
|
|
2210
|
+
return this._ws.url;
|
|
2211
|
+
}
|
|
2212
|
+
get readyState() {
|
|
2213
|
+
return this._ws.readyState;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
class $7f41aaa208a19660$export$4f3d0ffd941ebefb extends (0, $1clrS$events.EventEmitter) {
|
|
2217
|
+
constructor(address, protocols, options = {}){
|
|
2218
|
+
super();
|
|
2219
|
+
if (!address) throw new Error("Need a valid WebSocket URL");
|
|
2220
|
+
this._ws = null;
|
|
2221
|
+
this._url = address;
|
|
2222
|
+
this._protocols = protocols;
|
|
2223
|
+
this._parseBlobToJson = options?.parseBlobToJson ?? true;
|
|
2224
|
+
this.init();
|
|
2225
|
+
}
|
|
2226
|
+
init() {
|
|
2227
|
+
this._keepAliveTimeout = $7f41aaa208a19660$var$KEEP_ALIVE_TIMEOUT;
|
|
2228
|
+
this._keepAliveInterval = $7f41aaa208a19660$var$KEEP_ALIVE_INTERVAL;
|
|
2229
|
+
this._disconnected = false;
|
|
2230
|
+
this._keepIntervalID = null;
|
|
2231
|
+
this._shouldRetryFn = null;
|
|
2232
|
+
this._connectionTimeout = $7f41aaa208a19660$var$WEBSOCKET_CONNECTION_TIMEOUT;
|
|
2233
|
+
this._reconnectAttempts = 0;
|
|
2234
|
+
this._allowedReconnectAttempts = $7f41aaa208a19660$var$DEFAULT_RECONNECT_ATTEMPTS;
|
|
2235
|
+
this._reconnectInterval = $7f41aaa208a19660$var$DEFAULT_RECONNECT_INTERVAL;
|
|
2236
|
+
this._maxReconnectInterval = $7f41aaa208a19660$var$MAX_RECONNECT_INTERVAL;
|
|
2237
|
+
this._reconnectDecay = $7f41aaa208a19660$var$DEFAULT_RECONNECT_DECAY;
|
|
2238
|
+
}
|
|
2239
|
+
async connect() {
|
|
2240
|
+
return new Promise((resolve, reject)=>{
|
|
2241
|
+
this._disconnected = false;
|
|
2242
|
+
this.clearReconnectTimeout();
|
|
2243
|
+
let ws = new $7f41aaa208a19660$var$rWebSocket(this._url, this._protocols);
|
|
2244
|
+
this.setConnectionTimeout();
|
|
2245
|
+
ws.addEventListener("close", (evt)=>{
|
|
2246
|
+
const closeEvent = evt;
|
|
2247
|
+
let code = ws._timed_out ? $7f41aaa208a19660$var$WEBSOCKET_TIMEOUT_CODE : closeEvent.code;
|
|
2248
|
+
let reason = ws._timed_out ? "websocket connection timed out" : closeEvent.reason;
|
|
2249
|
+
ws._timed_out = false;
|
|
2250
|
+
if (!ws._closedManually && ws._initialConnectionOk) {
|
|
2251
|
+
console.warn(`signaling socket closed unexpectedly: ${code}${reason ? " " + reason : ""}`);
|
|
2252
|
+
this._closeSocket();
|
|
2253
|
+
this.emit("close", code, reason);
|
|
2254
|
+
} else this.log("signaling socket closed");
|
|
2255
|
+
if (!ws._closedManually && (ws._errored || ws._timed_out)) {
|
|
2256
|
+
console.warn(`signaling socket closed on error: ${code}${reason ? " " + reason : ""}`);
|
|
2257
|
+
if (!ws._rejected) {
|
|
2258
|
+
ws._rejected = true;
|
|
2259
|
+
const err = new Error(`WebSocket connection error (${code}): ${reason}`);
|
|
2260
|
+
err.name = $7f41aaa208a19660$var$WEBSOCKET_ERROR;
|
|
2261
|
+
reject(err);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
|
+
ws.addEventListener("open", (evt)=>{
|
|
2266
|
+
this.log("wss connection opened to", $7f41aaa208a19660$var$LOG_LEVEL.DEBUG, this._url);
|
|
2267
|
+
this.clearConnectionTimeout();
|
|
2268
|
+
// now that the timeout closes the socket, in theory this onopen
|
|
2269
|
+
// callback should never happen in the first place, but seems
|
|
2270
|
+
// harmless to leave these safeguards in
|
|
2271
|
+
if (ws._rejected || ws._timed_out) return;
|
|
2272
|
+
if (ws._closedManually || this._ws && this._ws !== ws) {
|
|
2273
|
+
ws._rejected = true;
|
|
2274
|
+
ws.close();
|
|
2275
|
+
let err = Error("wss connection interrupted by disconnect or newer connection");
|
|
2276
|
+
err.name = $7f41aaa208a19660$var$SIG_CONNECTION_CANCELED;
|
|
2277
|
+
reject(err);
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
ws._initialConnectionOk = this._url;
|
|
2281
|
+
this._lastMsgRecvTime = Date.now();
|
|
2282
|
+
if (this._keepAliveInterval) this._keepIntervalID = setInterval(()=>this.checkSocketHealthAndSendKeepAlive(), this._keepAliveInterval);
|
|
2283
|
+
this._ws = ws;
|
|
2284
|
+
this.emit("open");
|
|
2285
|
+
resolve(ws);
|
|
2286
|
+
});
|
|
2287
|
+
ws.addEventListener("error", (evt)=>{
|
|
2288
|
+
// fyi: evt is an Event here, with 0 amount of helpful info. If there
|
|
2289
|
+
// happens to be info about the error, it's included in the
|
|
2290
|
+
// accompanying close event (because that make sense. shakes head)
|
|
2291
|
+
// SO. We do not reject here. Instead, we just set the _errored
|
|
2292
|
+
// flag on the socket so when the close event occurs, it knows to
|
|
2293
|
+
// reject the promise
|
|
2294
|
+
if (!ws._closedManually) {
|
|
2295
|
+
const wsTarget = evt.currentTarget;
|
|
2296
|
+
this.log(`websocket error event: ${wsTarget?.url}`);
|
|
2297
|
+
}
|
|
2298
|
+
ws._errored = true;
|
|
2299
|
+
});
|
|
2300
|
+
ws.addEventListener("message", (msg)=>{
|
|
2301
|
+
this._handleMessage(msg);
|
|
2302
|
+
});
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
setConnectionTimeout() {
|
|
2306
|
+
this._connectionTimeoutID = setTimeout(async ()=>{
|
|
2307
|
+
this.log("Connection reconnect attempt timed out.");
|
|
2308
|
+
this.emit("connection-timeout");
|
|
2309
|
+
this.clearConnectionTimeout();
|
|
2310
|
+
await this._closeSocket();
|
|
2311
|
+
}, this._connectionTimeout);
|
|
2312
|
+
}
|
|
2313
|
+
clearConnectionTimeout() {
|
|
2314
|
+
clearTimeout(this._connectionTimeoutID);
|
|
2315
|
+
this._connectionTimeoutID = undefined;
|
|
2316
|
+
}
|
|
2317
|
+
clearReconnectTimeout() {
|
|
2318
|
+
clearTimeout(this._reconnectTimeoutID);
|
|
2319
|
+
this._reconnectTimeoutID = undefined;
|
|
2320
|
+
}
|
|
2321
|
+
clearKeepAliveInterval() {
|
|
2322
|
+
if (this._keepIntervalID) {
|
|
2323
|
+
clearInterval(this._keepIntervalID);
|
|
2324
|
+
this._keepIntervalID = null;
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
async checkSocketHealthAndSendKeepAlive() {
|
|
2328
|
+
if (!(this._ws && this._ws.readyState === WebSocket.OPEN)) return;
|
|
2329
|
+
if (!this._keepAliveTimeout || !this._keepAliveInterval) return;
|
|
2330
|
+
// See if we haven't gotten a message back recently, and if we
|
|
2331
|
+
// haven't, close the socket. the os timeouts to detect if a socket
|
|
2332
|
+
// has gone stale are longer than we want.
|
|
2333
|
+
if (Date.now() - this._lastMsgRecvTime > this._keepAliveTimeout) {
|
|
2334
|
+
this.log("Connection is stale, need to reconnect", $7f41aaa208a19660$var$LOG_LEVEL.WARN);
|
|
2335
|
+
await this._closeSocket();
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
// Only emit the keep-alive event if we haven't sent anything else recently
|
|
2339
|
+
if (Date.now() - this._lastMsgSendTime < this._keepAliveInterval) return;
|
|
2340
|
+
this.log("Emitting keep-alive", $7f41aaa208a19660$var$LOG_LEVEL.DEBUG);
|
|
2341
|
+
this.emit("keep-alive");
|
|
2342
|
+
}
|
|
2343
|
+
// We use the word manually here to imply the application using this code
|
|
2344
|
+
// or this code itself will decide to close the socket.
|
|
2345
|
+
async _closeSocket() {
|
|
2346
|
+
this.log("Closing");
|
|
2347
|
+
try {
|
|
2348
|
+
this.clearKeepAliveInterval();
|
|
2349
|
+
this._lastMsgRecvTime = 0;
|
|
2350
|
+
if (this._ws) {
|
|
2351
|
+
this._ws._closedManually = true;
|
|
2352
|
+
this._ws.close();
|
|
2353
|
+
}
|
|
2354
|
+
// query retry function if we want to retry.
|
|
2355
|
+
const shouldRetry = this._ws?._initialConnectionOk && this._shouldRetryFn && this._shouldRetryFn();
|
|
2356
|
+
this._ws = null;
|
|
2357
|
+
if (shouldRetry) {
|
|
2358
|
+
this.log("Emitting reconnect", $7f41aaa208a19660$var$LOG_LEVEL.DEBUG);
|
|
2359
|
+
this.emit("reconnecting");
|
|
2360
|
+
await this.retryFailedConnection();
|
|
2361
|
+
}
|
|
2362
|
+
} catch (error) {
|
|
2363
|
+
this.log(`Error while closing and retrying: ${error}`, $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
async retryFailedConnection() {
|
|
2367
|
+
if (this._reconnectAttempts < this._allowedReconnectAttempts) {
|
|
2368
|
+
if (this._reconnectTimeoutID) {
|
|
2369
|
+
this.log("Retry already scheduled");
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
this.log("Retrying failed connection");
|
|
2373
|
+
let timeout = // The timeout logic is taken from
|
|
2374
|
+
// https://github.com/joewalnes/reconnecting-websocket
|
|
2375
|
+
this._reconnectInterval * Math.pow(this._reconnectDecay, this._reconnectAttempts);
|
|
2376
|
+
timeout = timeout > this._maxReconnectInterval ? this._maxReconnectInterval : timeout;
|
|
2377
|
+
this.log(`Reconnecting in ${timeout / 1000} seconds`);
|
|
2378
|
+
this._reconnectAttempts += 1;
|
|
2379
|
+
this._reconnectTimeoutID = setTimeout(()=>this.connect(), timeout);
|
|
2380
|
+
} else {
|
|
2381
|
+
this.log("Maximum connection retry attempts exceeded", $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2382
|
+
this.emit("reconnect-failed");
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
log(msg, log_level = $7f41aaa208a19660$var$LOG_LEVEL.DEBUG, ...args) {
|
|
2386
|
+
switch(log_level){
|
|
2387
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.DEBUG:
|
|
2388
|
+
console.debug(`websocket: ${msg}`, ...args);
|
|
2389
|
+
break;
|
|
2390
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.ERROR:
|
|
2391
|
+
console.error(`websocket: ${msg}`, ...args);
|
|
2392
|
+
break;
|
|
2393
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.WARN:
|
|
2394
|
+
console.warn(`websocket: ${msg}`, ...args);
|
|
2395
|
+
break;
|
|
2396
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.INFO:
|
|
2397
|
+
default:
|
|
2398
|
+
console.log(`websocket: ${msg}`, ...args);
|
|
2399
|
+
break;
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
async send(data) {
|
|
2403
|
+
try {
|
|
2404
|
+
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
|
|
2405
|
+
this._lastMsgSendTime = Date.now();
|
|
2406
|
+
this._ws.send(data);
|
|
2407
|
+
} else this.log(`Failed to send data, web socket not open.`, $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2408
|
+
} catch (error) {
|
|
2409
|
+
this.log(`Failed to send data. ${error}`, $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
async close() {
|
|
2413
|
+
try {
|
|
2414
|
+
this.log("Closing websocket");
|
|
2415
|
+
this._disconnected = true;
|
|
2416
|
+
this.clearReconnectTimeout();
|
|
2417
|
+
this._closeSocket();
|
|
2418
|
+
} catch (error) {
|
|
2419
|
+
this.log(`Failed to close websocket. ${error}`);
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
get readyState() {
|
|
2423
|
+
return this._ws?.readyState ?? WebSocket.CLOSED;
|
|
2424
|
+
}
|
|
2425
|
+
get url() {
|
|
2426
|
+
return this._url;
|
|
2427
|
+
}
|
|
2428
|
+
get keepAliveTimeout() {
|
|
2429
|
+
return this._keepAliveTimeout;
|
|
2430
|
+
}
|
|
2431
|
+
set keepAliveTimeout(keepAliveTimeout) {
|
|
2432
|
+
if (typeof keepAliveTimeout === "number") {
|
|
2433
|
+
this.log(`Setting ACK freshness timeout to ${keepAliveTimeout}`);
|
|
2434
|
+
this._keepAliveTimeout = keepAliveTimeout;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
get keepAliveInterval() {
|
|
2438
|
+
return this._keepAliveInterval;
|
|
2439
|
+
}
|
|
2440
|
+
set keepAliveInterval(keepAliveInterval) {
|
|
2441
|
+
if (typeof keepAliveInterval === "number") {
|
|
2442
|
+
this.log(`Setting keep-alive interval to ${keepAliveInterval}`);
|
|
2443
|
+
this._keepAliveInterval = keepAliveInterval;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
set shouldRetryFn(cb) {
|
|
2447
|
+
if (typeof cb === "function") this._shouldRetryFn = cb;
|
|
2448
|
+
}
|
|
2449
|
+
get connectionTimeout() {
|
|
2450
|
+
return this._connectionTimeout;
|
|
2451
|
+
}
|
|
2452
|
+
set connectionTimeout(timeout) {
|
|
2453
|
+
if (typeof timeout === "number") this._connectionTimeout = timeout;
|
|
2454
|
+
}
|
|
2455
|
+
get maxReconnectAttempts() {
|
|
2456
|
+
return this._allowedReconnectAttempts;
|
|
2457
|
+
}
|
|
2458
|
+
set maxReconnectAttempts(attempts) {
|
|
2459
|
+
if (attempts > 0 && attempts < $7f41aaa208a19660$var$MAX_RECONNECT_ATTEMPTS) {
|
|
2460
|
+
this.log(`Setting maximum connection retry attempts to ${attempts}`);
|
|
2461
|
+
this._allowedReconnectAttempts = attempts;
|
|
2462
|
+
} else this._allowedReconnectAttempts = $7f41aaa208a19660$var$DEFAULT_RECONNECT_ATTEMPTS;
|
|
2463
|
+
}
|
|
2464
|
+
get reconnectInterval() {
|
|
2465
|
+
return this._reconnectInterval;
|
|
2466
|
+
}
|
|
2467
|
+
set reconnectInterval(interval) {
|
|
2468
|
+
if (typeof interval === "number") this._reconnectInterval = interval < this._maxReconnectInterval ? interval : this._maxReconnectInterval;
|
|
2469
|
+
}
|
|
2470
|
+
async _handleMessage(event) {
|
|
2471
|
+
this._lastMsgRecvTime = Date.now();
|
|
2472
|
+
const data = event.data;
|
|
2473
|
+
const _parsePromise = new Promise((resolve, reject)=>{
|
|
2474
|
+
if (typeof data === "string") // Handle text message
|
|
2475
|
+
resolve(data);
|
|
2476
|
+
else if (data instanceof ArrayBuffer) {
|
|
2477
|
+
// Handle binary message
|
|
2478
|
+
const arrayBuffer = data;
|
|
2479
|
+
// Parse the ArrayBuffer as needed
|
|
2480
|
+
// Example: Convert ArrayBuffer to Uint8Array
|
|
2481
|
+
resolve(new Uint8Array(arrayBuffer));
|
|
2482
|
+
// Process the Uint8Array as needed
|
|
2483
|
+
} else if (data instanceof Blob) {
|
|
2484
|
+
if (!this._parseBlobToJson) {
|
|
2485
|
+
resolve(data);
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
// Handle Blob message
|
|
2489
|
+
const blob = data;
|
|
2490
|
+
// Convert Blob to ArrayBuffer
|
|
2491
|
+
const reader = new FileReader();
|
|
2492
|
+
reader.onload = ()=>{
|
|
2493
|
+
const text = reader.result;
|
|
2494
|
+
try {
|
|
2495
|
+
const json = JSON.parse(text);
|
|
2496
|
+
resolve(json);
|
|
2497
|
+
} catch (e) {
|
|
2498
|
+
console.error("Failed to parse JSON from Blob:", e);
|
|
2499
|
+
}
|
|
2500
|
+
};
|
|
2501
|
+
reader.readAsText(blob);
|
|
2502
|
+
}
|
|
2503
|
+
});
|
|
2504
|
+
let msg = await _parsePromise;
|
|
2505
|
+
this.emit("message", msg);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
[
|
|
2509
|
+
"binaryType",
|
|
2510
|
+
"bufferedAmount",
|
|
2511
|
+
"extensions",
|
|
2512
|
+
"protocol",
|
|
2513
|
+
"readyState",
|
|
2514
|
+
"url",
|
|
2515
|
+
"keepAliveTimeout",
|
|
2516
|
+
"keepAliveInterval",
|
|
2517
|
+
"shouldRetryFn",
|
|
2518
|
+
"connectionTimeout",
|
|
2519
|
+
"maxReconnectAttempts",
|
|
2520
|
+
"reconnectInterval"
|
|
2521
|
+
].forEach((property)=>{
|
|
2522
|
+
Object.defineProperty($7f41aaa208a19660$export$4f3d0ffd941ebefb.prototype, property, {
|
|
2523
|
+
enumerable: true
|
|
2524
|
+
});
|
|
2525
|
+
});
|
|
2526
|
+
[
|
|
2527
|
+
"CONNECTING",
|
|
2528
|
+
"OPEN",
|
|
2529
|
+
"CLOSING",
|
|
2530
|
+
"CLOSED"
|
|
2531
|
+
].forEach((property)=>{
|
|
2532
|
+
Object.defineProperty($7f41aaa208a19660$export$4f3d0ffd941ebefb.prototype, property, {
|
|
2533
|
+
enumerable: true,
|
|
2534
|
+
value: $7f41aaa208a19660$var$readyStates.indexOf(property)
|
|
2535
|
+
});
|
|
2536
|
+
});
|
|
2537
|
+
[
|
|
2538
|
+
"CONNECTING",
|
|
2539
|
+
"OPEN",
|
|
2540
|
+
"CLOSING",
|
|
2541
|
+
"CLOSED"
|
|
2542
|
+
].forEach((property)=>{
|
|
2543
|
+
Object.defineProperty($7f41aaa208a19660$export$4f3d0ffd941ebefb, property, {
|
|
2544
|
+
enumerable: true,
|
|
2545
|
+
value: $7f41aaa208a19660$var$readyStates.indexOf(property)
|
|
2546
|
+
});
|
|
2547
|
+
});
|
|
2548
|
+
|
|
2549
|
+
|
|
2550
|
+
|
|
2551
|
+
|
|
2552
|
+
|
|
2553
|
+
var $48b67f1ef231aa26$exports = {};
|
|
2554
|
+
$48b67f1ef231aa26$exports = JSON.parse("{\"name\":\"@pipecat-ai/daily-transport\",\"version\":\"1.7.0\",\"license\":\"BSD-2-Clause\",\"main\":\"dist/index.js\",\"module\":\"dist/index.module.js\",\"types\":\"dist/index.d.ts\",\"source\":\"src/index.ts\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/pipecat-ai/pipecat-client-web-transports.git\"},\"exports\":{\".\":{\"types\":\"./dist/index.d.ts\",\"import\":\"./dist/index.module.js\",\"require\":\"./dist/index.js\"}},\"files\":[\"dist\",\"package.json\",\"README.md\"],\"targets\":{\"main\":{\"includeNodeModules\":[\"@pipecat-ai/transport-lib\"]},\"module\":{\"includeNodeModules\":[\"@pipecat-ai/transport-lib\"]}},\"scripts\":{\"build\":\"parcel build --no-cache\",\"dev\":\"parcel watch\",\"lint\":\"eslint . --ext ts --report-unused-disable-directives --max-warnings 0\"},\"devDependencies\":{\"@pipecat-ai/client-js\":\"^1.14.0\",\"@pipecat-ai/transport-lib\":\"^0.2.0\",\"eslint\":\"9.39.1\",\"eslint-config-prettier\":\"^9.1.0\",\"eslint-plugin-simple-import-sort\":\"^12.1.1\"},\"peerDependencies\":{\"@pipecat-ai/client-js\":\"~1.14.0\"},\"dependencies\":{\"@daily-co/daily-js\":\"^0.94.0\"},\"description\":\"Pipecat Daily Transport Package\",\"author\":\"Daily.co\",\"bugs\":{\"url\":\"https://github.com/pipecat-ai/pipecat-client-web-transports/issues\"},\"homepage\":\"https://github.com/pipecat-ai/pipecat-client-web-transports/blob/main/transports/daily-webrtc/README.md\"}");
|
|
2555
|
+
|
|
2556
|
+
|
|
2557
|
+
var $1c83796b12dd4e49$export$ef180de88fd317cc;
|
|
1530
2558
|
(function(DailyRTVIMessageType) {
|
|
1531
2559
|
DailyRTVIMessageType["AUDIO_BUFFERING_STARTED"] = "audio-buffering-started";
|
|
1532
2560
|
DailyRTVIMessageType["AUDIO_BUFFERING_STOPPED"] = "audio-buffering-stopped";
|
|
1533
|
-
})($
|
|
1534
|
-
class $
|
|
2561
|
+
})($1c83796b12dd4e49$export$ef180de88fd317cc || ($1c83796b12dd4e49$export$ef180de88fd317cc = {}));
|
|
2562
|
+
class $1c83796b12dd4e49$var$DailyCallWrapper {
|
|
1535
2563
|
constructor(daily){
|
|
1536
2564
|
this._daily = daily;
|
|
1537
2565
|
this._proxy = new Proxy(this._daily, {
|
|
@@ -1574,7 +2602,7 @@ class $28bdeb35415d61e8$var$DailyCallWrapper {
|
|
|
1574
2602
|
return this._proxy;
|
|
1575
2603
|
}
|
|
1576
2604
|
}
|
|
1577
|
-
class $
|
|
2605
|
+
class $1c83796b12dd4e49$export$b1ca982aa1e488c1 extends (0, $1clrS$pipecataiclientjs.Transport) {
|
|
1578
2606
|
constructor(opts = {}){
|
|
1579
2607
|
super();
|
|
1580
2608
|
this._botId = "";
|
|
@@ -1583,6 +2611,19 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1583
2611
|
this._selectedSpeaker = {};
|
|
1584
2612
|
this._currentAudioTrack = null;
|
|
1585
2613
|
this._audioQueue = [];
|
|
2614
|
+
// NOTE: deliberately not read live off `this._daily.localAudio()` /
|
|
2615
|
+
// `localVideo()` in the isMicEnabled/isCamEnabled getters below. Daily
|
|
2616
|
+
// fires 'track-started'/'track-stopped' *before* it commits the new state
|
|
2617
|
+
// to the participant object those calls read from (daily-js emits the
|
|
2618
|
+
// track event from within its participant-updated handling, then
|
|
2619
|
+
// reassigns its internal participant cache afterwards). Code that reacts
|
|
2620
|
+
// to TrackStarted/TrackStopped by reading isMicEnabled/isCamEnabled to
|
|
2621
|
+
// resync UI state — e.g. PipecatClientState's mic/cam sync — would
|
|
2622
|
+
// otherwise always observe the pre-toggle value. These fields are updated
|
|
2623
|
+
// synchronously in enableMic/enableCam and in handleTrackStarted/
|
|
2624
|
+
// handleTrackStopped, before those callbacks fire.
|
|
2625
|
+
this._micEnabled = true;
|
|
2626
|
+
this._camEnabled = false;
|
|
1586
2627
|
this._callbacks = {};
|
|
1587
2628
|
const { bufferLocalAudioUntilBotReady: bufferLocalAudioUntilBotReady, ...dailyOpts } = opts;
|
|
1588
2629
|
this._dailyFactoryOptions = dailyOpts;
|
|
@@ -1593,15 +2634,15 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1593
2634
|
this._dailyFactoryOptions.dailyConfig.useDevicePreferenceCookies = true;
|
|
1594
2635
|
}
|
|
1595
2636
|
this._bufferLocalAudioUntilBotReady = bufferLocalAudioUntilBotReady || false;
|
|
1596
|
-
this._daily = (0, ($parcel$interopDefault($
|
|
2637
|
+
this._daily = (0, ($parcel$interopDefault($1clrS$dailycodailyjs))).createCallObject({
|
|
1597
2638
|
...this._dailyFactoryOptions,
|
|
1598
2639
|
allowMultipleCallInstances: true
|
|
1599
2640
|
});
|
|
1600
|
-
this._dailyWrapper = new $
|
|
2641
|
+
this._dailyWrapper = new $1c83796b12dd4e49$var$DailyCallWrapper(this._daily);
|
|
1601
2642
|
}
|
|
1602
2643
|
setupRecorder() {
|
|
1603
|
-
this._mediaStreamRecorder = new (0, $
|
|
1604
|
-
sampleRate: $
|
|
2644
|
+
this._mediaStreamRecorder = new (0, $ab812aec7679ec67$export$2934cf2d25c67a48)({
|
|
2645
|
+
sampleRate: $1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_SAMPLE_RATE
|
|
1605
2646
|
});
|
|
1606
2647
|
}
|
|
1607
2648
|
handleUserAudioStream(data) {
|
|
@@ -1610,7 +2651,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1610
2651
|
flushAudioQueue() {
|
|
1611
2652
|
const batchSize = 10; // Number of buffers to send in one message
|
|
1612
2653
|
if (this._audioQueue.length === 0) return;
|
|
1613
|
-
(0, $
|
|
2654
|
+
(0, $1clrS$pipecataiclientjs.logger).debug(`Will flush audio queue: ${this._audioQueue.length}`);
|
|
1614
2655
|
while(this._audioQueue.length > 0){
|
|
1615
2656
|
const batch = [];
|
|
1616
2657
|
// Collect up to `batchSize` items
|
|
@@ -1632,7 +2673,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1632
2673
|
type: "raw-audio-batch",
|
|
1633
2674
|
data: {
|
|
1634
2675
|
base64AudioBatch: encodedBatch,
|
|
1635
|
-
sampleRate: $
|
|
2676
|
+
sampleRate: $1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_SAMPLE_RATE,
|
|
1636
2677
|
numChannels: 1
|
|
1637
2678
|
}
|
|
1638
2679
|
};
|
|
@@ -1646,9 +2687,11 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1646
2687
|
this._dailyFactoryOptions.startVideoOff = !(options.enableCam ?? false);
|
|
1647
2688
|
if (this._dailyFactoryOptions.startAudioOff == null || options.enableMic != null) // Default is mic on
|
|
1648
2689
|
this._dailyFactoryOptions.startAudioOff = !(options.enableMic ?? true);
|
|
2690
|
+
this._camEnabled = !this._dailyFactoryOptions.startVideoOff;
|
|
2691
|
+
this._micEnabled = !this._dailyFactoryOptions.startAudioOff;
|
|
1649
2692
|
this.attachEventListeners();
|
|
1650
2693
|
this.state = "disconnected";
|
|
1651
|
-
(0, $
|
|
2694
|
+
(0, $1clrS$pipecataiclientjs.logger).debug("[Daily Transport] Initialized", (0, (/*@__PURE__*/$parcel$interopDefault($48b67f1ef231aa26$exports))).version);
|
|
1652
2695
|
}
|
|
1653
2696
|
get dailyCallClient() {
|
|
1654
2697
|
return this._dailyWrapper.proxy;
|
|
@@ -1702,7 +2745,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1702
2745
|
}).then((infos)=>{
|
|
1703
2746
|
this._selectedSpeaker = infos.speaker;
|
|
1704
2747
|
}).catch((e)=>{
|
|
1705
|
-
this._callbacks.onDeviceError?.(new (0, $
|
|
2748
|
+
this._callbacks.onDeviceError?.(new (0, $1clrS$pipecataiclientjs.DeviceError)([
|
|
1706
2749
|
"speaker"
|
|
1707
2750
|
], e.type ?? "unknown", e.message));
|
|
1708
2751
|
});
|
|
@@ -1717,17 +2760,19 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1717
2760
|
// joined — pre-session, daily-js can't act on the request because the
|
|
1718
2761
|
// call object isn't part of a meeting yet.
|
|
1719
2762
|
this._dailyFactoryOptions.startAudioOff = !enable;
|
|
2763
|
+
this._micEnabled = enable;
|
|
1720
2764
|
if (this._daily.participants()?.local) this._daily.setLocalAudio(enable);
|
|
1721
2765
|
}
|
|
1722
2766
|
get isMicEnabled() {
|
|
1723
|
-
return this.
|
|
2767
|
+
return this._micEnabled;
|
|
1724
2768
|
}
|
|
1725
2769
|
enableCam(enable) {
|
|
1726
2770
|
this._dailyFactoryOptions.startVideoOff = !enable;
|
|
2771
|
+
this._camEnabled = enable;
|
|
1727
2772
|
if (this._daily.participants()?.local) this._daily.setLocalVideo(enable);
|
|
1728
2773
|
}
|
|
1729
2774
|
get isCamEnabled() {
|
|
1730
|
-
return this.
|
|
2775
|
+
return this._camEnabled;
|
|
1731
2776
|
}
|
|
1732
2777
|
enableScreenShare(enable) {
|
|
1733
2778
|
if (enable) this._daily.startScreenShare();
|
|
@@ -1736,6 +2781,15 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1736
2781
|
get isSharingScreen() {
|
|
1737
2782
|
return this._daily.localScreenAudio() || this._daily.localScreenVideo();
|
|
1738
2783
|
}
|
|
2784
|
+
/** Carries every kind of media; screen share where the browser can. */ get mediaSupport() {
|
|
2785
|
+
return {
|
|
2786
|
+
mic: true,
|
|
2787
|
+
cam: true,
|
|
2788
|
+
screenShare: (0, $15398512372f76d1$export$7f8f33b9b54c8307)(),
|
|
2789
|
+
botAudio: true,
|
|
2790
|
+
botVideo: true
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
1739
2793
|
tracks() {
|
|
1740
2794
|
const participants = this._daily.participants() ?? {};
|
|
1741
2795
|
const bot = participants?.[this._botId];
|
|
@@ -1755,15 +2809,15 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1755
2809
|
}
|
|
1756
2810
|
async startRecording() {
|
|
1757
2811
|
try {
|
|
1758
|
-
(0, $
|
|
2812
|
+
(0, $1clrS$pipecataiclientjs.logger).info("[Daily Transport] Initializing recording");
|
|
1759
2813
|
await this._mediaStreamRecorder.record((data)=>{
|
|
1760
2814
|
this.handleUserAudioStream(data.mono);
|
|
1761
|
-
}, $
|
|
2815
|
+
}, $1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_CHUNK_SIZE);
|
|
1762
2816
|
this._callbacks.onAudioBufferingStarted?.();
|
|
1763
|
-
(0, $
|
|
2817
|
+
(0, $1clrS$pipecataiclientjs.logger).info("[Daily Transport] Recording Initialized");
|
|
1764
2818
|
} catch (e) {
|
|
1765
2819
|
const err = e;
|
|
1766
|
-
if (!err.message.includes("Already recording")) (0, $
|
|
2820
|
+
if (!err.message.includes("Already recording")) (0, $1clrS$pipecataiclientjs.logger).error("Error starting recording", e);
|
|
1767
2821
|
}
|
|
1768
2822
|
}
|
|
1769
2823
|
async preAuth(dailyCallOptions) {
|
|
@@ -1771,7 +2825,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1771
2825
|
await this._daily.preAuth(dailyCallOptions);
|
|
1772
2826
|
}
|
|
1773
2827
|
async initDevices() {
|
|
1774
|
-
if (!this._daily) throw new (0, $
|
|
2828
|
+
if (!this._daily) throw new (0, $1clrS$pipecataiclientjs.RTVIError)("Transport instance not initialized");
|
|
1775
2829
|
this.state = "initializing";
|
|
1776
2830
|
const infos = await this._daily.startCamera(this._dailyFactoryOptions);
|
|
1777
2831
|
const { devices: devices } = await this._daily.enumerateDevices();
|
|
@@ -1787,14 +2841,20 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1787
2841
|
this._callbacks.onCamUpdated?.(infos.camera);
|
|
1788
2842
|
this._callbacks.onMicUpdated?.(infos.mic);
|
|
1789
2843
|
this._callbacks.onSpeakerUpdated?.(infos.speaker);
|
|
1790
|
-
|
|
1791
|
-
if (!this._daily.isLocalAudioLevelObserverRunning()) await this._daily.startLocalAudioLevelObserver(100);
|
|
1792
|
-
if (!this._daily.isRemoteParticipantsAudioLevelObserverRunning()) await this._daily.startRemoteParticipantsAudioLevelObserver(100);
|
|
2844
|
+
await this.startAudioLevelObservers();
|
|
1793
2845
|
this.state = "initialized";
|
|
1794
2846
|
}
|
|
2847
|
+
async startAudioLevelObservers() {
|
|
2848
|
+
try {
|
|
2849
|
+
if (!this._daily.isLocalAudioLevelObserverRunning()) await this._daily.startLocalAudioLevelObserver(100);
|
|
2850
|
+
if (!this._daily.isRemoteParticipantsAudioLevelObserverRunning()) await this._daily.startRemoteParticipantsAudioLevelObserver(100);
|
|
2851
|
+
} catch (e) {
|
|
2852
|
+
(0, $1clrS$pipecataiclientjs.logger).warn("[Daily Transport] Failed to start audio level observers", e);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
1795
2855
|
_validateConnectionParams(connectParams) {
|
|
1796
2856
|
if (connectParams === undefined || connectParams === null) return undefined;
|
|
1797
|
-
if (typeof connectParams !== "object") throw new (0, $
|
|
2857
|
+
if (typeof connectParams !== "object") throw new (0, $1clrS$pipecataiclientjs.RTVIError)("Invalid connection parameters");
|
|
1798
2858
|
const tmpParams = connectParams;
|
|
1799
2859
|
if (tmpParams.room_url) {
|
|
1800
2860
|
tmpParams.url = tmpParams.room_url;
|
|
@@ -1812,7 +2872,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1812
2872
|
return tmpParams;
|
|
1813
2873
|
}
|
|
1814
2874
|
async _connect(connectParams) {
|
|
1815
|
-
if (!this._daily) throw new (0, $
|
|
2875
|
+
if (!this._daily) throw new (0, $1clrS$pipecataiclientjs.RTVIError)("Transport instance not initialized");
|
|
1816
2876
|
if (connectParams) this._dailyFactoryOptions = {
|
|
1817
2877
|
...this._dailyFactoryOptions,
|
|
1818
2878
|
...connectParams
|
|
@@ -1821,11 +2881,17 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1821
2881
|
try {
|
|
1822
2882
|
await this._daily.join(this._dailyFactoryOptions);
|
|
1823
2883
|
} catch (e) {
|
|
1824
|
-
(0, $
|
|
2884
|
+
(0, $1clrS$pipecataiclientjs.logger).error("Failed to join room", e);
|
|
1825
2885
|
this.state = "error";
|
|
1826
|
-
throw new (0, $
|
|
2886
|
+
throw new (0, $1clrS$pipecataiclientjs.TransportStartError)();
|
|
1827
2887
|
}
|
|
1828
2888
|
if (this._abortController?.signal.aborted) return;
|
|
2889
|
+
// initDevices() is not guaranteed to have run before we get here:
|
|
2890
|
+
// PipecatClient skips it when both mic and cam start disabled, and on a
|
|
2891
|
+
// reconnect once devices are already initialized. _disconnect() stops
|
|
2892
|
+
// the observers, so make sure they are running for this session or
|
|
2893
|
+
// onLocalAudioLevel / onRemoteAudioLevel never fire.
|
|
2894
|
+
await this.startAudioLevelObservers();
|
|
1829
2895
|
const r = await this._daily.room();
|
|
1830
2896
|
this._maxMessageSize = r?.domainConfig?.max_app_message_size || 10485760;
|
|
1831
2897
|
this.state = "connected";
|
|
@@ -1844,7 +2910,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1844
2910
|
// we've received the bot_ready signal
|
|
1845
2911
|
this.state = "ready";
|
|
1846
2912
|
this.flushAudioQueue();
|
|
1847
|
-
this.sendMessage((0, $
|
|
2913
|
+
this.sendMessage((0, $1clrS$pipecataiclientjs.RTVIMessage).clientReady());
|
|
1848
2914
|
this.stopRecording();
|
|
1849
2915
|
resolve();
|
|
1850
2916
|
};
|
|
@@ -1862,7 +2928,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1862
2928
|
this._daily.off("track-started", readyHandler);
|
|
1863
2929
|
// Check if it's an iOS device
|
|
1864
2930
|
if (isIOS()) {
|
|
1865
|
-
(0, $
|
|
2931
|
+
(0, $1clrS$pipecataiclientjs.logger).debug("[Daily Transport] iOS device detected, adding 0.5 second delay before sending ready message");
|
|
1866
2932
|
// Add 500ms delay for iOS devices:
|
|
1867
2933
|
// This is a workaround for iOS devices clipping a portion
|
|
1868
2934
|
// of the audio after the track becomes playable.
|
|
@@ -1909,7 +2975,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1909
2975
|
try {
|
|
1910
2976
|
this._daily.sendAppMessage(message, "*");
|
|
1911
2977
|
} catch (error) {
|
|
1912
|
-
if (error instanceof Error && error.message.includes("Message data too large")) throw new (0, $
|
|
2978
|
+
if (error instanceof Error && error.message.includes("Message data too large")) throw new (0, $1clrS$pipecataiclientjs.MessageTooLargeError)(error.message);
|
|
1913
2979
|
throw error;
|
|
1914
2980
|
}
|
|
1915
2981
|
}
|
|
@@ -1948,40 +3014,51 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1948
3014
|
error.blockedMedia.forEach((d)=>{
|
|
1949
3015
|
devices.push(d === "video" ? "cam" : "mic");
|
|
1950
3016
|
});
|
|
1951
|
-
return new (0, $
|
|
3017
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1952
3018
|
blockedBy: error.blockedBy
|
|
1953
3019
|
});
|
|
1954
3020
|
case "not-found":
|
|
1955
3021
|
error.missingMedia.forEach((d)=>{
|
|
1956
3022
|
devices.push(d === "video" ? "cam" : "mic");
|
|
1957
3023
|
});
|
|
1958
|
-
return new (0, $
|
|
3024
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1959
3025
|
case "constraints":
|
|
1960
3026
|
error.failedMedia.forEach((d)=>{
|
|
1961
3027
|
devices.push(d === "video" ? "cam" : "mic");
|
|
1962
3028
|
});
|
|
1963
|
-
return new (0, $
|
|
3029
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1964
3030
|
reason: error.reason
|
|
1965
3031
|
});
|
|
1966
3032
|
case "cam-in-use":
|
|
1967
3033
|
devices.push("cam");
|
|
1968
|
-
return new (0, $
|
|
3034
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1969
3035
|
case "mic-in-use":
|
|
1970
3036
|
devices.push("mic");
|
|
1971
|
-
return new (0, $
|
|
3037
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1972
3038
|
case "cam-mic-in-use":
|
|
1973
3039
|
devices.push("cam");
|
|
1974
3040
|
devices.push("mic");
|
|
1975
|
-
return new (0, $
|
|
3041
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1976
3042
|
case "undefined-mediadevices":
|
|
1977
3043
|
case "unknown":
|
|
1978
3044
|
default:
|
|
1979
3045
|
devices.push("cam");
|
|
1980
3046
|
devices.push("mic");
|
|
1981
|
-
return new (0, $
|
|
3047
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1982
3048
|
}
|
|
1983
3049
|
};
|
|
1984
|
-
|
|
3050
|
+
const deviceError = generateDeviceError(ev.error);
|
|
3051
|
+
// enableMic()/enableCam() set _micEnabled/_camEnabled optimistically,
|
|
3052
|
+
// but setLocalAudio()/setLocalVideo() are fire-and-forget — no promise,
|
|
3053
|
+
// no synchronous failure signal — so a failed request (blocked
|
|
3054
|
+
// permission, device in use, etc.) leaves that optimistic value wrong
|
|
3055
|
+
// with nothing to correct it: no track-started/stopped ever fires for
|
|
3056
|
+
// an operation that didn't actually take effect. This is the only
|
|
3057
|
+
// signal we get that the request failed, so resync from Daily's actual
|
|
3058
|
+
// state for whichever device(s) it implicates.
|
|
3059
|
+
if (deviceError.devices.includes("mic")) this._micEnabled = this._daily.localAudio();
|
|
3060
|
+
if (deviceError.devices.includes("cam")) this._camEnabled = this._daily.localVideo();
|
|
3061
|
+
this._callbacks.onDeviceError?.(deviceError);
|
|
1985
3062
|
}
|
|
1986
3063
|
async handleLocalAudioTrack(track) {
|
|
1987
3064
|
if (this.state == "ready" || !this._bufferLocalAudioUntilBotReady) return;
|
|
@@ -2007,31 +3084,42 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2007
3084
|
} catch (e) {
|
|
2008
3085
|
// void. nothing to do.
|
|
2009
3086
|
}
|
|
2010
|
-
else (0, $
|
|
3087
|
+
else (0, $1clrS$pipecataiclientjs.logger).warn("track-started event received for current track and already recording");
|
|
2011
3088
|
break;
|
|
2012
3089
|
}
|
|
2013
3090
|
this._currentAudioTrack = track;
|
|
2014
3091
|
}
|
|
2015
3092
|
handleTrackStarted(ev) {
|
|
2016
|
-
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStarted?.(ev.track, ev.participant ? $
|
|
3093
|
+
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStarted?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
2017
3094
|
else {
|
|
2018
|
-
if (ev.participant?.local
|
|
2019
|
-
|
|
3095
|
+
if (ev.participant?.local) {
|
|
3096
|
+
if (ev.track.kind === "audio") {
|
|
3097
|
+
this._micEnabled = true;
|
|
3098
|
+
this.handleLocalAudioTrack(ev.track);
|
|
3099
|
+
} else if (ev.track.kind === "video") this._camEnabled = true;
|
|
3100
|
+
}
|
|
3101
|
+
this._callbacks.onTrackStarted?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
2020
3102
|
}
|
|
2021
3103
|
}
|
|
2022
3104
|
handleTrackStopped(ev) {
|
|
2023
|
-
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStopped?.(ev.track, ev.participant ? $
|
|
2024
|
-
else
|
|
3105
|
+
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStopped?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
3106
|
+
else {
|
|
3107
|
+
if (ev.participant?.local) {
|
|
3108
|
+
if (ev.track.kind === "audio") this._micEnabled = false;
|
|
3109
|
+
else if (ev.track.kind === "video") this._camEnabled = false;
|
|
3110
|
+
}
|
|
3111
|
+
this._callbacks.onTrackStopped?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
3112
|
+
}
|
|
2025
3113
|
}
|
|
2026
3114
|
handleParticipantJoined(ev) {
|
|
2027
|
-
const p = $
|
|
3115
|
+
const p = $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant);
|
|
2028
3116
|
this._callbacks.onParticipantJoined?.(p);
|
|
2029
3117
|
if (p.local) return;
|
|
2030
3118
|
this._botId = ev.participant.session_id;
|
|
2031
3119
|
this._callbacks.onBotConnected?.(p);
|
|
2032
3120
|
}
|
|
2033
3121
|
handleParticipantLeft(ev) {
|
|
2034
|
-
const p = $
|
|
3122
|
+
const p = $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant);
|
|
2035
3123
|
this._callbacks.onParticipantLeft?.(p);
|
|
2036
3124
|
if (p.local) return;
|
|
2037
3125
|
this._botId = "";
|
|
@@ -2046,7 +3134,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2046
3134
|
for(let i = 0; i < ids.length; i++){
|
|
2047
3135
|
const id = ids[i];
|
|
2048
3136
|
const level = ev.participantsAudioLevel[id];
|
|
2049
|
-
this._callbacks.onRemoteAudioLevel?.(level, $
|
|
3137
|
+
this._callbacks.onRemoteAudioLevel?.(level, $1c83796b12dd4e49$var$dailyParticipantToParticipant(participants[id]));
|
|
2050
3138
|
}
|
|
2051
3139
|
}
|
|
2052
3140
|
handleLeftMeeting() {
|
|
@@ -2055,10 +3143,10 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2055
3143
|
this._callbacks.onDisconnected?.();
|
|
2056
3144
|
}
|
|
2057
3145
|
handleFatalError(ev) {
|
|
2058
|
-
(0, $
|
|
3146
|
+
(0, $1clrS$pipecataiclientjs.logger).error("Daily fatal error", ev.errorMsg);
|
|
2059
3147
|
this.state = "error";
|
|
2060
3148
|
this._botId = "";
|
|
2061
|
-
this._callbacks.onError?.((0, $
|
|
3149
|
+
this._callbacks.onError?.((0, $1clrS$pipecataiclientjs.RTVIMessage).error(ev.errorMsg, true));
|
|
2062
3150
|
}
|
|
2063
3151
|
handleNonFatalError(ev) {
|
|
2064
3152
|
switch(ev.type){
|
|
@@ -2068,16 +3156,16 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2068
3156
|
}
|
|
2069
3157
|
}
|
|
2070
3158
|
}
|
|
2071
|
-
$
|
|
2072
|
-
$
|
|
2073
|
-
const $
|
|
3159
|
+
$1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_SAMPLE_RATE = 16000;
|
|
3160
|
+
$1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_CHUNK_SIZE = 512;
|
|
3161
|
+
const $1c83796b12dd4e49$var$dailyParticipantToParticipant = (p)=>({
|
|
2074
3162
|
id: p.user_id,
|
|
2075
3163
|
local: p.local,
|
|
2076
3164
|
name: p.user_name
|
|
2077
3165
|
});
|
|
2078
3166
|
|
|
2079
3167
|
|
|
2080
|
-
$parcel$exportWildcard(module.exports, $
|
|
3168
|
+
$parcel$exportWildcard(module.exports, $1c83796b12dd4e49$exports);
|
|
2081
3169
|
|
|
2082
3170
|
|
|
2083
3171
|
//# sourceMappingURL=index.js.map
|