@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 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 { RTVIClient } from "@pipecat-ai/client-js";
36
+ import { PipecatClient } from "@pipecat-ai/client-js";
37
37
  import { DailyTransport } from "@pipecat-ai/daily-transport";
38
38
 
39
- const transport = new DailyTransport({
40
- dailyFactoryOptions: {
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
- await rtviClient.connect();
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 [RTVI event handlers](https://docs.pipecat.ai/client/js/api-reference/callbacks). Check out the docs or samples for more info.
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
 
@@ -1 +1 @@
1
- {"mappings":";;ASiCA;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;IAQ/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;IA6FjC,WAAW;IAYV,WAAW,CAAC,OAAO,EAAE,WAAW;CAiLxC","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"}
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') window.alert('You must grant microphone access to use this feature.');
969
- else if (permissionStatus.state === 'prompt') try {
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
- window.alert('You must grant microphone access to use this feature.');
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)) throw new Error('Could not request user media');
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.0.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.0.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.0.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\"}");
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
- await this._mediaStreamRecorder.begin(track);
1835
- await this.startRecording();
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
- } else (0, $jrPAn$pipecataiclientjs.logger).warn("track-started event received for current track and already recording");
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;