testaugnitorecorder4 1.0.90 → 1.0.92

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.
@@ -728,6 +728,9 @@ function WorkerBlob(doneMessage, eosMessage, closeMessage, connectionRetryTimeou
728
728
  break;
729
729
  }
730
730
  if (shouldSendAudioDataSequence) {
731
+ if (!(data instanceof ArrayBuffer)) {
732
+ continue;
733
+ }
731
734
  var view = new DataView(data);
732
735
  packetId = Number(view.getBigInt64(4));
733
736
  var sentPacket = {
@@ -780,7 +783,9 @@ function WorkerBlob(doneMessage, eosMessage, closeMessage, connectionRetryTimeou
780
783
  } else if (event.data === startListeningClickedMessage) {
781
784
  pendingStartStreamCapture = true;
782
785
  } else if (event.data === resumeSocketMessage) {
783
- add(pauseStateAudio);
786
+ if (pauseStateAudio instanceof ArrayBuffer) {
787
+ add(pauseStateAudio);
788
+ }
784
789
  if (pendingStartStreamBuffer.length > 0) {
785
790
  for (var i = 0; i < pendingStartStreamBuffer.length; i++) {
786
791
  add(pendingStartStreamBuffer[i]);
@@ -830,6 +835,12 @@ var Streamer = /*#__PURE__*/function () {
830
835
  this.echoCancellation = echoCancellation;
831
836
  this.noiseSuppression = noiseSuppression;
832
837
  this.autoGainControl = autoGainControl;
838
+ this.micNeedsRecovery = false;
839
+ this.trackEndedHandler = null;
840
+ this.isRecovering = false;
841
+ this.currentWsUrl = "";
842
+ this.currentDuration = 0;
843
+ this.deviceChangeHandler = null;
833
844
  if (this.shouldPreIntialiseRecorder) {
834
845
  this.InitialiseMediaStream(reconnectAudioDuration, socketUrl);
835
846
  }
@@ -837,30 +848,33 @@ var Streamer = /*#__PURE__*/function () {
837
848
  return _createClass(Streamer, [{
838
849
  key: "InitialiseMediaStream",
839
850
  value: function () {
840
- var _InitialiseMediaStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(duration, wsUrl) {
841
- return _regeneratorRuntime().wrap(function _callee$(_context) {
842
- while (1) switch (_context.prev = _context.next) {
851
+ var _InitialiseMediaStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(duration, wsUrl) {
852
+ var _this = this;
853
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
854
+ while (1) switch (_context2.prev = _context2.next) {
843
855
  case 0:
844
- _context.next = 2;
856
+ this.currentDuration = duration;
857
+ this.currentWsUrl = wsUrl;
858
+ _context2.next = 4;
845
859
  return this.createMediaStreamSourceNode();
846
- case 2:
860
+ case 4:
847
861
  if (this.source) {
848
- _context.next = 5;
862
+ _context2.next = 7;
849
863
  break;
850
864
  }
851
865
  console.error("Error: unable to create source node");
852
- return _context.abrupt("return", false);
853
- case 5:
854
- _context.next = 7;
855
- return this.createProcessorNode();
866
+ return _context2.abrupt("return", false);
856
867
  case 7:
868
+ _context2.next = 9;
869
+ return this.createProcessorNode();
870
+ case 9:
857
871
  if (this.processorNode) {
858
- _context.next = 10;
872
+ _context2.next = 12;
859
873
  break;
860
874
  }
861
875
  console.error("Error: unable to create processor node");
862
- return _context.abrupt("return", false);
863
- case 10:
876
+ return _context2.abrupt("return", false);
877
+ case 12:
864
878
  this.source.connect(this.processorNode).connect(this.audioContext.destination);
865
879
  this.log("AudioContext Sample Rate: " + this.audioContext.sampleRate);
866
880
  if (wsUrl !== "") {
@@ -869,11 +883,39 @@ var Streamer = /*#__PURE__*/function () {
869
883
  // if (this.audioContext && this.audioContext.state == "running") {
870
884
  // await this.audioContext.suspend();
871
885
  // }
872
- case 13:
886
+ if (!this.deviceChangeHandler) {
887
+ this.deviceChangeHandler = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
888
+ var _this$audioStream, _this$audioStream$get;
889
+ var track;
890
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
891
+ while (1) switch (_context.prev = _context.next) {
892
+ case 0:
893
+ track = (_this$audioStream = _this.audioStream) === null || _this$audioStream === void 0 || (_this$audioStream$get = _this$audioStream.getAudioTracks) === null || _this$audioStream$get === void 0 ? void 0 : _this$audioStream$get.call(_this$audioStream)[0];
894
+ if (!(!track || track.readyState === "ended")) {
895
+ _context.next = 7;
896
+ break;
897
+ }
898
+ _this.log("Detected invalid audio track");
899
+ _this.micNeedsRecovery = true;
900
+ if (_this.isPaused) {
901
+ _context.next = 7;
902
+ break;
903
+ }
904
+ _context.next = 7;
905
+ return _this.recoverAudioGraph();
906
+ case 7:
907
+ case "end":
908
+ return _context.stop();
909
+ }
910
+ }, _callee);
911
+ }));
912
+ navigator.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
913
+ }
914
+ case 16:
873
915
  case "end":
874
- return _context.stop();
916
+ return _context2.stop();
875
917
  }
876
- }, _callee, this);
918
+ }, _callee2, this);
877
919
  }));
878
920
  function InitialiseMediaStream(_x, _x2) {
879
921
  return _InitialiseMediaStream.apply(this, arguments);
@@ -883,9 +925,9 @@ var Streamer = /*#__PURE__*/function () {
883
925
  }, {
884
926
  key: "StartStream",
885
927
  value: function () {
886
- var _StartStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(duration, wsUrl) {
887
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
888
- while (1) switch (_context2.prev = _context2.next) {
928
+ var _StartStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(duration, wsUrl) {
929
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
930
+ while (1) switch (_context3.prev = _context3.next) {
889
931
  case 0:
890
932
  this.log("New stream started...");
891
933
 
@@ -893,13 +935,13 @@ var Streamer = /*#__PURE__*/function () {
893
935
  // await this.createBufferedSourceNode();
894
936
  // Uncomment to stream microphone audio
895
937
  if (!(!this.shouldPreIntialiseRecorder || !this.source)) {
896
- _context2.next = 6;
938
+ _context3.next = 6;
897
939
  break;
898
940
  }
899
- _context2.next = 4;
941
+ _context3.next = 4;
900
942
  return this.InitialiseMediaStream(duration, wsUrl, false);
901
943
  case 4:
902
- _context2.next = 7;
944
+ _context3.next = 7;
903
945
  break;
904
946
  case 6:
905
947
  if (this.shouldPreIntialiseRecorder) {
@@ -907,30 +949,30 @@ var Streamer = /*#__PURE__*/function () {
907
949
  }
908
950
  case 7:
909
951
  if (!this.IsMicrophoneMuted) {
910
- _context2.next = 13;
952
+ _context3.next = 13;
911
953
  break;
912
954
  }
913
955
  if (!(this.audioContext && this.audioContext.state == "running")) {
914
- _context2.next = 11;
956
+ _context3.next = 11;
915
957
  break;
916
958
  }
917
- _context2.next = 11;
959
+ _context3.next = 11;
918
960
  return this.audioContext.suspend();
919
961
  case 11:
920
962
  this.onError(JSON.stringify({
921
963
  Type: "ERROR",
922
964
  Data: "Microphone is muted."
923
965
  }));
924
- return _context2.abrupt("return", false);
966
+ return _context3.abrupt("return", false);
925
967
  case 13:
926
968
  this.onStateChanged(true);
927
969
  this.isStreaming = true;
928
- return _context2.abrupt("return", true);
970
+ return _context3.abrupt("return", true);
929
971
  case 16:
930
972
  case "end":
931
- return _context2.stop();
973
+ return _context3.stop();
932
974
  }
933
- }, _callee2, this);
975
+ }, _callee3, this);
934
976
  }));
935
977
  function StartStream(_x3, _x4) {
936
978
  return _StartStream.apply(this, arguments);
@@ -940,21 +982,21 @@ var Streamer = /*#__PURE__*/function () {
940
982
  }, {
941
983
  key: "createBufferedSourceNode",
942
984
  value: function () {
943
- var _createBufferedSourceNode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
985
+ var _createBufferedSourceNode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
944
986
  var audioBuffer;
945
- return _regeneratorRuntime().wrap(function _callee3$(_context3) {
946
- while (1) switch (_context3.prev = _context3.next) {
987
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
988
+ while (1) switch (_context4.prev = _context4.next) {
947
989
  case 0:
948
- _context3.next = 2;
990
+ _context4.next = 2;
949
991
  return this.loadAudio();
950
992
  case 2:
951
- audioBuffer = _context3.sent;
993
+ audioBuffer = _context4.sent;
952
994
  if (audioBuffer) {
953
- _context3.next = 6;
995
+ _context4.next = 6;
954
996
  break;
955
997
  }
956
998
  console.error("Error: unable to create audio buffer");
957
- return _context3.abrupt("return");
999
+ return _context4.abrupt("return");
958
1000
  case 6:
959
1001
  this.source = this.audioContext.createBufferSource();
960
1002
  this.source.buffer = audioBuffer;
@@ -962,9 +1004,9 @@ var Streamer = /*#__PURE__*/function () {
962
1004
  this.source.start();
963
1005
  case 10:
964
1006
  case "end":
965
- return _context3.stop();
1007
+ return _context4.stop();
966
1008
  }
967
- }, _callee3, this);
1009
+ }, _callee4, this);
968
1010
  }));
969
1011
  function createBufferedSourceNode() {
970
1012
  return _createBufferedSourceNode.apply(this, arguments);
@@ -974,13 +1016,13 @@ var Streamer = /*#__PURE__*/function () {
974
1016
  }, {
975
1017
  key: "createMediaStreamSourceNode",
976
1018
  value: function () {
977
- var _createMediaStreamSourceNode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
978
- var _this = this;
979
- var audioConstraints, errMessage;
980
- return _regeneratorRuntime().wrap(function _callee4$(_context4) {
981
- while (1) switch (_context4.prev = _context4.next) {
1019
+ var _createMediaStreamSourceNode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
1020
+ var _this2 = this;
1021
+ var audioConstraints, track, errMessage;
1022
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
1023
+ while (1) switch (_context6.prev = _context6.next) {
982
1024
  case 0:
983
- _context4.prev = 0;
1025
+ _context6.prev = 0;
984
1026
  audioConstraints = {
985
1027
  channelCount: CHANNEL_COUNT,
986
1028
  noiseSuppression: this.noiseSuppression !== undefined ? this.noiseSuppression : NOISE_SUPPRESS_ENABLED
@@ -998,41 +1040,62 @@ var Streamer = /*#__PURE__*/function () {
998
1040
  audioConstraints.autoGainControl = this.autoGainControl;
999
1041
  audioConstraints.googAutoGainControl = this.autoGainControl;
1000
1042
  }
1001
- _context4.next = 7;
1043
+ _context6.next = 7;
1002
1044
  return navigator.mediaDevices.getUserMedia({
1003
1045
  audio: audioConstraints
1004
1046
  });
1005
1047
  case 7:
1006
- this.audioStream = _context4.sent;
1007
- console.log("Audio stream created with settings: ", this.audioStream.getAudioTracks()[0].getSettings());
1008
- this.audioContext = new AudioContext();
1048
+ this.audioStream = _context6.sent;
1049
+ if (!this.audioContext || this.audioContext.state === "closed") {
1050
+ this.audioContext = new AudioContext();
1051
+ }
1009
1052
  this.source = this.audioContext.createMediaStreamSource(this.audioStream);
1010
- this.audioStream.getAudioTracks()[0].addEventListener("ended", function () {
1011
- _this.onError(JSON.stringify({
1012
- Type: "ERROR",
1013
- Data: "Audio track ended. Possibly the mic was unplugged."
1014
- }));
1015
- });
1016
- _context4.next = 19;
1053
+ track = this.audioStream.getAudioTracks()[0];
1054
+ this.trackEndedHandler = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
1055
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
1056
+ while (1) switch (_context5.prev = _context5.next) {
1057
+ case 0:
1058
+ _this2.log("Microphone disconnected");
1059
+ _this2.micNeedsRecovery = true;
1060
+ _this2.onError(JSON.stringify({
1061
+ Type: "ERROR",
1062
+ Data: "Audio track ended. Possibly the mic was unplugged."
1063
+ }));
1064
+ if (_this2.isPaused) {
1065
+ _context5.next = 6;
1066
+ break;
1067
+ }
1068
+ _context5.next = 6;
1069
+ return _this2.recoverAudioGraph();
1070
+ case 6:
1071
+ case "end":
1072
+ return _context5.stop();
1073
+ }
1074
+ }, _callee5);
1075
+ }));
1076
+ track.addEventListener("ended", this.trackEndedHandler);
1077
+ _context6.next = 20;
1017
1078
  break;
1018
- case 14:
1019
- _context4.prev = 14;
1020
- _context4.t0 = _context4["catch"](0);
1079
+ case 15:
1080
+ _context6.prev = 15;
1081
+ _context6.t0 = _context6["catch"](0);
1021
1082
  errMessage = "";
1022
- if (_context4.t0.name == "NotAllowedError") {
1083
+ if (_context6.t0.name == "NotAllowedError") {
1023
1084
  errMessage = "Mic permission denied";
1024
- } else if (_context4.t0.name === "NotFoundError") {
1085
+ } else if (_context6.t0.name === "NotFoundError") {
1025
1086
  errMessage = "No suitable media device found";
1087
+ } else if (_context6.t0.name === "NotReadableError") {
1088
+ errMessage = "Microphone is being used by another application";
1026
1089
  }
1027
1090
  this.onError(JSON.stringify({
1028
1091
  Type: "ERROR",
1029
1092
  Data: errMessage
1030
1093
  }));
1031
- case 19:
1094
+ case 20:
1032
1095
  case "end":
1033
- return _context4.stop();
1096
+ return _context6.stop();
1034
1097
  }
1035
- }, _callee4, this, [[0, 14]]);
1098
+ }, _callee6, this, [[0, 15]]);
1036
1099
  }));
1037
1100
  function createMediaStreamSourceNode() {
1038
1101
  return _createMediaStreamSourceNode.apply(this, arguments);
@@ -1042,35 +1105,35 @@ var Streamer = /*#__PURE__*/function () {
1042
1105
  }, {
1043
1106
  key: "loadAudio",
1044
1107
  value: function () {
1045
- var _loadAudio = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
1108
+ var _loadAudio = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {
1046
1109
  var response, arrayBuffer, audioBuffer;
1047
- return _regeneratorRuntime().wrap(function _callee5$(_context5) {
1048
- while (1) switch (_context5.prev = _context5.next) {
1110
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
1111
+ while (1) switch (_context7.prev = _context7.next) {
1049
1112
  case 0:
1050
- _context5.prev = 0;
1051
- _context5.next = 3;
1113
+ _context7.prev = 0;
1114
+ _context7.next = 3;
1052
1115
  return fetch("./radiology_speed_test.wav");
1053
1116
  case 3:
1054
- response = _context5.sent;
1055
- _context5.next = 6;
1117
+ response = _context7.sent;
1118
+ _context7.next = 6;
1056
1119
  return response.arrayBuffer();
1057
1120
  case 6:
1058
- arrayBuffer = _context5.sent;
1059
- _context5.next = 9;
1121
+ arrayBuffer = _context7.sent;
1122
+ _context7.next = 9;
1060
1123
  return this.audioContext.decodeAudioData(arrayBuffer);
1061
1124
  case 9:
1062
- audioBuffer = _context5.sent;
1063
- return _context5.abrupt("return", audioBuffer);
1125
+ audioBuffer = _context7.sent;
1126
+ return _context7.abrupt("return", audioBuffer);
1064
1127
  case 13:
1065
- _context5.prev = 13;
1066
- _context5.t0 = _context5["catch"](0);
1067
- console.error("Unable to fetch the audio file. Error: ".concat(_context5.t0.message));
1068
- return _context5.abrupt("return", null);
1128
+ _context7.prev = 13;
1129
+ _context7.t0 = _context7["catch"](0);
1130
+ console.error("Unable to fetch the audio file. Error: ".concat(_context7.t0.message));
1131
+ return _context7.abrupt("return", null);
1069
1132
  case 17:
1070
1133
  case "end":
1071
- return _context5.stop();
1134
+ return _context7.stop();
1072
1135
  }
1073
- }, _callee5, this, [[0, 13]]);
1136
+ }, _callee7, this, [[0, 13]]);
1074
1137
  }));
1075
1138
  function loadAudio() {
1076
1139
  return _loadAudio.apply(this, arguments);
@@ -1080,14 +1143,14 @@ var Streamer = /*#__PURE__*/function () {
1080
1143
  }, {
1081
1144
  key: "createProcessorNode",
1082
1145
  value: function () {
1083
- var _createProcessorNode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
1084
- var _this2 = this;
1146
+ var _createProcessorNode = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8() {
1147
+ var _this3 = this;
1085
1148
  var _this$shouldReadInten, sampleRateParam, bufferSizeIntervalParam, pausedBufferIntervalParam, shouldReadIntensityParam;
1086
- return _regeneratorRuntime().wrap(function _callee6$(_context6) {
1087
- while (1) switch (_context6.prev = _context6.next) {
1149
+ return _regeneratorRuntime().wrap(function _callee8$(_context8) {
1150
+ while (1) switch (_context8.prev = _context8.next) {
1088
1151
  case 0:
1089
- _context6.prev = 0;
1090
- _context6.next = 3;
1152
+ _context8.prev = 0;
1153
+ _context8.next = 3;
1091
1154
  return this.audioContext.audioWorklet.addModule("data:application/javascript,".concat(encodeURIComponent(worklet)));
1092
1155
  case 3:
1093
1156
  this.processorNode = new AudioWorkletNode(this.audioContext, WORKLET_PROCESSOR);
@@ -1105,47 +1168,47 @@ var Streamer = /*#__PURE__*/function () {
1105
1168
  type = _event$data.type,
1106
1169
  value = _event$data.value;
1107
1170
  if (type == DONE_MSG) {
1108
- _this2.log("Worklet processing done, clearing resources...");
1171
+ _this3.log("Worklet processing done, clearing resources...");
1109
1172
 
1110
1173
  // Uncomment to save recording
1111
- if (_this2.isDebug) _this2.saveAudio();
1112
- _this2.cleanup();
1174
+ if (_this3.isDebug) _this3.saveAudio();
1175
+ _this3.cleanup();
1113
1176
  } else if (event.data == PAUSE_SOCKET_MSG) {
1114
- _this2.executor.Send(PAUSE_SOCKET_MSG);
1177
+ _this3.executor.Send(PAUSE_SOCKET_MSG);
1115
1178
  }
1116
1179
  // Uncomment to save recording
1117
1180
  else {
1118
1181
  if (type === "intensity") {
1119
- var _this2$onIntensity;
1120
- (_this2$onIntensity = _this2.onIntensity) === null || _this2$onIntensity === void 0 || _this2$onIntensity.call(_this2, value);
1182
+ var _this3$onIntensity;
1183
+ (_this3$onIntensity = _this3.onIntensity) === null || _this3$onIntensity === void 0 || _this3$onIntensity.call(_this3, value);
1121
1184
  } else if (type === "audioData") {
1122
- if (_this2.isDebug) {
1185
+ if (_this3.isDebug) {
1123
1186
  new Int16Array(value).forEach(function (element) {
1124
- if (_this2.audioData.length <= MAX_AUDIO_SAMPLES) _this2.audioData.push(element);
1187
+ if (_this3.audioData.length <= MAX_AUDIO_SAMPLES) _this3.audioData.push(element);
1125
1188
  });
1126
1189
  }
1127
1190
  }
1128
1191
  }
1129
- if (_this2.executor) {
1130
- if (_this2.closeSocketWithoutEOS) {
1131
- _this2.executor.Send(CLOSE_MSG);
1132
- _this2.closeSocketWithoutEOS = false;
1192
+ if (_this3.executor) {
1193
+ if (_this3.closeSocketWithoutEOS) {
1194
+ _this3.executor.Send(CLOSE_MSG);
1195
+ _this3.closeSocketWithoutEOS = false;
1133
1196
  } else {
1134
- if (type !== "intensity") _this2.executor.Send(value);
1197
+ if (type !== "intensity") _this3.executor.Send(value);
1135
1198
  }
1136
1199
  }
1137
1200
  };
1138
- _context6.next = 18;
1201
+ _context8.next = 18;
1139
1202
  break;
1140
1203
  case 15:
1141
- _context6.prev = 15;
1142
- _context6.t0 = _context6["catch"](0);
1143
- console.error("Error: Unable to create worklet node: ", _context6.t0);
1204
+ _context8.prev = 15;
1205
+ _context8.t0 = _context8["catch"](0);
1206
+ console.error("Error: Unable to create worklet node: ", _context8.t0);
1144
1207
  case 18:
1145
1208
  case "end":
1146
- return _context6.stop();
1209
+ return _context8.stop();
1147
1210
  }
1148
- }, _callee6, this, [[0, 15]]);
1211
+ }, _callee8, this, [[0, 15]]);
1149
1212
  }));
1150
1213
  function createProcessorNode() {
1151
1214
  return _createProcessorNode.apply(this, arguments);
@@ -1155,25 +1218,25 @@ var Streamer = /*#__PURE__*/function () {
1155
1218
  }, {
1156
1219
  key: "PauseStream",
1157
1220
  value: function () {
1158
- var _PauseStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {
1159
- return _regeneratorRuntime().wrap(function _callee7$(_context7) {
1160
- while (1) switch (_context7.prev = _context7.next) {
1221
+ var _PauseStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {
1222
+ return _regeneratorRuntime().wrap(function _callee9$(_context9) {
1223
+ while (1) switch (_context9.prev = _context9.next) {
1161
1224
  case 0:
1162
1225
  if (!(this.audioContext.state == "running")) {
1163
- _context7.next = 9;
1226
+ _context9.next = 9;
1164
1227
  break;
1165
1228
  }
1166
1229
  if (this.shouldPreIntialiseRecorder) {
1167
- _context7.next = 8;
1230
+ _context9.next = 8;
1168
1231
  break;
1169
1232
  }
1170
- _context7.next = 4;
1233
+ _context9.next = 4;
1171
1234
  return this.audioContext.suspend();
1172
1235
  case 4:
1173
1236
  this.log("Stream paused...");
1174
1237
  // message sent to worklet-thread
1175
1238
  this.processorNode.port.postMessage(PAUSE_MSG);
1176
- _context7.next = 9;
1239
+ _context9.next = 9;
1177
1240
  break;
1178
1241
  case 8:
1179
1242
  this.processorNode.port.postMessage(PAUSE_SOCKET_MSG);
@@ -1183,9 +1246,9 @@ var Streamer = /*#__PURE__*/function () {
1183
1246
  this.isStreaming = false;
1184
1247
  case 12:
1185
1248
  case "end":
1186
- return _context7.stop();
1249
+ return _context9.stop();
1187
1250
  }
1188
- }, _callee7, this);
1251
+ }, _callee9, this);
1189
1252
  }));
1190
1253
  function PauseStream() {
1191
1254
  return _PauseStream.apply(this, arguments);
@@ -1195,42 +1258,54 @@ var Streamer = /*#__PURE__*/function () {
1195
1258
  }, {
1196
1259
  key: "ResumeStream",
1197
1260
  value: function () {
1198
- var _ResumeStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8() {
1199
- return _regeneratorRuntime().wrap(function _callee8$(_context8) {
1200
- while (1) switch (_context8.prev = _context8.next) {
1261
+ var _ResumeStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10() {
1262
+ var _this$audioStream2, _this$audioStream2$ge;
1263
+ var track, trackEnded;
1264
+ return _regeneratorRuntime().wrap(function _callee10$(_context10) {
1265
+ while (1) switch (_context10.prev = _context10.next) {
1201
1266
  case 0:
1267
+ track = (_this$audioStream2 = this.audioStream) === null || _this$audioStream2 === void 0 || (_this$audioStream2$ge = _this$audioStream2.getAudioTracks) === null || _this$audioStream2$ge === void 0 ? void 0 : _this$audioStream2$ge.call(_this$audioStream2)[0];
1268
+ trackEnded = !track || track.readyState === "ended";
1269
+ if (!(trackEnded || this.micNeedsRecovery)) {
1270
+ _context10.next = 6;
1271
+ break;
1272
+ }
1273
+ this.log("Recovering before resume");
1274
+ _context10.next = 6;
1275
+ return this.recoverAudioGraph();
1276
+ case 6:
1202
1277
  if (!(!this.shouldPreIntialiseRecorder && this.audioContext.state == "suspended")) {
1203
- _context8.next = 9;
1278
+ _context10.next = 15;
1204
1279
  break;
1205
1280
  }
1206
1281
  if (!this.IsMicrophoneMuted) {
1207
- _context8.next = 4;
1282
+ _context10.next = 10;
1208
1283
  break;
1209
1284
  }
1210
1285
  this.onError(JSON.stringify({
1211
1286
  Type: "ERROR",
1212
1287
  Data: "Microphone is muted."
1213
1288
  }));
1214
- return _context8.abrupt("return");
1215
- case 4:
1216
- _context8.next = 6;
1289
+ return _context10.abrupt("return");
1290
+ case 10:
1291
+ _context10.next = 12;
1217
1292
  return this.audioContext.resume();
1218
- case 6:
1293
+ case 12:
1219
1294
  this.log("Stream resumed...");
1220
- _context8.next = 11;
1295
+ _context10.next = 17;
1221
1296
  break;
1222
- case 9:
1297
+ case 15:
1223
1298
  this.processorNode.port.postMessage(RESUME_SOCKET_MSG);
1224
1299
  this.executor.Send(RESUME_SOCKET_MSG);
1225
- case 11:
1300
+ case 17:
1226
1301
  this.onStateChanged(true);
1227
1302
  this.isPaused = false;
1228
1303
  this.isStreaming = true;
1229
- case 14:
1304
+ case 20:
1230
1305
  case "end":
1231
- return _context8.stop();
1306
+ return _context10.stop();
1232
1307
  }
1233
- }, _callee8, this);
1308
+ }, _callee10, this);
1234
1309
  }));
1235
1310
  function ResumeStream() {
1236
1311
  return _ResumeStream.apply(this, arguments);
@@ -1250,22 +1325,27 @@ var Streamer = /*#__PURE__*/function () {
1250
1325
  }, {
1251
1326
  key: "IsMicrophoneMuted",
1252
1327
  get: function get() {
1253
- return this.audioStream.getAudioTracks()[0].muted;
1328
+ var _this$audioStream3, _this$audioStream3$ge;
1329
+ var track = (_this$audioStream3 = this.audioStream) === null || _this$audioStream3 === void 0 || (_this$audioStream3$ge = _this$audioStream3.getAudioTracks) === null || _this$audioStream3$ge === void 0 ? void 0 : _this$audioStream3$ge.call(_this$audioStream3)[0];
1330
+ if (!track) {
1331
+ return true;
1332
+ }
1333
+ return track.muted || track.readyState === "ended";
1254
1334
  }
1255
1335
  }, {
1256
1336
  key: "StopStream",
1257
1337
  value: function () {
1258
- var _StopStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(shouldSendEOS) {
1259
- var _this$audioContext, _this$processorNode, _this$audioStream;
1338
+ var _StopStream = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(shouldSendEOS) {
1339
+ var _this$audioContext, _this$processorNode, _this$audioStream4;
1260
1340
  var _this$audioContext2;
1261
- return _regeneratorRuntime().wrap(function _callee9$(_context9) {
1262
- while (1) switch (_context9.prev = _context9.next) {
1341
+ return _regeneratorRuntime().wrap(function _callee11$(_context11) {
1342
+ while (1) switch (_context11.prev = _context11.next) {
1263
1343
  case 0:
1264
1344
  if (!(((_this$audioContext = this.audioContext) === null || _this$audioContext === void 0 ? void 0 : _this$audioContext.state) !== "suspended")) {
1265
- _context9.next = 4;
1345
+ _context11.next = 4;
1266
1346
  break;
1267
1347
  }
1268
- _context9.next = 3;
1348
+ _context11.next = 3;
1269
1349
  return (_this$audioContext2 = this.audioContext) === null || _this$audioContext2 === void 0 ? void 0 : _this$audioContext2.suspend();
1270
1350
  case 3:
1271
1351
  this.onStateChanged(false);
@@ -1275,18 +1355,106 @@ var Streamer = /*#__PURE__*/function () {
1275
1355
  this.closeSocketWithoutEOS = !shouldSendEOS;
1276
1356
  // message sent to worklet-thread
1277
1357
  (_this$processorNode = this.processorNode) === null || _this$processorNode === void 0 || (_this$processorNode = _this$processorNode.port) === null || _this$processorNode === void 0 || _this$processorNode.postMessage(STOP_MSG);
1278
- (_this$audioStream = this.audioStream) === null || _this$audioStream === void 0 || _this$audioStream.getAudioTracks()[0].removeEventListener("ended", function () {});
1358
+ (_this$audioStream4 = this.audioStream) === null || _this$audioStream4 === void 0 || _this$audioStream4.getAudioTracks()[0].removeEventListener("ended", function () {});
1279
1359
  case 9:
1280
1360
  case "end":
1281
- return _context9.stop();
1361
+ return _context11.stop();
1282
1362
  }
1283
- }, _callee9, this);
1363
+ }, _callee11, this);
1284
1364
  }));
1285
1365
  function StopStream(_x5) {
1286
1366
  return _StopStream.apply(this, arguments);
1287
1367
  }
1288
1368
  return StopStream;
1289
1369
  }()
1370
+ }, {
1371
+ key: "recoverAudioGraph",
1372
+ value: function () {
1373
+ var _recoverAudioGraph = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {
1374
+ var _this$audioStream5, _this$source, _this$processorNode2;
1375
+ return _regeneratorRuntime().wrap(function _callee12$(_context12) {
1376
+ while (1) switch (_context12.prev = _context12.next) {
1377
+ case 0:
1378
+ if (!this.isRecovering) {
1379
+ _context12.next = 2;
1380
+ break;
1381
+ }
1382
+ return _context12.abrupt("return");
1383
+ case 2:
1384
+ this.isRecovering = true;
1385
+ _context12.prev = 3;
1386
+ this.log("Recovering audio graph...");
1387
+
1388
+ // stop old track
1389
+ (_this$audioStream5 = this.audioStream) === null || _this$audioStream5 === void 0 || (_this$audioStream5 = _this$audioStream5.getTracks()) === null || _this$audioStream5 === void 0 || _this$audioStream5.forEach(function (t) {
1390
+ try {
1391
+ t.stop();
1392
+ } catch (_unused) {}
1393
+ });
1394
+
1395
+ // disconnect source
1396
+ try {
1397
+ (_this$source = this.source) === null || _this$source === void 0 || _this$source.disconnect();
1398
+ } catch (_unused2) {}
1399
+
1400
+ // disconnect processor
1401
+ try {
1402
+ (_this$processorNode2 = this.processorNode) === null || _this$processorNode2 === void 0 || _this$processorNode2.disconnect();
1403
+ } catch (_unused3) {}
1404
+
1405
+ // recreate media stream ONLY
1406
+ _context12.next = 10;
1407
+ return this.createMediaStreamSourceNode();
1408
+ case 10:
1409
+ if (this.source) {
1410
+ _context12.next = 12;
1411
+ break;
1412
+ }
1413
+ throw new Error("Failed to recreate source");
1414
+ case 12:
1415
+ // AudioContext may become closed/suspended
1416
+ if (!this.audioContext || this.audioContext.state === "closed") {
1417
+ this.audioContext = new AudioContext();
1418
+ }
1419
+ if (!(this.audioContext.state === "suspended")) {
1420
+ _context12.next = 16;
1421
+ break;
1422
+ }
1423
+ _context12.next = 16;
1424
+ return this.audioContext.resume();
1425
+ case 16:
1426
+ _context12.next = 18;
1427
+ return this.createProcessorNode();
1428
+ case 18:
1429
+ // reconnect graph
1430
+ this.source.connect(this.processorNode).connect(this.audioContext.destination);
1431
+ this.micNeedsRecovery = false;
1432
+ this.log("Audio graph recovery completed");
1433
+ _context12.next = 27;
1434
+ break;
1435
+ case 23:
1436
+ _context12.prev = 23;
1437
+ _context12.t0 = _context12["catch"](3);
1438
+ console.error("Recovery failed", _context12.t0);
1439
+ this.onError(JSON.stringify({
1440
+ Type: "ERROR",
1441
+ Data: "Failed to recover microphone"
1442
+ }));
1443
+ case 27:
1444
+ _context12.prev = 27;
1445
+ this.isRecovering = false;
1446
+ return _context12.finish(27);
1447
+ case 30:
1448
+ case "end":
1449
+ return _context12.stop();
1450
+ }
1451
+ }, _callee12, this, [[3, 23, 27, 30]]);
1452
+ }));
1453
+ function recoverAudioGraph() {
1454
+ return _recoverAudioGraph.apply(this, arguments);
1455
+ }
1456
+ return recoverAudioGraph;
1457
+ }()
1290
1458
  }, {
1291
1459
  key: "IntentStartStream",
1292
1460
  value: function IntentStartStream() {
@@ -1295,10 +1463,15 @@ var Streamer = /*#__PURE__*/function () {
1295
1463
  }, {
1296
1464
  key: "cleanup",
1297
1465
  value: function cleanup() {
1466
+ var _this$audioStream6;
1298
1467
  // Uncomment to stop recorded audio
1299
1468
  // this.source.stop();
1300
1469
  // Uncomment to stop microphone audio
1301
- this.source.mediaStream.getAudioTracks()[0].stop();
1470
+ (_this$audioStream6 = this.audioStream) === null || _this$audioStream6 === void 0 || (_this$audioStream6 = _this$audioStream6.getTracks()) === null || _this$audioStream6 === void 0 || _this$audioStream6.forEach(function (track) {
1471
+ try {
1472
+ track.stop();
1473
+ } catch (_unused4) {}
1474
+ });
1302
1475
  this.source.disconnect();
1303
1476
  this.processorNode.disconnect();
1304
1477
  this.processorNode.port.close();