@pipecat-ai/daily-transport 1.6.7 → 1.6.9
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.map +1 -1
- package/dist/index.js +1097 -113
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +1097 -113
- package/dist/index.module.js.map +1 -1
- package/package.json +16 -3
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,10 +27,10 @@ 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
|
/**
|
|
@@ -43,7 +44,7 @@ $parcel$export($28bdeb35415d61e8$exports, "DailyTransport", () => $28bdeb35415d6
|
|
|
43
44
|
*/ /**
|
|
44
45
|
* Utility class for assembling PCM16 "audio/wav" data
|
|
45
46
|
* @class
|
|
46
|
-
*/ class $
|
|
47
|
+
*/ class $45766326c6faa3c4$export$13afda237b1c9846 {
|
|
47
48
|
/**
|
|
48
49
|
* Converts Float32Array of amplitude data to ArrayBuffer in Int16Array format
|
|
49
50
|
* @param {Float32Array} float32Array
|
|
@@ -131,7 +132,7 @@ $parcel$export($28bdeb35415d61e8$exports, "DailyTransport", () => $28bdeb35415d6
|
|
|
131
132
|
};
|
|
132
133
|
}
|
|
133
134
|
}
|
|
134
|
-
globalThis.WavPacker = $
|
|
135
|
+
globalThis.WavPacker = $45766326c6faa3c4$export$13afda237b1c9846;
|
|
135
136
|
|
|
136
137
|
|
|
137
138
|
/**
|
|
@@ -140,7 +141,7 @@ globalThis.WavPacker = $a61750b8fbee4dae$export$13afda237b1c9846;
|
|
|
140
141
|
* to human-interpretable ranges, notably music ranges and
|
|
141
142
|
* human vocal ranges.
|
|
142
143
|
*/ // Eighth octave frequencies
|
|
143
|
-
const $
|
|
144
|
+
const $550c0e438054ce18$var$octave8Frequencies = [
|
|
144
145
|
4186.01,
|
|
145
146
|
4434.92,
|
|
146
147
|
4698.63,
|
|
@@ -155,7 +156,7 @@ const $e10a9de47f58e137$var$octave8Frequencies = [
|
|
|
155
156
|
7902.13
|
|
156
157
|
];
|
|
157
158
|
// Labels for each of the above frequencies
|
|
158
|
-
const $
|
|
159
|
+
const $550c0e438054ce18$var$octave8FrequencyLabels = [
|
|
159
160
|
"C",
|
|
160
161
|
"C#",
|
|
161
162
|
"D",
|
|
@@ -169,29 +170,29 @@ const $e10a9de47f58e137$var$octave8FrequencyLabels = [
|
|
|
169
170
|
"A#",
|
|
170
171
|
"B"
|
|
171
172
|
];
|
|
172
|
-
const $
|
|
173
|
-
const $
|
|
174
|
-
for(let i = 1; i <= 8; i++)for(let f = 0; f < $
|
|
175
|
-
const freq = $
|
|
176
|
-
$
|
|
177
|
-
$
|
|
173
|
+
const $550c0e438054ce18$export$776c63898ae5b636 = [];
|
|
174
|
+
const $550c0e438054ce18$export$facd167cc27ea9b0 = [];
|
|
175
|
+
for(let i = 1; i <= 8; i++)for(let f = 0; f < $550c0e438054ce18$var$octave8Frequencies.length; f++){
|
|
176
|
+
const freq = $550c0e438054ce18$var$octave8Frequencies[f];
|
|
177
|
+
$550c0e438054ce18$export$776c63898ae5b636.push(freq / Math.pow(2, 8 - i));
|
|
178
|
+
$550c0e438054ce18$export$facd167cc27ea9b0.push($550c0e438054ce18$var$octave8FrequencyLabels[f] + i);
|
|
178
179
|
}
|
|
179
180
|
/**
|
|
180
181
|
* Subset of the note frequencies between 32 and 2000 Hz
|
|
181
182
|
* 6 octave range: C1 to B6
|
|
182
|
-
*/ const $
|
|
183
|
+
*/ const $550c0e438054ce18$var$voiceFrequencyRange = [
|
|
183
184
|
32.0,
|
|
184
185
|
2000.0
|
|
185
186
|
];
|
|
186
|
-
const $
|
|
187
|
-
return $
|
|
187
|
+
const $550c0e438054ce18$export$dbc1581ed2cfa183 = $550c0e438054ce18$export$776c63898ae5b636.filter((_, i)=>{
|
|
188
|
+
return $550c0e438054ce18$export$776c63898ae5b636[i] > $550c0e438054ce18$var$voiceFrequencyRange[0] && $550c0e438054ce18$export$776c63898ae5b636[i] < $550c0e438054ce18$var$voiceFrequencyRange[1];
|
|
188
189
|
});
|
|
189
|
-
const $
|
|
190
|
-
return $
|
|
190
|
+
const $550c0e438054ce18$export$30a6f2881311088f = $550c0e438054ce18$export$facd167cc27ea9b0.filter((_, i)=>{
|
|
191
|
+
return $550c0e438054ce18$export$776c63898ae5b636[i] > $550c0e438054ce18$var$voiceFrequencyRange[0] && $550c0e438054ce18$export$776c63898ae5b636[i] < $550c0e438054ce18$var$voiceFrequencyRange[1];
|
|
191
192
|
});
|
|
192
193
|
|
|
193
194
|
|
|
194
|
-
class $
|
|
195
|
+
class $3f7a723e434a4b86$export$2c3136da0bf130f9 {
|
|
195
196
|
/**
|
|
196
197
|
* Retrieves frequency domain data from an AnalyserNode adjusted to a decibel range
|
|
197
198
|
* returns human-readable formatting and labels
|
|
@@ -213,7 +214,7 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
213
214
|
let frequencies;
|
|
214
215
|
let labels;
|
|
215
216
|
if (analysisType === "music" || analysisType === "voice") {
|
|
216
|
-
const useFrequencies = analysisType === "voice" ? (0, $
|
|
217
|
+
const useFrequencies = analysisType === "voice" ? (0, $550c0e438054ce18$export$dbc1581ed2cfa183) : (0, $550c0e438054ce18$export$776c63898ae5b636);
|
|
217
218
|
const aggregateOutput = Array(useFrequencies.length).fill(minDecibels);
|
|
218
219
|
for(let i = 0; i < fftResult.length; i++){
|
|
219
220
|
const frequency = i * frequencyStep;
|
|
@@ -224,8 +225,8 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
227
|
outputValues = aggregateOutput;
|
|
227
|
-
frequencies = analysisType === "voice" ? (0, $
|
|
228
|
-
labels = analysisType === "voice" ? (0, $
|
|
228
|
+
frequencies = analysisType === "voice" ? (0, $550c0e438054ce18$export$dbc1581ed2cfa183) : (0, $550c0e438054ce18$export$776c63898ae5b636);
|
|
229
|
+
labels = analysisType === "voice" ? (0, $550c0e438054ce18$export$30a6f2881311088f) : (0, $550c0e438054ce18$export$facd167cc27ea9b0);
|
|
229
230
|
} else {
|
|
230
231
|
outputValues = Array.from(fftResult);
|
|
231
232
|
frequencies = outputValues.map((_, i)=>frequencyStep * i);
|
|
@@ -318,7 +319,7 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
318
319
|
const index = Math.min(pct * this.fftResults.length | 0, this.fftResults.length - 1);
|
|
319
320
|
fftResult = this.fftResults[index];
|
|
320
321
|
}
|
|
321
|
-
return $
|
|
322
|
+
return $3f7a723e434a4b86$export$2c3136da0bf130f9.getFrequencies(this.analyser, this.sampleRate, fftResult, analysisType, minDecibels, maxDecibels);
|
|
322
323
|
}
|
|
323
324
|
/**
|
|
324
325
|
* Resume the internal AudioContext if it was suspended due to the lack of
|
|
@@ -329,10 +330,10 @@ class $5853841ab58516d4$export$2c3136da0bf130f9 {
|
|
|
329
330
|
return true;
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
|
-
globalThis.AudioAnalysis = $
|
|
333
|
+
globalThis.AudioAnalysis = $3f7a723e434a4b86$export$2c3136da0bf130f9;
|
|
333
334
|
|
|
334
335
|
|
|
335
|
-
const $
|
|
336
|
+
const $ff75ae50979bb4fc$export$50b76700e2b15e9 = `
|
|
336
337
|
class StreamProcessor extends AudioWorkletProcessor {
|
|
337
338
|
constructor() {
|
|
338
339
|
super();
|
|
@@ -422,23 +423,23 @@ class StreamProcessor extends AudioWorkletProcessor {
|
|
|
422
423
|
|
|
423
424
|
registerProcessor('stream_processor', StreamProcessor);
|
|
424
425
|
`;
|
|
425
|
-
const $
|
|
426
|
-
$
|
|
426
|
+
const $ff75ae50979bb4fc$var$script = new Blob([
|
|
427
|
+
$ff75ae50979bb4fc$export$50b76700e2b15e9
|
|
427
428
|
], {
|
|
428
429
|
type: "application/javascript"
|
|
429
430
|
});
|
|
430
|
-
const $
|
|
431
|
-
const $
|
|
431
|
+
const $ff75ae50979bb4fc$var$src = URL.createObjectURL($ff75ae50979bb4fc$var$script);
|
|
432
|
+
const $ff75ae50979bb4fc$export$bfa8c596114d74df = $ff75ae50979bb4fc$var$src;
|
|
432
433
|
|
|
433
434
|
|
|
434
435
|
|
|
435
|
-
class $
|
|
436
|
+
class $347522367945ce82$export$9698d62c78b8f366 {
|
|
436
437
|
/**
|
|
437
438
|
* Creates a new WavStreamPlayer instance
|
|
438
439
|
* @param {{sampleRate?: number}} options
|
|
439
440
|
* @returns {WavStreamPlayer}
|
|
440
441
|
*/ constructor({ sampleRate: sampleRate = 44100 } = {}){
|
|
441
|
-
this.scriptSrc = (0, $
|
|
442
|
+
this.scriptSrc = (0, $ff75ae50979bb4fc$export$bfa8c596114d74df);
|
|
442
443
|
this.sampleRate = sampleRate;
|
|
443
444
|
this.context = null;
|
|
444
445
|
this.stream = null;
|
|
@@ -475,7 +476,7 @@ class $1e7ce9484a3c4077$export$9698d62c78b8f366 {
|
|
|
475
476
|
* @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}
|
|
476
477
|
*/ getFrequencies(analysisType = "frequency", minDecibels = -100, maxDecibels = -30) {
|
|
477
478
|
if (!this.analyser) throw new Error("Not connected, please call .connect() first");
|
|
478
|
-
return (0, $
|
|
479
|
+
return (0, $3f7a723e434a4b86$export$2c3136da0bf130f9).getFrequencies(this.analyser, this.sampleRate, null, analysisType, minDecibels, maxDecibels);
|
|
479
480
|
}
|
|
480
481
|
/**
|
|
481
482
|
* @param {string} speaker deviceId
|
|
@@ -566,10 +567,10 @@ class $1e7ce9484a3c4077$export$9698d62c78b8f366 {
|
|
|
566
567
|
return this.getTrackSampleOffset(true);
|
|
567
568
|
}
|
|
568
569
|
}
|
|
569
|
-
globalThis.WavStreamPlayer = $
|
|
570
|
+
globalThis.WavStreamPlayer = $347522367945ce82$export$9698d62c78b8f366;
|
|
570
571
|
|
|
571
572
|
|
|
572
|
-
const $
|
|
573
|
+
const $5a5c5ac16a3be24c$var$AudioProcessorWorklet = `
|
|
573
574
|
class AudioProcessor extends AudioWorkletProcessor {
|
|
574
575
|
|
|
575
576
|
constructor() {
|
|
@@ -777,25 +778,25 @@ class AudioProcessor extends AudioWorkletProcessor {
|
|
|
777
778
|
|
|
778
779
|
registerProcessor('audio_processor', AudioProcessor);
|
|
779
780
|
`;
|
|
780
|
-
const $
|
|
781
|
-
$
|
|
781
|
+
const $5a5c5ac16a3be24c$var$script = new Blob([
|
|
782
|
+
$5a5c5ac16a3be24c$var$AudioProcessorWorklet
|
|
782
783
|
], {
|
|
783
784
|
type: "application/javascript"
|
|
784
785
|
});
|
|
785
|
-
const $
|
|
786
|
-
const $
|
|
786
|
+
const $5a5c5ac16a3be24c$var$src = URL.createObjectURL($5a5c5ac16a3be24c$var$script);
|
|
787
|
+
const $5a5c5ac16a3be24c$export$1f65f50a8cbff43c = $5a5c5ac16a3be24c$var$src;
|
|
787
788
|
|
|
788
789
|
|
|
789
790
|
|
|
790
791
|
|
|
791
|
-
class $
|
|
792
|
+
class $35ad6181fc724add$export$439b217ca659a877 {
|
|
792
793
|
/**
|
|
793
794
|
* Create a new WavRecorder instance
|
|
794
795
|
* @param {{sampleRate?: number, outputToSpeakers?: boolean, debug?: boolean}} [options]
|
|
795
796
|
* @returns {WavRecorder}
|
|
796
797
|
*/ constructor({ sampleRate: sampleRate = 44100, outputToSpeakers: outputToSpeakers = false, debug: debug = false } = {}){
|
|
797
798
|
// Script source
|
|
798
|
-
this.scriptSrc = (0, $
|
|
799
|
+
this.scriptSrc = (0, $5a5c5ac16a3be24c$export$1f65f50a8cbff43c);
|
|
799
800
|
// Config
|
|
800
801
|
this.sampleRate = sampleRate;
|
|
801
802
|
this.outputToSpeakers = outputToSpeakers;
|
|
@@ -858,7 +859,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
858
859
|
else throw new Error(`"audioData" must be one of: Blob, Float32Arrray, Int16Array, ArrayBuffer, Array<number>`);
|
|
859
860
|
if (fromSampleRate === -1) throw new Error(`Must specify "fromSampleRate" when reading from Float32Array, In16Array or Array`);
|
|
860
861
|
else if (fromSampleRate < 3000) throw new Error(`Minimum "fromSampleRate" is 3000 (3kHz)`);
|
|
861
|
-
if (!data) data = (0, $
|
|
862
|
+
if (!data) data = (0, $45766326c6faa3c4$export$13afda237b1c9846).floatTo16BitPCM(float32Array);
|
|
862
863
|
const audio = {
|
|
863
864
|
bitsPerSample: 16,
|
|
864
865
|
channels: [
|
|
@@ -866,7 +867,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
866
867
|
],
|
|
867
868
|
data: data
|
|
868
869
|
};
|
|
869
|
-
const packer = new (0, $
|
|
870
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
870
871
|
const result = packer.pack(fromSampleRate, audio);
|
|
871
872
|
blob = result.blob;
|
|
872
873
|
arrayBuffer = await blob.arrayBuffer();
|
|
@@ -1088,8 +1089,8 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1088
1089
|
if (this._chunkProcessorSize) {
|
|
1089
1090
|
const buffer = this._chunkProcessorBuffer;
|
|
1090
1091
|
this._chunkProcessorBuffer = {
|
|
1091
|
-
raw: (0, $
|
|
1092
|
-
mono: (0, $
|
|
1092
|
+
raw: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.raw, data.raw),
|
|
1093
|
+
mono: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.mono, data.mono)
|
|
1093
1094
|
};
|
|
1094
1095
|
if (this._chunkProcessorBuffer.mono.byteLength >= this._chunkProcessorSize) {
|
|
1095
1096
|
this._chunkProcessor(this._chunkProcessorBuffer);
|
|
@@ -1126,7 +1127,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1126
1127
|
* @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}
|
|
1127
1128
|
*/ getFrequencies(analysisType = "frequency", minDecibels = -100, maxDecibels = -30) {
|
|
1128
1129
|
if (!this.processor) throw new Error("Session ended: please call .begin() first");
|
|
1129
|
-
return (0, $
|
|
1130
|
+
return (0, $3f7a723e434a4b86$export$2c3136da0bf130f9).getFrequencies(this.analyser, this.sampleRate, null, analysisType, minDecibels, maxDecibels);
|
|
1130
1131
|
}
|
|
1131
1132
|
/**
|
|
1132
1133
|
* Pauses the recording
|
|
@@ -1143,7 +1144,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1143
1144
|
}
|
|
1144
1145
|
/**
|
|
1145
1146
|
* Start recording stream and storing to memory from the connected audio source
|
|
1146
|
-
* @param {(data: { mono:
|
|
1147
|
+
* @param {(data: { mono: ArrayBuffer; raw: ArrayBuffer }) => any} [chunkProcessor]
|
|
1147
1148
|
* @param {number} [chunkSize] chunkProcessor will not be triggered until this size threshold met in mono audio
|
|
1148
1149
|
* @returns {Promise<true>}
|
|
1149
1150
|
*/ async record(chunkProcessor = ()=>{}, chunkSize = 8192) {
|
|
@@ -1187,7 +1188,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1187
1188
|
if (!force && this.recording) throw new Error("Currently recording: please call .pause() first, or call .save(true) to force");
|
|
1188
1189
|
this.log("Exporting ...");
|
|
1189
1190
|
const exportData = await this._event("export");
|
|
1190
|
-
const packer = new (0, $
|
|
1191
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1191
1192
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1192
1193
|
return result;
|
|
1193
1194
|
}
|
|
@@ -1212,7 +1213,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1212
1213
|
this.processor = null;
|
|
1213
1214
|
this.source = null;
|
|
1214
1215
|
this.node = null;
|
|
1215
|
-
const packer = new (0, $
|
|
1216
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1216
1217
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1217
1218
|
return result;
|
|
1218
1219
|
}
|
|
@@ -1228,7 +1229,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1228
1229
|
return true;
|
|
1229
1230
|
}
|
|
1230
1231
|
}
|
|
1231
|
-
globalThis.WavRecorder = $
|
|
1232
|
+
globalThis.WavRecorder = $35ad6181fc724add$export$439b217ca659a877;
|
|
1232
1233
|
|
|
1233
1234
|
|
|
1234
1235
|
|
|
@@ -1240,7 +1241,7 @@ globalThis.WavRecorder = $0d471c38435bdab6$export$439b217ca659a877;
|
|
|
1240
1241
|
* @param {number} inputSampleRate - Sample rate of input audio
|
|
1241
1242
|
* @param {number} outputSampleRate - Desired output sample rate
|
|
1242
1243
|
* @returns {ArrayBuffer} - Resampled audio data as Int16 PCM
|
|
1243
|
-
*/ function $
|
|
1244
|
+
*/ function $ab812aec7679ec67$var$resampleAudioBuffer(inputBuffer, inputSampleRate, outputSampleRate) {
|
|
1244
1245
|
if (inputSampleRate === outputSampleRate) return inputBuffer;
|
|
1245
1246
|
const inputView = new Int16Array(inputBuffer);
|
|
1246
1247
|
const ratio = inputSampleRate / outputSampleRate;
|
|
@@ -1257,14 +1258,14 @@ globalThis.WavRecorder = $0d471c38435bdab6$export$439b217ca659a877;
|
|
|
1257
1258
|
}
|
|
1258
1259
|
return outputBuffer;
|
|
1259
1260
|
}
|
|
1260
|
-
class $
|
|
1261
|
+
class $ab812aec7679ec67$export$2934cf2d25c67a48 {
|
|
1261
1262
|
/**
|
|
1262
1263
|
* Create a new MediaStreamRecorder instance
|
|
1263
1264
|
* @param {{sampleRate?: number, outputToSpeakers?: boolean, debug?: boolean}} [options]
|
|
1264
1265
|
* @returns {MediaStreamRecorder}
|
|
1265
1266
|
*/ constructor({ sampleRate: sampleRate = 44100, outputToSpeakers: outputToSpeakers = false, debug: debug = false } = {}){
|
|
1266
1267
|
// Script source
|
|
1267
|
-
this.scriptSrc = (0, $
|
|
1268
|
+
this.scriptSrc = (0, $5a5c5ac16a3be24c$export$1f65f50a8cbff43c);
|
|
1268
1269
|
// Config
|
|
1269
1270
|
this.sampleRate = sampleRate;
|
|
1270
1271
|
this.outputToSpeakers = outputToSpeakers;
|
|
@@ -1376,14 +1377,14 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1376
1377
|
// Resample chunk data from native sample rate to target sample rate
|
|
1377
1378
|
// (no-op if rates match, i.e. for non-Firefox browsers)
|
|
1378
1379
|
const resampledData = {
|
|
1379
|
-
raw: $
|
|
1380
|
-
mono: $
|
|
1380
|
+
raw: $ab812aec7679ec67$var$resampleAudioBuffer(data.raw, contextSampleRate, this.sampleRate),
|
|
1381
|
+
mono: $ab812aec7679ec67$var$resampleAudioBuffer(data.mono, contextSampleRate, this.sampleRate)
|
|
1381
1382
|
};
|
|
1382
1383
|
if (this._chunkProcessorSize) {
|
|
1383
1384
|
const buffer = this._chunkProcessorBuffer;
|
|
1384
1385
|
this._chunkProcessorBuffer = {
|
|
1385
|
-
raw: (0, $
|
|
1386
|
-
mono: (0, $
|
|
1386
|
+
raw: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.raw, resampledData.raw),
|
|
1387
|
+
mono: (0, $45766326c6faa3c4$export$13afda237b1c9846).mergeBuffers(buffer.mono, resampledData.mono)
|
|
1387
1388
|
};
|
|
1388
1389
|
if (this._chunkProcessorBuffer.mono.byteLength >= this._chunkProcessorSize) {
|
|
1389
1390
|
this._chunkProcessor(this._chunkProcessorBuffer);
|
|
@@ -1419,7 +1420,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1419
1420
|
* @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}
|
|
1420
1421
|
*/ getFrequencies(analysisType = "frequency", minDecibels = -100, maxDecibels = -30) {
|
|
1421
1422
|
if (!this.processor) throw new Error("Session ended: please call .begin() first");
|
|
1422
|
-
return (0, $
|
|
1423
|
+
return (0, $3f7a723e434a4b86$export$2c3136da0bf130f9).getFrequencies(this.analyser, this.sampleRate, null, analysisType, minDecibels, maxDecibels);
|
|
1423
1424
|
}
|
|
1424
1425
|
/**
|
|
1425
1426
|
* Pauses the recording
|
|
@@ -1436,7 +1437,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1436
1437
|
}
|
|
1437
1438
|
/**
|
|
1438
1439
|
* Start recording stream and storing to memory from the connected audio source
|
|
1439
|
-
* @param {(data: { mono:
|
|
1440
|
+
* @param {(data: { mono: ArrayBuffer; raw: ArrayBuffer }) => any} [chunkProcessor]
|
|
1440
1441
|
* @param {number} [chunkSize] chunkProcessor will not be triggered until this size threshold met in mono audio
|
|
1441
1442
|
* @returns {Promise<true>}
|
|
1442
1443
|
*/ async record(chunkProcessor = ()=>{}, chunkSize = 8192) {
|
|
@@ -1480,7 +1481,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1480
1481
|
if (!force && this.recording) throw new Error("Currently recording: please call .pause() first, or call .save(true) to force");
|
|
1481
1482
|
this.log("Exporting ...");
|
|
1482
1483
|
const exportData = await this._event("export");
|
|
1483
|
-
const packer = new (0, $
|
|
1484
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1484
1485
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1485
1486
|
return result;
|
|
1486
1487
|
}
|
|
@@ -1503,7 +1504,7 @@ class $7cef7a69bdf8f84d$export$2934cf2d25c67a48 {
|
|
|
1503
1504
|
this.processor = null;
|
|
1504
1505
|
this.source = null;
|
|
1505
1506
|
this.node = null;
|
|
1506
|
-
const packer = new (0, $
|
|
1507
|
+
const packer = new (0, $45766326c6faa3c4$export$13afda237b1c9846)();
|
|
1507
1508
|
const result = packer.pack(this.sampleRate, exportData.audio);
|
|
1508
1509
|
return result;
|
|
1509
1510
|
}
|
|
@@ -1522,16 +1523,960 @@ globalThis.WavRecorder = WavRecorder;
|
|
|
1522
1523
|
|
|
1523
1524
|
|
|
1524
1525
|
|
|
1525
|
-
|
|
1526
|
-
$
|
|
1526
|
+
|
|
1527
|
+
class $48faeb169c82673e$export$4a0c46dbbe2ddb67 {
|
|
1528
|
+
constructor(){
|
|
1529
|
+
this._callbacks = {};
|
|
1530
|
+
this._micEnabled = true;
|
|
1531
|
+
this._camEnabled = false;
|
|
1532
|
+
this._supportsScreenShare = false;
|
|
1533
|
+
}
|
|
1534
|
+
setUserAudioCallback(userAudioCallback) {
|
|
1535
|
+
this._userAudioCallback = userAudioCallback;
|
|
1536
|
+
}
|
|
1537
|
+
setClientOptions(options, override = false) {
|
|
1538
|
+
if (this._options && !override) return;
|
|
1539
|
+
this._options = options;
|
|
1540
|
+
this._callbacks = options.callbacks ?? {};
|
|
1541
|
+
this._micEnabled = options.enableMic ?? true;
|
|
1542
|
+
this._camEnabled = options.enableCam ?? false;
|
|
1543
|
+
}
|
|
1544
|
+
get supportsScreenShare() {
|
|
1545
|
+
return this._supportsScreenShare;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
class $48faeb169c82673e$export$45c5b9bfba2f6304 extends $48faeb169c82673e$export$4a0c46dbbe2ddb67 {
|
|
1549
|
+
constructor(recorderChunkSize, recorderSampleRate = 24000){
|
|
1550
|
+
super();
|
|
1551
|
+
this._initialized = false;
|
|
1552
|
+
this._recorderChunkSize = undefined;
|
|
1553
|
+
this._recorderChunkSize = recorderChunkSize;
|
|
1554
|
+
this._wavRecorder = new (0, $35ad6181fc724add$export$439b217ca659a877)({
|
|
1555
|
+
sampleRate: recorderSampleRate
|
|
1556
|
+
});
|
|
1557
|
+
this._wavStreamPlayer = new (0, $347522367945ce82$export$9698d62c78b8f366)({
|
|
1558
|
+
sampleRate: 24000
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
async initialize() {
|
|
1562
|
+
try {
|
|
1563
|
+
await this._wavRecorder.begin();
|
|
1564
|
+
} catch (error) {
|
|
1565
|
+
// void. swallow the error. we still want to set up
|
|
1566
|
+
// the listeners and the player.
|
|
1567
|
+
}
|
|
1568
|
+
this._wavRecorder.listenForDeviceChange(null);
|
|
1569
|
+
this._wavRecorder.listenForDeviceChange(this._handleAvailableDevicesUpdated.bind(this));
|
|
1570
|
+
this._wavRecorder.listenForDeviceErrors(null);
|
|
1571
|
+
this._wavRecorder.listenForDeviceErrors(this._handleDeviceError.bind(this));
|
|
1572
|
+
await this._wavStreamPlayer.connect();
|
|
1573
|
+
this._initialized = true;
|
|
1574
|
+
}
|
|
1575
|
+
async connect() {
|
|
1576
|
+
if (!this._initialized) await this.initialize();
|
|
1577
|
+
const isAlreadyRecording = this._wavRecorder.getStatus() == "recording";
|
|
1578
|
+
if (this._micEnabled && !isAlreadyRecording) await this._startRecording();
|
|
1579
|
+
if (this._camEnabled) console.warn("WavMediaManager does not support video input.");
|
|
1580
|
+
}
|
|
1581
|
+
async disconnect() {
|
|
1582
|
+
if (!this._initialized) return;
|
|
1583
|
+
await this._wavRecorder.end();
|
|
1584
|
+
await this._wavStreamPlayer.interrupt();
|
|
1585
|
+
this._initialized = false;
|
|
1586
|
+
}
|
|
1587
|
+
async userStartedSpeaking() {
|
|
1588
|
+
return this._wavStreamPlayer.interrupt();
|
|
1589
|
+
}
|
|
1590
|
+
bufferBotAudio(data, id) {
|
|
1591
|
+
return this._wavStreamPlayer.add16BitPCM(data, id);
|
|
1592
|
+
}
|
|
1593
|
+
getAllMics() {
|
|
1594
|
+
return this._wavRecorder.listDevices();
|
|
1595
|
+
}
|
|
1596
|
+
getAllCams() {
|
|
1597
|
+
// TODO: Video not supported yet
|
|
1598
|
+
return Promise.resolve([]);
|
|
1599
|
+
}
|
|
1600
|
+
getAllSpeakers() {
|
|
1601
|
+
// TODO: Implement speaker support
|
|
1602
|
+
return Promise.resolve([]);
|
|
1603
|
+
}
|
|
1604
|
+
async updateMic(micId) {
|
|
1605
|
+
const prevMic = this._wavRecorder.deviceSelection;
|
|
1606
|
+
if (this._wavRecorder.getStatus() !== "ended") await this._wavRecorder.end();
|
|
1607
|
+
try {
|
|
1608
|
+
await this._wavRecorder.begin(micId);
|
|
1609
|
+
if (this._micEnabled) await this._startRecording();
|
|
1610
|
+
const curMic = this._wavRecorder.deviceSelection;
|
|
1611
|
+
if (curMic && prevMic && prevMic.label !== curMic.label) this._callbacks.onMicUpdated?.(curMic);
|
|
1612
|
+
} catch (error) {
|
|
1613
|
+
// void. If begin() fails, it will have already logged and called
|
|
1614
|
+
// onDeviceError if necessary.
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
updateCam(camId) {
|
|
1618
|
+
// TODO: Video not supported yet
|
|
1619
|
+
}
|
|
1620
|
+
updateSpeaker(speakerId) {
|
|
1621
|
+
// TODO: Implement speaker support
|
|
1622
|
+
}
|
|
1623
|
+
get selectedMic() {
|
|
1624
|
+
return this._wavRecorder.deviceSelection ?? {};
|
|
1625
|
+
}
|
|
1626
|
+
get selectedCam() {
|
|
1627
|
+
// TODO: Video not supported yet
|
|
1628
|
+
return {};
|
|
1629
|
+
}
|
|
1630
|
+
get selectedSpeaker() {
|
|
1631
|
+
// TODO: Implement speaker support
|
|
1632
|
+
return {};
|
|
1633
|
+
}
|
|
1634
|
+
async enableMic(enable) {
|
|
1635
|
+
this._micEnabled = enable;
|
|
1636
|
+
if (!this._wavRecorder.stream) return;
|
|
1637
|
+
this._wavRecorder.stream.getAudioTracks().forEach((track)=>{
|
|
1638
|
+
track.enabled = enable;
|
|
1639
|
+
if (!enable) this._callbacks.onTrackStopped?.(track, $48faeb169c82673e$var$localParticipant());
|
|
1640
|
+
});
|
|
1641
|
+
if (enable) await this._startRecording();
|
|
1642
|
+
else await this._wavRecorder.pause();
|
|
1643
|
+
}
|
|
1644
|
+
enableCam(enable) {
|
|
1645
|
+
// TODO: Video not supported yet
|
|
1646
|
+
console.warn("WavMediaManager does not support video input.");
|
|
1647
|
+
}
|
|
1648
|
+
enableScreenShare(enable) {
|
|
1649
|
+
// TODO: Screensharing not supported yet
|
|
1650
|
+
console.warn("WavMediaManager does not support screen sharing.");
|
|
1651
|
+
}
|
|
1652
|
+
get isCamEnabled() {
|
|
1653
|
+
// TODO: Video not supported yet
|
|
1654
|
+
return false;
|
|
1655
|
+
}
|
|
1656
|
+
get isMicEnabled() {
|
|
1657
|
+
return this._micEnabled;
|
|
1658
|
+
}
|
|
1659
|
+
get isSharingScreen() {
|
|
1660
|
+
// TODO: Screensharing not supported yet
|
|
1661
|
+
return false;
|
|
1662
|
+
}
|
|
1663
|
+
tracks() {
|
|
1664
|
+
const tracks = this._wavRecorder.stream?.getTracks()[0];
|
|
1665
|
+
return {
|
|
1666
|
+
local: tracks ? {
|
|
1667
|
+
audio: tracks
|
|
1668
|
+
} : {}
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
async _startRecording() {
|
|
1672
|
+
await this._wavRecorder.record((data)=>{
|
|
1673
|
+
this._userAudioCallback?.(data.mono);
|
|
1674
|
+
}, this._recorderChunkSize);
|
|
1675
|
+
const track = this._wavRecorder.stream?.getAudioTracks()[0];
|
|
1676
|
+
if (track) this._callbacks.onTrackStarted?.(track, $48faeb169c82673e$var$localParticipant());
|
|
1677
|
+
}
|
|
1678
|
+
_handleAvailableDevicesUpdated(devices) {
|
|
1679
|
+
this._callbacks.onAvailableCamsUpdated?.(devices.filter((d)=>d.kind === "videoinput"));
|
|
1680
|
+
this._callbacks.onAvailableMicsUpdated?.(devices.filter((d)=>d.kind === "audioinput"));
|
|
1681
|
+
// if the current device went away or we're using the default and
|
|
1682
|
+
// the default changed, reset the mic.
|
|
1683
|
+
const defaultDevice = devices.find((d)=>d.deviceId === "default");
|
|
1684
|
+
const currentDevice = this._wavRecorder.deviceSelection;
|
|
1685
|
+
if (currentDevice && (!devices.some((d)=>d.deviceId === currentDevice.deviceId) || currentDevice.deviceId === "default" && currentDevice.label !== defaultDevice?.label)) this.updateMic("");
|
|
1686
|
+
}
|
|
1687
|
+
_handleDeviceError({ devices: devices, type: type, error: error }) {
|
|
1688
|
+
const deviceError = new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, type, error?.message, error ? {
|
|
1689
|
+
sourceError: error
|
|
1690
|
+
} : undefined);
|
|
1691
|
+
this._callbacks.onDeviceError?.(deviceError);
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
const $48faeb169c82673e$var$localParticipant = ()=>{
|
|
1695
|
+
return {
|
|
1696
|
+
id: "local",
|
|
1697
|
+
name: "",
|
|
1698
|
+
local: true
|
|
1699
|
+
};
|
|
1700
|
+
};
|
|
1701
|
+
|
|
1702
|
+
|
|
1527
1703
|
|
|
1528
1704
|
|
|
1529
|
-
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
class $00a190ef6aa79f0d$export$c95c65abc5f47125 extends (0, $48faeb169c82673e$export$4a0c46dbbe2ddb67) {
|
|
1708
|
+
constructor(enablePlayer = true, enableRecording = true, onTrackStartedCallback, onTrackStoppedCallback, recorderChunkSize, recorderSampleRate = 24000, playerSampleRate = 24000){
|
|
1709
|
+
super();
|
|
1710
|
+
this._selectedCam = {};
|
|
1711
|
+
this._selectedMic = {};
|
|
1712
|
+
this._selectedSpeaker = {};
|
|
1713
|
+
this._remoteAudioLevelInterval = null;
|
|
1714
|
+
this._recorderChunkSize = undefined;
|
|
1715
|
+
this._initialized = false;
|
|
1716
|
+
this._connected = false;
|
|
1717
|
+
this._currentAudioTrack = null;
|
|
1718
|
+
this._connectResolve = null;
|
|
1719
|
+
this.onTrackStartedCallback = onTrackStartedCallback;
|
|
1720
|
+
this.onTrackStoppedCallback = onTrackStoppedCallback;
|
|
1721
|
+
this._recorderChunkSize = recorderChunkSize;
|
|
1722
|
+
this._supportsScreenShare = true;
|
|
1723
|
+
this._daily = (0, ($parcel$interopDefault($1clrS$dailycodailyjs))).getCallInstance() ?? (0, ($parcel$interopDefault($1clrS$dailycodailyjs))).createCallObject();
|
|
1724
|
+
if (enableRecording) this._mediaStreamRecorder = new (0, $ab812aec7679ec67$export$2934cf2d25c67a48)({
|
|
1725
|
+
sampleRate: recorderSampleRate
|
|
1726
|
+
});
|
|
1727
|
+
if (enablePlayer) this._wavStreamPlayer = new (0, $347522367945ce82$export$9698d62c78b8f366)({
|
|
1728
|
+
sampleRate: playerSampleRate
|
|
1729
|
+
});
|
|
1730
|
+
this._daily.on("track-started", this.handleTrackStarted.bind(this));
|
|
1731
|
+
this._daily.on("track-stopped", this.handleTrackStopped.bind(this));
|
|
1732
|
+
this._daily.on("available-devices-updated", this._handleAvailableDevicesUpdated.bind(this));
|
|
1733
|
+
this._daily.on("selected-devices-updated", this._handleSelectedDevicesUpdated.bind(this));
|
|
1734
|
+
this._daily.on("camera-error", this.handleDeviceError.bind(this));
|
|
1735
|
+
this._daily.on("local-audio-level", this._handleLocalAudioLevel.bind(this));
|
|
1736
|
+
}
|
|
1737
|
+
async initialize() {
|
|
1738
|
+
if (this._initialized) {
|
|
1739
|
+
console.warn("DailyMediaManager already initialized");
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
const infos = await this._daily.startCamera({
|
|
1743
|
+
startVideoOff: !this._camEnabled,
|
|
1744
|
+
startAudioOff: !this._micEnabled,
|
|
1745
|
+
dailyConfig: {
|
|
1746
|
+
useDevicePreferenceCookies: true
|
|
1747
|
+
}
|
|
1748
|
+
});
|
|
1749
|
+
const { devices: devices } = await this._daily.enumerateDevices();
|
|
1750
|
+
const cams = devices.filter((d)=>d.kind === "videoinput");
|
|
1751
|
+
const mics = devices.filter((d)=>d.kind === "audioinput");
|
|
1752
|
+
const speakers = devices.filter((d)=>d.kind === "audiooutput");
|
|
1753
|
+
this._callbacks.onAvailableCamsUpdated?.(cams);
|
|
1754
|
+
this._callbacks.onAvailableMicsUpdated?.(mics);
|
|
1755
|
+
this._callbacks.onAvailableSpeakersUpdated?.(speakers);
|
|
1756
|
+
this._selectedCam = infos.camera;
|
|
1757
|
+
this._callbacks.onCamUpdated?.(infos.camera);
|
|
1758
|
+
this._selectedMic = infos.mic;
|
|
1759
|
+
this._callbacks.onMicUpdated?.(infos.mic);
|
|
1760
|
+
this._selectedSpeaker = infos.speaker;
|
|
1761
|
+
this._callbacks.onSpeakerUpdated?.(infos.speaker);
|
|
1762
|
+
// Instantiate audio observers
|
|
1763
|
+
if (!this._daily.isLocalAudioLevelObserverRunning()) await this._daily.startLocalAudioLevelObserver(100);
|
|
1764
|
+
if (this._wavStreamPlayer) {
|
|
1765
|
+
await this._wavStreamPlayer.connect();
|
|
1766
|
+
if (!this._remoteAudioLevelInterval) this._remoteAudioLevelInterval = setInterval(()=>{
|
|
1767
|
+
const frequencies = this._wavStreamPlayer.getFrequencies();
|
|
1768
|
+
let aveVal = 0;
|
|
1769
|
+
if (frequencies.values?.length) aveVal = frequencies.values.reduce((a, c)=>a + c, 0) / frequencies.values.length;
|
|
1770
|
+
this._handleRemoteAudioLevel(aveVal);
|
|
1771
|
+
}, 100);
|
|
1772
|
+
}
|
|
1773
|
+
this._initialized = true;
|
|
1774
|
+
}
|
|
1775
|
+
async connect() {
|
|
1776
|
+
if (this._connected) {
|
|
1777
|
+
console.warn("DailyMediaManager already connected");
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
this._connected = true;
|
|
1781
|
+
if (!this._initialized) return new Promise((resolve)=>{
|
|
1782
|
+
(async ()=>{
|
|
1783
|
+
this._connectResolve = resolve;
|
|
1784
|
+
await this.initialize();
|
|
1785
|
+
// Without a recorder, handleTrackStarted never fires to resolve this
|
|
1786
|
+
// promise, so resolve here once initialization is complete.
|
|
1787
|
+
if (this._connectResolve && !this._mediaStreamRecorder) {
|
|
1788
|
+
this._connectResolve();
|
|
1789
|
+
this._connectResolve = null;
|
|
1790
|
+
}
|
|
1791
|
+
})();
|
|
1792
|
+
});
|
|
1793
|
+
if (this._micEnabled) this._startRecording();
|
|
1794
|
+
}
|
|
1795
|
+
async disconnect() {
|
|
1796
|
+
if (this._remoteAudioLevelInterval) clearInterval(this._remoteAudioLevelInterval);
|
|
1797
|
+
this._remoteAudioLevelInterval = null;
|
|
1798
|
+
this._daily.leave();
|
|
1799
|
+
this._currentAudioTrack = null;
|
|
1800
|
+
await this._mediaStreamRecorder?.end();
|
|
1801
|
+
this._wavStreamPlayer?.interrupt();
|
|
1802
|
+
this._initialized = false;
|
|
1803
|
+
this._connected = false;
|
|
1804
|
+
}
|
|
1805
|
+
async userStartedSpeaking() {
|
|
1806
|
+
return this._wavStreamPlayer?.interrupt();
|
|
1807
|
+
}
|
|
1808
|
+
bufferBotAudio(data, id) {
|
|
1809
|
+
return this._wavStreamPlayer?.add16BitPCM(data, id);
|
|
1810
|
+
}
|
|
1811
|
+
async getAllMics() {
|
|
1812
|
+
let devices = (await this._daily.enumerateDevices()).devices;
|
|
1813
|
+
return devices.filter((device)=>device.kind === "audioinput");
|
|
1814
|
+
}
|
|
1815
|
+
async getAllCams() {
|
|
1816
|
+
let devices = (await this._daily.enumerateDevices()).devices;
|
|
1817
|
+
return devices.filter((device)=>device.kind === "videoinput");
|
|
1818
|
+
}
|
|
1819
|
+
async getAllSpeakers() {
|
|
1820
|
+
let devices = (await this._daily.enumerateDevices()).devices;
|
|
1821
|
+
return devices.filter((device)=>device.kind === "audiooutput");
|
|
1822
|
+
}
|
|
1823
|
+
updateMic(micId) {
|
|
1824
|
+
this._daily.setInputDevicesAsync({
|
|
1825
|
+
audioDeviceId: micId
|
|
1826
|
+
}).then((deviceInfo)=>{
|
|
1827
|
+
this._selectedMic = deviceInfo.mic;
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
updateCam(camId) {
|
|
1831
|
+
this._daily.setInputDevicesAsync({
|
|
1832
|
+
videoDeviceId: camId
|
|
1833
|
+
}).then((deviceInfo)=>{
|
|
1834
|
+
this._selectedCam = deviceInfo.camera;
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
async updateSpeaker(speakerId) {
|
|
1838
|
+
if (!this._wavStreamPlayer) {
|
|
1839
|
+
try {
|
|
1840
|
+
const dInfo = await this._daily.setOutputDeviceAsync({
|
|
1841
|
+
outputDeviceId: speakerId
|
|
1842
|
+
});
|
|
1843
|
+
this._selectedSpeaker = dInfo.speaker;
|
|
1844
|
+
this._callbacks.onSpeakerUpdated?.(this._selectedSpeaker);
|
|
1845
|
+
} catch (e) {
|
|
1846
|
+
console.error("Error setting output device", e);
|
|
1847
|
+
}
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
if (speakerId !== "default" && this._selectedSpeaker.deviceId === speakerId) return;
|
|
1851
|
+
let sID = speakerId;
|
|
1852
|
+
if (sID === "default") {
|
|
1853
|
+
const speakers = await this.getAllSpeakers();
|
|
1854
|
+
const defaultSpeaker = speakers.find((s)=>s.deviceId === "default");
|
|
1855
|
+
if (!defaultSpeaker) {
|
|
1856
|
+
console.warn("No default speaker found");
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
speakers.splice(speakers.indexOf(defaultSpeaker), 1);
|
|
1860
|
+
const defaultSpeakerCp = speakers.find((s)=>defaultSpeaker.label.includes(s.label));
|
|
1861
|
+
sID = defaultSpeakerCp?.deviceId ?? speakerId;
|
|
1862
|
+
}
|
|
1863
|
+
this._wavStreamPlayer?.updateSpeaker(sID).then(()=>{
|
|
1864
|
+
this._selectedSpeaker = {
|
|
1865
|
+
deviceId: speakerId
|
|
1866
|
+
};
|
|
1867
|
+
this._callbacks.onSpeakerUpdated?.(this._selectedSpeaker);
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
get selectedMic() {
|
|
1871
|
+
return this._selectedMic;
|
|
1872
|
+
}
|
|
1873
|
+
get selectedCam() {
|
|
1874
|
+
return this._selectedCam;
|
|
1875
|
+
}
|
|
1876
|
+
get selectedSpeaker() {
|
|
1877
|
+
return this._selectedSpeaker;
|
|
1878
|
+
}
|
|
1879
|
+
async enableMic(enable) {
|
|
1880
|
+
this._micEnabled = enable;
|
|
1881
|
+
if (!this._daily.participants()?.local) return;
|
|
1882
|
+
this._daily.setLocalAudio(enable);
|
|
1883
|
+
if (this._mediaStreamRecorder) {
|
|
1884
|
+
if (enable) {
|
|
1885
|
+
if (this._mediaStreamRecorder.getStatus() === "paused") this._startRecording();
|
|
1886
|
+
// else, we'll record on the track-started event
|
|
1887
|
+
} else if (this._mediaStreamRecorder.getStatus() === "recording") this._mediaStreamRecorder.pause();
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
enableCam(enable) {
|
|
1891
|
+
this._camEnabled = enable;
|
|
1892
|
+
this._daily.setLocalVideo(enable);
|
|
1893
|
+
}
|
|
1894
|
+
enableScreenShare(enable) {
|
|
1895
|
+
if (enable) this._daily.startScreenShare();
|
|
1896
|
+
else this._daily.stopScreenShare();
|
|
1897
|
+
}
|
|
1898
|
+
// NOTE: deliberately not `this._daily.localVideo()` / `localAudio()`. Daily
|
|
1899
|
+
// fires 'track-started'/'track-stopped' *before* it commits the new state
|
|
1900
|
+
// to the participant object those getters read from (see daily-js's
|
|
1901
|
+
// DAILY_EVENT_PARTICIPANT_UPDATED handling: maybeEventTrackStopped/Started
|
|
1902
|
+
// run, then `this._participants[id]` is reassigned). Callers that react to
|
|
1903
|
+
// TrackStarted/TrackStopped by reading isCamEnabled/isMicEnabled — e.g. to
|
|
1904
|
+
// resync UI state — would otherwise always observe the pre-toggle value.
|
|
1905
|
+
// _camEnabled/_micEnabled are updated synchronously in
|
|
1906
|
+
// handleTrackStarted/handleTrackStopped below, before those callbacks fire.
|
|
1907
|
+
get isCamEnabled() {
|
|
1908
|
+
return this._camEnabled;
|
|
1909
|
+
}
|
|
1910
|
+
get isMicEnabled() {
|
|
1911
|
+
return this._micEnabled;
|
|
1912
|
+
}
|
|
1913
|
+
get isSharingScreen() {
|
|
1914
|
+
return this._daily.localScreenAudio() || this._daily.localScreenVideo();
|
|
1915
|
+
}
|
|
1916
|
+
tracks() {
|
|
1917
|
+
const participants = this._daily.participants();
|
|
1918
|
+
return {
|
|
1919
|
+
local: {
|
|
1920
|
+
audio: participants?.local?.tracks?.audio?.persistentTrack,
|
|
1921
|
+
screenAudio: participants?.local?.tracks?.screenAudio?.persistentTrack,
|
|
1922
|
+
screenVideo: participants?.local?.tracks?.screenVideo?.persistentTrack,
|
|
1923
|
+
video: participants?.local?.tracks?.video?.persistentTrack
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
}
|
|
1927
|
+
_startRecording() {
|
|
1928
|
+
if (!this._connected || !this._mediaStreamRecorder) return;
|
|
1929
|
+
try {
|
|
1930
|
+
this._mediaStreamRecorder.record((data)=>{
|
|
1931
|
+
this._userAudioCallback(data.mono);
|
|
1932
|
+
}, this._recorderChunkSize);
|
|
1933
|
+
} catch (e) {
|
|
1934
|
+
const err = e;
|
|
1935
|
+
if (!err.message.includes("Already recording")) console.error("Error starting recording", e);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
_handleAvailableDevicesUpdated(event) {
|
|
1939
|
+
this._callbacks.onAvailableCamsUpdated?.(event.availableDevices.filter((d)=>d.kind === "videoinput"));
|
|
1940
|
+
this._callbacks.onAvailableMicsUpdated?.(event.availableDevices.filter((d)=>d.kind === "audioinput"));
|
|
1941
|
+
this._callbacks.onAvailableSpeakersUpdated?.(event.availableDevices.filter((d)=>d.kind === "audiooutput"));
|
|
1942
|
+
if (this._selectedSpeaker.deviceId === "default") this.updateSpeaker("default");
|
|
1943
|
+
}
|
|
1944
|
+
_handleSelectedDevicesUpdated(event) {
|
|
1945
|
+
if (this._selectedCam?.deviceId !== event.devices.camera) {
|
|
1946
|
+
this._selectedCam = event.devices.camera;
|
|
1947
|
+
this._callbacks.onCamUpdated?.(event.devices.camera);
|
|
1948
|
+
}
|
|
1949
|
+
if (this._selectedMic?.deviceId !== event.devices.mic) {
|
|
1950
|
+
this._selectedMic = event.devices.mic;
|
|
1951
|
+
this._callbacks.onMicUpdated?.(event.devices.mic);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
handleDeviceError(ev) {
|
|
1955
|
+
const generateDeviceError = (error)=>{
|
|
1956
|
+
const devices = [];
|
|
1957
|
+
switch(error.type){
|
|
1958
|
+
case "permissions":
|
|
1959
|
+
error.blockedMedia.forEach((d)=>{
|
|
1960
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1961
|
+
});
|
|
1962
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1963
|
+
blockedBy: error.blockedBy
|
|
1964
|
+
});
|
|
1965
|
+
case "not-found":
|
|
1966
|
+
error.missingMedia.forEach((d)=>{
|
|
1967
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1968
|
+
});
|
|
1969
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1970
|
+
case "constraints":
|
|
1971
|
+
error.failedMedia.forEach((d)=>{
|
|
1972
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1973
|
+
});
|
|
1974
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1975
|
+
reason: error.reason
|
|
1976
|
+
});
|
|
1977
|
+
case "cam-in-use":
|
|
1978
|
+
devices.push("cam");
|
|
1979
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1980
|
+
case "mic-in-use":
|
|
1981
|
+
devices.push("mic");
|
|
1982
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1983
|
+
case "cam-mic-in-use":
|
|
1984
|
+
devices.push("cam");
|
|
1985
|
+
devices.push("mic");
|
|
1986
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1987
|
+
case "undefined-mediadevices":
|
|
1988
|
+
case "unknown":
|
|
1989
|
+
default:
|
|
1990
|
+
devices.push("cam");
|
|
1991
|
+
devices.push("mic");
|
|
1992
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
const deviceError = generateDeviceError(ev.error);
|
|
1996
|
+
// enableMic()/enableCam() set _micEnabled/_camEnabled optimistically,
|
|
1997
|
+
// but setLocalAudio()/setLocalVideo() are fire-and-forget — no promise,
|
|
1998
|
+
// no synchronous failure signal — so a failed request (blocked
|
|
1999
|
+
// permission, device in use, etc.) leaves that optimistic value wrong
|
|
2000
|
+
// with nothing to correct it: no track-started/stopped ever fires for
|
|
2001
|
+
// an operation that didn't actually take effect. This is the only
|
|
2002
|
+
// signal we get that the request failed, so resync from Daily's actual
|
|
2003
|
+
// state for whichever device(s) it implicates.
|
|
2004
|
+
if (deviceError.devices.includes("mic")) this._micEnabled = this._daily.localAudio();
|
|
2005
|
+
if (deviceError.devices.includes("cam")) this._camEnabled = this._daily.localVideo();
|
|
2006
|
+
this._callbacks.onDeviceError?.(deviceError);
|
|
2007
|
+
}
|
|
2008
|
+
_handleLocalAudioLevel(ev) {
|
|
2009
|
+
this._callbacks.onLocalAudioLevel?.(ev.audioLevel);
|
|
2010
|
+
}
|
|
2011
|
+
_handleRemoteAudioLevel(audioLevel) {
|
|
2012
|
+
this._callbacks.onRemoteAudioLevel?.(audioLevel, $00a190ef6aa79f0d$var$botParticipant());
|
|
2013
|
+
}
|
|
2014
|
+
async handleTrackStarted(event) {
|
|
2015
|
+
if (!event.participant?.local) return;
|
|
2016
|
+
if (event.track.kind === "audio") {
|
|
2017
|
+
this._micEnabled = true;
|
|
2018
|
+
if (this._mediaStreamRecorder) {
|
|
2019
|
+
const status = this._mediaStreamRecorder.getStatus();
|
|
2020
|
+
switch(status){
|
|
2021
|
+
case "ended":
|
|
2022
|
+
try {
|
|
2023
|
+
await this._mediaStreamRecorder.begin(event.track);
|
|
2024
|
+
if (this._connected) {
|
|
2025
|
+
this._startRecording();
|
|
2026
|
+
if (this._connectResolve) {
|
|
2027
|
+
this._connectResolve();
|
|
2028
|
+
this._connectResolve = null;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
} catch (e) {
|
|
2032
|
+
// void. nothing to do.
|
|
2033
|
+
}
|
|
2034
|
+
break;
|
|
2035
|
+
case "paused":
|
|
2036
|
+
this._startRecording();
|
|
2037
|
+
break;
|
|
2038
|
+
case "recording":
|
|
2039
|
+
default:
|
|
2040
|
+
if (this._currentAudioTrack !== event.track) {
|
|
2041
|
+
await this._mediaStreamRecorder.end();
|
|
2042
|
+
try {
|
|
2043
|
+
await this._mediaStreamRecorder.begin(event.track);
|
|
2044
|
+
this._startRecording();
|
|
2045
|
+
} catch (e) {
|
|
2046
|
+
// void. nothing to do.
|
|
2047
|
+
}
|
|
2048
|
+
} else console.warn("track-started event received for current track and already recording");
|
|
2049
|
+
break;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
this._currentAudioTrack = event.track;
|
|
2053
|
+
} else if (event.track.kind === "video") this._camEnabled = true;
|
|
2054
|
+
this._callbacks.onTrackStarted?.(event.track, event.participant ? $00a190ef6aa79f0d$var$dailyParticipantToParticipant(event.participant) : undefined);
|
|
2055
|
+
this.onTrackStartedCallback?.(event);
|
|
2056
|
+
}
|
|
2057
|
+
handleTrackStopped(event) {
|
|
2058
|
+
if (!event.participant?.local) return;
|
|
2059
|
+
if (event.track.kind === "audio") {
|
|
2060
|
+
this._micEnabled = false;
|
|
2061
|
+
if (this._mediaStreamRecorder && this._mediaStreamRecorder.getStatus() === "recording") this._mediaStreamRecorder.pause();
|
|
2062
|
+
} else if (event.track.kind === "video") this._camEnabled = false;
|
|
2063
|
+
this._callbacks.onTrackStopped?.(event.track, event.participant ? $00a190ef6aa79f0d$var$dailyParticipantToParticipant(event.participant) : undefined);
|
|
2064
|
+
this.onTrackStoppedCallback?.(event);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
const $00a190ef6aa79f0d$var$dailyParticipantToParticipant = (p)=>({
|
|
2068
|
+
id: p.user_id,
|
|
2069
|
+
local: p.local,
|
|
2070
|
+
name: p.user_name
|
|
2071
|
+
});
|
|
2072
|
+
const $00a190ef6aa79f0d$var$botParticipant = ()=>({
|
|
2073
|
+
id: "bot",
|
|
2074
|
+
local: false,
|
|
2075
|
+
name: "Bot"
|
|
2076
|
+
});
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
const $7f41aaa208a19660$var$readyStates = [
|
|
2081
|
+
"CONNECTING",
|
|
2082
|
+
"OPEN",
|
|
2083
|
+
"CLOSING",
|
|
2084
|
+
"CLOSED"
|
|
2085
|
+
];
|
|
2086
|
+
const $7f41aaa208a19660$var$KEEP_ALIVE_INTERVAL = 5000;
|
|
2087
|
+
const $7f41aaa208a19660$var$KEEP_ALIVE_TIMEOUT = 15000;
|
|
2088
|
+
// client side code in soupSFU has a timeout of 15 seconds for command response
|
|
2089
|
+
// 5 seconds seems reasonable that it provides roughly 3 retry attempts
|
|
2090
|
+
const $7f41aaa208a19660$var$WEBSOCKET_CONNECTION_TIMEOUT = 150000;
|
|
2091
|
+
const $7f41aaa208a19660$var$DEFAULT_RECONNECT_ATTEMPTS = 2;
|
|
2092
|
+
const $7f41aaa208a19660$var$MAX_RECONNECT_ATTEMPTS = 10;
|
|
2093
|
+
const $7f41aaa208a19660$var$DEFAULT_RECONNECT_INTERVAL = 1000;
|
|
2094
|
+
const $7f41aaa208a19660$var$MAX_RECONNECT_INTERVAL = 30000;
|
|
2095
|
+
const $7f41aaa208a19660$var$DEFAULT_RECONNECT_DECAY = 1.5;
|
|
2096
|
+
const $7f41aaa208a19660$var$WEBSOCKET_TIMEOUT_CODE = 4100;
|
|
2097
|
+
const $7f41aaa208a19660$var$SIG_CONNECTION_CANCELED = "SIG_CONNECTION_CANCELED";
|
|
2098
|
+
const $7f41aaa208a19660$var$WEBSOCKET_ERROR = "WEBSOCKET_ERROR";
|
|
2099
|
+
var $7f41aaa208a19660$var$LOG_LEVEL;
|
|
2100
|
+
(function(LOG_LEVEL) {
|
|
2101
|
+
LOG_LEVEL[LOG_LEVEL["DEBUG"] = 0] = "DEBUG";
|
|
2102
|
+
LOG_LEVEL[LOG_LEVEL["ERROR"] = 1] = "ERROR";
|
|
2103
|
+
LOG_LEVEL[LOG_LEVEL["INFO"] = 2] = "INFO";
|
|
2104
|
+
LOG_LEVEL[LOG_LEVEL["WARN"] = 3] = "WARN";
|
|
2105
|
+
})($7f41aaa208a19660$var$LOG_LEVEL || ($7f41aaa208a19660$var$LOG_LEVEL = {}));
|
|
2106
|
+
class $7f41aaa208a19660$var$rWebSocket {
|
|
2107
|
+
constructor(url, protocols){
|
|
2108
|
+
this._closedManually = false;
|
|
2109
|
+
this._errored = false;
|
|
2110
|
+
this._rejected = false;
|
|
2111
|
+
this._timed_out = false;
|
|
2112
|
+
this._initialConnectionOk = false;
|
|
2113
|
+
this._ws = new WebSocket(url, protocols);
|
|
2114
|
+
}
|
|
2115
|
+
addEventListener(type, listener) {
|
|
2116
|
+
this._ws.addEventListener(type, listener);
|
|
2117
|
+
}
|
|
2118
|
+
// Add other WebSocket methods as needed
|
|
2119
|
+
close(code, reason) {
|
|
2120
|
+
this._ws.close(code, reason);
|
|
2121
|
+
}
|
|
2122
|
+
send(data) {
|
|
2123
|
+
this._ws.send(data);
|
|
2124
|
+
}
|
|
2125
|
+
// Add getters for WebSocket properties
|
|
2126
|
+
get url() {
|
|
2127
|
+
return this._ws.url;
|
|
2128
|
+
}
|
|
2129
|
+
get readyState() {
|
|
2130
|
+
return this._ws.readyState;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
class $7f41aaa208a19660$export$4f3d0ffd941ebefb extends (0, $1clrS$events.EventEmitter) {
|
|
2134
|
+
constructor(address, protocols, options = {}){
|
|
2135
|
+
super();
|
|
2136
|
+
if (!address) throw new Error("Need a valid WebSocket URL");
|
|
2137
|
+
this._ws = null;
|
|
2138
|
+
this._url = address;
|
|
2139
|
+
this._protocols = protocols;
|
|
2140
|
+
this._parseBlobToJson = options?.parseBlobToJson ?? true;
|
|
2141
|
+
this.init();
|
|
2142
|
+
}
|
|
2143
|
+
init() {
|
|
2144
|
+
this._keepAliveTimeout = $7f41aaa208a19660$var$KEEP_ALIVE_TIMEOUT;
|
|
2145
|
+
this._keepAliveInterval = $7f41aaa208a19660$var$KEEP_ALIVE_INTERVAL;
|
|
2146
|
+
this._disconnected = false;
|
|
2147
|
+
this._keepIntervalID = null;
|
|
2148
|
+
this._shouldRetryFn = null;
|
|
2149
|
+
this._connectionTimeout = $7f41aaa208a19660$var$WEBSOCKET_CONNECTION_TIMEOUT;
|
|
2150
|
+
this._reconnectAttempts = 0;
|
|
2151
|
+
this._allowedReconnectAttempts = $7f41aaa208a19660$var$DEFAULT_RECONNECT_ATTEMPTS;
|
|
2152
|
+
this._reconnectInterval = $7f41aaa208a19660$var$DEFAULT_RECONNECT_INTERVAL;
|
|
2153
|
+
this._maxReconnectInterval = $7f41aaa208a19660$var$MAX_RECONNECT_INTERVAL;
|
|
2154
|
+
this._reconnectDecay = $7f41aaa208a19660$var$DEFAULT_RECONNECT_DECAY;
|
|
2155
|
+
}
|
|
2156
|
+
async connect() {
|
|
2157
|
+
return new Promise((resolve, reject)=>{
|
|
2158
|
+
this._disconnected = false;
|
|
2159
|
+
this.clearReconnectTimeout();
|
|
2160
|
+
let ws = new $7f41aaa208a19660$var$rWebSocket(this._url, this._protocols);
|
|
2161
|
+
this.setConnectionTimeout();
|
|
2162
|
+
ws.addEventListener("close", (evt)=>{
|
|
2163
|
+
const closeEvent = evt;
|
|
2164
|
+
let code = ws._timed_out ? $7f41aaa208a19660$var$WEBSOCKET_TIMEOUT_CODE : closeEvent.code;
|
|
2165
|
+
let reason = ws._timed_out ? "websocket connection timed out" : closeEvent.reason;
|
|
2166
|
+
ws._timed_out = false;
|
|
2167
|
+
if (!ws._closedManually && ws._initialConnectionOk) {
|
|
2168
|
+
console.warn(`signaling socket closed unexpectedly: ${code}${reason ? " " + reason : ""}`);
|
|
2169
|
+
this._closeSocket();
|
|
2170
|
+
this.emit("close", code, reason);
|
|
2171
|
+
} else this.log("signaling socket closed");
|
|
2172
|
+
if (!ws._closedManually && (ws._errored || ws._timed_out)) {
|
|
2173
|
+
console.warn(`signaling socket closed on error: ${code}${reason ? " " + reason : ""}`);
|
|
2174
|
+
if (!ws._rejected) {
|
|
2175
|
+
ws._rejected = true;
|
|
2176
|
+
const err = new Error(`WebSocket connection error (${code}): ${reason}`);
|
|
2177
|
+
err.name = $7f41aaa208a19660$var$WEBSOCKET_ERROR;
|
|
2178
|
+
reject(err);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
ws.addEventListener("open", (evt)=>{
|
|
2183
|
+
this.log("wss connection opened to", $7f41aaa208a19660$var$LOG_LEVEL.DEBUG, this._url);
|
|
2184
|
+
this.clearConnectionTimeout();
|
|
2185
|
+
// now that the timeout closes the socket, in theory this onopen
|
|
2186
|
+
// callback should never happen in the first place, but seems
|
|
2187
|
+
// harmless to leave these safeguards in
|
|
2188
|
+
if (ws._rejected || ws._timed_out) return;
|
|
2189
|
+
if (ws._closedManually || this._ws && this._ws !== ws) {
|
|
2190
|
+
ws._rejected = true;
|
|
2191
|
+
ws.close();
|
|
2192
|
+
let err = Error("wss connection interrupted by disconnect or newer connection");
|
|
2193
|
+
err.name = $7f41aaa208a19660$var$SIG_CONNECTION_CANCELED;
|
|
2194
|
+
reject(err);
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
ws._initialConnectionOk = this._url;
|
|
2198
|
+
this._lastMsgRecvTime = Date.now();
|
|
2199
|
+
if (this._keepAliveInterval) this._keepIntervalID = setInterval(()=>this.checkSocketHealthAndSendKeepAlive(), this._keepAliveInterval);
|
|
2200
|
+
this._ws = ws;
|
|
2201
|
+
this.emit("open");
|
|
2202
|
+
resolve(ws);
|
|
2203
|
+
});
|
|
2204
|
+
ws.addEventListener("error", (evt)=>{
|
|
2205
|
+
// fyi: evt is an Event here, with 0 amount of helpful info. If there
|
|
2206
|
+
// happens to be info about the error, it's included in the
|
|
2207
|
+
// accompanying close event (because that make sense. shakes head)
|
|
2208
|
+
// SO. We do not reject here. Instead, we just set the _errored
|
|
2209
|
+
// flag on the socket so when the close event occurs, it knows to
|
|
2210
|
+
// reject the promise
|
|
2211
|
+
if (!ws._closedManually) {
|
|
2212
|
+
const wsTarget = evt.currentTarget;
|
|
2213
|
+
this.log(`websocket error event: ${wsTarget?.url}`);
|
|
2214
|
+
}
|
|
2215
|
+
ws._errored = true;
|
|
2216
|
+
});
|
|
2217
|
+
ws.addEventListener("message", (msg)=>{
|
|
2218
|
+
this._handleMessage(msg);
|
|
2219
|
+
});
|
|
2220
|
+
});
|
|
2221
|
+
}
|
|
2222
|
+
setConnectionTimeout() {
|
|
2223
|
+
this._connectionTimeoutID = setTimeout(async ()=>{
|
|
2224
|
+
this.log("Connection reconnect attempt timed out.");
|
|
2225
|
+
this.emit("connection-timeout");
|
|
2226
|
+
this.clearConnectionTimeout();
|
|
2227
|
+
await this._closeSocket();
|
|
2228
|
+
}, this._connectionTimeout);
|
|
2229
|
+
}
|
|
2230
|
+
clearConnectionTimeout() {
|
|
2231
|
+
clearTimeout(this._connectionTimeoutID);
|
|
2232
|
+
this._connectionTimeoutID = undefined;
|
|
2233
|
+
}
|
|
2234
|
+
clearReconnectTimeout() {
|
|
2235
|
+
clearTimeout(this._reconnectTimeoutID);
|
|
2236
|
+
this._reconnectTimeoutID = undefined;
|
|
2237
|
+
}
|
|
2238
|
+
clearKeepAliveInterval() {
|
|
2239
|
+
if (this._keepIntervalID) {
|
|
2240
|
+
clearInterval(this._keepIntervalID);
|
|
2241
|
+
this._keepIntervalID = null;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
async checkSocketHealthAndSendKeepAlive() {
|
|
2245
|
+
if (!(this._ws && this._ws.readyState === WebSocket.OPEN)) return;
|
|
2246
|
+
if (!this._keepAliveTimeout || !this._keepAliveInterval) return;
|
|
2247
|
+
// See if we haven't gotten a message back recently, and if we
|
|
2248
|
+
// haven't, close the socket. the os timeouts to detect if a socket
|
|
2249
|
+
// has gone stale are longer than we want.
|
|
2250
|
+
if (Date.now() - this._lastMsgRecvTime > this._keepAliveTimeout) {
|
|
2251
|
+
this.log("Connection is stale, need to reconnect", $7f41aaa208a19660$var$LOG_LEVEL.WARN);
|
|
2252
|
+
await this._closeSocket();
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2255
|
+
// Only emit the keep-alive event if we haven't sent anything else recently
|
|
2256
|
+
if (Date.now() - this._lastMsgSendTime < this._keepAliveInterval) return;
|
|
2257
|
+
this.log("Emitting keep-alive", $7f41aaa208a19660$var$LOG_LEVEL.DEBUG);
|
|
2258
|
+
this.emit("keep-alive");
|
|
2259
|
+
}
|
|
2260
|
+
// We use the word manually here to imply the application using this code
|
|
2261
|
+
// or this code itself will decide to close the socket.
|
|
2262
|
+
async _closeSocket() {
|
|
2263
|
+
this.log("Closing");
|
|
2264
|
+
try {
|
|
2265
|
+
this.clearKeepAliveInterval();
|
|
2266
|
+
this._lastMsgRecvTime = 0;
|
|
2267
|
+
if (this._ws) {
|
|
2268
|
+
this._ws._closedManually = true;
|
|
2269
|
+
this._ws.close();
|
|
2270
|
+
}
|
|
2271
|
+
// query retry function if we want to retry.
|
|
2272
|
+
const shouldRetry = this._ws?._initialConnectionOk && this._shouldRetryFn && this._shouldRetryFn();
|
|
2273
|
+
this._ws = null;
|
|
2274
|
+
if (shouldRetry) {
|
|
2275
|
+
this.log("Emitting reconnect", $7f41aaa208a19660$var$LOG_LEVEL.DEBUG);
|
|
2276
|
+
this.emit("reconnecting");
|
|
2277
|
+
await this.retryFailedConnection();
|
|
2278
|
+
}
|
|
2279
|
+
} catch (error) {
|
|
2280
|
+
this.log(`Error while closing and retrying: ${error}`, $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
async retryFailedConnection() {
|
|
2284
|
+
if (this._reconnectAttempts < this._allowedReconnectAttempts) {
|
|
2285
|
+
if (this._reconnectTimeoutID) {
|
|
2286
|
+
this.log("Retry already scheduled");
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
this.log("Retrying failed connection");
|
|
2290
|
+
let timeout = // The timeout logic is taken from
|
|
2291
|
+
// https://github.com/joewalnes/reconnecting-websocket
|
|
2292
|
+
this._reconnectInterval * Math.pow(this._reconnectDecay, this._reconnectAttempts);
|
|
2293
|
+
timeout = timeout > this._maxReconnectInterval ? this._maxReconnectInterval : timeout;
|
|
2294
|
+
this.log(`Reconnecting in ${timeout / 1000} seconds`);
|
|
2295
|
+
this._reconnectAttempts += 1;
|
|
2296
|
+
this._reconnectTimeoutID = setTimeout(()=>this.connect(), timeout);
|
|
2297
|
+
} else {
|
|
2298
|
+
this.log("Maximum connection retry attempts exceeded", $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2299
|
+
this.emit("reconnect-failed");
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
log(msg, log_level = $7f41aaa208a19660$var$LOG_LEVEL.DEBUG, ...args) {
|
|
2303
|
+
switch(log_level){
|
|
2304
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.DEBUG:
|
|
2305
|
+
console.debug(`websocket: ${msg}`, ...args);
|
|
2306
|
+
break;
|
|
2307
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.ERROR:
|
|
2308
|
+
console.error(`websocket: ${msg}`, ...args);
|
|
2309
|
+
break;
|
|
2310
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.WARN:
|
|
2311
|
+
console.warn(`websocket: ${msg}`, ...args);
|
|
2312
|
+
break;
|
|
2313
|
+
case $7f41aaa208a19660$var$LOG_LEVEL.INFO:
|
|
2314
|
+
default:
|
|
2315
|
+
console.log(`websocket: ${msg}`, ...args);
|
|
2316
|
+
break;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
async send(data) {
|
|
2320
|
+
try {
|
|
2321
|
+
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
|
|
2322
|
+
this._lastMsgSendTime = Date.now();
|
|
2323
|
+
this._ws.send(data);
|
|
2324
|
+
} else this.log(`Failed to send data, web socket not open.`, $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2325
|
+
} catch (error) {
|
|
2326
|
+
this.log(`Failed to send data. ${error}`, $7f41aaa208a19660$var$LOG_LEVEL.ERROR);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
async close() {
|
|
2330
|
+
try {
|
|
2331
|
+
this.log("Closing websocket");
|
|
2332
|
+
this._disconnected = true;
|
|
2333
|
+
this.clearReconnectTimeout();
|
|
2334
|
+
this._closeSocket();
|
|
2335
|
+
} catch (error) {
|
|
2336
|
+
this.log(`Failed to close websocket. ${error}`);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
get readyState() {
|
|
2340
|
+
return this._ws?.readyState ?? WebSocket.CLOSED;
|
|
2341
|
+
}
|
|
2342
|
+
get url() {
|
|
2343
|
+
return this._url;
|
|
2344
|
+
}
|
|
2345
|
+
get keepAliveTimeout() {
|
|
2346
|
+
return this._keepAliveTimeout;
|
|
2347
|
+
}
|
|
2348
|
+
set keepAliveTimeout(keepAliveTimeout) {
|
|
2349
|
+
if (typeof keepAliveTimeout === "number") {
|
|
2350
|
+
this.log(`Setting ACK freshness timeout to ${keepAliveTimeout}`);
|
|
2351
|
+
this._keepAliveTimeout = keepAliveTimeout;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
get keepAliveInterval() {
|
|
2355
|
+
return this._keepAliveInterval;
|
|
2356
|
+
}
|
|
2357
|
+
set keepAliveInterval(keepAliveInterval) {
|
|
2358
|
+
if (typeof keepAliveInterval === "number") {
|
|
2359
|
+
this.log(`Setting keep-alive interval to ${keepAliveInterval}`);
|
|
2360
|
+
this._keepAliveInterval = keepAliveInterval;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
set shouldRetryFn(cb) {
|
|
2364
|
+
if (typeof cb === "function") this._shouldRetryFn = cb;
|
|
2365
|
+
}
|
|
2366
|
+
get connectionTimeout() {
|
|
2367
|
+
return this._connectionTimeout;
|
|
2368
|
+
}
|
|
2369
|
+
set connectionTimeout(timeout) {
|
|
2370
|
+
if (typeof timeout === "number") this._connectionTimeout = timeout;
|
|
2371
|
+
}
|
|
2372
|
+
get maxReconnectAttempts() {
|
|
2373
|
+
return this._allowedReconnectAttempts;
|
|
2374
|
+
}
|
|
2375
|
+
set maxReconnectAttempts(attempts) {
|
|
2376
|
+
if (attempts > 0 && attempts < $7f41aaa208a19660$var$MAX_RECONNECT_ATTEMPTS) {
|
|
2377
|
+
this.log(`Setting maximum connection retry attempts to ${attempts}`);
|
|
2378
|
+
this._allowedReconnectAttempts = attempts;
|
|
2379
|
+
} else this._allowedReconnectAttempts = $7f41aaa208a19660$var$DEFAULT_RECONNECT_ATTEMPTS;
|
|
2380
|
+
}
|
|
2381
|
+
get reconnectInterval() {
|
|
2382
|
+
return this._reconnectInterval;
|
|
2383
|
+
}
|
|
2384
|
+
set reconnectInterval(interval) {
|
|
2385
|
+
if (typeof interval === "number") this._reconnectInterval = interval < this._maxReconnectInterval ? interval : this._maxReconnectInterval;
|
|
2386
|
+
}
|
|
2387
|
+
async _handleMessage(event) {
|
|
2388
|
+
this._lastMsgRecvTime = Date.now();
|
|
2389
|
+
const data = event.data;
|
|
2390
|
+
const _parsePromise = new Promise((resolve, reject)=>{
|
|
2391
|
+
if (typeof data === "string") // Handle text message
|
|
2392
|
+
resolve(data);
|
|
2393
|
+
else if (data instanceof ArrayBuffer) {
|
|
2394
|
+
// Handle binary message
|
|
2395
|
+
const arrayBuffer = data;
|
|
2396
|
+
// Parse the ArrayBuffer as needed
|
|
2397
|
+
// Example: Convert ArrayBuffer to Uint8Array
|
|
2398
|
+
resolve(new Uint8Array(arrayBuffer));
|
|
2399
|
+
// Process the Uint8Array as needed
|
|
2400
|
+
} else if (data instanceof Blob) {
|
|
2401
|
+
if (!this._parseBlobToJson) {
|
|
2402
|
+
resolve(data);
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2405
|
+
// Handle Blob message
|
|
2406
|
+
const blob = data;
|
|
2407
|
+
// Convert Blob to ArrayBuffer
|
|
2408
|
+
const reader = new FileReader();
|
|
2409
|
+
reader.onload = ()=>{
|
|
2410
|
+
const text = reader.result;
|
|
2411
|
+
try {
|
|
2412
|
+
const json = JSON.parse(text);
|
|
2413
|
+
resolve(json);
|
|
2414
|
+
} catch (e) {
|
|
2415
|
+
console.error("Failed to parse JSON from Blob:", e);
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
reader.readAsText(blob);
|
|
2419
|
+
}
|
|
2420
|
+
});
|
|
2421
|
+
let msg = await _parsePromise;
|
|
2422
|
+
this.emit("message", msg);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
[
|
|
2426
|
+
"binaryType",
|
|
2427
|
+
"bufferedAmount",
|
|
2428
|
+
"extensions",
|
|
2429
|
+
"protocol",
|
|
2430
|
+
"readyState",
|
|
2431
|
+
"url",
|
|
2432
|
+
"keepAliveTimeout",
|
|
2433
|
+
"keepAliveInterval",
|
|
2434
|
+
"shouldRetryFn",
|
|
2435
|
+
"connectionTimeout",
|
|
2436
|
+
"maxReconnectAttempts",
|
|
2437
|
+
"reconnectInterval"
|
|
2438
|
+
].forEach((property)=>{
|
|
2439
|
+
Object.defineProperty($7f41aaa208a19660$export$4f3d0ffd941ebefb.prototype, property, {
|
|
2440
|
+
enumerable: true
|
|
2441
|
+
});
|
|
2442
|
+
});
|
|
2443
|
+
[
|
|
2444
|
+
"CONNECTING",
|
|
2445
|
+
"OPEN",
|
|
2446
|
+
"CLOSING",
|
|
2447
|
+
"CLOSED"
|
|
2448
|
+
].forEach((property)=>{
|
|
2449
|
+
Object.defineProperty($7f41aaa208a19660$export$4f3d0ffd941ebefb.prototype, property, {
|
|
2450
|
+
enumerable: true,
|
|
2451
|
+
value: $7f41aaa208a19660$var$readyStates.indexOf(property)
|
|
2452
|
+
});
|
|
2453
|
+
});
|
|
2454
|
+
[
|
|
2455
|
+
"CONNECTING",
|
|
2456
|
+
"OPEN",
|
|
2457
|
+
"CLOSING",
|
|
2458
|
+
"CLOSED"
|
|
2459
|
+
].forEach((property)=>{
|
|
2460
|
+
Object.defineProperty($7f41aaa208a19660$export$4f3d0ffd941ebefb, property, {
|
|
2461
|
+
enumerable: true,
|
|
2462
|
+
value: $7f41aaa208a19660$var$readyStates.indexOf(property)
|
|
2463
|
+
});
|
|
2464
|
+
});
|
|
2465
|
+
|
|
2466
|
+
|
|
2467
|
+
|
|
2468
|
+
|
|
2469
|
+
|
|
2470
|
+
var $48b67f1ef231aa26$exports = {};
|
|
2471
|
+
$48b67f1ef231aa26$exports = JSON.parse("{\"name\":\"@pipecat-ai/daily-transport\",\"version\":\"1.6.9\",\"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.13.0\",\"@pipecat-ai/transport-lib\":\"^0.1.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.13.0\"},\"dependencies\":{\"@daily-co/daily-js\":\"^0.90.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\"}");
|
|
2472
|
+
|
|
2473
|
+
|
|
2474
|
+
var $1c83796b12dd4e49$export$ef180de88fd317cc;
|
|
1530
2475
|
(function(DailyRTVIMessageType) {
|
|
1531
2476
|
DailyRTVIMessageType["AUDIO_BUFFERING_STARTED"] = "audio-buffering-started";
|
|
1532
2477
|
DailyRTVIMessageType["AUDIO_BUFFERING_STOPPED"] = "audio-buffering-stopped";
|
|
1533
|
-
})($
|
|
1534
|
-
class $
|
|
2478
|
+
})($1c83796b12dd4e49$export$ef180de88fd317cc || ($1c83796b12dd4e49$export$ef180de88fd317cc = {}));
|
|
2479
|
+
class $1c83796b12dd4e49$var$DailyCallWrapper {
|
|
1535
2480
|
constructor(daily){
|
|
1536
2481
|
this._daily = daily;
|
|
1537
2482
|
this._proxy = new Proxy(this._daily, {
|
|
@@ -1574,7 +2519,7 @@ class $28bdeb35415d61e8$var$DailyCallWrapper {
|
|
|
1574
2519
|
return this._proxy;
|
|
1575
2520
|
}
|
|
1576
2521
|
}
|
|
1577
|
-
class $
|
|
2522
|
+
class $1c83796b12dd4e49$export$b1ca982aa1e488c1 extends (0, $1clrS$pipecataiclientjs.Transport) {
|
|
1578
2523
|
constructor(opts = {}){
|
|
1579
2524
|
super();
|
|
1580
2525
|
this._botId = "";
|
|
@@ -1583,6 +2528,19 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1583
2528
|
this._selectedSpeaker = {};
|
|
1584
2529
|
this._currentAudioTrack = null;
|
|
1585
2530
|
this._audioQueue = [];
|
|
2531
|
+
// NOTE: deliberately not read live off `this._daily.localAudio()` /
|
|
2532
|
+
// `localVideo()` in the isMicEnabled/isCamEnabled getters below. Daily
|
|
2533
|
+
// fires 'track-started'/'track-stopped' *before* it commits the new state
|
|
2534
|
+
// to the participant object those calls read from (daily-js emits the
|
|
2535
|
+
// track event from within its participant-updated handling, then
|
|
2536
|
+
// reassigns its internal participant cache afterwards). Code that reacts
|
|
2537
|
+
// to TrackStarted/TrackStopped by reading isMicEnabled/isCamEnabled to
|
|
2538
|
+
// resync UI state — e.g. PipecatClientState's mic/cam sync — would
|
|
2539
|
+
// otherwise always observe the pre-toggle value. These fields are updated
|
|
2540
|
+
// synchronously in enableMic/enableCam and in handleTrackStarted/
|
|
2541
|
+
// handleTrackStopped, before those callbacks fire.
|
|
2542
|
+
this._micEnabled = true;
|
|
2543
|
+
this._camEnabled = false;
|
|
1586
2544
|
this._callbacks = {};
|
|
1587
2545
|
const { bufferLocalAudioUntilBotReady: bufferLocalAudioUntilBotReady, ...dailyOpts } = opts;
|
|
1588
2546
|
this._dailyFactoryOptions = dailyOpts;
|
|
@@ -1593,15 +2551,15 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1593
2551
|
this._dailyFactoryOptions.dailyConfig.useDevicePreferenceCookies = true;
|
|
1594
2552
|
}
|
|
1595
2553
|
this._bufferLocalAudioUntilBotReady = bufferLocalAudioUntilBotReady || false;
|
|
1596
|
-
this._daily = (0, ($parcel$interopDefault($
|
|
2554
|
+
this._daily = (0, ($parcel$interopDefault($1clrS$dailycodailyjs))).createCallObject({
|
|
1597
2555
|
...this._dailyFactoryOptions,
|
|
1598
2556
|
allowMultipleCallInstances: true
|
|
1599
2557
|
});
|
|
1600
|
-
this._dailyWrapper = new $
|
|
2558
|
+
this._dailyWrapper = new $1c83796b12dd4e49$var$DailyCallWrapper(this._daily);
|
|
1601
2559
|
}
|
|
1602
2560
|
setupRecorder() {
|
|
1603
|
-
this._mediaStreamRecorder = new (0, $
|
|
1604
|
-
sampleRate: $
|
|
2561
|
+
this._mediaStreamRecorder = new (0, $ab812aec7679ec67$export$2934cf2d25c67a48)({
|
|
2562
|
+
sampleRate: $1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_SAMPLE_RATE
|
|
1605
2563
|
});
|
|
1606
2564
|
}
|
|
1607
2565
|
handleUserAudioStream(data) {
|
|
@@ -1610,7 +2568,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1610
2568
|
flushAudioQueue() {
|
|
1611
2569
|
const batchSize = 10; // Number of buffers to send in one message
|
|
1612
2570
|
if (this._audioQueue.length === 0) return;
|
|
1613
|
-
(0, $
|
|
2571
|
+
(0, $1clrS$pipecataiclientjs.logger).debug(`Will flush audio queue: ${this._audioQueue.length}`);
|
|
1614
2572
|
while(this._audioQueue.length > 0){
|
|
1615
2573
|
const batch = [];
|
|
1616
2574
|
// Collect up to `batchSize` items
|
|
@@ -1632,7 +2590,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1632
2590
|
type: "raw-audio-batch",
|
|
1633
2591
|
data: {
|
|
1634
2592
|
base64AudioBatch: encodedBatch,
|
|
1635
|
-
sampleRate: $
|
|
2593
|
+
sampleRate: $1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_SAMPLE_RATE,
|
|
1636
2594
|
numChannels: 1
|
|
1637
2595
|
}
|
|
1638
2596
|
};
|
|
@@ -1646,9 +2604,11 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1646
2604
|
this._dailyFactoryOptions.startVideoOff = !(options.enableCam ?? false);
|
|
1647
2605
|
if (this._dailyFactoryOptions.startAudioOff == null || options.enableMic != null) // Default is mic on
|
|
1648
2606
|
this._dailyFactoryOptions.startAudioOff = !(options.enableMic ?? true);
|
|
2607
|
+
this._camEnabled = !this._dailyFactoryOptions.startVideoOff;
|
|
2608
|
+
this._micEnabled = !this._dailyFactoryOptions.startAudioOff;
|
|
1649
2609
|
this.attachEventListeners();
|
|
1650
2610
|
this.state = "disconnected";
|
|
1651
|
-
(0, $
|
|
2611
|
+
(0, $1clrS$pipecataiclientjs.logger).debug("[Daily Transport] Initialized", (0, (/*@__PURE__*/$parcel$interopDefault($48b67f1ef231aa26$exports))).version);
|
|
1652
2612
|
}
|
|
1653
2613
|
get dailyCallClient() {
|
|
1654
2614
|
return this._dailyWrapper.proxy;
|
|
@@ -1702,7 +2662,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1702
2662
|
}).then((infos)=>{
|
|
1703
2663
|
this._selectedSpeaker = infos.speaker;
|
|
1704
2664
|
}).catch((e)=>{
|
|
1705
|
-
this._callbacks.onDeviceError?.(new (0, $
|
|
2665
|
+
this._callbacks.onDeviceError?.(new (0, $1clrS$pipecataiclientjs.DeviceError)([
|
|
1706
2666
|
"speaker"
|
|
1707
2667
|
], e.type ?? "unknown", e.message));
|
|
1708
2668
|
});
|
|
@@ -1717,17 +2677,19 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1717
2677
|
// joined — pre-session, daily-js can't act on the request because the
|
|
1718
2678
|
// call object isn't part of a meeting yet.
|
|
1719
2679
|
this._dailyFactoryOptions.startAudioOff = !enable;
|
|
2680
|
+
this._micEnabled = enable;
|
|
1720
2681
|
if (this._daily.participants()?.local) this._daily.setLocalAudio(enable);
|
|
1721
2682
|
}
|
|
1722
2683
|
get isMicEnabled() {
|
|
1723
|
-
return this.
|
|
2684
|
+
return this._micEnabled;
|
|
1724
2685
|
}
|
|
1725
2686
|
enableCam(enable) {
|
|
1726
2687
|
this._dailyFactoryOptions.startVideoOff = !enable;
|
|
2688
|
+
this._camEnabled = enable;
|
|
1727
2689
|
if (this._daily.participants()?.local) this._daily.setLocalVideo(enable);
|
|
1728
2690
|
}
|
|
1729
2691
|
get isCamEnabled() {
|
|
1730
|
-
return this.
|
|
2692
|
+
return this._camEnabled;
|
|
1731
2693
|
}
|
|
1732
2694
|
enableScreenShare(enable) {
|
|
1733
2695
|
if (enable) this._daily.startScreenShare();
|
|
@@ -1755,15 +2717,15 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1755
2717
|
}
|
|
1756
2718
|
async startRecording() {
|
|
1757
2719
|
try {
|
|
1758
|
-
(0, $
|
|
2720
|
+
(0, $1clrS$pipecataiclientjs.logger).info("[Daily Transport] Initializing recording");
|
|
1759
2721
|
await this._mediaStreamRecorder.record((data)=>{
|
|
1760
2722
|
this.handleUserAudioStream(data.mono);
|
|
1761
|
-
}, $
|
|
2723
|
+
}, $1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_CHUNK_SIZE);
|
|
1762
2724
|
this._callbacks.onAudioBufferingStarted?.();
|
|
1763
|
-
(0, $
|
|
2725
|
+
(0, $1clrS$pipecataiclientjs.logger).info("[Daily Transport] Recording Initialized");
|
|
1764
2726
|
} catch (e) {
|
|
1765
2727
|
const err = e;
|
|
1766
|
-
if (!err.message.includes("Already recording")) (0, $
|
|
2728
|
+
if (!err.message.includes("Already recording")) (0, $1clrS$pipecataiclientjs.logger).error("Error starting recording", e);
|
|
1767
2729
|
}
|
|
1768
2730
|
}
|
|
1769
2731
|
async preAuth(dailyCallOptions) {
|
|
@@ -1771,7 +2733,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1771
2733
|
await this._daily.preAuth(dailyCallOptions);
|
|
1772
2734
|
}
|
|
1773
2735
|
async initDevices() {
|
|
1774
|
-
if (!this._daily) throw new (0, $
|
|
2736
|
+
if (!this._daily) throw new (0, $1clrS$pipecataiclientjs.RTVIError)("Transport instance not initialized");
|
|
1775
2737
|
this.state = "initializing";
|
|
1776
2738
|
const infos = await this._daily.startCamera(this._dailyFactoryOptions);
|
|
1777
2739
|
const { devices: devices } = await this._daily.enumerateDevices();
|
|
@@ -1794,7 +2756,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1794
2756
|
}
|
|
1795
2757
|
_validateConnectionParams(connectParams) {
|
|
1796
2758
|
if (connectParams === undefined || connectParams === null) return undefined;
|
|
1797
|
-
if (typeof connectParams !== "object") throw new (0, $
|
|
2759
|
+
if (typeof connectParams !== "object") throw new (0, $1clrS$pipecataiclientjs.RTVIError)("Invalid connection parameters");
|
|
1798
2760
|
const tmpParams = connectParams;
|
|
1799
2761
|
if (tmpParams.room_url) {
|
|
1800
2762
|
tmpParams.url = tmpParams.room_url;
|
|
@@ -1812,7 +2774,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1812
2774
|
return tmpParams;
|
|
1813
2775
|
}
|
|
1814
2776
|
async _connect(connectParams) {
|
|
1815
|
-
if (!this._daily) throw new (0, $
|
|
2777
|
+
if (!this._daily) throw new (0, $1clrS$pipecataiclientjs.RTVIError)("Transport instance not initialized");
|
|
1816
2778
|
if (connectParams) this._dailyFactoryOptions = {
|
|
1817
2779
|
...this._dailyFactoryOptions,
|
|
1818
2780
|
...connectParams
|
|
@@ -1821,9 +2783,9 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1821
2783
|
try {
|
|
1822
2784
|
await this._daily.join(this._dailyFactoryOptions);
|
|
1823
2785
|
} catch (e) {
|
|
1824
|
-
(0, $
|
|
2786
|
+
(0, $1clrS$pipecataiclientjs.logger).error("Failed to join room", e);
|
|
1825
2787
|
this.state = "error";
|
|
1826
|
-
throw new (0, $
|
|
2788
|
+
throw new (0, $1clrS$pipecataiclientjs.TransportStartError)();
|
|
1827
2789
|
}
|
|
1828
2790
|
if (this._abortController?.signal.aborted) return;
|
|
1829
2791
|
const r = await this._daily.room();
|
|
@@ -1844,7 +2806,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1844
2806
|
// we've received the bot_ready signal
|
|
1845
2807
|
this.state = "ready";
|
|
1846
2808
|
this.flushAudioQueue();
|
|
1847
|
-
this.sendMessage((0, $
|
|
2809
|
+
this.sendMessage((0, $1clrS$pipecataiclientjs.RTVIMessage).clientReady());
|
|
1848
2810
|
this.stopRecording();
|
|
1849
2811
|
resolve();
|
|
1850
2812
|
};
|
|
@@ -1862,7 +2824,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1862
2824
|
this._daily.off("track-started", readyHandler);
|
|
1863
2825
|
// Check if it's an iOS device
|
|
1864
2826
|
if (isIOS()) {
|
|
1865
|
-
(0, $
|
|
2827
|
+
(0, $1clrS$pipecataiclientjs.logger).debug("[Daily Transport] iOS device detected, adding 0.5 second delay before sending ready message");
|
|
1866
2828
|
// Add 500ms delay for iOS devices:
|
|
1867
2829
|
// This is a workaround for iOS devices clipping a portion
|
|
1868
2830
|
// of the audio after the track becomes playable.
|
|
@@ -1909,7 +2871,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1909
2871
|
try {
|
|
1910
2872
|
this._daily.sendAppMessage(message, "*");
|
|
1911
2873
|
} catch (error) {
|
|
1912
|
-
if (error instanceof Error && error.message.includes("Message data too large")) throw new (0, $
|
|
2874
|
+
if (error instanceof Error && error.message.includes("Message data too large")) throw new (0, $1clrS$pipecataiclientjs.MessageTooLargeError)(error.message);
|
|
1913
2875
|
throw error;
|
|
1914
2876
|
}
|
|
1915
2877
|
}
|
|
@@ -1948,40 +2910,51 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1948
2910
|
error.blockedMedia.forEach((d)=>{
|
|
1949
2911
|
devices.push(d === "video" ? "cam" : "mic");
|
|
1950
2912
|
});
|
|
1951
|
-
return new (0, $
|
|
2913
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1952
2914
|
blockedBy: error.blockedBy
|
|
1953
2915
|
});
|
|
1954
2916
|
case "not-found":
|
|
1955
2917
|
error.missingMedia.forEach((d)=>{
|
|
1956
2918
|
devices.push(d === "video" ? "cam" : "mic");
|
|
1957
2919
|
});
|
|
1958
|
-
return new (0, $
|
|
2920
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1959
2921
|
case "constraints":
|
|
1960
2922
|
error.failedMedia.forEach((d)=>{
|
|
1961
2923
|
devices.push(d === "video" ? "cam" : "mic");
|
|
1962
2924
|
});
|
|
1963
|
-
return new (0, $
|
|
2925
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1964
2926
|
reason: error.reason
|
|
1965
2927
|
});
|
|
1966
2928
|
case "cam-in-use":
|
|
1967
2929
|
devices.push("cam");
|
|
1968
|
-
return new (0, $
|
|
2930
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1969
2931
|
case "mic-in-use":
|
|
1970
2932
|
devices.push("mic");
|
|
1971
|
-
return new (0, $
|
|
2933
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1972
2934
|
case "cam-mic-in-use":
|
|
1973
2935
|
devices.push("cam");
|
|
1974
2936
|
devices.push("mic");
|
|
1975
|
-
return new (0, $
|
|
2937
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1976
2938
|
case "undefined-mediadevices":
|
|
1977
2939
|
case "unknown":
|
|
1978
2940
|
default:
|
|
1979
2941
|
devices.push("cam");
|
|
1980
2942
|
devices.push("mic");
|
|
1981
|
-
return new (0, $
|
|
2943
|
+
return new (0, $1clrS$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1982
2944
|
}
|
|
1983
2945
|
};
|
|
1984
|
-
|
|
2946
|
+
const deviceError = generateDeviceError(ev.error);
|
|
2947
|
+
// enableMic()/enableCam() set _micEnabled/_camEnabled optimistically,
|
|
2948
|
+
// but setLocalAudio()/setLocalVideo() are fire-and-forget — no promise,
|
|
2949
|
+
// no synchronous failure signal — so a failed request (blocked
|
|
2950
|
+
// permission, device in use, etc.) leaves that optimistic value wrong
|
|
2951
|
+
// with nothing to correct it: no track-started/stopped ever fires for
|
|
2952
|
+
// an operation that didn't actually take effect. This is the only
|
|
2953
|
+
// signal we get that the request failed, so resync from Daily's actual
|
|
2954
|
+
// state for whichever device(s) it implicates.
|
|
2955
|
+
if (deviceError.devices.includes("mic")) this._micEnabled = this._daily.localAudio();
|
|
2956
|
+
if (deviceError.devices.includes("cam")) this._camEnabled = this._daily.localVideo();
|
|
2957
|
+
this._callbacks.onDeviceError?.(deviceError);
|
|
1985
2958
|
}
|
|
1986
2959
|
async handleLocalAudioTrack(track) {
|
|
1987
2960
|
if (this.state == "ready" || !this._bufferLocalAudioUntilBotReady) return;
|
|
@@ -2007,31 +2980,42 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2007
2980
|
} catch (e) {
|
|
2008
2981
|
// void. nothing to do.
|
|
2009
2982
|
}
|
|
2010
|
-
else (0, $
|
|
2983
|
+
else (0, $1clrS$pipecataiclientjs.logger).warn("track-started event received for current track and already recording");
|
|
2011
2984
|
break;
|
|
2012
2985
|
}
|
|
2013
2986
|
this._currentAudioTrack = track;
|
|
2014
2987
|
}
|
|
2015
2988
|
handleTrackStarted(ev) {
|
|
2016
|
-
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStarted?.(ev.track, ev.participant ? $
|
|
2989
|
+
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStarted?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
2017
2990
|
else {
|
|
2018
|
-
if (ev.participant?.local
|
|
2019
|
-
|
|
2991
|
+
if (ev.participant?.local) {
|
|
2992
|
+
if (ev.track.kind === "audio") {
|
|
2993
|
+
this._micEnabled = true;
|
|
2994
|
+
this.handleLocalAudioTrack(ev.track);
|
|
2995
|
+
} else if (ev.track.kind === "video") this._camEnabled = true;
|
|
2996
|
+
}
|
|
2997
|
+
this._callbacks.onTrackStarted?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
2020
2998
|
}
|
|
2021
2999
|
}
|
|
2022
3000
|
handleTrackStopped(ev) {
|
|
2023
|
-
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStopped?.(ev.track, ev.participant ? $
|
|
2024
|
-
else
|
|
3001
|
+
if (ev.type === "screenAudio" || ev.type === "screenVideo") this._callbacks.onScreenTrackStopped?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
3002
|
+
else {
|
|
3003
|
+
if (ev.participant?.local) {
|
|
3004
|
+
if (ev.track.kind === "audio") this._micEnabled = false;
|
|
3005
|
+
else if (ev.track.kind === "video") this._camEnabled = false;
|
|
3006
|
+
}
|
|
3007
|
+
this._callbacks.onTrackStopped?.(ev.track, ev.participant ? $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant) : undefined);
|
|
3008
|
+
}
|
|
2025
3009
|
}
|
|
2026
3010
|
handleParticipantJoined(ev) {
|
|
2027
|
-
const p = $
|
|
3011
|
+
const p = $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant);
|
|
2028
3012
|
this._callbacks.onParticipantJoined?.(p);
|
|
2029
3013
|
if (p.local) return;
|
|
2030
3014
|
this._botId = ev.participant.session_id;
|
|
2031
3015
|
this._callbacks.onBotConnected?.(p);
|
|
2032
3016
|
}
|
|
2033
3017
|
handleParticipantLeft(ev) {
|
|
2034
|
-
const p = $
|
|
3018
|
+
const p = $1c83796b12dd4e49$var$dailyParticipantToParticipant(ev.participant);
|
|
2035
3019
|
this._callbacks.onParticipantLeft?.(p);
|
|
2036
3020
|
if (p.local) return;
|
|
2037
3021
|
this._botId = "";
|
|
@@ -2046,7 +3030,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2046
3030
|
for(let i = 0; i < ids.length; i++){
|
|
2047
3031
|
const id = ids[i];
|
|
2048
3032
|
const level = ev.participantsAudioLevel[id];
|
|
2049
|
-
this._callbacks.onRemoteAudioLevel?.(level, $
|
|
3033
|
+
this._callbacks.onRemoteAudioLevel?.(level, $1c83796b12dd4e49$var$dailyParticipantToParticipant(participants[id]));
|
|
2050
3034
|
}
|
|
2051
3035
|
}
|
|
2052
3036
|
handleLeftMeeting() {
|
|
@@ -2055,10 +3039,10 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2055
3039
|
this._callbacks.onDisconnected?.();
|
|
2056
3040
|
}
|
|
2057
3041
|
handleFatalError(ev) {
|
|
2058
|
-
(0, $
|
|
3042
|
+
(0, $1clrS$pipecataiclientjs.logger).error("Daily fatal error", ev.errorMsg);
|
|
2059
3043
|
this.state = "error";
|
|
2060
3044
|
this._botId = "";
|
|
2061
|
-
this._callbacks.onError?.((0, $
|
|
3045
|
+
this._callbacks.onError?.((0, $1clrS$pipecataiclientjs.RTVIMessage).error(ev.errorMsg, true));
|
|
2062
3046
|
}
|
|
2063
3047
|
handleNonFatalError(ev) {
|
|
2064
3048
|
switch(ev.type){
|
|
@@ -2068,16 +3052,16 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
2068
3052
|
}
|
|
2069
3053
|
}
|
|
2070
3054
|
}
|
|
2071
|
-
$
|
|
2072
|
-
$
|
|
2073
|
-
const $
|
|
3055
|
+
$1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_SAMPLE_RATE = 16000;
|
|
3056
|
+
$1c83796b12dd4e49$export$b1ca982aa1e488c1.RECORDER_CHUNK_SIZE = 512;
|
|
3057
|
+
const $1c83796b12dd4e49$var$dailyParticipantToParticipant = (p)=>({
|
|
2074
3058
|
id: p.user_id,
|
|
2075
3059
|
local: p.local,
|
|
2076
3060
|
name: p.user_name
|
|
2077
3061
|
});
|
|
2078
3062
|
|
|
2079
3063
|
|
|
2080
|
-
$parcel$exportWildcard(module.exports, $
|
|
3064
|
+
$parcel$exportWildcard(module.exports, $1c83796b12dd4e49$exports);
|
|
2081
3065
|
|
|
2082
3066
|
|
|
2083
3067
|
//# sourceMappingURL=index.js.map
|