@livedigital/client 1.1.5 → 1.4.1

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.
@@ -21,14 +21,11 @@ class System {
21
21
 
22
22
  public currentVideoDeviceId?: string;
23
23
 
24
- public getUserMediaError?: string = undefined;
25
-
26
- public deviceIsBusy?: boolean = false;
27
-
28
24
  private readonly logger: Logger;
29
25
 
30
26
  constructor() {
31
27
  this.logger = new Logger('System');
28
+ this.listenDevices();
32
29
  }
33
30
 
34
31
  setIsEnableVideoDevicesLock(value: boolean): void {
@@ -98,26 +95,35 @@ class System {
98
95
  };
99
96
  }
100
97
 
101
- async startVideoStream(params?: VideoConstraintParams): Promise<MediaStream | undefined> {
98
+ async getVideoTrack(): Promise<MediaStreamTrack> {
99
+ const videoStream = this.videoStream || await this.startVideoStream();
100
+ const [track] = videoStream.getVideoTracks();
101
+ return track;
102
+ }
103
+
104
+ async getAudioTrack(): Promise<MediaStreamTrack> {
105
+ const videoStream = this.videoStream || await this.startAudioStream();
106
+ const [track] = videoStream.getAudioTracks();
107
+ return track;
108
+ }
109
+
110
+ async startVideoStream(params?: VideoConstraintParams): Promise<MediaStream> {
102
111
  if (!this.videoStream || !this.videoStream.active) {
103
112
  try {
104
113
  this.videoStream = await navigator.mediaDevices.getUserMedia({
105
114
  video: this.getVideoConstraints(params),
106
115
  });
116
+ this.logger.debug('startVideoStream()');
107
117
  } catch (error) {
108
- this.logger.error('startVideoStream()');
118
+ this.logger.error('startVideoStream()', { error });
109
119
 
110
120
  if (error.name === 'NotReadableError') {
111
- this.deviceIsBusy = true;
112
121
  this.videoStream = undefined;
113
-
114
- return undefined;
122
+ throw new Error('DeviceIsBusy');
115
123
  }
116
124
 
117
- if (error.name === 'NotAllowedError') {
118
- this.getUserMediaError = error.name;
119
-
120
- return undefined;
125
+ if (error.name === 'This action is not allowed') {
126
+ throw new Error('NotAllowedError');
121
127
  }
122
128
 
123
129
  throw new Error('Can`t start video stream');
@@ -127,26 +133,23 @@ class System {
127
133
  return this.videoStream;
128
134
  }
129
135
 
130
- async startAudioStream(params?: AudioConstraintParams): Promise<MediaStream | undefined> {
136
+ async startAudioStream(params?: AudioConstraintParams): Promise<MediaStream> {
131
137
  if (!this.audioStream || !this.audioStream.active) {
132
138
  try {
133
139
  this.audioStream = await navigator.mediaDevices.getUserMedia({
134
140
  audio: this.getAudioConstraints(params),
135
141
  });
142
+ this.logger.debug('startAudioStream()');
136
143
  } catch (error) {
137
- this.logger.error('startAudioStream()', error);
144
+ this.logger.error('startAudioStream()', { error });
138
145
 
139
146
  if (error.name === 'NotReadableError') {
140
- this.deviceIsBusy = true;
141
147
  this.audioStream = undefined;
142
-
143
- return undefined;
148
+ throw new Error('DeviceIsBusy');
144
149
  }
145
150
 
146
151
  if (error.name === 'NotAllowedError') {
147
- this.getUserMediaError = error.name;
148
-
149
- return undefined;
152
+ throw new Error('Device access denied');
150
153
  }
151
154
 
152
155
  throw new Error('Can`t start audio stream');
@@ -158,8 +161,6 @@ class System {
158
161
 
159
162
  async detectDevices(): Promise<void> {
160
163
  this.isDevicesLoaded = false;
161
- this.deviceIsBusy = false;
162
- this.getUserMediaError = undefined;
163
164
 
164
165
  try {
165
166
  const mediaDevices = await navigator.mediaDevices.enumerateDevices();
@@ -175,8 +176,9 @@ class System {
175
176
  audio: availableDevicesTypes.audio && this.getAudioConstraints(),
176
177
  });
177
178
  } catch (error) {
179
+ this.logger.error('getUserMedia()', { error });
178
180
  if (error.name === 'NotReadableError') {
179
- this.deviceIsBusy = true;
181
+ throw new Error('DeviceIsBusy');
180
182
  }
181
183
  }
182
184
 
@@ -201,15 +203,25 @@ class System {
201
203
  this.setAvailableVideoDevices(videoDevices);
202
204
  this.setAvailableAudioDevices(audioDevices);
203
205
  this.isDevicesLoaded = true;
206
+ this.logger.debug('detectDevices()', { videoDevices, audioDevices });
204
207
  } catch (error) {
205
- this.getUserMediaError = error.name || error;
206
- this.logger.error('detectDevices()');
208
+ this.logger.error('detectDevices()', { error });
207
209
  throw new Error('Can`t detect devices');
208
210
  }
209
211
  }
210
212
 
213
+ listenDevices(): void {
214
+ navigator.mediaDevices.ondevicechange = () => {
215
+ if (this.isDevicesLoaded) {
216
+ this.logger.debug('Available devices list was changed');
217
+ this.detectDevices();
218
+ }
219
+ };
220
+ }
221
+
211
222
  stopVideoStream(): void {
212
223
  if (!this.videoStream) {
224
+ this.logger.warn('stopVideoStream()', { message: 'No available video stream' });
213
225
  return;
214
226
  }
215
227
 
@@ -218,10 +230,12 @@ class System {
218
230
  });
219
231
 
220
232
  this.videoStream = undefined;
233
+ this.logger.debug('stopVideoStream()');
221
234
  }
222
235
 
223
236
  stopAudioStream(): void {
224
237
  if (!this.audioStream) {
238
+ this.logger.warn('stopVideoStream()', { message: 'No available audio stream' });
225
239
  return;
226
240
  }
227
241
 
@@ -230,6 +244,7 @@ class System {
230
244
  });
231
245
 
232
246
  this.audioStream = undefined;
247
+ this.logger.debug('stopAudioStream()');
233
248
  }
234
249
 
235
250
  async restartVideoStream(): Promise<void> {
package/src/index.ts CHANGED
@@ -43,7 +43,23 @@ class Client {
43
43
  return !!this.engine.media.audioProducer?.paused;
44
44
  }
45
45
 
46
- async getDevices(): Promise<AvailableMediaDevices> {
46
+ get availableVideoDevices(): MediaDeviceInfo[] {
47
+ return this.engine.system.availableVideoDevices;
48
+ }
49
+
50
+ get availableAudioDevices(): MediaDeviceInfo[] {
51
+ return this.engine.system.availableAudioDevices;
52
+ }
53
+
54
+ get currentAudioDeviceId(): string | undefined {
55
+ return this.engine.system.currentAudioDeviceId;
56
+ }
57
+
58
+ get currentVideoDeviceId(): string | undefined {
59
+ return this.engine.system.currentVideoDeviceId;
60
+ }
61
+
62
+ async detectDevices(): Promise<AvailableMediaDevices> {
47
63
  await this.engine.system.detectDevices();
48
64
  return {
49
65
  video: this.engine.system.availableVideoDevices,
@@ -51,6 +67,22 @@ class Client {
51
67
  };
52
68
  }
53
69
 
70
+ async getVideoStream(): Promise<MediaStream> {
71
+ return this.engine.system.videoStream || this.engine.system.startVideoStream();
72
+ }
73
+
74
+ async getAudioStream(): Promise<MediaStream> {
75
+ return this.engine.system.audioStream || this.engine.system.startAudioStream();
76
+ }
77
+
78
+ async getVideoTrack(): Promise<MediaStreamTrack> {
79
+ return this.engine.system.getVideoTrack();
80
+ }
81
+
82
+ async getAudioTrack(): Promise<MediaStreamTrack> {
83
+ return this.engine.system.getAudioTrack();
84
+ }
85
+
54
86
  setVideoDevice(deviceId: string): void {
55
87
  this.engine.system.setCurrentVideoDevice(deviceId);
56
88
  }