@stormstreaming/stormstreamer 0.9.0-beta.4 → 0.9.0-beta.5

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/amd/index.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * contact@stormstreaming.com
5
5
  * https://stormstreaming.com
6
6
  *
7
- * Version: 0.9.0-beta.4
8
- * Version: 12/7/2024, 6:37:55 PM
7
+ * Version: 0.9.0-beta.5
8
+ * Version: 12/10/2024, 10:26:03 AM
9
9
  *
10
10
  * LEGAL NOTICE:
11
11
  * This software is subject to the terms and conditions defined in
@@ -578,20 +578,22 @@
578
578
  this.startOnDOMReady = false;
579
579
  this.iOSOnDomReadyFix = true;
580
580
  this._restartOnFocus = true;
581
+ this._forceDeviceSelection = false;
581
582
  this.parse(config);
582
583
  }
583
584
  parse(config) {
584
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
585
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
585
586
  this._settingsConfig = config;
586
587
  this._autoConnect = (_a = this._settingsConfig.autoConnect) !== null && _a !== void 0 ? _a : this._autoConnect;
587
588
  this._autoStart = (_b = this._settingsConfig.autoStart) !== null && _b !== void 0 ? _b : this._autoStart;
588
589
  this._restartOnFocus = (_c = this._settingsConfig.restartOnFocus) !== null && _c !== void 0 ? _c : this._restartOnFocus;
589
590
  this._restartOnError = (_d = this._settingsConfig.restartOnError) !== null && _d !== void 0 ? _d : this._restartOnError;
590
591
  this._reconnectTime = (_e = this._settingsConfig.reconnectTime) !== null && _e !== void 0 ? _e : this._reconnectTime;
591
- this._videoData = new VideoData((_f = this._settingsConfig.video) !== null && _f !== void 0 ? _f : null);
592
- this._audioData = new AudioData((_g = this._settingsConfig.audio) !== null && _g !== void 0 ? _g : null);
593
- this._storageData = new StorageData((_h = this._settingsConfig.storage) !== null && _h !== void 0 ? _h : null);
594
- this._debugData = new DebugData((_j = this._settingsConfig.debug) !== null && _j !== void 0 ? _j : null);
592
+ this._forceDeviceSelection = (_f = this._settingsConfig.forceDeviceSelection) !== null && _f !== void 0 ? _f : this._forceDeviceSelection;
593
+ this._videoData = new VideoData((_g = this._settingsConfig.video) !== null && _g !== void 0 ? _g : null);
594
+ this._audioData = new AudioData((_h = this._settingsConfig.audio) !== null && _h !== void 0 ? _h : null);
595
+ this._storageData = new StorageData((_j = this._settingsConfig.storage) !== null && _j !== void 0 ? _j : null);
596
+ this._debugData = new DebugData((_k = this._settingsConfig.debug) !== null && _k !== void 0 ? _k : null);
595
597
  }
596
598
  getAudioData() {
597
599
  return this._audioData;
@@ -623,6 +625,9 @@
623
625
  getDebugData() {
624
626
  return this._debugData;
625
627
  }
628
+ getIfForceSelection() {
629
+ return this._forceDeviceSelection;
630
+ }
626
631
  getIfStartOnDOMReadyEnabled() {
627
632
  return this.startOnDOMReady;
628
633
  }
@@ -2467,74 +2472,103 @@
2467
2472
 
2468
2473
  class SoundMeter {
2469
2474
  constructor(main) {
2470
- this._stream = null;
2471
2475
  this._audioContext = null;
2472
2476
  this._analyser = null;
2473
2477
  this._microphone = null;
2474
2478
  this._lastEventTime = 0;
2475
2479
  this.THROTTLE_INTERVAL = 100;
2480
+ this._isMonitoring = false;
2476
2481
  this._instant = 0.0;
2477
2482
  this._slow = 0.0;
2478
- this._clip = 0.0;
2479
2483
  this._main = main;
2480
2484
  }
2481
2485
  attach(stream) {
2482
- this._stream = stream;
2483
- this._audioContext = new AudioContext();
2484
- this._microphone = this._audioContext.createMediaStreamSource(stream);
2485
- this._analyser = this._audioContext.createAnalyser();
2486
- this._analyser.fftSize = 2048;
2487
- this._analyser.smoothingTimeConstant = 0.3;
2488
- this._microphone.connect(this._analyser);
2489
- this.startMonitoring();
2486
+ if (!stream.getAudioTracks().length) {
2487
+ console.warn('SoundMeter: Attempted to attach stream without audio tracks');
2488
+ return;
2489
+ }
2490
+ this.detach();
2491
+ try {
2492
+ this._audioContext = new AudioContext();
2493
+ this._microphone = this._audioContext.createMediaStreamSource(stream);
2494
+ this._analyser = this._audioContext.createAnalyser();
2495
+ this._analyser.fftSize = 2048;
2496
+ this._analyser.smoothingTimeConstant = 0.3;
2497
+ this._microphone.connect(this._analyser);
2498
+ this.startMonitoring();
2499
+ console.log('SoundMeter: Successfully attached to new audio stream');
2500
+ } catch (error) {
2501
+ console.error('SoundMeter: Error during attach:', error);
2502
+ this.detach();
2503
+ }
2490
2504
  }
2491
2505
  detach() {
2506
+ var _a, _b;
2507
+ this._isMonitoring = false;
2492
2508
  if (this._microphone) {
2493
- this._microphone.disconnect();
2509
+ try {
2510
+ this._microphone.disconnect();
2511
+ } catch (e) {
2512
+ console.warn('SoundMeter: Error disconnecting microphone:', e);
2513
+ }
2494
2514
  this._microphone = null;
2495
2515
  }
2496
2516
  if (this._analyser) {
2497
- this._analyser.disconnect();
2517
+ try {
2518
+ this._analyser.disconnect();
2519
+ } catch (e) {
2520
+ console.warn('SoundMeter: Error disconnecting analyser:', e);
2521
+ }
2498
2522
  this._analyser = null;
2499
2523
  }
2500
- if (this._audioContext) {
2501
- this._audioContext.close();
2502
- this._audioContext = null;
2524
+ if (((_a = this._audioContext) === null || _a === void 0 ? void 0 : _a.state) !== 'closed') {
2525
+ try {
2526
+ (_b = this._audioContext) === null || _b === void 0 ? void 0 : _b.close();
2527
+ } catch (e) {
2528
+ console.warn('SoundMeter: Error closing audio context:', e);
2529
+ }
2503
2530
  }
2504
- this._stream = null;
2531
+ this._audioContext = null;
2505
2532
  this.clear();
2533
+ console.log('SoundMeter: Successfully detached');
2506
2534
  }
2507
2535
  clear() {
2508
2536
  this._instant = 0;
2509
2537
  this._slow = 0;
2510
- this._clip = 0;
2538
+ this._lastEventTime = 0;
2511
2539
  }
2512
2540
  startMonitoring() {
2513
- if (!this._analyser) return;
2541
+ if (!this._analyser || this._isMonitoring) return;
2542
+ this._isMonitoring = true;
2514
2543
  const dataArray = new Float32Array(this._analyser.frequencyBinCount);
2515
2544
  const analyze = () => {
2516
- if (!this._analyser) return;
2545
+ if (!this._analyser || !this._isMonitoring) return;
2517
2546
  const now = Date.now();
2518
- this._analyser.getFloatTimeDomainData(dataArray);
2519
- let sum = 0.0;
2520
- let clipcount = 0;
2521
- for (let i = 0; i < dataArray.length; ++i) {
2522
- const amplitude = dataArray[i] * 3.16;
2523
- sum += amplitude * amplitude;
2524
- if (Math.abs(amplitude) > 0.99) {
2525
- clipcount += 1;
2547
+ try {
2548
+ this._analyser.getFloatTimeDomainData(dataArray);
2549
+ let sum = 0.0;
2550
+ let clipcount = 0;
2551
+ for (let i = 0; i < dataArray.length; ++i) {
2552
+ const amplitude = dataArray[i];
2553
+ sum += amplitude * amplitude;
2554
+ if (Math.abs(amplitude) > 0.99) {
2555
+ clipcount += 1;
2556
+ }
2526
2557
  }
2527
- }
2528
- this._instant = Math.min(1, Math.sqrt(sum / dataArray.length));
2529
- this._slow = Math.min(1, 0.05 * this._instant + 0.95 * this._slow);
2530
- this._clip = clipcount / dataArray.length;
2531
- if (now - this._lastEventTime >= this.THROTTLE_INTERVAL) {
2532
- this._lastEventTime = now;
2533
- this._main.dispatchEvent("soundMeter", {
2534
- ref: this._main,
2535
- high: Number(this._instant.toFixed(4)),
2536
- low: Number(this._slow.toFixed(4))
2537
- });
2558
+ this._instant = Math.sqrt(sum / dataArray.length);
2559
+ this._slow = 0.05 * this._instant + 0.95 * this._slow;
2560
+ if (now - this._lastEventTime >= this.THROTTLE_INTERVAL) {
2561
+ this._lastEventTime = now;
2562
+ this._main.dispatchEvent("soundMeter", {
2563
+ ref: this._main,
2564
+ high: this._instant,
2565
+ low: this._slow
2566
+ });
2567
+ }
2568
+ } catch (error) {
2569
+ console.error('SoundMeter: Error during analysis:', error);
2570
+ this._isMonitoring = false;
2571
+ return;
2538
2572
  }
2539
2573
  requestAnimationFrame(analyze);
2540
2574
  };
@@ -2542,6 +2576,16 @@
2542
2576
  }
2543
2577
  }
2544
2578
 
2579
+ var InputDeviceState;
2580
+ (function (InputDeviceState) {
2581
+ InputDeviceState["NOT_INITIALIZED"] = "NOT_INITIALIZED";
2582
+ InputDeviceState["INITIALIZED"] = "INITIALIZED";
2583
+ InputDeviceState["READY"] = "READY";
2584
+ InputDeviceState["UPDATING"] = "UPDATING";
2585
+ InputDeviceState["INVALID"] = "INVALID";
2586
+ InputDeviceState["UNKNOWN"] = "UNKNOWN";
2587
+ })(InputDeviceState || (InputDeviceState = {}));
2588
+
2545
2589
  class PlaybackController {
2546
2590
  constructor(main) {
2547
2591
  this._isWindowActive = true;
@@ -2572,6 +2616,7 @@
2572
2616
  audio: true
2573
2617
  };
2574
2618
  this._publishState = exports.PublishState.NOT_INITIALIZED;
2619
+ this._inputDeviceState = InputDeviceState.NOT_INITIALIZED;
2575
2620
  this.onServerDisconnect = () => {};
2576
2621
  this.onServerConnect = () => {
2577
2622
  if (this._peerConnection) {
@@ -2709,6 +2754,7 @@
2709
2754
  handlePermissionChange(device, state) {
2710
2755
  return __awaiter(this, void 0, void 0, function* () {
2711
2756
  if (state === 'denied') {
2757
+ this.setInputDeviceState(InputDeviceState.INVALID);
2712
2758
  if (this._publishState == exports.PublishState.PUBLISHED) {
2713
2759
  this.closeStream();
2714
2760
  }
@@ -2966,7 +3012,13 @@
2966
3012
  if (deviceAccess.microphone.allowed) {
2967
3013
  this._selectedMicrophone = this.pickMicrophone();
2968
3014
  }
3015
+ if (this._selectedCamera != null && this._selectedMicrophone != null) {
3016
+ this.setInputDeviceState(InputDeviceState.READY);
3017
+ } else {
3018
+ this.setInputDeviceState(InputDeviceState.INVALID);
3019
+ }
2969
3020
  } catch (error) {
3021
+ this.setInputDeviceState(InputDeviceState.INVALID);
2970
3022
  this._logger.error(this, "Errror on grab devices: " + JSON.stringify(error));
2971
3023
  }
2972
3024
  this._main.dispatchEvent("deviceListUpdate", {
@@ -2992,6 +3044,8 @@
2992
3044
  }
2993
3045
  selectCamera(cameraID) {
2994
3046
  var _a, _b;
3047
+ this._selectedCamera = null;
3048
+ this.setInputDeviceState(InputDeviceState.UPDATING);
2995
3049
  const streamKey = (_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey;
2996
3050
  const wasPublished = this._publishState === exports.PublishState.PUBLISHED;
2997
3051
  for (let i = 0; i < this._cameraList.getSize(); i++) {
@@ -3003,16 +3057,27 @@
3003
3057
  }
3004
3058
  }
3005
3059
  this.stopCameraStream();
3006
- this._constraints.video.deviceId = this._selectedCamera.getID();
3007
- this.startCamera().then(() => {
3008
- if (wasPublished && streamKey) {
3009
- this.publish(streamKey);
3060
+ if (this._selectedCamera != null) {
3061
+ this._constraints.video.deviceId = this._selectedCamera.getID();
3062
+ if (this._selectedCamera != null && this._selectedMicrophone != null) {
3063
+ this.setInputDeviceState(InputDeviceState.READY);
3064
+ } else {
3065
+ this.setInputDeviceState(InputDeviceState.INVALID);
3010
3066
  }
3011
- });
3067
+ this.startCamera().then(() => {
3068
+ if (wasPublished && streamKey) {
3069
+ this.publish(streamKey);
3070
+ }
3071
+ });
3072
+ } else {
3073
+ this.setInputDeviceState(InputDeviceState.INVALID);
3074
+ }
3012
3075
  }
3013
3076
  selectMicrophone(micID) {
3014
- var _a, _b, _c, _d, _e, _f;
3077
+ var _a, _b, _c, _d;
3015
3078
  return __awaiter(this, void 0, void 0, function* () {
3079
+ this._selectedMicrophone = null;
3080
+ this.setInputDeviceState(InputDeviceState.UPDATING);
3016
3081
  console.log("🎤 Selecting microphone:", micID);
3017
3082
  const streamKey = (_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey;
3018
3083
  const wasPublished = this._publishState === exports.PublishState.PUBLISHED;
@@ -3024,33 +3089,41 @@
3024
3089
  }
3025
3090
  }
3026
3091
  this._soundMeter.detach();
3027
- (_c = this._stream) === null || _c === void 0 ? void 0 : _c.getAudioTracks().forEach(track => track.stop());
3028
3092
  try {
3029
3093
  const audioStream = yield navigator.mediaDevices.getUserMedia({
3030
3094
  audio: {
3031
3095
  deviceId: {
3032
- exact: (_d = this._selectedMicrophone) === null || _d === void 0 ? void 0 : _d.getID()
3096
+ exact: (_c = this._selectedMicrophone) === null || _c === void 0 ? void 0 : _c.getID()
3033
3097
  }
3034
3098
  }
3035
3099
  });
3036
- const oldAudioTracks = ((_e = this._stream) === null || _e === void 0 ? void 0 : _e.getAudioTracks()) || [];
3100
+ const oldAudioTracks = ((_d = this._stream) === null || _d === void 0 ? void 0 : _d.getAudioTracks()) || [];
3037
3101
  oldAudioTracks.forEach(track => {
3038
3102
  var _a;
3039
3103
  (_a = this._stream) === null || _a === void 0 ? void 0 : _a.removeTrack(track);
3040
3104
  track.stop();
3041
3105
  });
3042
3106
  const newAudioTrack = audioStream.getAudioTracks()[0];
3043
- (_f = this._stream) === null || _f === void 0 ? void 0 : _f.addTrack(newAudioTrack);
3044
- this._soundMeter.detach();
3045
- yield new Promise(resolve => setTimeout(resolve, 100));
3046
3107
  if (this._stream) {
3047
- this._soundMeter.attach(this._stream);
3108
+ this._stream.addTrack(newAudioTrack);
3109
+ if (newAudioTrack.readyState === 'live') {
3110
+ this._soundMeter.attach(this._stream);
3111
+ }
3112
+ }
3113
+ if (this._selectedCamera != null && this._selectedMicrophone != null) {
3114
+ this.setInputDeviceState(InputDeviceState.READY);
3115
+ } else {
3116
+ this.setInputDeviceState(InputDeviceState.INVALID);
3048
3117
  }
3049
3118
  if (wasPublished && streamKey) {
3050
3119
  this.publish(streamKey);
3051
3120
  }
3052
3121
  } catch (error) {
3053
3122
  console.error("Error changing microphone:", error);
3123
+ this.setInputDeviceState(InputDeviceState.INVALID);
3124
+ this._main.dispatchEvent("inputDeviceError", {
3125
+ ref: this._main
3126
+ });
3054
3127
  }
3055
3128
  });
3056
3129
  }
@@ -3123,7 +3196,7 @@
3123
3196
  this.setPublishState(exports.PublishState.UNPUBLISHED);
3124
3197
  }
3125
3198
  pickCamera() {
3126
- var _a, _b;
3199
+ var _a, _b, _c;
3127
3200
  for (let i = 0; i < this._cameraList.getSize(); i++) {
3128
3201
  this._cameraList.get(i).setSelected(false);
3129
3202
  }
@@ -3142,18 +3215,24 @@
3142
3215
  }
3143
3216
  if (!found) {
3144
3217
  this._main.dispatchEvent("savedCameraNotFound", {
3145
- ref: this._main
3218
+ ref: this._main,
3219
+ savedDeviceID: savedCameraID
3146
3220
  });
3147
- throw new Error("Specific camera was not found!");
3221
+ return null;
3148
3222
  }
3149
3223
  }
3150
3224
  if (!this._selectedCamera) {
3151
3225
  this._main.dispatchEvent("savedCameraNotFound", {
3152
- ref: this._main
3226
+ ref: this._main,
3227
+ savedDeviceID: null
3153
3228
  });
3154
- this._selectedCamera = this._cameraList.get(0);
3155
- this._selectedCamera.setSelected(true);
3156
- this._constraints.video.deviceId = this._selectedCamera.getID();
3229
+ if (!((_c = this._main.getConfigManager()) === null || _c === void 0 ? void 0 : _c.getSettingsData().getIfForceSelection())) {
3230
+ this._selectedCamera = this._cameraList.get(0);
3231
+ this._selectedCamera.setSelected(true);
3232
+ this._constraints.video.deviceId = this._selectedCamera.getID();
3233
+ } else {
3234
+ return null;
3235
+ }
3157
3236
  }
3158
3237
  }
3159
3238
  this._main.dispatchEvent("deviceListUpdate", {
@@ -3164,7 +3243,7 @@
3164
3243
  return this._selectedCamera;
3165
3244
  }
3166
3245
  pickMicrophone() {
3167
- var _a, _b;
3246
+ var _a, _b, _c;
3168
3247
  for (let i = 0; i < this._microphoneList.getSize(); i++) {
3169
3248
  this._microphoneList.get(i).setSelected(false);
3170
3249
  }
@@ -3181,13 +3260,22 @@
3181
3260
  }
3182
3261
  if (!found) {
3183
3262
  this._main.dispatchEvent("savedMicrophoneNotFound", {
3184
- ref: this._main
3263
+ ref: this._main,
3264
+ savedDeviceID: savedMicID
3185
3265
  });
3186
- throw new Error("Specific microphone was not found!");
3266
+ return null;
3187
3267
  }
3188
3268
  }
3189
3269
  if (!this._selectedMicrophone) {
3190
- this._selectedMicrophone = this._microphoneList.get(0);
3270
+ this._main.dispatchEvent("savedMicrophoneNotFound", {
3271
+ ref: this._main,
3272
+ savedDeviceID: null
3273
+ });
3274
+ if (!((_c = this._main.getConfigManager()) === null || _c === void 0 ? void 0 : _c.getSettingsData().getIfForceSelection())) {
3275
+ this._selectedMicrophone = this._microphoneList.get(0);
3276
+ } else {
3277
+ return null;
3278
+ }
3191
3279
  }
3192
3280
  this._selectedMicrophone.setSelected(true);
3193
3281
  this._constraints.audio = {
@@ -3273,6 +3361,15 @@
3273
3361
  state: this._publishState
3274
3362
  });
3275
3363
  }
3364
+ setInputDeviceState(newState) {
3365
+ this._inputDeviceState = newState;
3366
+ this._main.dispatchEvent("deviceStateChange", {
3367
+ ref: this._main,
3368
+ state: this._inputDeviceState,
3369
+ selectedCamera: this._selectedCamera,
3370
+ selectedMicrophone: this._selectedMicrophone
3371
+ });
3372
+ }
3276
3373
  getCameraList() {
3277
3374
  return this._cameraList != null ? this._cameraList.getArray() : [];
3278
3375
  }
@@ -3282,6 +3379,9 @@
3282
3379
  getPublishState() {
3283
3380
  return this._publishState;
3284
3381
  }
3382
+ getInputDeviceState() {
3383
+ return this._inputDeviceState;
3384
+ }
3285
3385
  getPlayer() {
3286
3386
  return this._selectedPlayer;
3287
3387
  }
@@ -3685,8 +3785,8 @@
3685
3785
  constructor(streamConfig, autoInitialize = false) {
3686
3786
  super();
3687
3787
  this.DEV_MODE = true;
3688
- this.STREAMER_VERSION = "0.9.0-beta.4";
3689
- this.COMPILE_DATE = "12/7/2024, 6:37:54 PM";
3788
+ this.STREAMER_VERSION = "0.9.0-beta.5";
3789
+ this.COMPILE_DATE = "12/10/2024, 10:26:02 AM";
3690
3790
  this.STREAMER_BRANCH = "Experimental";
3691
3791
  this.STREAMER_PROTOCOL_VERSION = 1;
3692
3792
  this._initialized = false;
@@ -3842,6 +3942,10 @@
3842
3942
  var _a, _b;
3843
3943
  return (_b = (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.publish(streamKey)) !== null && _b !== void 0 ? _b : false;
3844
3944
  }
3945
+ getDeviceState() {
3946
+ var _a, _b;
3947
+ return (_b = (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.getInputDeviceState()) !== null && _b !== void 0 ? _b : InputDeviceState.NOT_INITIALIZED;
3948
+ }
3845
3949
  clearSavedDevices() {
3846
3950
  var _a;
3847
3951
  return (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.clearSavedDevices();