livekit-client 1.7.1 → 1.8.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.
Files changed (73) hide show
  1. package/README.md +20 -1
  2. package/dist/livekit-client.esm.mjs +2178 -1060
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/src/index.d.ts +3 -1
  7. package/dist/src/index.d.ts.map +1 -1
  8. package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -1
  9. package/dist/src/proto/livekit_models.d.ts +32 -0
  10. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  11. package/dist/src/proto/livekit_rtc.d.ts +315 -75
  12. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  13. package/dist/src/room/RTCEngine.d.ts +8 -1
  14. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  15. package/dist/src/room/ReconnectPolicy.d.ts +1 -0
  16. package/dist/src/room/ReconnectPolicy.d.ts.map +1 -1
  17. package/dist/src/room/RegionUrlProvider.d.ts +14 -0
  18. package/dist/src/room/RegionUrlProvider.d.ts.map +1 -0
  19. package/dist/src/room/Room.d.ts +4 -0
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/errors.d.ts +2 -1
  22. package/dist/src/room/errors.d.ts.map +1 -1
  23. package/dist/src/room/events.d.ts +8 -2
  24. package/dist/src/room/events.d.ts.map +1 -1
  25. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/LocalTrack.d.ts +3 -2
  27. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  28. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  29. package/dist/src/room/track/RemoteTrackPublication.d.ts +1 -1
  30. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
  31. package/dist/src/room/track/RemoteVideoTrack.d.ts +1 -1
  32. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  33. package/dist/src/room/track/Track.d.ts +3 -1
  34. package/dist/src/room/track/Track.d.ts.map +1 -1
  35. package/dist/src/room/types.d.ts +4 -0
  36. package/dist/src/room/types.d.ts.map +1 -1
  37. package/dist/src/room/utils.d.ts +4 -0
  38. package/dist/src/room/utils.d.ts.map +1 -1
  39. package/dist/ts4.2/src/index.d.ts +3 -1
  40. package/dist/ts4.2/src/proto/livekit_models.d.ts +32 -0
  41. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +348 -84
  42. package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -1
  43. package/dist/ts4.2/src/room/ReconnectPolicy.d.ts +1 -0
  44. package/dist/ts4.2/src/room/RegionUrlProvider.d.ts +14 -0
  45. package/dist/ts4.2/src/room/Room.d.ts +4 -0
  46. package/dist/ts4.2/src/room/errors.d.ts +2 -1
  47. package/dist/ts4.2/src/room/events.d.ts +8 -2
  48. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -2
  49. package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +1 -1
  50. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +1 -1
  51. package/dist/ts4.2/src/room/track/Track.d.ts +3 -1
  52. package/dist/ts4.2/src/room/types.d.ts +4 -0
  53. package/dist/ts4.2/src/room/utils.d.ts +4 -0
  54. package/package.json +19 -19
  55. package/src/api/SignalClient.ts +4 -4
  56. package/src/index.ts +3 -0
  57. package/src/proto/google/protobuf/timestamp.ts +15 -6
  58. package/src/proto/livekit_models.ts +903 -222
  59. package/src/proto/livekit_rtc.ts +1053 -279
  60. package/src/room/RTCEngine.ts +143 -40
  61. package/src/room/ReconnectPolicy.ts +2 -0
  62. package/src/room/RegionUrlProvider.ts +73 -0
  63. package/src/room/Room.ts +201 -132
  64. package/src/room/errors.ts +1 -0
  65. package/src/room/events.ts +7 -0
  66. package/src/room/track/LocalAudioTrack.ts +13 -6
  67. package/src/room/track/LocalTrack.ts +22 -8
  68. package/src/room/track/LocalVideoTrack.ts +12 -6
  69. package/src/room/track/RemoteTrackPublication.ts +4 -3
  70. package/src/room/track/RemoteVideoTrack.ts +5 -4
  71. package/src/room/track/Track.ts +46 -31
  72. package/src/room/types.ts +6 -0
  73. package/src/room/utils.ts +53 -0
@@ -42,7 +42,7 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
42
42
 
43
43
  protected _mediaStreamID: string;
44
44
 
45
- protected isInBackground: boolean;
45
+ protected isInBackground: boolean = false;
46
46
 
47
47
  private backgroundTimeout: ReturnType<typeof setTimeout> | undefined;
48
48
 
@@ -57,12 +57,6 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
57
57
  this._mediaStreamTrack = mediaTrack;
58
58
  this._mediaStreamID = mediaTrack.id;
59
59
  this.source = Track.Source.Unknown;
60
- if (isWeb()) {
61
- this.isInBackground = document.visibilityState === 'hidden';
62
- document.addEventListener('visibilitychange', this.appVisibilityChangedListener);
63
- } else {
64
- this.isInBackground = false;
65
- }
66
60
  }
67
61
 
68
62
  /** current receive bits per second */
@@ -97,6 +91,9 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
97
91
  if (this.kind === Track.Kind.Video) {
98
92
  elementType = 'video';
99
93
  }
94
+ if (this.attachedElements.length === 0 && Track.Kind.Video) {
95
+ this.addAppVisibilityListener();
96
+ }
100
97
  if (!element) {
101
98
  if (elementType === 'audio') {
102
99
  recycledElements.forEach((e) => {
@@ -167,37 +164,40 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
167
164
  */
168
165
  detach(element: HTMLMediaElement): HTMLMediaElement;
169
166
  detach(element?: HTMLMediaElement): HTMLMediaElement | HTMLMediaElement[] {
170
- // detach from a single element
171
- if (element) {
172
- detachTrack(this._mediaStreamTrack, element);
173
- const idx = this.attachedElements.indexOf(element);
174
- if (idx >= 0) {
175
- this.attachedElements.splice(idx, 1);
176
- this.recycleElement(element);
177
- this.emit(TrackEvent.ElementDetached, element);
167
+ try {
168
+ // detach from a single element
169
+ if (element) {
170
+ detachTrack(this._mediaStreamTrack, element);
171
+ const idx = this.attachedElements.indexOf(element);
172
+ if (idx >= 0) {
173
+ this.attachedElements.splice(idx, 1);
174
+ this.recycleElement(element);
175
+ this.emit(TrackEvent.ElementDetached, element);
176
+ }
177
+ return element;
178
178
  }
179
- return element;
180
- }
181
179
 
182
- const detached: HTMLMediaElement[] = [];
183
- this.attachedElements.forEach((elm) => {
184
- detachTrack(this._mediaStreamTrack, elm);
185
- detached.push(elm);
186
- this.recycleElement(elm);
187
- this.emit(TrackEvent.ElementDetached, elm);
188
- });
180
+ const detached: HTMLMediaElement[] = [];
181
+ this.attachedElements.forEach((elm) => {
182
+ detachTrack(this._mediaStreamTrack, elm);
183
+ detached.push(elm);
184
+ this.recycleElement(elm);
185
+ this.emit(TrackEvent.ElementDetached, elm);
186
+ });
189
187
 
190
- // remove all tracks
191
- this.attachedElements = [];
192
- return detached;
188
+ // remove all tracks
189
+ this.attachedElements = [];
190
+ return detached;
191
+ } finally {
192
+ if (this.attachedElements.length === 0) {
193
+ this.removeAppVisibilityListener();
194
+ }
195
+ }
193
196
  }
194
197
 
195
198
  stop() {
196
199
  this.stopMonitor();
197
200
  this._mediaStreamTrack.stop();
198
- if (isWeb()) {
199
- document.removeEventListener('visibilitychange', this.appVisibilityChangedListener);
200
- }
201
201
  }
202
202
 
203
203
  protected enable() {
@@ -212,7 +212,7 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
212
212
  abstract startMonitor(signalClient?: SignalClient): void;
213
213
 
214
214
  /* @internal */
215
- protected stopMonitor() {
215
+ stopMonitor() {
216
216
  if (this.monitorInterval) {
217
217
  clearInterval(this.monitorInterval);
218
218
  }
@@ -253,6 +253,21 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
253
253
  protected async handleAppVisibilityChanged() {
254
254
  this.isInBackground = document.visibilityState === 'hidden';
255
255
  }
256
+
257
+ protected addAppVisibilityListener() {
258
+ if (isWeb()) {
259
+ this.isInBackground = document.visibilityState === 'hidden';
260
+ document.addEventListener('visibilitychange', this.appVisibilityChangedListener);
261
+ } else {
262
+ this.isInBackground = false;
263
+ }
264
+ }
265
+
266
+ protected removeAppVisibilityListener() {
267
+ if (isWeb()) {
268
+ document.removeEventListener('visibilitychange', this.appVisibilityChangedListener);
269
+ }
270
+ }
256
271
  }
257
272
 
258
273
  /** @internal */
package/src/room/types.ts CHANGED
@@ -20,3 +20,9 @@ export type DataPublishOptions = {
20
20
  /** the topic under which the message gets published */
21
21
  topic?: string;
22
22
  };
23
+
24
+ export type LiveKitReactNativeInfo = {
25
+ // Corresponds to RN's PlatformOSType
26
+ platform: 'ios' | 'android' | 'windows' | 'macos' | 'web' | 'native';
27
+ devicePixelRatio: number;
28
+ };
package/src/room/utils.ts CHANGED
@@ -4,6 +4,7 @@ import { protocolVersion, version } from '../version';
4
4
  import type LocalAudioTrack from './track/LocalAudioTrack';
5
5
  import type RemoteAudioTrack from './track/RemoteAudioTrack';
6
6
  import { getNewAudioContext } from './track/utils';
7
+ import type { LiveKitReactNativeInfo } from './types';
7
8
 
8
9
  const separator = '|';
9
10
 
@@ -122,6 +123,54 @@ export function isWeb(): boolean {
122
123
  return typeof document !== 'undefined';
123
124
  }
124
125
 
126
+ export function isReactNative(): boolean {
127
+ // navigator.product is deprecated on browsers, but will be set appropriately for react-native.
128
+ return navigator.product == 'ReactNative';
129
+ }
130
+
131
+ export function isCloud(serverUrl: URL) {
132
+ return serverUrl.hostname.endsWith('.livekit.cloud');
133
+ }
134
+
135
+ function getLKReactNativeInfo(): LiveKitReactNativeInfo | undefined {
136
+ // global defined only for ReactNative.
137
+ // @ts-ignore
138
+ if (global && global.LiveKitReactNativeGlobal) {
139
+ // @ts-ignore
140
+ return global.LiveKitReactNativeGlobal as LiveKitReactNativeInfo;
141
+ }
142
+
143
+ return undefined;
144
+ }
145
+
146
+ export function getReactNativeOs(): string | undefined {
147
+ if (!isReactNative()) {
148
+ return undefined;
149
+ }
150
+
151
+ let info = getLKReactNativeInfo();
152
+ if (info) {
153
+ return info.platform;
154
+ }
155
+
156
+ return undefined;
157
+ }
158
+
159
+ export function getDevicePixelRatio(): number {
160
+ if (isWeb()) {
161
+ return window.devicePixelRatio;
162
+ }
163
+
164
+ if (isReactNative()) {
165
+ let info = getLKReactNativeInfo();
166
+ if (info) {
167
+ return info.devicePixelRatio;
168
+ }
169
+ }
170
+
171
+ return 1;
172
+ }
173
+
125
174
  export function compareVersions(v1: string, v2: string): number {
126
175
  const parts1 = v1.split('.');
127
176
  const parts2 = v2.split('.');
@@ -174,6 +223,10 @@ export function getClientInfo(): ClientInfo {
174
223
  protocol: protocolVersion,
175
224
  version,
176
225
  });
226
+
227
+ if (isReactNative()) {
228
+ info.os = getReactNativeOs() ?? '';
229
+ }
177
230
  return info;
178
231
  }
179
232