@pipecat-ai/daily-transport 1.0.0 → 1.2.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/README.md +11 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +109 -9
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +110 -10
- package/dist/index.module.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,30 +33,26 @@ The DailyTransport class provides a WebRTC transport layer using [Daily.co's](ht
|
|
|
33
33
|
### Basic Setup
|
|
34
34
|
|
|
35
35
|
```javascript
|
|
36
|
-
import {
|
|
36
|
+
import { PipecatClient } from "@pipecat-ai/client-js";
|
|
37
37
|
import { DailyTransport } from "@pipecat-ai/daily-transport";
|
|
38
38
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
// Daily.co specific configuration
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const rtviClient = new RTVIClient({
|
|
46
|
-
transport,
|
|
39
|
+
const pcClient = new PipecatClient({
|
|
40
|
+
transport: new DailyTransport({ dailyFactoryOptions }),
|
|
47
41
|
enableCam: false, // Default camera off
|
|
48
42
|
enableMic: true, // Default microphone on
|
|
49
43
|
callbacks: {
|
|
50
44
|
// Event handlers
|
|
51
45
|
},
|
|
52
|
-
params: {
|
|
53
|
-
baseUrl,
|
|
54
|
-
endpoints
|
|
55
|
-
}
|
|
56
46
|
// ...
|
|
57
47
|
});
|
|
58
48
|
|
|
59
|
-
|
|
49
|
+
pcClient.connect({
|
|
50
|
+
url: 'https://your.daily.co/room'
|
|
51
|
+
});
|
|
52
|
+
// OR...
|
|
53
|
+
pcClient.connect({
|
|
54
|
+
endpoint: 'https://your-server/connect', // endpoint to return url
|
|
55
|
+
});
|
|
60
56
|
```
|
|
61
57
|
|
|
62
58
|
## API Reference
|
|
@@ -82,7 +78,7 @@ The transport can be in one of these states:
|
|
|
82
78
|
|
|
83
79
|
## Events
|
|
84
80
|
|
|
85
|
-
The transport implements the various [
|
|
81
|
+
The transport implements the various [Pipecat event handlers](https://docs.pipecat.ai/client/js/api-reference/callbacks). Check out the docs or samples for more info.
|
|
86
82
|
|
|
87
83
|
## Error Handling
|
|
88
84
|
|
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;IA+BzB,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\":\"1.
|
|
1485
|
+
$c2e964a535c1120e$exports = JSON.parse("{\"name\":\"@pipecat-ai/daily-transport\",\"version\":\"1.2.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.2.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.2.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;
|
|
@@ -1616,6 +1654,10 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1616
1654
|
outputDeviceId: speakerId
|
|
1617
1655
|
}).then((infos)=>{
|
|
1618
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));
|
|
1619
1661
|
});
|
|
1620
1662
|
}
|
|
1621
1663
|
get selectedSpeaker() {
|
|
@@ -1703,6 +1745,13 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1703
1745
|
if (tmpParams.room_url) {
|
|
1704
1746
|
tmpParams.url = tmpParams.room_url;
|
|
1705
1747
|
delete tmpParams.room_url;
|
|
1748
|
+
} else if (tmpParams.dailyRoom) {
|
|
1749
|
+
tmpParams.url = tmpParams.dailyRoom;
|
|
1750
|
+
delete tmpParams.dailyRoom;
|
|
1751
|
+
}
|
|
1752
|
+
if (tmpParams.dailyToken) {
|
|
1753
|
+
tmpParams.token = tmpParams.dailyToken;
|
|
1754
|
+
delete tmpParams.dailyToken;
|
|
1706
1755
|
}
|
|
1707
1756
|
if (!tmpParams.token) // Daily doesn't like token being in the map and undefined or null
|
|
1708
1757
|
delete tmpParams.token;
|
|
@@ -1776,6 +1825,7 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1776
1825
|
attachEventListeners() {
|
|
1777
1826
|
this._daily.on("available-devices-updated", this.handleAvailableDevicesUpdated.bind(this));
|
|
1778
1827
|
this._daily.on("selected-devices-updated", this.handleSelectedDevicesUpdated.bind(this));
|
|
1828
|
+
this._daily.on("camera-error", this.handleDeviceError.bind(this));
|
|
1779
1829
|
this._daily.on("track-started", this.handleTrackStarted.bind(this));
|
|
1780
1830
|
this._daily.on("track-stopped", this.handleTrackStopped.bind(this));
|
|
1781
1831
|
this._daily.on("participant-joined", this.handleParticipantJoined.bind(this));
|
|
@@ -1826,24 +1876,74 @@ class $28bdeb35415d61e8$export$b1ca982aa1e488c1 extends (0, $jrPAn$pipecataiclie
|
|
|
1826
1876
|
this._callbacks.onSpeakerUpdated?.(ev.devices.speaker);
|
|
1827
1877
|
}
|
|
1828
1878
|
}
|
|
1879
|
+
handleDeviceError(ev) {
|
|
1880
|
+
const generateDeviceError = (error)=>{
|
|
1881
|
+
const devices = [];
|
|
1882
|
+
switch(error.type){
|
|
1883
|
+
case "permissions":
|
|
1884
|
+
error.blockedMedia.forEach((d)=>{
|
|
1885
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1886
|
+
});
|
|
1887
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1888
|
+
blockedBy: error.blockedBy
|
|
1889
|
+
});
|
|
1890
|
+
case "not-found":
|
|
1891
|
+
error.missingMedia.forEach((d)=>{
|
|
1892
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1893
|
+
});
|
|
1894
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1895
|
+
case "constraints":
|
|
1896
|
+
error.failedMedia.forEach((d)=>{
|
|
1897
|
+
devices.push(d === "video" ? "cam" : "mic");
|
|
1898
|
+
});
|
|
1899
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg, {
|
|
1900
|
+
reason: error.reason
|
|
1901
|
+
});
|
|
1902
|
+
case "cam-in-use":
|
|
1903
|
+
devices.push("cam");
|
|
1904
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1905
|
+
case "mic-in-use":
|
|
1906
|
+
devices.push("mic");
|
|
1907
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1908
|
+
case "cam-mic-in-use":
|
|
1909
|
+
devices.push("cam");
|
|
1910
|
+
devices.push("mic");
|
|
1911
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, "in-use", error.msg);
|
|
1912
|
+
case "undefined-mediadevices":
|
|
1913
|
+
case "unknown":
|
|
1914
|
+
default:
|
|
1915
|
+
devices.push("cam");
|
|
1916
|
+
devices.push("mic");
|
|
1917
|
+
return new (0, $jrPAn$pipecataiclientjs.DeviceError)(devices, error.type, error.msg);
|
|
1918
|
+
}
|
|
1919
|
+
};
|
|
1920
|
+
this._callbacks.onDeviceError?.(generateDeviceError(ev.error));
|
|
1921
|
+
}
|
|
1829
1922
|
async handleLocalAudioTrack(track) {
|
|
1830
1923
|
if (this.state == "ready" || !this._bufferLocalAudioUntilBotReady) return;
|
|
1831
1924
|
const status = this._mediaStreamRecorder.getStatus();
|
|
1832
1925
|
switch(status){
|
|
1833
1926
|
case "ended":
|
|
1834
|
-
|
|
1835
|
-
|
|
1927
|
+
try {
|
|
1928
|
+
await this._mediaStreamRecorder.begin(track);
|
|
1929
|
+
await this.startRecording();
|
|
1930
|
+
} catch (e) {
|
|
1931
|
+
// void. nothing to do.
|
|
1932
|
+
}
|
|
1836
1933
|
break;
|
|
1837
1934
|
case "paused":
|
|
1838
1935
|
await this.startRecording();
|
|
1839
1936
|
break;
|
|
1840
1937
|
case "recording":
|
|
1841
1938
|
default:
|
|
1842
|
-
if (this._currentAudioTrack !== track) {
|
|
1939
|
+
if (this._currentAudioTrack !== track) try {
|
|
1843
1940
|
await this._mediaStreamRecorder.end();
|
|
1844
1941
|
await this._mediaStreamRecorder.begin(track);
|
|
1845
1942
|
await this.startRecording();
|
|
1846
|
-
}
|
|
1943
|
+
} catch (e) {
|
|
1944
|
+
// void. nothing to do.
|
|
1945
|
+
}
|
|
1946
|
+
else (0, $jrPAn$pipecataiclientjs.logger).warn("track-started event received for current track and already recording");
|
|
1847
1947
|
break;
|
|
1848
1948
|
}
|
|
1849
1949
|
this._currentAudioTrack = track;
|