livekit-client 1.0.0 → 1.0.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.
@@ -16,15 +16,37 @@ export default class RemoteVideoTrack extends RemoteTrack {
16
16
  setMuted(muted: boolean): void;
17
17
  attach(): HTMLMediaElement;
18
18
  attach(element: HTMLMediaElement): HTMLMediaElement;
19
+ /**
20
+ * Observe an ElementInfo for changes when adaptive streaming.
21
+ * @param elementInfo
22
+ * @internal
23
+ */
24
+ observeElementInfo(elementInfo: ElementInfo): void;
25
+ /**
26
+ * Stop observing an ElementInfo for changes.
27
+ * @param elementInfo
28
+ * @internal
29
+ */
30
+ stopObservingElementInfo(elementInfo: ElementInfo): void;
19
31
  detach(): HTMLMediaElement[];
20
32
  detach(element: HTMLMediaElement): HTMLMediaElement;
21
33
  protected monitorReceiver: () => Promise<void>;
22
34
  private getReceiverStats;
23
35
  private stopObservingElement;
24
- private handleVisibilityChanged;
25
36
  protected handleAppVisibilityChanged(): Promise<void>;
26
37
  private readonly debouncedHandleResize;
27
38
  private updateVisibility;
28
39
  private updateDimensions;
29
40
  }
41
+ export interface ElementInfo {
42
+ element: object;
43
+ width(): number;
44
+ height(): number;
45
+ visible: boolean;
46
+ visibilityChangedAt: number | undefined;
47
+ handleResize?: () => void;
48
+ handleVisibilityChanged?: () => void;
49
+ observe(): void;
50
+ stopObserving(): void;
51
+ }
30
52
  //# sourceMappingURL=RemoteVideoTrack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteVideoTrack.d.ts","sourceRoot":"","sources":["../../../src/room/track/RemoteVideoTrack.ts"],"names":[],"mappings":"AASA,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAKjD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACvD,gBAAgB;IAChB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B,OAAO,CAAC,SAAS,CAAC,CAAqB;IAEvC,OAAO,CAAC,YAAY,CAAqB;IAEzC,OAAO,CAAC,sBAAsB,CAAC,CAAyB;IAExD,OAAO,CAAC,WAAW,CAAC,CAAU;IAE9B,OAAO,CAAC,cAAc,CAAC,CAAmB;IAE1C,OAAO,CAAC,aAAa,CAAkB;gBAGrC,UAAU,EAAE,gBAAgB,EAC5B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,EACzB,sBAAsB,CAAC,EAAE,sBAAsB;IASjD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,qBAOnB;IAED,gBAAgB;IAChB,QAAQ,CAAC,KAAK,EAAE,OAAO;IAavB,MAAM,IAAI,gBAAgB;IAC1B,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB;IAkCnD,MAAM,IAAI,gBAAgB,EAAE;IAC5B,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB;IAgBnD,SAAS,CAAC,eAAe,sBAevB;YAEY,gBAAgB;IA8B9B,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,uBAAuB,CAQ7B;cAEc,0BAA0B;IAQ1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAEnB;IAEnB,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,gBAAgB;CAwBzB"}
1
+ {"version":3,"file":"RemoteVideoTrack.d.ts","sourceRoot":"","sources":["../../../src/room/track/RemoteVideoTrack.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAKjD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACvD,gBAAgB;IAChB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B,OAAO,CAAC,SAAS,CAAC,CAAqB;IAEvC,OAAO,CAAC,YAAY,CAAqB;IAEzC,OAAO,CAAC,sBAAsB,CAAC,CAAyB;IAExD,OAAO,CAAC,WAAW,CAAC,CAAU;IAE9B,OAAO,CAAC,cAAc,CAAC,CAAmB;IAE1C,OAAO,CAAC,aAAa,CAAkB;gBAGrC,UAAU,EAAE,gBAAgB,EAC5B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,EACzB,sBAAsB,CAAC,EAAE,sBAAsB;IASjD,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,gBAAgB,qBAOnB;IAED,gBAAgB;IAChB,QAAQ,CAAC,KAAK,EAAE,OAAO;IAavB,MAAM,IAAI,gBAAgB;IAC1B,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB;IAqBnD;;;;OAIG;IACH,kBAAkB,CAAC,WAAW,EAAE,WAAW;IAqB3C;;;;OAIG;IACH,wBAAwB,CAAC,WAAW,EAAE,WAAW;IASjD,MAAM,IAAI,gBAAgB,EAAE;IAC5B,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB;IAgBnD,SAAS,CAAC,eAAe,sBAevB;YAEY,gBAAgB;IA8B9B,OAAO,CAAC,oBAAoB;cAQZ,0BAA0B;IAM1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAEnB;IAEnB,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,gBAAgB;CAyBzB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,IAAI,MAAM,CAAC;IAChB,MAAM,IAAI,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IAExC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,aAAa,IAAI,IAAI,CAAC;CACvB"}
@@ -17,6 +17,7 @@ export declare class Track extends Track_base {
17
17
  mediaStream?: MediaStream;
18
18
  protected _mediaStreamTrack: MediaStreamTrack;
19
19
  protected isInBackground: boolean;
20
+ private backgroundTimeout;
20
21
  protected _currentBitrate: number;
21
22
  protected constructor(mediaTrack: MediaStreamTrack, kind: Track.Kind);
22
23
  /** current receive bits per second */
@@ -43,7 +44,7 @@ export declare class Track extends Track_base {
43
44
  protected enable(): void;
44
45
  protected disable(): void;
45
46
  private recycleElement;
46
- appVisibilityChangedListener: () => void;
47
+ protected appVisibilityChangedListener: () => void;
47
48
  protected handleAppVisibilityChanged(): Promise<void>;
48
49
  }
49
50
  /** @internal */
@@ -1 +1 @@
1
- {"version":3,"file":"Track.d.ts","sourceRoot":"","sources":["../../../src/room/track/Track.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Track.d.ts","sourceRoot":"","sources":["../../../src/room/track/Track.ts"],"names":[],"mappings":"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"}
@@ -15,5 +15,10 @@ export declare type AdaptiveStreamSettings = {
15
15
  * streaming on high definition screens.
16
16
  */
17
17
  pixelDensity?: number | 'screen';
18
+ /**
19
+ * If true, video gets paused when switching to another tab.
20
+ * Defaults to true.
21
+ */
22
+ pauseVideoInBackground?: boolean;
18
23
  };
19
24
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/room/track/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,gBAAgB,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,gBAAgB,MAAM,oBAAoB,CAAC;AAEvD,oBAAY,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAC9D,oBAAY,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAC5D,oBAAY,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE5D,oBAAY,sBAAsB,GAAG;IACnC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/room/track/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,gBAAgB,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,gBAAgB,MAAM,oBAAoB,CAAC;AAEvD,oBAAY,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAC9D,oBAAY,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAC5D,oBAAY,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE5D,oBAAY,sBAAsB,GAAG;IACnC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACjC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC"}
@@ -0,0 +1,26 @@
1
+ export default class MockMediaStreamTrack implements MediaStreamTrack {
2
+ contentHint: string;
3
+ enabled: boolean;
4
+ id: string;
5
+ kind: string;
6
+ label: string;
7
+ muted: boolean;
8
+ onended: ((this: MediaStreamTrack, ev: Event) => any) | null;
9
+ onmute: ((this: MediaStreamTrack, ev: Event) => any) | null;
10
+ onunmute: ((this: MediaStreamTrack, ev: Event) => any) | null;
11
+ readyState: MediaStreamTrackState;
12
+ isolated: boolean;
13
+ onisolationchange: ((this: MediaStreamTrack, ev: Event) => any) | null;
14
+ applyConstraints(constraints?: MediaTrackConstraints): Promise<void>;
15
+ clone(): MediaStreamTrack;
16
+ getCapabilities(): MediaTrackCapabilities;
17
+ getConstraints(): MediaTrackConstraints;
18
+ getSettings(): MediaTrackSettings;
19
+ stop(): void;
20
+ addEventListener<K extends keyof MediaStreamTrackEventMap>(type: K, listener: (this: MediaStreamTrack, ev: MediaStreamTrackEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
21
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
22
+ removeEventListener<K extends keyof MediaStreamTrackEventMap>(type: K, listener: (this: MediaStreamTrack, ev: MediaStreamTrackEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
23
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
24
+ dispatchEvent(event: Event): boolean;
25
+ }
26
+ //# sourceMappingURL=MockMediaStreamTrack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockMediaStreamTrack.d.ts","sourceRoot":"","sources":["../../src/test/MockMediaStreamTrack.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,gBAAgB;IACnE,WAAW,EAAE,MAAM,CAAM;IAEzB,OAAO,EAAE,OAAO,CAAQ;IAExB,EAAE,EAAE,MAAM,CAAQ;IAElB,IAAI,EAAE,MAAM,CAAW;IAEvB,KAAK,EAAE,MAAM,CAAW;IAExB,KAAK,EAAE,OAAO,CAAS;IAEvB,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,CAAQ;IAEpE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,CAAQ;IAEnE,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,CAAQ;IAErE,UAAU,EAAE,qBAAqB,CAAU;IAE3C,QAAQ,EAAE,OAAO,CAAS;IAE1B,iBAAiB,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,CAAQ;IAG9E,gBAAgB,CAAC,WAAW,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,KAAK,IAAI,gBAAgB;IAIzB,eAAe,IAAI,sBAAsB;IAIzC,cAAc,IAAI,qBAAqB;IAIvC,WAAW,IAAI,kBAAkB;IAIjC,IAAI,IAAI,IAAI;IAIZ,gBAAgB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EACvD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,GAAG,EAC1E,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI;IACP,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI;IAKP,mBAAmB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAC1D,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,GAAG,EAC1E,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI;IACP,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI;IAKP,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;CAGrC"}
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare const version = "1.0.0";
1
+ export declare const version = "1.0.1";
2
2
  export declare const protocolVersion = 7;
3
3
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "JavaScript/TypeScript client SDK for LiveKit",
5
5
  "main": "./dist/livekit-client.umd.js",
6
6
  "unpkg": "./dist/livekit-client.umd.js",
@@ -57,6 +57,7 @@
57
57
  "jest": "^27.4.3",
58
58
  "prettier": "^2.6.1",
59
59
  "rollup": "^2.70.1",
60
+ "rollup-plugin-livereload": "^2.0.5",
60
61
  "rollup-plugin-re": "^1.0.7",
61
62
  "rollup-plugin-serve": "^1.1.0",
62
63
  "rollup-plugin-terser": "^7.0.2",
package/src/index.ts CHANGED
@@ -12,7 +12,7 @@ import LocalVideoTrack from './room/track/LocalVideoTrack';
12
12
  import RemoteAudioTrack from './room/track/RemoteAudioTrack';
13
13
  import RemoteTrack from './room/track/RemoteTrack';
14
14
  import RemoteTrackPublication from './room/track/RemoteTrackPublication';
15
- import RemoteVideoTrack from './room/track/RemoteVideoTrack';
15
+ import RemoteVideoTrack, { ElementInfo } from './room/track/RemoteVideoTrack';
16
16
  import { TrackPublication } from './room/track/TrackPublication';
17
17
 
18
18
  export * from './options';
@@ -46,4 +46,5 @@ export {
46
46
  TrackPublication,
47
47
  VideoQuality,
48
48
  ConnectionQuality,
49
+ ElementInfo,
49
50
  };
package/src/room/Room.ts CHANGED
@@ -560,7 +560,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
560
560
 
561
561
  this.localParticipant.tracks.forEach((pub) => {
562
562
  if (pub.track) {
563
- this.localParticipant.unpublishTrack(pub.track);
563
+ this.localParticipant.unpublishTrack(pub.track, shouldStopTracks);
564
564
  }
565
565
  if (shouldStopTracks) {
566
566
  pub.track?.detach();
@@ -89,7 +89,7 @@ export default class LocalVideoTrack extends LocalTrack {
89
89
  bytesSent: v.bytesSent,
90
90
  framesSent: v.framesSent,
91
91
  timestamp: v.timestamp,
92
- rid: v.rid ?? '',
92
+ rid: v.rid ?? v.id,
93
93
  retransmittedPacketsSent: v.retransmittedPacketsSent,
94
94
  qualityLimitationReason: v.qualityLimitationReason,
95
95
  qualityLimitationResolutionChanges: v.qualityLimitationResolutionChanges,
@@ -0,0 +1,149 @@
1
+ import { TrackEvent } from '../events';
2
+ import RemoteVideoTrack, { ElementInfo } from './RemoteVideoTrack';
3
+ import MockMediaStreamTrack from '../../test/MockMediaStreamTrack';
4
+ import { Track } from './Track';
5
+
6
+ jest.useFakeTimers();
7
+
8
+ describe('RemoteVideoTrack', () => {
9
+ let track: RemoteVideoTrack;
10
+
11
+ beforeEach(() => {
12
+ track = new RemoteVideoTrack(new MockMediaStreamTrack(), 'sid', undefined, {});
13
+ });
14
+ describe('element visibility', () => {
15
+ let events: boolean[] = [];
16
+
17
+ beforeEach(() => {
18
+ track.on(TrackEvent.VisibilityChanged, (visible) => {
19
+ events.push(visible);
20
+ });
21
+ });
22
+ afterEach(() => {
23
+ events = [];
24
+ });
25
+
26
+ it('emits a visibility event upon observing visible element', () => {
27
+ const elementInfo = new MockElementInfo();
28
+ elementInfo.visible = true;
29
+
30
+ track.observeElementInfo(elementInfo);
31
+
32
+ expect(events).toHaveLength(1);
33
+ expect(events[0]).toBeTruthy();
34
+ });
35
+
36
+ it('emits a visibility event upon element becoming visible', () => {
37
+ const elementInfo = new MockElementInfo();
38
+ track.observeElementInfo(elementInfo);
39
+
40
+ elementInfo.setVisible(true);
41
+
42
+ expect(events).toHaveLength(2);
43
+ expect(events[1]).toBeTruthy();
44
+ });
45
+
46
+ it('emits a visibility event upon removing only visible element', () => {
47
+ const elementInfo = new MockElementInfo();
48
+ elementInfo.visible = true;
49
+
50
+ track.observeElementInfo(elementInfo);
51
+ track.stopObservingElementInfo(elementInfo);
52
+
53
+ expect(events).toHaveLength(2);
54
+ expect(events[1]).toBeFalsy();
55
+ });
56
+ });
57
+
58
+ describe('element dimensions', () => {
59
+ let events: Track.Dimensions[] = [];
60
+
61
+ beforeEach(() => {
62
+ track.on(TrackEvent.VideoDimensionsChanged, (dimensions) => {
63
+ events.push(dimensions);
64
+ });
65
+ });
66
+
67
+ afterEach(() => {
68
+ events = [];
69
+ });
70
+
71
+ it('emits a dimensions event upon observing element', () => {
72
+ const elementInfo = new MockElementInfo();
73
+ elementInfo.setDimensions(100, 100);
74
+
75
+ track.observeElementInfo(elementInfo);
76
+ jest.runAllTimers();
77
+
78
+ expect(events).toHaveLength(1);
79
+ expect(events[0].width).toBe(100);
80
+ expect(events[0].height).toBe(100);
81
+ });
82
+
83
+ it('emits a dimensions event upon element resize', () => {
84
+ const elementInfo = new MockElementInfo();
85
+ elementInfo.setDimensions(100, 100);
86
+
87
+ track.observeElementInfo(elementInfo);
88
+ jest.runAllTimers();
89
+
90
+ elementInfo.setDimensions(200, 200);
91
+ jest.runAllTimers();
92
+
93
+ expect(events).toHaveLength(2);
94
+ expect(events[1].width).toBe(200);
95
+ expect(events[1].height).toBe(200);
96
+ });
97
+ });
98
+ });
99
+
100
+ class MockElementInfo implements ElementInfo {
101
+ element: object = {};
102
+
103
+ private _width = 0;
104
+
105
+ private _height = 0;
106
+
107
+ setDimensions(width: number, height: number) {
108
+ let shouldEmit = false;
109
+ if (this._width !== width) {
110
+ this._width = width;
111
+ shouldEmit = true;
112
+ }
113
+ if (this._height !== height) {
114
+ this._height = height;
115
+ shouldEmit = true;
116
+ }
117
+
118
+ if (shouldEmit) {
119
+ this.handleResize?.();
120
+ }
121
+ }
122
+
123
+ width(): number {
124
+ return this._width;
125
+ }
126
+
127
+ height(): number {
128
+ return this._height;
129
+ }
130
+
131
+ visible = false;
132
+
133
+ setVisible = (visible: boolean) => {
134
+ if (this.visible !== visible) {
135
+ this.visible = visible;
136
+ this.handleVisibilityChanged?.();
137
+ }
138
+ };
139
+
140
+ visibilityChangedAt = 0;
141
+
142
+ handleResize?: () => void;
143
+
144
+ handleVisibilityChanged?: () => void;
145
+
146
+ observe(): void {}
147
+
148
+ stopObserving(): void {}
149
+ }
@@ -1,12 +1,7 @@
1
1
  import { debounce } from 'ts-debounce';
2
2
  import { TrackEvent } from '../events';
3
3
  import { computeBitrate, monitorFrequency, VideoReceiverStats } from '../stats';
4
- import {
5
- getIntersectionObserver,
6
- getResizeObserver,
7
- isMobile,
8
- ObservableMediaElement,
9
- } from '../utils';
4
+ import { getIntersectionObserver, getResizeObserver, ObservableMediaElement } from '../utils';
10
5
  import RemoteTrack from './RemoteTrack';
11
6
  import { attachToElement, detachTrack, Track } from './Track';
12
7
  import { AdaptiveStreamSettings } from './types';
@@ -85,24 +80,51 @@ export default class RemoteVideoTrack extends RemoteTrack {
85
80
  this.adaptiveStreamSettings &&
86
81
  this.elementInfos.find((info) => info.element === element) === undefined
87
82
  ) {
88
- this.elementInfos.push({
89
- element,
90
- visible: true, // default visible
91
- });
92
-
93
- (element as ObservableMediaElement).handleResize = this.debouncedHandleResize;
94
- (element as ObservableMediaElement).handleVisibilityChanged = this.handleVisibilityChanged;
95
-
96
- getIntersectionObserver().observe(element);
97
- getResizeObserver().observe(element);
83
+ const elementInfo = new HTMLElementInfo(element);
84
+ this.observeElementInfo(elementInfo);
85
+ }
86
+ this.hasUsedAttach = true;
87
+ return element;
88
+ }
98
89
 
90
+ /**
91
+ * Observe an ElementInfo for changes when adaptive streaming.
92
+ * @param elementInfo
93
+ * @internal
94
+ */
95
+ observeElementInfo(elementInfo: ElementInfo) {
96
+ if (
97
+ this.adaptiveStreamSettings &&
98
+ this.elementInfos.find((info) => info === elementInfo) === undefined
99
+ ) {
100
+ elementInfo.handleResize = () => {
101
+ this.debouncedHandleResize();
102
+ };
103
+ elementInfo.handleVisibilityChanged = () => {
104
+ this.updateVisibility();
105
+ };
106
+ this.elementInfos.push(elementInfo);
107
+ elementInfo.observe();
99
108
  // trigger the first resize update cycle
100
109
  // if the tab is backgrounded, the initial resize event does not fire until
101
110
  // the tab comes into focus for the first time.
102
111
  this.debouncedHandleResize();
112
+ this.updateVisibility();
103
113
  }
104
- this.hasUsedAttach = true;
105
- return element;
114
+ }
115
+
116
+ /**
117
+ * Stop observing an ElementInfo for changes.
118
+ * @param elementInfo
119
+ * @internal
120
+ */
121
+ stopObservingElementInfo(elementInfo: ElementInfo) {
122
+ const stopElementInfos = this.elementInfos.filter((info) => info === elementInfo);
123
+ for (const info of stopElementInfos) {
124
+ info.stopObserving();
125
+ }
126
+ this.elementInfos = this.elementInfos.filter((info) => info !== elementInfo);
127
+ this.updateVisibility();
106
128
  }
107
129
 
108
130
  detach(): HTMLMediaElement[];
@@ -170,26 +192,16 @@ export default class RemoteVideoTrack extends RemoteTrack {
170
192
  }
171
193
 
172
194
  private stopObservingElement(element: HTMLMediaElement) {
173
- getIntersectionObserver()?.unobserve(element);
174
- getResizeObserver()?.unobserve(element);
195
+ const stopElementInfos = this.elementInfos.filter((info) => info.element === element);
196
+ for (const info of stopElementInfos) {
197
+ info.stopObserving();
198
+ }
175
199
  this.elementInfos = this.elementInfos.filter((info) => info.element !== element);
176
200
  }
177
201
 
178
- private handleVisibilityChanged = (entry: IntersectionObserverEntry) => {
179
- const { target, isIntersecting } = entry;
180
- const elementInfo = this.elementInfos.find((info) => info.element === target);
181
- if (elementInfo) {
182
- elementInfo.visible = isIntersecting;
183
- elementInfo.visibilityChangedAt = Date.now();
184
- }
185
- this.updateVisibility();
186
- };
187
-
188
202
  protected async handleAppVisibilityChanged() {
189
203
  await super.handleAppVisibilityChanged();
190
204
  if (!this.isAdaptiveStream) return;
191
- // on desktop don't pause when tab is backgrounded
192
- if (!isMobile()) return;
193
205
  this.updateVisibility();
194
206
  }
195
207
 
@@ -202,7 +214,12 @@ export default class RemoteVideoTrack extends RemoteTrack {
202
214
  (prev, info) => Math.max(prev, info.visibilityChangedAt || 0),
203
215
  0,
204
216
  );
205
- const isVisible = this.elementInfos.some((info) => info.visible) && !this.isInBackground;
217
+
218
+ const backgroundPause =
219
+ this.adaptiveStreamSettings?.pauseVideoInBackground ?? true // default to true
220
+ ? this.isInBackground
221
+ : false;
222
+ const isVisible = this.elementInfos.some((info) => info.visible) && !backgroundPause;
206
223
 
207
224
  if (this.lastVisible === isVisible) {
208
225
  return;
@@ -226,8 +243,8 @@ export default class RemoteVideoTrack extends RemoteTrack {
226
243
  for (const info of this.elementInfos) {
227
244
  const pixelDensity = this.adaptiveStreamSettings?.pixelDensity ?? 1;
228
245
  const pixelDensityValue = pixelDensity === 'screen' ? window.devicePixelRatio : pixelDensity;
229
- const currentElementWidth = info.element.clientWidth * pixelDensityValue;
230
- const currentElementHeight = info.element.clientHeight * pixelDensityValue;
246
+ const currentElementWidth = info.width() * pixelDensityValue;
247
+ const currentElementHeight = info.height() * pixelDensityValue;
231
248
  if (currentElementWidth + currentElementHeight > maxWidth + maxHeight) {
232
249
  maxWidth = currentElementWidth;
233
250
  maxHeight = currentElementHeight;
@@ -242,12 +259,70 @@ export default class RemoteVideoTrack extends RemoteTrack {
242
259
  width: maxWidth,
243
260
  height: maxHeight,
244
261
  };
262
+
245
263
  this.emit(TrackEvent.VideoDimensionsChanged, this.lastDimensions, this);
246
264
  }
247
265
  }
248
266
 
249
- interface ElementInfo {
267
+ export interface ElementInfo {
268
+ element: object;
269
+ width(): number;
270
+ height(): number;
271
+ visible: boolean;
272
+ visibilityChangedAt: number | undefined;
273
+
274
+ handleResize?: () => void;
275
+ handleVisibilityChanged?: () => void;
276
+ observe(): void;
277
+ stopObserving(): void;
278
+ }
279
+
280
+ class HTMLElementInfo implements ElementInfo {
250
281
  element: HTMLMediaElement;
282
+
251
283
  visible: boolean;
252
- visibilityChangedAt?: number;
284
+
285
+ visibilityChangedAt: number | undefined;
286
+
287
+ handleResize?: () => void;
288
+
289
+ handleVisibilityChanged?: () => void;
290
+
291
+ constructor(element: HTMLMediaElement, visible: boolean = false) {
292
+ this.element = element;
293
+ this.visible = visible;
294
+ this.visibilityChangedAt = 0;
295
+ }
296
+
297
+ width(): number {
298
+ return this.element.clientWidth;
299
+ }
300
+
301
+ height(): number {
302
+ return this.element.clientWidth;
303
+ }
304
+
305
+ observe() {
306
+ (this.element as ObservableMediaElement).handleResize = () => {
307
+ this.handleResize?.();
308
+ };
309
+ (this.element as ObservableMediaElement).handleVisibilityChanged = this.onVisibilityChanged;
310
+
311
+ getIntersectionObserver().observe(this.element);
312
+ getResizeObserver().observe(this.element);
313
+ }
314
+
315
+ private onVisibilityChanged = (entry: IntersectionObserverEntry) => {
316
+ const { target, isIntersecting } = entry;
317
+ if (target === this.element) {
318
+ this.visible = isIntersecting;
319
+ this.visibilityChangedAt = Date.now();
320
+ this.handleVisibilityChanged?.();
321
+ }
322
+ };
323
+
324
+ stopObserving() {
325
+ getIntersectionObserver()?.unobserve(this.element);
326
+ getResizeObserver()?.unobserve(this.element);
327
+ }
253
328
  }
@@ -5,6 +5,8 @@ import { StreamState as ProtoStreamState } from '../../proto/livekit_rtc';
5
5
  import { TrackEvent } from '../events';
6
6
  import { isFireFox, isSafari, isWeb } from '../utils';
7
7
 
8
+ const BACKGROUND_REACTION_DELAY = 5000;
9
+
8
10
  // keep old audio elements when detached, we would re-use them since on iOS
9
11
  // Safari tracks which audio elements have been "blessed" by the user.
10
12
  const recycledElements: Array<HTMLAudioElement> = [];
@@ -32,6 +34,8 @@ export class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEve
32
34
 
33
35
  protected isInBackground: boolean;
34
36
 
37
+ private backgroundTimeout: ReturnType<typeof setTimeout> | undefined;
38
+
35
39
  protected _currentBitrate: number = 0;
36
40
 
37
41
  protected constructor(mediaTrack: MediaStreamTrack, kind: Track.Kind) {
@@ -179,8 +183,20 @@ export class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEve
179
183
  }
180
184
  }
181
185
 
182
- appVisibilityChangedListener = () => {
183
- this.handleAppVisibilityChanged();
186
+ protected appVisibilityChangedListener = () => {
187
+ if (this.backgroundTimeout) {
188
+ clearTimeout(this.backgroundTimeout);
189
+ }
190
+ // delay app visibility update if it goes to hidden
191
+ // update immediately if it comes back to focus
192
+ if (document.visibilityState === 'hidden') {
193
+ this.backgroundTimeout = setTimeout(
194
+ () => this.handleAppVisibilityChanged(),
195
+ BACKGROUND_REACTION_DELAY,
196
+ );
197
+ } else {
198
+ this.handleAppVisibilityChanged();
199
+ }
184
200
  };
185
201
 
186
202
  protected async handleAppVisibilityChanged() {
@@ -17,4 +17,9 @@ export type AdaptiveStreamSettings = {
17
17
  * streaming on high definition screens.
18
18
  */
19
19
  pixelDensity?: number | 'screen';
20
+ /**
21
+ * If true, video gets paused when switching to another tab.
22
+ * Defaults to true.
23
+ */
24
+ pauseVideoInBackground?: boolean;
20
25
  };