@pipecat-ai/daily-transport 0.4.0 → 1.1.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 +20 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +153 -43
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +154 -44
- package/dist/index.module.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
|
-
import { DailyCall, DailyFactoryOptions, DailyMediaDeviceInfo } from "@daily-co/daily-js";
|
|
2
|
-
import {
|
|
3
|
-
export interface
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { DailyCall, DailyCallOptions, DailyFactoryOptions, DailyMeetingSessionSummary, DailyMediaDeviceInfo } from "@daily-co/daily-js";
|
|
2
|
+
import { PipecatClientOptions, RTVIEventCallbacks, RTVIMessage, Tracks, Transport, TransportState } from "@pipecat-ai/client-js";
|
|
3
|
+
export interface DailyConnectionEndpoint {
|
|
4
|
+
endpoint: string;
|
|
5
|
+
headers?: Headers;
|
|
6
|
+
requestData?: object;
|
|
7
|
+
timeout?: number;
|
|
6
8
|
}
|
|
7
|
-
export interface DailyTransportConstructorOptions {
|
|
9
|
+
export interface DailyTransportConstructorOptions extends DailyFactoryOptions {
|
|
8
10
|
bufferLocalAudioUntilBotReady?: boolean;
|
|
9
|
-
dailyFactoryOptions?: DailyFactoryOptions;
|
|
10
11
|
}
|
|
11
12
|
export enum DailyRTVIMessageType {
|
|
12
13
|
AUDIO_BUFFERING_STARTED = "audio-buffering-started",
|
|
13
14
|
AUDIO_BUFFERING_STOPPED = "audio-buffering-stopped"
|
|
14
15
|
}
|
|
16
|
+
export type DailyEventCallbacks = RTVIEventCallbacks & Partial<{
|
|
17
|
+
onAudioBufferingStarted: () => void;
|
|
18
|
+
onAudioBufferingStopped: () => void;
|
|
19
|
+
}>;
|
|
15
20
|
export class DailyTransport extends Transport {
|
|
16
|
-
|
|
21
|
+
protected _callbacks: DailyEventCallbacks;
|
|
22
|
+
constructor(opts?: DailyTransportConstructorOptions);
|
|
17
23
|
handleUserAudioStream(data: ArrayBuffer): void;
|
|
18
24
|
_sendAudioBatch(dataBatch: ArrayBuffer[]): void;
|
|
19
|
-
initialize(options:
|
|
25
|
+
initialize(options: PipecatClientOptions, messageHandler: (ev: RTVIMessage) => void): void;
|
|
20
26
|
get dailyCallClient(): DailyCall;
|
|
21
27
|
get state(): TransportState;
|
|
22
28
|
private set state(value);
|
|
29
|
+
getSessionInfo(): DailyMeetingSessionSummary;
|
|
23
30
|
getAllCams(): Promise<DailyMediaDeviceInfo[]>;
|
|
24
31
|
updateCam(camId: string): void;
|
|
25
32
|
get selectedCam(): MediaDeviceInfo | Record<string, never>;
|
|
@@ -36,11 +43,12 @@ export class DailyTransport extends Transport {
|
|
|
36
43
|
enableScreenShare(enable: boolean): void;
|
|
37
44
|
get isSharingScreen(): boolean;
|
|
38
45
|
tracks(): Tracks;
|
|
39
|
-
preAuth(
|
|
46
|
+
preAuth(dailyCallOptions: DailyCallOptions): Promise<void>;
|
|
40
47
|
initDevices(): Promise<void>;
|
|
41
|
-
|
|
48
|
+
_validateConnectionParams(connectParams?: unknown): DailyCallOptions | undefined;
|
|
49
|
+
_connect(connectParams?: DailyCallOptions): Promise<void>;
|
|
42
50
|
sendReadyMessage(): Promise<void>;
|
|
43
|
-
|
|
51
|
+
_disconnect(): Promise<void>;
|
|
44
52
|
sendMessage(message: RTVIMessage): void;
|
|
45
53
|
}
|
|
46
54
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;
|
|
1
|
+
{"mappings":";;ASsCA;IACE,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,iDAAkD,SAAQ,mBAAmB;IAC3E,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED;IACE,uBAAuB,4BAA4B;IACnD,uBAAuB,4BAA4B;CACpD;AAED,kCAAkC,kBAAkB,GAClD,OAAO,CAAC;IACN,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,uBAAuB,EAAE,MAAM,IAAI,CAAC;CACrC,CAAC,CAAC;AAoDL,2BAA4B,SAAQ,SAAS;IAE3C,UAAkB,UAAU,EAAE,mBAAmB,CAAC;gBAkBtC,IAAI,GAAE,gCAAqC;IAuBvD,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IA2B9C,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,IAAI;IAoBxC,UAAU,CACf,OAAO,EAAE,oBAAoB,EAC7B,cAAc,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,GACxC,IAAI;IA8BP,IAAI,eAAe,IAAI,SAAS,CAE/B;IAED,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,OAAO,KAAK,KAAK,QAKhB;IAED,cAAc;IAIR,UAAU;IAKhB,SAAS,CAAC,KAAK,EAAE,MAAM;IAUvB,IAAI,WAAW,4CAEd;IAEK,UAAU;IAKhB,SAAS,CAAC,KAAK,EAAE,MAAM;IAUvB,IAAI,WAAW,4CAEd;IAEK,cAAc;IAKpB,aAAa,CAAC,SAAS,EAAE,MAAM;IAa/B,IAAI,eAAe,4CAElB;IAED,SAAS,CAAC,MAAM,EAAE,OAAO;IAIzB,IAAI,YAAY,YAEf;IAED,SAAS,CAAC,MAAM,EAAE,OAAO;IAIzB,IAAI,YAAY,YAEf;IAEM,iBAAiB,CAAC,MAAM,EAAE,OAAO;IAQxC,IAAW,eAAe,IAAI,OAAO,CAEpC;IAED,MAAM;IAuCA,OAAO,CAAC,gBAAgB,EAAE,gBAAgB;IAK1C,WAAW;IAgCjB,yBAAyB,CACvB,aAAa,CAAC,EAAE,OAAO,GACtB,gBAAgB,GAAG,SAAS;IAsBzB,QAAQ,CAAC,aAAa,CAAC,EAAE,gBAAgB;IA6BzC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IA8FjC,WAAW;IAYV,WAAW,CAAC,OAAO,EAAE,WAAW;CA8OxC","sources":["transports/lib/wavtools/lib/wav_packer.js","transports/lib/wavtools/lib/analysis/constants.js","transports/lib/wavtools/lib/analysis/audio_analysis.js","transports/lib/wavtools/lib/worklets/stream_processor.js","transports/lib/wavtools/lib/wav_stream_player.js","transports/lib/wavtools/lib/worklets/audio_processor.js","transports/lib/wavtools/lib/wav_recorder.js","transports/lib/wavtools/lib/mediastream_recorder.js","transports/lib/wavtools/index.js","transports/daily/src/src/transport.ts","transports/daily/src/src/index.ts","transports/daily/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,"export * from \"./transport\";\n"],"names":[],"version":3,"file":"index.d.ts.map"}
|
package/dist/index.js
CHANGED
|
@@ -801,6 +801,7 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
801
801
|
this.outputToSpeakers = outputToSpeakers;
|
|
802
802
|
this.debug = !!debug;
|
|
803
803
|
this._deviceChangeCallback = null;
|
|
804
|
+
this._deviceErrorCallback = null;
|
|
804
805
|
this._devices = [];
|
|
805
806
|
this.deviceSelection = null;
|
|
806
807
|
// State variables
|
|
@@ -959,21 +960,42 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
959
960
|
return true;
|
|
960
961
|
}
|
|
961
962
|
/**
|
|
963
|
+
* Provide a callback for if/when device errors occur
|
|
964
|
+
* @param {(({devices: Array<"cam" | "mic">, type: string, error?: Error}) => void) | null} callback
|
|
965
|
+
* @returns {true}
|
|
966
|
+
*/ listenForDeviceErrors(callback) {
|
|
967
|
+
this._deviceErrorCallback = callback;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
962
970
|
* Manually request permission to use the microphone
|
|
963
971
|
* @returns {Promise<true>}
|
|
964
972
|
*/ async requestPermission() {
|
|
965
973
|
const permissionStatus = await navigator.permissions.query({
|
|
966
974
|
name: 'microphone'
|
|
967
975
|
});
|
|
968
|
-
if (permissionStatus.state === 'denied')
|
|
969
|
-
|
|
976
|
+
if (permissionStatus.state === 'denied') {
|
|
977
|
+
if (this._deviceErrorCallback) this._deviceErrorCallback({
|
|
978
|
+
devices: [
|
|
979
|
+
"mic"
|
|
980
|
+
],
|
|
981
|
+
type: "unknown",
|
|
982
|
+
error: new Error("Microphone access denied")
|
|
983
|
+
});
|
|
984
|
+
} else if (permissionStatus.state === 'prompt') try {
|
|
970
985
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
971
986
|
audio: true
|
|
972
987
|
});
|
|
973
988
|
const tracks = stream.getTracks();
|
|
974
989
|
tracks.forEach((track)=>track.stop());
|
|
975
990
|
} catch (e) {
|
|
976
|
-
|
|
991
|
+
console.error("Error accessing microphone.");
|
|
992
|
+
if (this._deviceErrorCallback) this._deviceErrorCallback({
|
|
993
|
+
devices: [
|
|
994
|
+
"mic"
|
|
995
|
+
],
|
|
996
|
+
type: "unknown",
|
|
997
|
+
error: e
|
|
998
|
+
});
|
|
977
999
|
}
|
|
978
1000
|
return true;
|
|
979
1001
|
}
|
|
@@ -1010,7 +1032,16 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1010
1032
|
* @returns {Promise<true>}
|
|
1011
1033
|
*/ async begin(deviceId) {
|
|
1012
1034
|
if (this.processor) throw new Error(`Already connected: please call .end() to start a new session`);
|
|
1013
|
-
if (!navigator.mediaDevices || !('getUserMedia' in navigator.mediaDevices))
|
|
1035
|
+
if (!navigator.mediaDevices || !('getUserMedia' in navigator.mediaDevices)) {
|
|
1036
|
+
if (this._deviceErrorCallback) this._deviceErrorCallback({
|
|
1037
|
+
devices: [
|
|
1038
|
+
"mic",
|
|
1039
|
+
"cam"
|
|
1040
|
+
],
|
|
1041
|
+
type: "undefined-mediadevices"
|
|
1042
|
+
});
|
|
1043
|
+
throw new Error('Could not request user media');
|
|
1044
|
+
}
|
|
1014
1045
|
deviceId = deviceId ?? this.deviceSelection?.deviceId;
|
|
1015
1046
|
try {
|
|
1016
1047
|
const config = {
|
|
@@ -1023,6 +1054,13 @@ class $0d471c38435bdab6$export$439b217ca659a877 {
|
|
|
1023
1054
|
};
|
|
1024
1055
|
this.stream = await navigator.mediaDevices.getUserMedia(config);
|
|
1025
1056
|
} catch (err) {
|
|
1057
|
+
if (this._deviceErrorCallback) this._deviceErrorCallback({
|
|
1058
|
+
devices: [
|
|
1059
|
+
"mic"
|
|
1060
|
+
],
|
|
1061
|
+
type: "unknown",
|
|
1062
|
+
error: err
|
|
1063
|
+
});
|
|
1026
1064
|
throw new Error('Could not start media stream');
|
|
1027
1065
|
}
|
|
1028
1066
|
this.listDevices().then((devices)=>{
|
|
@@ -1444,7 +1482,7 @@ globalThis.WavRecorder = WavRecorder;
|
|
|
1444
1482
|
|
|
1445
1483
|
|
|
1446
1484
|
var $c2e964a535c1120e$exports = {};
|
|
1447
|
-
$c2e964a535c1120e$exports = JSON.parse("{\"name\":\"@pipecat-ai/daily-transport\",\"version\":\"
|
|
1485
|
+
$c2e964a535c1120e$exports = JSON.parse("{\"name\":\"@pipecat-ai/daily-transport\",\"version\":\"1.1.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\"},\"files\":[\"dist\",\"package.json\",\"README.md\"],\"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.1.0\",\"eslint\":\"9.11.1\",\"eslint-config-prettier\":\"^9.1.0\",\"eslint-plugin-simple-import-sort\":\"^12.1.1\"},\"peerDependencies\":{\"@pipecat-ai/client-js\":\"~1.1.0\"},\"dependencies\":{\"@daily-co/daily-js\":\"^0.77.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\"}");
|
|
1448
1486
|
|
|
1449
1487
|
|
|
1450
1488
|
var $28bdeb35415d61e8$export$ef180de88fd317cc;
|
|
@@ -1461,18 +1499,18 @@ class $28bdeb35415d61e8$var$DailyCallWrapper {
|
|
|
1461
1499
|
let errMsg;
|
|
1462
1500
|
switch(String(prop)){
|
|
1463
1501
|
// Disable methods that modify the lifecycle of the call. These operations
|
|
1464
|
-
// should be performed via the
|
|
1502
|
+
// should be performed via the PipecatClient in order to keep state in sync.
|
|
1465
1503
|
case "preAuth":
|
|
1466
1504
|
errMsg = `Calls to preAuth() are disabled. Please use Transport.preAuth()`;
|
|
1467
1505
|
break;
|
|
1468
1506
|
case "startCamera":
|
|
1469
|
-
errMsg = `Calls to startCamera() are disabled. Please use
|
|
1507
|
+
errMsg = `Calls to startCamera() are disabled. Please use PipecatClient.initDevices()`;
|
|
1470
1508
|
break;
|
|
1471
1509
|
case "join":
|
|
1472
|
-
errMsg = `Calls to join() are disabled. Please use
|
|
1510
|
+
errMsg = `Calls to join() are disabled. Please use PipecatClient.connect()`;
|
|
1473
1511
|
break;
|
|
1474
1512
|
case "leave":
|
|
1475
|
-
errMsg = `Calls to leave() are disabled. Please use
|
|
1513
|
+
errMsg = `Calls to leave() are disabled. Please use PipecatClient.disconnect()`;
|
|
1476
1514
|
break;
|
|
1477
1515
|
case "destroy":
|
|
1478
1516
|
errMsg = `Calls to destroy() are disabled.`;
|
|
@@ -1496,7 +1534,7 @@ class $28bdeb35415d61e8$var$DailyCallWrapper {
|
|
|
1496
1534
|
}
|
|
1497
1535
|
}
|
|
1498
1536
|
class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclientjs.Transport) {
|
|
1499
|
-
constructor(
|
|
1537
|
+
constructor(opts = {}){
|
|
1500
1538
|
super();
|
|
1501
1539
|
this._botId = "";
|
|
1502
1540
|
this._selectedCam = {};
|
|
@@ -1505,8 +1543,9 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1505
1543
|
this._currentAudioTrack = null;
|
|
1506
1544
|
this._audioQueue = [];
|
|
1507
1545
|
this._callbacks = {};
|
|
1508
|
-
|
|
1509
|
-
this.
|
|
1546
|
+
const { bufferLocalAudioUntilBotReady: bufferLocalAudioUntilBotReady, ...dailyOpts } = opts;
|
|
1547
|
+
this._dailyFactoryOptions = dailyOpts;
|
|
1548
|
+
this._bufferLocalAudioUntilBotReady = bufferLocalAudioUntilBotReady || false;
|
|
1510
1549
|
this._daily = (0, ($parcel$interopDefault($jrPAn$dailycodailyjs))).createCallObject({
|
|
1511
1550
|
...this._dailyFactoryOptions,
|
|
1512
1551
|
allowMultipleCallInstances: true
|
|
@@ -1540,7 +1579,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1540
1579
|
const pcmByteArray = new Uint8Array(data);
|
|
1541
1580
|
return btoa(String.fromCharCode(...pcmByteArray));
|
|
1542
1581
|
});
|
|
1543
|
-
const
|
|
1582
|
+
const audioMessage = {
|
|
1544
1583
|
id: "raw-audio-batch",
|
|
1545
1584
|
label: "rtvi-ai",
|
|
1546
1585
|
type: "raw-audio-batch",
|
|
@@ -1550,7 +1589,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1550
1589
|
numChannels: 1
|
|
1551
1590
|
}
|
|
1552
1591
|
};
|
|
1553
|
-
this.sendMessage(
|
|
1592
|
+
this.sendMessage(audioMessage);
|
|
1554
1593
|
}
|
|
1555
1594
|
initialize(options, messageHandler) {
|
|
1556
1595
|
if (this._bufferLocalAudioUntilBotReady) this.setupRecorder();
|
|
@@ -1562,7 +1601,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1562
1601
|
this._dailyFactoryOptions.startAudioOff = !(options.enableMic ?? true);
|
|
1563
1602
|
this.attachEventListeners();
|
|
1564
1603
|
this.state = "disconnected";
|
|
1565
|
-
(0, $jrPAn$pipecataiclientjs.logger).debug("[
|
|
1604
|
+
(0, $jrPAn$pipecataiclientjs.logger).debug("[Daily Transport] Initialized", (0, (/*@__PURE__*/$parcel$interopDefault($c2e964a535c1120e$exports))).version);
|
|
1566
1605
|
}
|
|
1567
1606
|
get dailyCallClient() {
|
|
1568
1607
|
return this._dailyWrapper.proxy;
|
|
@@ -1575,6 +1614,9 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1575
1614
|
this._state = state;
|
|
1576
1615
|
this._callbacks.onTransportStateChanged?.(state);
|
|
1577
1616
|
}
|
|
1617
|
+
getSessionInfo() {
|
|
1618
|
+
return this._daily.meetingSessionSummary();
|
|
1619
|
+
}
|
|
1578
1620
|
async getAllCams() {
|
|
1579
1621
|
const { devices: devices } = await this._daily.enumerateDevices();
|
|
1580
1622
|
return devices.filter((d)=>d.kind === "videoinput");
|
|
@@ -1612,6 +1654,10 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1612
1654
|
outputDeviceId: speakerId
|
|
1613
1655
|
}).then((infos)=>{
|
|
1614
1656
|
this._selectedSpeaker = infos.speaker;
|
|
1657
|
+
}).catch((e)=>{
|
|
1658
|
+
this._callbacks.onDeviceError?.(new (0, $jrPAn$pipecataiclientjs.DeviceError)([
|
|
1659
|
+
"speaker"
|
|
1660
|
+
], e.type ?? "unknown", e.message));
|
|
1615
1661
|
});
|
|
1616
1662
|
}
|
|
1617
1663
|
get selectedSpeaker() {
|
|
@@ -1655,23 +1701,20 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1655
1701
|
}
|
|
1656
1702
|
async startRecording() {
|
|
1657
1703
|
try {
|
|
1658
|
-
(0, $jrPAn$pipecataiclientjs.logger).info("[
|
|
1704
|
+
(0, $jrPAn$pipecataiclientjs.logger).info("[Daily Transport] Initializing recording");
|
|
1659
1705
|
await this._mediaStreamRecorder.record((data)=>{
|
|
1660
1706
|
this.handleUserAudioStream(data.mono);
|
|
1661
1707
|
}, $28bdeb35415d61e8$export$b1ca982aa1e488c1.RECORDER_CHUNK_SIZE);
|
|
1662
|
-
this.
|
|
1663
|
-
|
|
1664
|
-
data: {}
|
|
1665
|
-
});
|
|
1666
|
-
(0, $jrPAn$pipecataiclientjs.logger).info("[RTVI Transport] Recording Initialized");
|
|
1708
|
+
this._callbacks.onAudioBufferingStarted?.();
|
|
1709
|
+
(0, $jrPAn$pipecataiclientjs.logger).info("[Daily Transport] Recording Initialized");
|
|
1667
1710
|
} catch (e) {
|
|
1668
1711
|
const err = e;
|
|
1669
1712
|
if (!err.message.includes("Already recording")) (0, $jrPAn$pipecataiclientjs.logger).error("Error starting recording", e);
|
|
1670
1713
|
}
|
|
1671
1714
|
}
|
|
1672
|
-
async preAuth(
|
|
1673
|
-
this._dailyFactoryOptions =
|
|
1674
|
-
await this._daily.preAuth(
|
|
1715
|
+
async preAuth(dailyCallOptions) {
|
|
1716
|
+
this._dailyFactoryOptions = dailyCallOptions;
|
|
1717
|
+
await this._daily.preAuth(dailyCallOptions);
|
|
1675
1718
|
}
|
|
1676
1719
|
async initDevices() {
|
|
1677
1720
|
if (!this._daily) throw new (0, $jrPAn$pipecataiclientjs.RTVIError)("Transport instance not initialized");
|
|
@@ -1695,23 +1738,33 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1695
1738
|
if (!this._daily.isRemoteParticipantsAudioLevelObserverRunning()) await this._daily.startRemoteParticipantsAudioLevelObserver(100);
|
|
1696
1739
|
this.state = "initialized";
|
|
1697
1740
|
}
|
|
1698
|
-
|
|
1741
|
+
_validateConnectionParams(connectParams) {
|
|
1742
|
+
if (connectParams === undefined || connectParams === null) return undefined;
|
|
1743
|
+
if (typeof connectParams !== "object") throw new (0, $jrPAn$pipecataiclientjs.RTVIError)("Invalid connection parameters");
|
|
1744
|
+
const tmpParams = connectParams;
|
|
1745
|
+
if (tmpParams.room_url) {
|
|
1746
|
+
tmpParams.url = tmpParams.room_url;
|
|
1747
|
+
delete tmpParams.room_url;
|
|
1748
|
+
}
|
|
1749
|
+
if (!tmpParams.token) // Daily doesn't like token being in the map and undefined or null
|
|
1750
|
+
delete tmpParams.token;
|
|
1751
|
+
return tmpParams;
|
|
1752
|
+
}
|
|
1753
|
+
async _connect(connectParams) {
|
|
1699
1754
|
if (!this._daily) throw new (0, $jrPAn$pipecataiclientjs.RTVIError)("Transport instance not initialized");
|
|
1700
|
-
if (
|
|
1755
|
+
if (connectParams) this._dailyFactoryOptions = {
|
|
1756
|
+
...this._dailyFactoryOptions,
|
|
1757
|
+
...connectParams
|
|
1758
|
+
};
|
|
1701
1759
|
this.state = "connecting";
|
|
1702
|
-
const opts = this._dailyFactoryOptions;
|
|
1703
|
-
opts.url = authBundle.room_url ?? opts.url;
|
|
1704
|
-
if (authBundle.token != null) opts.token = authBundle.token;
|
|
1705
1760
|
try {
|
|
1706
|
-
await this._daily.join(
|
|
1707
|
-
const room = await this._daily.room();
|
|
1708
|
-
if (room && "id" in room) this._expiry = room.config?.exp;
|
|
1761
|
+
await this._daily.join(this._dailyFactoryOptions);
|
|
1709
1762
|
} catch (e) {
|
|
1710
1763
|
(0, $jrPAn$pipecataiclientjs.logger).error("Failed to join room", e);
|
|
1711
1764
|
this.state = "error";
|
|
1712
1765
|
throw new (0, $jrPAn$pipecataiclientjs.TransportStartError)();
|
|
1713
1766
|
}
|
|
1714
|
-
if (
|
|
1767
|
+
if (this._abortController?.signal.aborted) return;
|
|
1715
1768
|
this.state = "connected";
|
|
1716
1769
|
this._callbacks.onConnected?.();
|
|
1717
1770
|
}
|
|
@@ -1729,12 +1782,21 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1729
1782
|
this.stopRecording();
|
|
1730
1783
|
resolve();
|
|
1731
1784
|
};
|
|
1785
|
+
for(const id in this._daily.participants()){
|
|
1786
|
+
const p = this._daily.participants()[id];
|
|
1787
|
+
if (!p.local && p.tracks?.audio?.persistentTrack) {
|
|
1788
|
+
// If we already have a remote audio track, we can send the ready message immediately
|
|
1789
|
+
sendReadyMessage();
|
|
1790
|
+
resolve();
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1732
1794
|
const readyHandler = (ev)=>{
|
|
1733
1795
|
if (!ev.participant?.local) {
|
|
1734
1796
|
this._daily.off("track-started", readyHandler);
|
|
1735
1797
|
// Check if it's an iOS device
|
|
1736
1798
|
if (isIOS()) {
|
|
1737
|
-
(0, $jrPAn$pipecataiclientjs.logger).debug("[
|
|
1799
|
+
(0, $jrPAn$pipecataiclientjs.logger).debug("[Daily Transport] iOS device detected, adding 0.5 second delay before sending ready message");
|
|
1738
1800
|
// Add 500ms delay for iOS devices:
|
|
1739
1801
|
// This is a workaround for iOS devices clipping a portion
|
|
1740
1802
|
// of the audio after the track becomes playable.
|
|
@@ -1750,15 +1812,13 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1750
1812
|
if (this._mediaStreamRecorder && this._mediaStreamRecorder.getStatus() !== "ended") {
|
|
1751
1813
|
// disconnecting, we don't need to record anymore
|
|
1752
1814
|
this._mediaStreamRecorder.end();
|
|
1753
|
-
this.
|
|
1754
|
-
type: $28bdeb35415d61e8$export$ef180de88fd317cc.AUDIO_BUFFERING_STOPPED,
|
|
1755
|
-
data: {}
|
|
1756
|
-
});
|
|
1815
|
+
this._callbacks.onAudioBufferingStopped?.();
|
|
1757
1816
|
}
|
|
1758
1817
|
}
|
|
1759
1818
|
attachEventListeners() {
|
|
1760
1819
|
this._daily.on("available-devices-updated", this.handleAvailableDevicesUpdated.bind(this));
|
|
1761
1820
|
this._daily.on("selected-devices-updated", this.handleSelectedDevicesUpdated.bind(this));
|
|
1821
|
+
this._daily.on("camera-error", this.handleDeviceError.bind(this));
|
|
1762
1822
|
this._daily.on("track-started", this.handleTrackStarted.bind(this));
|
|
1763
1823
|
this._daily.on("track-stopped", this.handleTrackStopped.bind(this));
|
|
1764
1824
|
this._daily.on("participant-joined", this.handleParticipantJoined.bind(this));
|
|
@@ -1770,7 +1830,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1770
1830
|
this._daily.on("error", this.handleFatalError.bind(this));
|
|
1771
1831
|
this._daily.on("nonfatal-error", this.handleNonFatalError.bind(this));
|
|
1772
1832
|
}
|
|
1773
|
-
async
|
|
1833
|
+
async _disconnect() {
|
|
1774
1834
|
this.state = "disconnecting";
|
|
1775
1835
|
this._daily.stopLocalAudioLevelObserver();
|
|
1776
1836
|
this._daily.stopRemoteParticipantsAudioLevelObserver();
|
|
@@ -1809,24 +1869,74 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1809
1869
|
this._callbacks.onSpeakerUpdated?.(ev.devices.speaker);
|
|
1810
1870
|
}
|
|
1811
1871
|
}
|
|
1872
|
+
handleDeviceError(ev) {
|
|
1873
|
+
const generateDeviceError = (error)=>{
|
|
1874
|
+
const devices = [];
|
|
1875
|
+
switch(error.type){
|
|
1876
|
+
case "permissions":
|
|
1877
|
+
error.blockedMedia.forEach((d)=>{
|
|
1878
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1879
|
+
});
|
|
1880
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1881
|
+
blockedBy: error.blockedBy
|
|
1882
|
+
});
|
|
1883
|
+
case "not-found":
|
|
1884
|
+
error.missingMedia.forEach((d)=>{
|
|
1885
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1886
|
+
});
|
|
1887
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1888
|
+
case "constraints":
|
|
1889
|
+
error.failedMedia.forEach((d)=>{
|
|
1890
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1891
|
+
});
|
|
1892
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1893
|
+
reason: error.reason
|
|
1894
|
+
});
|
|
1895
|
+
case "cam-in-use":
|
|
1896
|
+
devices.push("cam");
|
|
1897
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1898
|
+
case "mic-in-use":
|
|
1899
|
+
devices.push("mic");
|
|
1900
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1901
|
+
case "cam-mic-in-use":
|
|
1902
|
+
devices.push("cam");
|
|
1903
|
+
devices.push("mic");
|
|
1904
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1905
|
+
case "undefined-mediadevices":
|
|
1906
|
+
case "unknown":
|
|
1907
|
+
default:
|
|
1908
|
+
devices.push("cam");
|
|
1909
|
+
devices.push("mic");
|
|
1910
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
this._callbacks.onDeviceError?.(generateDeviceError(ev.error));
|
|
1914
|
+
}
|
|
1812
1915
|
async handleLocalAudioTrack(track) {
|
|
1813
1916
|
if (this.state == "ready" || !this._bufferLocalAudioUntilBotReady) return;
|
|
1814
1917
|
const status = this._mediaStreamRecorder.getStatus();
|
|
1815
1918
|
switch(status){
|
|
1816
1919
|
case "ended":
|
|
1817
|
-
|
|
1818
|
-
|
|
1920
|
+
try {
|
|
1921
|
+
await this._mediaStreamRecorder.begin(track);
|
|
1922
|
+
await this.startRecording();
|
|
1923
|
+
} catch (e) {
|
|
1924
|
+
// void. nothing to do.
|
|
1925
|
+
}
|
|
1819
1926
|
break;
|
|
1820
1927
|
case "paused":
|
|
1821
1928
|
await this.startRecording();
|
|
1822
1929
|
break;
|
|
1823
1930
|
case "recording":
|
|
1824
1931
|
default:
|
|
1825
|
-
if (this._currentAudioTrack !== track) {
|
|
1932
|
+
if (this._currentAudioTrack !== track) try {
|
|
1826
1933
|
await this._mediaStreamRecorder.end();
|
|
1827
1934
|
await this._mediaStreamRecorder.begin(track);
|
|
1828
1935
|
await this.startRecording();
|
|
1829
|
-
}
|
|
1936
|
+
} catch (e) {
|
|
1937
|
+
// void. nothing to do.
|
|
1938
|
+
}
|
|
1939
|
+
else (0, $jrPAn$pipecataiclientjs.logger).warn("track-started event received for current track and already recording");
|
|
1830
1940
|
break;
|
|
1831
1941
|
}
|
|
1832
1942
|
this._currentAudioTrack = track;
|