diff --git a/.changeset/gorgeous-ducks-joke.md b/.changeset/gorgeous-ducks-joke.md new file mode 100644 index 0000000000..ceee41ac6f --- /dev/null +++ b/.changeset/gorgeous-ducks-joke.md @@ -0,0 +1,5 @@ +--- +'livekit-client': patch +--- + +Disable simulcast if an user provides empty array for custom layers diff --git a/src/room/participant/publishUtils.test.ts b/src/room/participant/publishUtils.test.ts index d8d5612613..a8ca56dd12 100644 --- a/src/room/participant/publishUtils.test.ts +++ b/src/room/participant/publishUtils.test.ts @@ -93,6 +93,18 @@ describe('computeVideoEncodings', () => { expect(encodings![1].maxBitrate).toBe(VideoPresets.h360.encoding.maxBitrate); }); + it('returns one encoding if an empty array is provided for custom screen share layers', () => { + const encodings = computeVideoEncodings(true, 1920, 1080, { + simulcast: true, + screenShareSimulcastLayers: [], + }); + expect(encodings).toHaveLength(1); + + // ensure they are what we expect + expect(encodings![0].rid).toBe('q'); + expect(encodings![0].scaleResolutionDownBy).toBe(1); + }); + it('respects provided min resolution', () => { const encodings = computeVideoEncodings(false, 100, 120, { simulcast: true, diff --git a/src/room/participant/publishUtils.ts b/src/room/participant/publishUtils.ts index 6dc5a03eff..9bd772745e 100644 --- a/src/room/participant/publishUtils.ts +++ b/src/room/participant/publishUtils.ts @@ -136,26 +136,28 @@ export function computeVideoEncodings( sortPresets(options?.videoSimulcastLayers) ?? defaultSimulcastLayers(isScreenShare, original); } let midPreset: VideoPreset | undefined; - const lowPreset = presets[0]; - if (presets.length > 1) { - [, midPreset] = presets; - } + if (presets.length > 0) { + const lowPreset = presets[0]; + if (presets.length > 1) { + [, midPreset] = presets; + } - // NOTE: - // 1. Ordering of these encodings is important. Chrome seems - // to use the index into encodings to decide which layer - // to disable when CPU constrained. - // So encodings should be ordered in increasing spatial - // resolution order. - // 2. ion-sfu translates rids into layers. So, all encodings - // should have the base layer `q` and then more added - // based on other conditions. - const size = Math.max(width, height); - if (size >= 960 && midPreset) { - return encodingsFromPresets(width, height, [lowPreset, midPreset, original]); - } - if (size >= 480) { - return encodingsFromPresets(width, height, [lowPreset, original]); + // NOTE: + // 1. Ordering of these encodings is important. Chrome seems + // to use the index into encodings to decide which layer + // to disable when CPU constrained. + // So encodings should be ordered in increasing spatial + // resolution order. + // 2. ion-sfu translates rids into layers. So, all encodings + // should have the base layer `q` and then more added + // based on other conditions. + const size = Math.max(width, height); + if (size >= 960 && midPreset) { + return encodingsFromPresets(width, height, [lowPreset, midPreset, original]); + } + if (size >= 480) { + return encodingsFromPresets(width, height, [lowPreset, original]); + } } return encodingsFromPresets(width, height, [original]); }