components-js icon indicating copy to clipboard operation
components-js copied to clipboard

Huge incoming traffic

Open Dozalex opened this issue 10 months ago • 0 comments

Select which package(s) are affected

@livekit/components-react

Describe the bug

Hi! Thank you for your project.

My case: I have a conference with 100 participants (all have their camera on), but only 25 participants are shown in the grid.

What I'm expecting

I receive incoming video traffic from 100 participants as 25 participants.

What happens instead

I receive incoming video traffic from 100 participants as 100 participants even though I don't render anything (just LiveKitRoom with no children).

I reproduced it even on https://meet.livekit.io

Workaround 1

If I render a VideoTrack for each participant and then unmount it and leave only 25 VideoTracks, I will receive the correct incoming traffic.

Workaround 2 (not the best solution, I have a problem on older versions of Safari)

import * as React from 'react';
import {
  useTracks,
  TrackReferenceOrPlaceholder,
} from '@livekit/components-react';
import { RemoteTrackPublication, Track } from 'livekit-client';

type Props = {
  visibleTrackRefs: TrackReferenceOrPlaceholder[];
};

/** Used to prevent unnecessary traffic */
export const useVideoSubscription = ({ visibleTrackRefs }: Props) => {
  const rawTrackReferences = useTracks([
    { source: Track.Source.Camera, withPlaceholder: true },
    { source: Track.Source.ScreenShare, withPlaceholder: false },
  ]);

  // Create visible track sids set.
  const visibleSids = React.useMemo(
    () =>
      new Set<string | undefined>(
        visibleTrackRefs.map(trackRef => {
          // Use getTrackPublications to find even unsubscribed track
          // because if publication is unsubscribed trackRef.publication is undefined.
          const videoPub = trackRef.participant
            .getTrackPublications()
            .find(pub => pub.kind === 'video');

          return videoPub?.trackSid;
        }),
      ),
    [visibleTrackRefs],
  );

  // It's required to unsubscribe here to avoid unnecessary traffic.
  React.useEffect(() => {
    rawTrackReferences.forEach(trackRef => {
      // Use getTrackPublications to find even unsubscribed track
      // because if publication is unsubscribed trackRef.publication is undefined.
      const videoPub = trackRef.participant
        .getTrackPublications()
        .find(pub => pub.kind === 'video');

      if (!(videoPub instanceof RemoteTrackPublication)) {
        return;
      }

      if (visibleSids.has(videoPub.trackSid)) {
        if (!videoPub.isSubscribed) {
          videoPub.setSubscribed(true);
        }
      } else if (videoPub.isSubscribed) {
        videoPub.setSubscribed(false);
      }
    });
  }, [rawTrackReferences, visibleSids]);

  return null;
};

Suggestion

Add an optional parameter to LiveKitRoom to initially unsubscribe from every publication and only subscribe to it when VideoTrack is rendered.

Reproduction

import { LiveKitRoom } from '@livekit/components-react';

...

return (
  <LiveKitRoom
      token={session?.token}
      serverUrl={session?.url}
      connect={isConnect}
      onError={onConnectionError}
      options={ROOM_OPTIONS}
  />
);

Logs


System Info

Any platform and browser.

"@livekit/components-react": "^2.2.1",
"livekit-client": "^2.1.3",

I checked the newest versions, same problem.

Severity

serious, but I can work around it

Additional Information

No response

Dozalex avatar Mar 03 '25 16:03 Dozalex