livekit-client 1.1.1 → 1.1.4
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/livekit-client.esm.mjs +299 -122
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +7 -0
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +2 -0
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +7 -2
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +4 -2
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +3 -2
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/proto/livekit_rtc.ts +12 -0
- package/src/room/Room.ts +79 -30
- package/src/room/participant/LocalParticipant.ts +135 -61
- package/src/room/participant/RemoteParticipant.ts +5 -11
- package/src/room/participant/publishUtils.ts +2 -2
- package/src/room/track/LocalAudioTrack.ts +7 -3
- package/src/room/track/LocalTrack.ts +11 -2
- package/src/room/track/LocalVideoTrack.ts +41 -10
- package/src/room/track/RemoteVideoTrack.ts +30 -2
- package/src/room/track/create.ts +2 -2
- package/src/room/utils.ts +3 -2
@@ -24,6 +24,8 @@ export class SimulcastTrackInfo {
|
|
24
24
|
}
|
25
25
|
}
|
26
26
|
|
27
|
+
const refreshSubscribedCodecAfterNewCodec = 5000;
|
28
|
+
|
27
29
|
export default class LocalVideoTrack extends LocalTrack {
|
28
30
|
/* internal */
|
29
31
|
signalClient?: SignalClient;
|
@@ -37,8 +39,14 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
37
39
|
SimulcastTrackInfo
|
38
40
|
>();
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
+
private subscribedCodecs?: SubscribedCodec[];
|
43
|
+
|
44
|
+
constructor(
|
45
|
+
mediaTrack: MediaStreamTrack,
|
46
|
+
constraints?: MediaTrackConstraints,
|
47
|
+
userProvidedTrack = true,
|
48
|
+
) {
|
49
|
+
super(mediaTrack, Track.Kind.Video, constraints, userProvidedTrack);
|
42
50
|
}
|
43
51
|
|
44
52
|
get isSimulcast(): boolean {
|
@@ -88,7 +96,7 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
88
96
|
}
|
89
97
|
|
90
98
|
async unmute(): Promise<LocalVideoTrack> {
|
91
|
-
if (this.source === Track.Source.Camera) {
|
99
|
+
if (this.source === Track.Source.Camera && !this.isUserProvided) {
|
92
100
|
log.debug('reacquiring camera track');
|
93
101
|
await this.restartTrack();
|
94
102
|
}
|
@@ -194,26 +202,48 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
194
202
|
return;
|
195
203
|
}
|
196
204
|
simulcastCodecInfo.sender = sender;
|
205
|
+
|
206
|
+
// browser will reenable disabled codec/layers after new codec has been published,
|
207
|
+
// so refresh subscribedCodecs after publish a new codec
|
208
|
+
setTimeout(() => {
|
209
|
+
if (this.subscribedCodecs) {
|
210
|
+
this.setPublishingCodecs(this.subscribedCodecs);
|
211
|
+
}
|
212
|
+
}, refreshSubscribedCodecAfterNewCodec);
|
197
213
|
}
|
198
214
|
|
199
215
|
/**
|
200
216
|
* @internal
|
201
217
|
* Sets codecs that should be publishing
|
202
218
|
*/
|
203
|
-
async setPublishingCodecs(codecs: SubscribedCodec[]) {
|
204
|
-
log.debug('setting publishing codecs',
|
219
|
+
async setPublishingCodecs(codecs: SubscribedCodec[]): Promise<VideoCodec[]> {
|
220
|
+
log.debug('setting publishing codecs', {
|
221
|
+
codecs,
|
222
|
+
currentCodec: this.codec,
|
223
|
+
});
|
224
|
+
// only enable simulcast codec for preference codec setted
|
225
|
+
if (!this.codec && codecs.length > 0) {
|
226
|
+
await this.setPublishingLayers(codecs[0].qualities);
|
227
|
+
return [];
|
228
|
+
}
|
205
229
|
|
230
|
+
this.subscribedCodecs = codecs;
|
231
|
+
|
232
|
+
const newCodecs: VideoCodec[] = [];
|
206
233
|
for await (const codec of codecs) {
|
207
|
-
if (this.codec === codec.codec) {
|
234
|
+
if (!this.codec || this.codec === codec.codec) {
|
208
235
|
await this.setPublishingLayers(codec.qualities);
|
209
236
|
} else {
|
210
237
|
const simulcastCodecInfo = this.simulcastCodecs.get(codec.codec as VideoCodec);
|
211
238
|
log.debug(`try setPublishingCodec for ${codec.codec}`, simulcastCodecInfo);
|
212
239
|
if (!simulcastCodecInfo || !simulcastCodecInfo.sender) {
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
240
|
+
for (const q of codec.qualities) {
|
241
|
+
if (q.enabled) {
|
242
|
+
newCodecs.push(codec.codec as VideoCodec);
|
243
|
+
break;
|
244
|
+
}
|
245
|
+
}
|
246
|
+
} else if (simulcastCodecInfo.encodings) {
|
217
247
|
log.debug(`try setPublishingLayersForSender ${codec.codec}`);
|
218
248
|
await setPublishingLayersForSender(
|
219
249
|
simulcastCodecInfo.sender,
|
@@ -223,6 +253,7 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
223
253
|
}
|
224
254
|
}
|
225
255
|
}
|
256
|
+
return newCodecs;
|
226
257
|
}
|
227
258
|
|
228
259
|
/**
|
@@ -110,6 +110,8 @@ export default class RemoteVideoTrack extends RemoteTrack {
|
|
110
110
|
// the tab comes into focus for the first time.
|
111
111
|
this.debouncedHandleResize();
|
112
112
|
this.updateVisibility();
|
113
|
+
} else {
|
114
|
+
log.warn('visibility resize observer not triggered');
|
113
115
|
}
|
114
116
|
}
|
115
117
|
|
@@ -294,9 +296,9 @@ class HTMLElementInfo implements ElementInfo {
|
|
294
296
|
|
295
297
|
handleVisibilityChanged?: () => void;
|
296
298
|
|
297
|
-
constructor(element: HTMLMediaElement, visible
|
299
|
+
constructor(element: HTMLMediaElement, visible?: boolean) {
|
298
300
|
this.element = element;
|
299
|
-
this.visible = visible;
|
301
|
+
this.visible = visible ?? isElementInViewport(element);
|
300
302
|
this.visibilityChangedAt = 0;
|
301
303
|
}
|
302
304
|
|
@@ -332,3 +334,29 @@ class HTMLElementInfo implements ElementInfo {
|
|
332
334
|
getResizeObserver()?.unobserve(this.element);
|
333
335
|
}
|
334
336
|
}
|
337
|
+
|
338
|
+
// does not account for occlusion by other elements
|
339
|
+
function isElementInViewport(el: HTMLElement) {
|
340
|
+
let top = el.offsetTop;
|
341
|
+
let left = el.offsetLeft;
|
342
|
+
const width = el.offsetWidth;
|
343
|
+
const height = el.offsetHeight;
|
344
|
+
const { hidden } = el;
|
345
|
+
const { opacity, display } = getComputedStyle(el);
|
346
|
+
|
347
|
+
while (el.offsetParent) {
|
348
|
+
el = el.offsetParent as HTMLElement;
|
349
|
+
top += el.offsetTop;
|
350
|
+
left += el.offsetLeft;
|
351
|
+
}
|
352
|
+
|
353
|
+
return (
|
354
|
+
top < window.pageYOffset + window.innerHeight &&
|
355
|
+
left < window.pageXOffset + window.innerWidth &&
|
356
|
+
top + height > window.pageYOffset &&
|
357
|
+
left + width > window.pageXOffset &&
|
358
|
+
!hidden &&
|
359
|
+
(opacity !== '' ? parseFloat(opacity) > 0 : true) &&
|
360
|
+
display !== 'none'
|
361
|
+
);
|
362
|
+
}
|
package/src/room/track/create.ts
CHANGED
@@ -110,11 +110,11 @@ export async function createLocalScreenTracks(
|
|
110
110
|
if (tracks.length === 0) {
|
111
111
|
throw new TrackInvalidError('no video track found');
|
112
112
|
}
|
113
|
-
const screenVideo = new LocalVideoTrack(tracks[0]);
|
113
|
+
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
|
114
114
|
screenVideo.source = Track.Source.ScreenShare;
|
115
115
|
const localTracks: Array<LocalTrack> = [screenVideo];
|
116
116
|
if (stream.getAudioTracks().length > 0) {
|
117
|
-
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0]);
|
117
|
+
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
|
118
118
|
screenAudio.source = Track.Source.ScreenShareAudio;
|
119
119
|
localTracks.push(screenAudio);
|
120
120
|
}
|
package/src/room/utils.ts
CHANGED
@@ -81,8 +81,9 @@ let emptyVideoStreamTrack: MediaStreamTrack | undefined;
|
|
81
81
|
export function getEmptyVideoStreamTrack() {
|
82
82
|
if (!emptyVideoStreamTrack) {
|
83
83
|
const canvas = document.createElement('canvas');
|
84
|
-
canvas
|
85
|
-
canvas.
|
84
|
+
// the canvas size is set to 16, because electron apps seem to fail with smaller values
|
85
|
+
canvas.width = 16;
|
86
|
+
canvas.height = 16;
|
86
87
|
canvas.getContext('2d')?.fillRect(0, 0, canvas.width, canvas.height);
|
87
88
|
// @ts-ignore
|
88
89
|
const emptyStream = canvas.captureStream();
|