# Call & Participant State

You can access call, participant, and client state using hooks. These hooks are reactive (their value is updated on WebSocket events and API calls).

## Best Practices

- Always load the call (`call.get()` or `call.join()`) before accessing state - hooks return empty values otherwise.
- Use `useCall()` to get the `Call` instance for API calls.
- Access hooks through `useCallStateHooks()` for type-safe destructuring.
- Filter participants by role or track type using utility functions like `hasVideo()`.
- Use `useRawParticipants` when sorting isn't needed to reduce renders.

## Call State

To observe call state, you need to provide a `Call` instance to the [`StreamCall` component](https://getstream.io/video/docs/react/v2/ui-components/core/stream-call/).

>
> **Note:** For the best experience, please make sure that the provided `Call` instance is loaded
> and connected to our backend: [Load Call](https://getstream.io/video/docs/react/v2/guides/joining-and-creating-calls/#load-call).
>
> Otherwise, `call.state` and the call state hooks will provide empty values.
>

Example:

```tsx
import {
  Call,
  StreamCall,
  useCall,
  useCallStateHooks,
} from "@stream-io/video-react-sdk";

export default function MyApp() {
  let call: Call;

  return (
    <StreamCall call={call}>
      <MyCallUI />
    </StreamCall>
  );
}

const MyCallUI = () => {
  const call = useCall();

  const { useCallCallingState, useParticipants } = useCallStateHooks();
  const callingState = useCallCallingState();
  const participants = useParticipants();

  return (
    <div>
      <div>Call: {call?.cid}</div>
      <div>State: {callingState}</div>
      <div>Participants: {participants.length}</div>
    </div>
  );
};
```

`StreamCall` is a context provider. `useCall` returns the `Call` instance for API calls.

### Call State Hooks

| Name                                                                              | Description                                                                                                   |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `useCall`                                                                         | The `Call` instance that is registered with `StreamCall`. You need the `Call` instance to initiate API calls. |
| `useCallBlockedUserIds`                                                           | The list of blocked user IDs.                                                                                 |
| [`useCallCallingState`](https://getstream.io/video/docs/react/v2/guides/calling-state-and-lifecycle/) | Provides information about the call state. For example, `RINGING`, `JOINED` or `RECONNECTING`.                |
| [`useCallClosedCaptions`](https://getstream.io/video/docs/react/v2/ui-cookbook/closed-captions/)      | The closed captions of the call.                                                                              |
| `useCallCreatedAt`                                                                | The time the call was created.                                                                                |
| `useCallCreatedBy`                                                                | The user that created the call.                                                                               |
| `useCallCustomData`                                                               | The custom data attached to the call.                                                                         |
| `useCallEgress`                                                                   | The egress information of the call.                                                                           |
| `useCallEndedAt`                                                                  | The time the call was ended.                                                                                  |
| `useCallEndedBy`                                                                  | The user that ended the call.                                                                                 |
| `useCallIngress`                                                                  | The ingress information of the call.                                                                          |
| `useCallMembers`                                                                  | The list of call members                                                                                      |
| `useCallSession`                                                                  | The information for the current call session.                                                                 |
| `useCallSettings`                                                                 | The settings of the call.                                                                                     |
| `useCallStartedAt`                                                                | The actual start time of the current call session.                                                            |
| `useCallStartsAt`                                                                 | The scheduled start time of the call.                                                                         |
| [`useCallStatsReport`](https://getstream.io/video/docs/react/v2/advanced/stats/)                      | When stats gathering is enabled, this observable will emit a new value at a regular (configurable) interval.  |
| `useCallThumbnail`                                                                | The thumbnail of the call.                                                                                    |
| `useCallUpdatedAt`                                                                | The time the call was last updated.                                                                           |
| `useCameraState`                                                                  | The camera state of the local participant.                                                                    |
| `useDominantSpeaker`                                                              | The participant that is the current dominant speaker of the call.                                             |
| [`useE2eeEnabled`](https://getstream.io/video/docs/react/v2/guides/end-to-end-encryption/)            | `true` if end-to-end encryption is active for the call.                                                       |
| `useHasOngoingScreenShare`                                                        | It will return `true` if at least one participant is sharing their screen.                                    |
| `useHasPermissions`                                                               | Returns `true` if the local participant has all the given permissions.                                        |
| `useIncomingVideoSettings`                                                        | The state of manual overrides to incoming video quality.                                                      |
| `useIsAutoplayBlocked`                                                            | `true` when the browser's autoplay policy is blocking audio playback. Use `call.resumeAudio()` to unblock.    |
| `useIsCallCaptioningInProgress`                                                   | `true` if the call is being close-captioned.                                                                  |
| `useIsCallHLSBroadcastingInProgress`                                              | `true` if the call is being broadcasted in HLS mode.                                                          |
| `useIsCallIndividualRecordingInProgress`                                          | `true` if the indivudal track recording is running.                                                           |
| `useIsCallLive`                                                                   | `true` if the call is currently live.                                                                         |
| `useIsCallRawRecordingInProgress`                                                 | `true` if the raw recording is currently running.                                                             |
| `useIsCallRecordingInProgress`                                                    | `true` if the call is being recorded.                                                                         |
| `useIsCallTranscribingInProgress`                                                 | `true` if the call is being transcribed.                                                                      |
| `useMicrophoneState`                                                              | The microphone state of the local participant.                                                                |
| `useOwnCapabilities`                                                              | The capabilities of the local participant.                                                                    |
| `useScreenShareState`                                                             | The screen share state of the local participant.                                                              |
| `useSpeakerState`                                                                 | The speaker state of the local participant.                                                                   |

Destructure `useCallStateHooks` for the full list:

```ts
import { useCallStateHooks } from "@stream-io/video-react-sdk";

const {
  useCallMembers,
  useDominantSpeaker,
  useParticipants,
  useLocalParticipant,
  useIsCallRecordingInProgress,
  // ...
} = useCallStateHooks();
```

## Participant state

Participant hooks return `StreamVideoParticipant` objects.

### Participant State Hooks

| Name                           | Description                                                                                                                                                                                     |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useAnonymousParticipantCount` | The approximate participant count of anonymous users in the active call.                                                                                                                        |
| `useLocalParticipant`          | The local participant is the logged-in user.                                                                                                                                                    |
| `useParticipantCount`          | The approximate participant count of the active call. This includes the [anonymous users](https://getstream.io/video/docs/react/v2/guides/client-auth/#anonymous-users) as well, it is computed on the server-side. |
| `useParticipants`              | All participants, including local and remote participants.                                                                                                                                      |
| `usePinnedParticipants`        | The participants that are currently pinned.                                                                                                                                                     |
| `useRawParticipants`           | A version of `useParticipants` that is not affected by participant sort settings and thus causes less component updates.                                                                        |
| `useRemoteParticipants`        | All participants except the local participant.                                                                                                                                                  |

>
> **Warning:** Warning: In a call with many participants, the value of the `useParticipants()` is truncated to 250 participants.
>
> The participants who are publishing video, audio, or screen sharing have priority over the other participants in the list.
> This means, for example, that in a livestream with one host and many viewers, the host is guaranteed to be in the list.
>

```tsx
import {
  useCallStateHooks,
  Call,
  StreamCall,
} from "@stream-io/video-react-sdk";

export default function App() {
  let call: Call;

  return (
    <StreamCall call={call}>
      <MyCallUI />
    </StreamCall>
  );
}

const MyCallUI = () => {
  const { useLocalParticipant, useParticipantCount } = useCallStateHooks();
  const participantCount = useParticipantCount();
  const localParticipant = useLocalParticipant();

  return (
    <div>
      <div>Number of participants: {participantCount}</div>
      <div>Session ID: {localParticipant.sessionId}</div>
    </div>
  );
};
```

### Participant data

The `StreamVideoParticipant` object has the following properties:

| Name                      | Description                                                                                                                                                                                                                    |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `audioLevel`              | The audio level of the participant (determined on the server).                                                                                                                                                                 |
| `audioStream`             | The audio `MediaStream`.                                                                                                                                                                                                       |
| `audioVolume`             | The audio volume level of the participant (overridable local audioVolume level).                                                                                                                                               |
| `connectionQuality`       | The participant's connection quality.                                                                                                                                                                                          |
| `custom`                  | The participant's custom data. Comes from the `custom` field of the user object.                                                                                                                                               |
| `image`                   | The image of the participant.                                                                                                                                                                                                  |
| `interruptedTracks`       | Tracks the participant intends to publish but that are currently not producing media (system mute, OS-level kill switch, Bluetooth disconnect, iOS audio interruption, sustained RTP stalls). Orthogonal to `publishedTracks`. |
| `isDominantSpeaker`       | It's `true` if the participant is the current dominant speaker in the call.                                                                                                                                                    |
| `isLocalParticipant`      | It's `true` if the participant is the local participant.                                                                                                                                                                       |
| `isSpeaking`              | It's `true` if the participant is currently speaking.                                                                                                                                                                          |
| `joinedAt`                | The time the participant joined the call.                                                                                                                                                                                      |
| `name`                    | The name of the participant.                                                                                                                                                                                                   |
| `pausedTracks`            | The tracks that are currently server-side paused for the local participant.                                                                                                                                                    |
| `pin`                     | Holds pinning information.                                                                                                                                                                                                     |
| `publishedTracks`         | The track types the participant is currently publishing                                                                                                                                                                        |
| `reaction`                | The last reaction this user has sent to this call.                                                                                                                                                                             |
| `roles`                   | The roles of the participant in this call.                                                                                                                                                                                     |
| `screenShareAudioStream`  | The screen share audio `MediaStream`.                                                                                                                                                                                          |
| `screenShareStream`       | The screen share `MediaStream`.                                                                                                                                                                                                |
| `sessionId`               | The identifier of the participant within the existing call session                                                                                                                                                             |
| `source`                  | The participant source: WebRTC (default), RTMP (OBS), WHIP, SIP, RTSP, SRT...                                                                                                                                                  |
| `userId`                  | The user ID of the participant.                                                                                                                                                                                                |
| `videoStream`             | The video `MediaStream`.                                                                                                                                                                                                       |
| `viewportVisibilityState` | The viewport visibility state of the participant.                                                                                                                                                                              |

### Utility functions

```ts
import {
  hasAudio,
  hasVideo,
  hasScreenShare,
  hasScreenShareAudio,
  hasInterruptedTrack,
  hasPausedTrack,
  isPinned,
  SfuModels,
  useCallStateHooks,
} from "@stream-io/video-react-sdk";

// example usage
const { useParticipants } = useCallStateHooks();
const participants = useParticipants();

// check if the participant has audio, video, screen share or screen share audio
const [participant] = participants;
const hasAudioOn = hasAudio(participant);
const hasVideoOn = hasVideo(participant);
const hasScreenShareOn = hasScreenShare(participant);
const hasScreenShareAudioOn = hasScreenShareAudio(participant);
const isPinnedOn = isPinned(participant);
const isVideoPaused = hasPausedTrack(participant, "videoTrack");
const isAudioInterrupted = hasInterruptedTrack(
  participant,
  SfuModels.TrackType.AUDIO,
);

// participants with a specific role
const hosts = participants.filter((p) => p.roles.includes("host"));

// participants that publish video and audio
const videoParticipants = participants.filter(
  (p) => hasVideo(p) && hasAudio(p),
);
```

### Detecting participant source

The `source` property indicates how participants joined (WebRTC, RTMP/OBS, WHIP, SIP, etc.):

```ts
import { SfuModels } from "@stream-io/video-react-sdk";

const { useParticipants } = useCallStateHooks();
const participants = useParticipants();

// participants joining through OBS have RTMP source
const rtmpParticipants = participants.filter(
  (p) => p.source === SfuModels.ParticipantSource.RTMP,
);
```

### Detecting interrupted tracks

A participant's published audio or video can be temporarily silenced by something outside the participant's control — the operating system muting the microphone, a Bluetooth headset disconnecting, an iOS audio session interruption, or transient SFU/RTP issues. Use the `hasInterruptedTrack(participant, trackType)` helper to detect this and surface a hint in the UI:

```tsx
import {
  hasInterruptedTrack,
  SfuModels,
  useCallStateHooks,
} from "@stream-io/video-react-sdk";

const MicStatus = () => {
  const { useLocalParticipant } = useCallStateHooks();
  const localParticipant = useLocalParticipant();
  if (!localParticipant) return null;

  const isMicInterrupted = hasInterruptedTrack(
    localParticipant,
    SfuModels.TrackType.AUDIO,
  );

  if (!isMicInterrupted) return null;
  return <div>Microphone is paused by your system</div>;
};
```

The helper intersects `interruptedTracks` with `publishedTracks`, so the indicator only fires while the participant is actively publishing the track. This avoids a stale "interrupted" indicator if a remote sender unpublishes the track while it was interrupted.

For remote participants, `interruptedTracks` currently only surfaces `TrackType.AUDIO`; remote video and screen-share interruption are not tracked. For the local participant, it covers both audio and video.

The built-in `ToggleAudioButton` and `ToggleVideoButton` already use this signal to show a "paused by your system" tooltip — use the snippet above if you build custom controls. See the [System Mute Indicator cookbook](https://getstream.io/video/docs/react/v2/ui-cookbook/system-mute-indicator/) for a full worked example.

## Client state

Use `useConnectedUser` to observe the connected user:

```tsx
import {
  useConnectedUser,
  StreamVideo,
  StreamVideoClient,
} from "@stream-io/video-react-sdk";

export default function App() {
  let client: StreamVideoClient;

  return (
    <StreamVideo client={client}>
      <MyHeader />
    </StreamVideo>
  );
}

const MyHeader = () => {
  const user = useConnectedUser();
  return <div>{user ? `Logged in: ${user.name}` : "Logged out"}</div>;
};
```

### Client state hooks

| Name                   | Description                                                                                                                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useStreamVideoClient` | The `StreamVideoClient` instance.                                                                                                                                               |
| `useConnectedUser`     | Returns the connected user. Holds the server-side data of the connected user.                                                                                                   |
| `useCalls`             | A list of all tracked calls. These calls can be outgoing (I have called somebody) or incoming (somebody has called me). Loaded calls (`call.get()`) are also part of this list. |

The `connectedUser` object contains the following properties:

| Name         | Description                                           |
| ------------ | ----------------------------------------------------- |
| `created_at` | The time the user was created.                        |
| `custom`     | Custom user data.                                     |
| `deleted_at` | The time the user was deleted.                        |
| `devices`    | The registered push notification devices of the user. |
| `id`         | The id of the user.                                   |
| `image`      | The profile image of the user.                        |
| `name`       | The name of the user.                                 |
| `role`       | The role of the user.                                 |
| `teams`      | The teams the user belongs to.                        |
| `updated_at` | The time when the user was updated.                   |

---

For the most recent version of this documentation, visit [https://getstream.io/video/docs/react/v2/guides/call-and-participant-state/](https://getstream.io/video/docs/react/v2/guides/call-and-participant-state/).