@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.
@@ -1,5 +1,5 @@
1
1
  import $7zbD8$dailycodailyjs from "@daily-co/daily-js";
2
- import {logger as $7zbD8$logger, RTVIError as $7zbD8$RTVIError, TransportStartError as $7zbD8$TransportStartError, RTVIMessage as $7zbD8$RTVIMessage, Transport as $7zbD8$Transport} from "@pipecat-ai/client-js";
2
+ import {logger as $7zbD8$logger, DeviceError as $7zbD8$DeviceError, RTVIError as $7zbD8$RTVIError, TransportStartError as $7zbD8$TransportStartError, RTVIMessage as $7zbD8$RTVIMessage, Transport as $7zbD8$Transport} from "@pipecat-ai/client-js";
3
3
 
4
4
 
5
5
  function $parcel$interopDefault(a) {
@@ -784,6 +784,7 @@ class $62bc376044a05513$export$439b217ca659a877 {
784
784
  this.outputToSpeakers = outputToSpeakers;
785
785
  this.debug = !!debug;
786
786
  this._deviceChangeCallback = null;
787
+ this._deviceErrorCallback = null;
787
788
  this._devices = [];
788
789
  this.deviceSelection = null;
789
790
  // State variables
@@ -942,21 +943,42 @@ class $62bc376044a05513$export$439b217ca659a877 {
942
943
  return true;
943
944
  }
944
945
  /**
946
+ * Provide a callback for if/when device errors occur
947
+ * @param {(({devices: Array<"cam" | "mic">, type: string, error?: Error}) => void) | null} callback
948
+ * @returns {true}
949
+ */ listenForDeviceErrors(callback) {
950
+ this._deviceErrorCallback = callback;
951
+ }
952
+ /**
945
953
  * Manually request permission to use the microphone
946
954
  * @returns {Promise<true>}
947
955
  */ async requestPermission() {
948
956
  const permissionStatus = await navigator.permissions.query({
949
957
  name: 'microphone'
950
958
  });
951
- if (permissionStatus.state === 'denied') window.alert('You must grant microphone access to use this feature.');
952
- else if (permissionStatus.state === 'prompt') try {
959
+ if (permissionStatus.state === 'denied') {
960
+ if (this._deviceErrorCallback) this._deviceErrorCallback({
961
+ devices: [
962
+ "mic"
963
+ ],
964
+ type: "unknown",
965
+ error: new Error("Microphone access denied")
966
+ });
967
+ } else if (permissionStatus.state === 'prompt') try {
953
968
  const stream = await navigator.mediaDevices.getUserMedia({
954
969
  audio: true
955
970
  });
956
971
  const tracks = stream.getTracks();
957
972
  tracks.forEach((track)=>track.stop());
958
973
  } catch (e) {
959
- window.alert('You must grant microphone access to use this feature.');
974
+ console.error("Error accessing microphone.");
975
+ if (this._deviceErrorCallback) this._deviceErrorCallback({
976
+ devices: [
977
+ "mic"
978
+ ],
979
+ type: "unknown",
980
+ error: e
981
+ });
960
982
  }
961
983
  return true;
962
984
  }
@@ -993,7 +1015,16 @@ class $62bc376044a05513$export$439b217ca659a877 {
993
1015
  * @returns {Promise<true>}
994
1016
  */ async begin(deviceId) {
995
1017
  if (this.processor) throw new Error(`Already connected: please call .end() to start a new session`);
996
- if (!navigator.mediaDevices || !('getUserMedia' in navigator.mediaDevices)) throw new Error('Could not request user media');
1018
+ if (!navigator.mediaDevices || !('getUserMedia' in navigator.mediaDevices)) {
1019
+ if (this._deviceErrorCallback) this._deviceErrorCallback({
1020
+ devices: [
1021
+ "mic",
1022
+ "cam"
1023
+ ],
1024
+ type: "undefined-mediadevices"
1025
+ });
1026
+ throw new Error('Could not request user media');
1027
+ }
997
1028
  deviceId = deviceId ?? this.deviceSelection?.deviceId;
998
1029
  try {
999
1030
  const config = {
@@ -1006,6 +1037,13 @@ class $62bc376044a05513$export$439b217ca659a877 {
1006
1037
  };
1007
1038
  this.stream = await navigator.mediaDevices.getUserMedia(config);
1008
1039
  } catch (err) {
1040
+ if (this._deviceErrorCallback) this._deviceErrorCallback({
1041
+ devices: [
1042
+ "mic"
1043
+ ],
1044
+ type: "unknown",
1045
+ error: err
1046
+ });
1009
1047
  throw new Error('Could not start media stream');
1010
1048
  }
1011
1049
  this.listDevices().then((devices)=>{
@@ -1427,7 +1465,7 @@ globalThis.WavRecorder = WavRecorder;
1427
1465
 
1428
1466
 
1429
1467
  var $58d19ff082af5e5c$exports = {};
1430
- $58d19ff082af5e5c$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\"}");
1468
+ $58d19ff082af5e5c$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\"}");
1431
1469
 
1432
1470
 
1433
1471
  var $683f111f61e07358$export$ef180de88fd317cc;
@@ -1599,6 +1637,10 @@ class $683f111f61e07358$export$b1ca982aa1e488c1 extends (0, $7zbD8$Transport) {
1599
1637
  outputDeviceId: speakerId
1600
1638
  }).then((infos)=>{
1601
1639
  this._selectedSpeaker = infos.speaker;
1640
+ }).catch((e)=>{
1641
+ this._callbacks.onDeviceError?.(new (0, $7zbD8$DeviceError)([
1642
+ "speaker"
1643
+ ], e.type ?? "unknown", e.message));
1602
1644
  });
1603
1645
  }
1604
1646
  get selectedSpeaker() {
@@ -1686,6 +1728,13 @@ class $683f111f61e07358$export$b1ca982aa1e488c1 extends (0, $7zbD8$Transport) {
1686
1728
  if (tmpParams.room_url) {
1687
1729
  tmpParams.url = tmpParams.room_url;
1688
1730
  delete tmpParams.room_url;
1731
+ } else if (tmpParams.dailyRoom) {
1732
+ tmpParams.url = tmpParams.dailyRoom;
1733
+ delete tmpParams.dailyRoom;
1734
+ }
1735
+ if (tmpParams.dailyToken) {
1736
+ tmpParams.token = tmpParams.dailyToken;
1737
+ delete tmpParams.dailyToken;
1689
1738
  }
1690
1739
  if (!tmpParams.token) // Daily doesn't like token being in the map and undefined or null
1691
1740
  delete tmpParams.token;
@@ -1759,6 +1808,7 @@ class $683f111f61e07358$export$b1ca982aa1e488c1 extends (0, $7zbD8$Transport) {
1759
1808
  attachEventListeners() {
1760
1809
  this._daily.on("available-devices-updated", this.handleAvailableDevicesUpdated.bind(this));
1761
1810
  this._daily.on("selected-devices-updated", this.handleSelectedDevicesUpdated.bind(this));
1811
+ this._daily.on("camera-error", this.handleDeviceError.bind(this));
1762
1812
  this._daily.on("track-started", this.handleTrackStarted.bind(this));
1763
1813
  this._daily.on("track-stopped", this.handleTrackStopped.bind(this));
1764
1814
  this._daily.on("participant-joined", this.handleParticipantJoined.bind(this));
@@ -1809,24 +1859,74 @@ class $683f111f61e07358$export$b1ca982aa1e488c1 extends (0, $7zbD8$Transport) {
1809
1859
  this._callbacks.onSpeakerUpdated?.(ev.devices.speaker);
1810
1860
  }
1811
1861
  }
1862
+ handleDeviceError(ev) {
1863
+ const generateDeviceError = (error)=>{
1864
+ const devices = [];
1865
+ switch(error.type){
1866
+ case "permissions":
1867
+ error.blockedMedia.forEach((d)=>{
1868
+ devices.push(d === "video" ? "cam" : "mic");
1869
+ });
1870
+ return new (0, $7zbD8$DeviceError)(devices, error.type, error.msg, {
1871
+ blockedBy: error.blockedBy
1872
+ });
1873
+ case "not-found":
1874
+ error.missingMedia.forEach((d)=>{
1875
+ devices.push(d === "video" ? "cam" : "mic");
1876
+ });
1877
+ return new (0, $7zbD8$DeviceError)(devices, error.type, error.msg);
1878
+ case "constraints":
1879
+ error.failedMedia.forEach((d)=>{
1880
+ devices.push(d === "video" ? "cam" : "mic");
1881
+ });
1882
+ return new (0, $7zbD8$DeviceError)(devices, error.type, error.msg, {
1883
+ reason: error.reason
1884
+ });
1885
+ case "cam-in-use":
1886
+ devices.push("cam");
1887
+ return new (0, $7zbD8$DeviceError)(devices, "in-use", error.msg);
1888
+ case "mic-in-use":
1889
+ devices.push("mic");
1890
+ return new (0, $7zbD8$DeviceError)(devices, "in-use", error.msg);
1891
+ case "cam-mic-in-use":
1892
+ devices.push("cam");
1893
+ devices.push("mic");
1894
+ return new (0, $7zbD8$DeviceError)(devices, "in-use", error.msg);
1895
+ case "undefined-mediadevices":
1896
+ case "unknown":
1897
+ default:
1898
+ devices.push("cam");
1899
+ devices.push("mic");
1900
+ return new (0, $7zbD8$DeviceError)(devices, error.type, error.msg);
1901
+ }
1902
+ };
1903
+ this._callbacks.onDeviceError?.(generateDeviceError(ev.error));
1904
+ }
1812
1905
  async handleLocalAudioTrack(track) {
1813
1906
  if (this.state == "ready" || !this._bufferLocalAudioUntilBotReady) return;
1814
1907
  const status = this._mediaStreamRecorder.getStatus();
1815
1908
  switch(status){
1816
1909
  case "ended":
1817
- await this._mediaStreamRecorder.begin(track);
1818
- await this.startRecording();
1910
+ try {
1911
+ await this._mediaStreamRecorder.begin(track);
1912
+ await this.startRecording();
1913
+ } catch (e) {
1914
+ // void. nothing to do.
1915
+ }
1819
1916
  break;
1820
1917
  case "paused":
1821
1918
  await this.startRecording();
1822
1919
  break;
1823
1920
  case "recording":
1824
1921
  default:
1825
- if (this._currentAudioTrack !== track) {
1922
+ if (this._currentAudioTrack !== track) try {
1826
1923
  await this._mediaStreamRecorder.end();
1827
1924
  await this._mediaStreamRecorder.begin(track);
1828
1925
  await this.startRecording();
1829
- } else (0, $7zbD8$logger).warn("track-started event received for current track and already recording");
1926
+ } catch (e) {
1927
+ // void. nothing to do.
1928
+ }
1929
+ else (0, $7zbD8$logger).warn("track-started event received for current track and already recording");
1830
1930
  break;
1831
1931
  }
1832
1932
  this._currentAudioTrack = track;