livekit-client 1.11.1 → 1.11.3

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.
Files changed (47) hide show
  1. package/dist/livekit-client.esm.mjs +4157 -4015
  2. package/dist/livekit-client.esm.mjs.map +1 -1
  3. package/dist/livekit-client.umd.js +1 -1
  4. package/dist/livekit-client.umd.js.map +1 -1
  5. package/dist/src/room/PCTransport.d.ts +4 -3
  6. package/dist/src/room/PCTransport.d.ts.map +1 -1
  7. package/dist/src/room/Room.d.ts +5 -4
  8. package/dist/src/room/Room.d.ts.map +1 -1
  9. package/dist/src/room/events.d.ts +6 -1
  10. package/dist/src/room/events.d.ts.map +1 -1
  11. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  12. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  13. package/dist/src/room/track/LocalAudioTrack.d.ts +1 -1
  14. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  15. package/dist/src/room/track/LocalVideoTrack.d.ts +1 -1
  16. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  17. package/dist/src/room/track/RemoteVideoTrack.d.ts +3 -1
  18. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  19. package/dist/src/room/track/options.d.ts +1 -1
  20. package/dist/src/room/track/utils.d.ts +39 -0
  21. package/dist/src/room/track/utils.d.ts.map +1 -1
  22. package/dist/src/room/utils.d.ts +1 -0
  23. package/dist/src/room/utils.d.ts.map +1 -1
  24. package/dist/ts4.2/src/room/PCTransport.d.ts +4 -3
  25. package/dist/ts4.2/src/room/Room.d.ts +5 -4
  26. package/dist/ts4.2/src/room/events.d.ts +6 -1
  27. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +1 -1
  28. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +1 -1
  29. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +3 -1
  30. package/dist/ts4.2/src/room/track/options.d.ts +1 -1
  31. package/dist/ts4.2/src/room/track/utils.d.ts +39 -0
  32. package/dist/ts4.2/src/room/utils.d.ts +1 -0
  33. package/package.json +1 -1
  34. package/src/room/PCTransport.ts +116 -48
  35. package/src/room/Room.test.ts +29 -0
  36. package/src/room/Room.ts +55 -10
  37. package/src/room/events.ts +6 -0
  38. package/src/room/participant/LocalParticipant.ts +32 -8
  39. package/src/room/participant/publishUtils.ts +4 -2
  40. package/src/room/track/LocalAudioTrack.ts +4 -3
  41. package/src/room/track/LocalTrack.ts +2 -2
  42. package/src/room/track/LocalVideoTrack.ts +8 -4
  43. package/src/room/track/RemoteVideoTrack.ts +3 -8
  44. package/src/room/track/options.ts +1 -1
  45. package/src/room/track/utils.test.ts +30 -1
  46. package/src/room/track/utils.ts +102 -0
  47. package/src/room/utils.ts +23 -0
@@ -1,4 +1,6 @@
1
1
  import { sleep } from '../utils';
2
+ import log from './../../logger';
3
+ import LocalTrack from './LocalTrack';
2
4
  import type { AudioCaptureOptions, CreateLocalTracksOptions, VideoCaptureOptions } from './options';
3
5
  import type { AudioTrack } from './types';
4
6
 
@@ -112,3 +114,103 @@ export function getNewAudioContext(): AudioContext | void {
112
114
  return new AudioContext({ latencyHint: 'interactive' });
113
115
  }
114
116
  }
117
+
118
+ type FacingMode = NonNullable<VideoCaptureOptions['facingMode']>;
119
+ type FacingModeFromLocalTrackOptions = {
120
+ /**
121
+ * If no facing mode can be determined, this value will be used.
122
+ * @defaultValue 'user'
123
+ */
124
+ defaultFacingMode?: FacingMode;
125
+ };
126
+ type FacingModeFromLocalTrackReturnValue = {
127
+ /**
128
+ * The (probable) facingMode of the track.
129
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode | MDN docs on facingMode}
130
+ */
131
+ facingMode: FacingMode;
132
+ /**
133
+ * The confidence that the returned facingMode is correct.
134
+ */
135
+ confidence: 'high' | 'medium' | 'low';
136
+ };
137
+
138
+ /**
139
+ * Try to analyze the local track to determine the facing mode of a track.
140
+ *
141
+ * @remarks
142
+ * There is no property supported by all browsers to detect whether a video track originated from a user- or environment-facing camera device.
143
+ * For this reason, we use the `facingMode` property when available, but will fall back on a string-based analysis of the device label to determine the facing mode.
144
+ * If both methods fail, the default facing mode will be used.
145
+ *
146
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode | MDN docs on facingMode}
147
+ * @experimental
148
+ */
149
+ export function facingModeFromLocalTrack(
150
+ localTrack: LocalTrack | MediaStreamTrack,
151
+ options: FacingModeFromLocalTrackOptions = {},
152
+ ): FacingModeFromLocalTrackReturnValue {
153
+ const track = localTrack instanceof LocalTrack ? localTrack.mediaStreamTrack : localTrack;
154
+ const trackSettings = track.getSettings();
155
+ let result: FacingModeFromLocalTrackReturnValue = {
156
+ facingMode: options.defaultFacingMode ?? 'user',
157
+ confidence: 'low',
158
+ };
159
+
160
+ // 1. Try to get facingMode from track settings.
161
+ if ('facingMode' in trackSettings) {
162
+ const rawFacingMode = trackSettings.facingMode;
163
+ log.debug('rawFacingMode', { rawFacingMode });
164
+ if (rawFacingMode && typeof rawFacingMode === 'string' && isFacingModeValue(rawFacingMode)) {
165
+ result = { facingMode: rawFacingMode, confidence: 'high' };
166
+ }
167
+ }
168
+
169
+ // 2. If we don't have a high confidence we try to get the facing mode from the device label.
170
+ if (['low', 'medium'].includes(result.confidence)) {
171
+ log.debug(`Try to get facing mode from device label: (${track.label})`);
172
+ const labelAnalysisResult = facingModeFromDeviceLabel(track.label);
173
+ if (labelAnalysisResult !== undefined) {
174
+ result = labelAnalysisResult;
175
+ }
176
+ }
177
+
178
+ return result;
179
+ }
180
+
181
+ const knownDeviceLabels = new Map<string, FacingModeFromLocalTrackReturnValue>([
182
+ ['obs virtual camera', { facingMode: 'environment', confidence: 'medium' }],
183
+ ]);
184
+ const knownDeviceLabelSections = new Map<string, FacingModeFromLocalTrackReturnValue>([
185
+ ['iphone', { facingMode: 'environment', confidence: 'medium' }],
186
+ ['ipad', { facingMode: 'environment', confidence: 'medium' }],
187
+ ]);
188
+ /**
189
+ * Attempt to analyze the device label to determine the facing mode.
190
+ *
191
+ * @experimental
192
+ */
193
+ export function facingModeFromDeviceLabel(
194
+ deviceLabel: string,
195
+ ): FacingModeFromLocalTrackReturnValue | undefined {
196
+ const label = deviceLabel.trim().toLowerCase();
197
+ // Empty string is a valid device label but we can't infer anything from it.
198
+ if (label === '') {
199
+ return undefined;
200
+ }
201
+
202
+ // Can we match against widely known device labels.
203
+ if (knownDeviceLabels.has(label)) {
204
+ return knownDeviceLabels.get(label);
205
+ }
206
+
207
+ // Can we match against sections of the device label.
208
+ return Array.from(knownDeviceLabelSections.entries()).find(([section]) =>
209
+ label.includes(section),
210
+ )?.[1];
211
+ }
212
+
213
+ function isFacingModeValue(item: string): item is FacingMode {
214
+ const allowedValues: FacingMode[] = ['user', 'environment', 'left', 'right'];
215
+ return item === undefined || allowedValues.includes(item as FacingMode);
216
+ }
package/src/room/utils.ts CHANGED
@@ -455,3 +455,26 @@ export class Mutex {
455
455
  return willUnlock;
456
456
  }
457
457
  }
458
+
459
+ export function unwrapConstraint(constraint: ConstrainDOMString): string {
460
+ if (typeof constraint === 'string') {
461
+ return constraint;
462
+ }
463
+
464
+ if (Array.isArray(constraint)) {
465
+ return constraint[0];
466
+ }
467
+ if (constraint.exact) {
468
+ if (Array.isArray(constraint.exact)) {
469
+ return constraint.exact[0];
470
+ }
471
+ return constraint.exact;
472
+ }
473
+ if (constraint.ideal) {
474
+ if (Array.isArray(constraint.ideal)) {
475
+ return constraint.ideal[0];
476
+ }
477
+ return constraint.ideal;
478
+ }
479
+ throw Error('could not unwrap constraint');
480
+ }