diff --git a/packages/hms-video-store/src/sdk/LocalTrackManager.ts b/packages/hms-video-store/src/sdk/LocalTrackManager.ts index 45e1f9a840..a72b3c20a0 100644 --- a/packages/hms-video-store/src/sdk/LocalTrackManager.ts +++ b/packages/hms-video-store/src/sdk/LocalTrackManager.ts @@ -158,8 +158,38 @@ export class LocalTrackManager { nativeTracks.push(...this.getEmptyTracks(fetchTrackOptions)); return nativeTracks; } - - async getLocalScreen(partialConfig?: HMSScreenShareConfig) { + private async optimizeScreenShareConstraint(stream: MediaStream, constraints: MediaStreamConstraints) { + if (typeof constraints.video === 'boolean' || !constraints.video?.width || !constraints.video?.height) { + return; + } + const publishParams = this.store.getPublishParams(); + if (!publishParams || !publishParams.allowed?.includes('screen')) { + return; + } + const videoElement = document.createElement('video'); + videoElement.srcObject = stream; + videoElement.addEventListener('loadedmetadata', async () => { + const { videoWidth, videoHeight } = videoElement; + const screen = publishParams.screen; + const pixels = screen.width * screen.height; + const actualAspectRatio = videoWidth / videoHeight; + const currentAspectRatio = screen.width / screen.height; + if (actualAspectRatio > currentAspectRatio) { + const videoConstraint = constraints.video as MediaTrackConstraints; + const ratio = actualAspectRatio / currentAspectRatio; + const sqrt_ratio = Math.sqrt(ratio); + if (videoWidth * videoHeight > pixels) { + videoConstraint.width = videoWidth / sqrt_ratio; + videoConstraint.height = videoHeight / sqrt_ratio; + } else { + videoConstraint.height = videoHeight * sqrt_ratio; + videoConstraint.width = videoWidth * sqrt_ratio; + } + await stream.getVideoTracks()[0].applyConstraints(videoConstraint); + } + }); + } + async getLocalScreen(partialConfig?: HMSScreenShareConfig, optimise = false) { const config = await this.getOrDefaultScreenshareConfig(partialConfig); const screenSettings = this.getScreenshareSettings(config.videoOnly); const constraints = { @@ -187,6 +217,9 @@ export class LocalTrackManager { HMSLogger.d('retrieving screenshare with ', { config }, { constraints }); // @ts-ignore [https://github.com/microsoft/TypeScript/issues/33232] stream = (await navigator.mediaDevices.getDisplayMedia(constraints)) as MediaStream; + if (optimise) { + await this.optimizeScreenShareConstraint(stream, constraints); + } } catch (err) { HMSLogger.w(this.TAG, 'error in getting screenshare - ', err); const error = BuildGetMediaError(err as Error, HMSGetMediaActions.SCREEN); diff --git a/packages/hms-video-store/src/sdk/index.ts b/packages/hms-video-store/src/sdk/index.ts index a3829c597a..f276305cdf 100644 --- a/packages/hms-video-store/src/sdk/index.ts +++ b/packages/hms-video-store/src/sdk/index.ts @@ -63,7 +63,7 @@ import { createRemotePeer } from '../notification-manager/managers/utils'; import { NotificationManager } from '../notification-manager/NotificationManager'; import { SessionStore } from '../session-store'; import { InteractivityCenter } from '../session-store/interactivity-center'; -import { InitConfig } from '../signal/init/models'; +import { InitConfig, InitFlags } from '../signal/init/models'; import { HLSRequestParams, HLSTimedMetadataParams, @@ -1346,7 +1346,8 @@ export class HMSSdk implements HMSInterface { * @returns */ private async getScreenshareTracks(onStop: () => void, config?: HMSScreenShareConfig) { - const [videoTrack, audioTrack] = await this.localTrackManager.getLocalScreen(config); + const isOptimizedScreenShare = this.transport.isFlagEnabled(InitFlags.FLAG_SCALE_SCREENSHARE_BASED_ON_PIXELS); + const [videoTrack, audioTrack] = await this.localTrackManager.getLocalScreen(config, isOptimizedScreenShare); const handleEnded = () => { this.stopEndedScreenshare(onStop); diff --git a/packages/hms-video-store/src/signal/init/models.ts b/packages/hms-video-store/src/signal/init/models.ts index 75e6b12c02..7467ab7812 100644 --- a/packages/hms-video-store/src/signal/init/models.ts +++ b/packages/hms-video-store/src/signal/init/models.ts @@ -60,4 +60,5 @@ export enum InitFlags { FLAG_EFFECTS_SDK_ENABLED = 'effectsSDKEnabled', FLAG_HIPAA_ENABLED = 'hipaa', FLAG_NOISE_CANCELLATION = 'noiseCancellation', + FLAG_SCALE_SCREENSHARE_BASED_ON_PIXELS = 'scaleScreenshareBasedOnPixels', } diff --git a/packages/roomkit-react/package.json b/packages/roomkit-react/package.json index a2c18a7a6a..7ac88de753 100644 --- a/packages/roomkit-react/package.json +++ b/packages/roomkit-react/package.json @@ -83,7 +83,7 @@ }, "dependencies": { "@100mslive/hls-player": "0.3.3", - "@100mslive/hms-noise-cancellation": "0.0.0-alpha.5", + "@100mslive/hms-noise-cancellation": "0.0.1", "@100mslive/hms-virtual-background": "1.13.3", "@100mslive/react-icons": "0.10.3", "@100mslive/react-sdk": "0.10.3", diff --git a/yarn.lock b/yarn.lock index 8bcea01204..e260b50eeb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@100mslive/hms-noise-cancellation@0.0.0-alpha.5": - version "0.0.0-alpha.5" - resolved "https://registry.yarnpkg.com/@100mslive/hms-noise-cancellation/-/hms-noise-cancellation-0.0.0-alpha.5.tgz#8aff14eb7168cbf91a6d54ecb831f88dcda86266" - integrity sha512-C44MLdFrS+4uzWuyauyKCnQ3kOT70jBsGdMXCdCPrK6OPRhZFuMYULYb7XP1NfJjslOcRdENarFqA0T+RNfmuQ== +"@100mslive/hms-noise-cancellation@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@100mslive/hms-noise-cancellation/-/hms-noise-cancellation-0.0.1.tgz#037c8bdfb6b2d7bf12f9d257422150fe6ca43acb" + integrity sha512-DGnzcXRDJREWypIjGX70er+f2k/XLLRF41lrXPs1+PtB1imdEkECPPS0Fg4BA0BCWKDNAGTZBHZPrBDgUmr9Lw== "@100mslive/types-prebuilt@0.12.7": version "0.12.7" @@ -15781,16 +15781,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15890,14 +15881,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17194,7 +17178,7 @@ worker-timers@^7.0.40: worker-timers-broker "^6.0.95" worker-timers-worker "^7.0.59" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17212,15 +17196,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"