# Camera & Microphone

Handling audio and video devices in your application means working with `MediaStream`, `MediaDeviceInfo` and other WebRTC API objects.
To simplify this, we hide all the complexity inside the SDK and export utility functions and states.
In this guide, we shall go over their usage.

## Camera management

The SDK does its best to make working with the camera easy. We expose the following camera object on the call:

```ts
const call = useCall();
const camera = call.camera;
```

### Call settings

The default state of the camera is determined by the settings in the call object.

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

const { useCallSettings } = useCallStateHooks();
const settings = useCallSettings();

console.log(settings?.video.camera_default_on);
```

<admonition type="note">

Make sure, `call.get()` is called at least once in the application, after the call is created.

</admonition>

### Start-Stop Camera

We can use the functions `camera.enable()` and `camera.disable()` to control the publishing and unpublishing our video stream.

Alternatively, you can use `camera.toggle()`.

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

const call = useCall();

const { useCameraState } = useCallStateHooks();
const { camera, isMute } = useCameraState();

console.log(`Camera is ${isMute ? "off" : "on"}`);
await camera.toggle();

// or, alternatively
await camera.enable();
await camera.disable();
```

It's always best to await calls to `enable()`, `disable()`, and `toggle()`, however the SDK does its best to resolve potential race conditions: the last call always wins, so it's safe to make these calls in an event handler.

The `status` is updated once the camera is actually enabled or disabled.
Use `optimisticIsMute` for the "optimistic" status that is updated immediately after toggling the camera.

### Manage Camera Facing Mode

We can toggle the camera face from front to back and vice versa using `camera.flip()`.

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

const { useCameraState } = useCallStateHooks();
const { camera } = useCameraState();

console.log(direction); // direction returns 'front' or 'back'.
camera.flip();
```

We can get the facing mode state of the camera by:

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

const { useCameraState } = useCallStateHooks();
const { direction } = useCameraState(); // direction returns 'front' or 'back'.
```

### Video mute status

We can get the mute state of our video stream by checking the `status` value returned from the `useCameraState` hook:

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

const { useCameraState } = useCallStateHooks();
const { status } = useCameraState(); // status returns enabled, disabled or undefined
```

### Show Video Preview

We can get the video stream from the camera using the media stream from the `call.camera` object and show it using the `RTCView` component from `@stream-io/react-native-webrtc` library:

```tsx
import { useCallStateHooks } from "@stream-io/video-react-native-sdk";
import { RTCView } from "@stream-io/react-native-webrtc";
const { useCameraState } = useCallStateHooks();
const { camera } = useCameraState();

const localVideoStream = camera.state.mediaStream;

return <RTCView streamURL={localVideoStream?.toURL()} />;
```

### Access to the Camera's MediaStream

Our SDK exposes the current `mediaStream` instance that you can use for your needs (for example, local recording, etc...):

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

const { useCameraState } = useCallStateHooks();
const { mediaStream } = useCameraState();

const [videoTrack] = mediaStream.getVideoTracks();
console.log("Video track", videoTrack);
```

## Microphone management

The SDK does its best to make working with the microphone easy. We expose the following microphone object on the call:

```ts
const call = useCall();
const microphone = call.microphone;
```

### Call settings

The default state of the microphone is determined by the settings in the call object.

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

const { useCallSettings } = useCallStateHooks();
const settings = useCallSettings();

console.log(settings?.audio.mic_default_on);
```

<admonition type="note">

Make sure, `call.get()` is called at least once in the application, after the call is created.

</admonition>

### Start-Stop Microphone

We can use the functions `microphone.enable()` and `microphone.disable()` to control the publishing and unpublishing our audio stream:

Alternatively, you can use `microphone.toggle()`.

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

const { useMicrophoneState } = useCallStateHooks();
const { microphone, isMute } = useMicrophoneState();

console.log(`Microphone is ${isMute ? "off" : "on"}`);
await microphone.toggle();

// or, alternatively
await microphone.enable();
await microphone.disable();
```

It's always best to await calls to `enable()`, `disable()`, and `toggle()`, however the SDK does its best to resolve potential race conditions: the last call always wins, so it's safe to make these calls in an event handler.

The `status` is updated once the microphone is actually enabled or disabled. Use `optimisticIsMute` for the "optimistic" status that is updated immediately after toggling the microphone.

### Audio mute status

We can get the mute state of our audio stream by checking the `status` value returned from the `useMicrophoneState` hook:

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

const { useMicrophoneState } = useCallStateHooks();
const { status } = useMicrophoneState(); // status returns enabled, disabled or undefined
```

### Speaking while muted detection

Our SDK provides a mechanism that can detect whether the user started to speak while being muted.
Through this mechanism, you can display a notification to the user, or apply any custom logic.

This feature is enabled by default unless the user doesn't have the permission to send audio or explicitly disabled.

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

const { useMicrophoneState } = useCallStateHooks();
const { isSpeakingWhileMuted, microphone } = useMicrophoneState();

if (isSpeakingWhileMuted) {
  // your custom logic comes here
  console.log("You are speaking while muted!");
}

// to disable this feature completely:
await microphone.disableSpeakingWhileMutedNotification();

// to enable it back:
await microphone.enableSpeakingWhileMutedNotification();
```

### Access to the Microphone's MediaStream

Our SDK exposes the current `mediaStream` instance that you can use for your needs (for example, local recording, etc...):

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

const { useMicrophoneState } = useCallStateHooks();
const { mediaStream } = useMicrophoneState();

const [audioTrack] = mediaStream.getAudioTracks();
console.log("Audio track", audioTrack);
```

## Speaker management

<admonition type="warning">

We do not support using hooks to change an audio output source for React Native SDK as React Native WebRTC doesn't support device switching in RN.
This means the following would not work with React Native SDK:

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

const { useMicrophoneState, useSpeakerState } = useCallStateHooks();

// This will give error on React Native.
const { selectedDevice } = useMicrophoneState();
// Also, This will give error on React Native.
const { speaker, selectedDevice, devices } = useSpeakerState();
```

</admonition>

We primarily use [react-native-incall-manager](https://github.com/react-native-webrtc/react-native-incall-manager) for managing speaker audio output in our SDK.

This functionality is seamlessly integrated into our video calling and livestream components.

<admonition type="info">
The InCallManager `start` and `stop` methods are only executed when our `CallContent`, `HostLivestream` or `ViewerLivestream` components are used. If you're implementing a custom UI without using these components, you'll need to manage these methods yourself.

</admonition>

In our SDK, we set the `media` type to `video` for video calls and livestream use-case, and `audio` for audio-only calls, in the [start](https://github.com/react-native-webrtc/react-native-incall-manager?tab=readme-ov-file#usage) method of the InCallManager.

```tsx
import InCallManager from "react-native-incall-manager";

// Called on call join
InCallManager.start({ media: "video" }); // `media` values - audio/video, default: audio

// Called when call is left
InCallManager.stop();
```

Passing `video` to `media`, routes the audio to device speaker by default unless an external device is connected.

Passing `audio` to `media`, enables the proximity sensor, routes the audio through earpiece by default unless an external device is connected.

When an external device is connected in between or before the call, the audio is always routed through it.

To force route the audio through the speaker (supported both on Android and iOS), use the following method:

```tsx
import InCallManager from "react-native-incall-manager";

InCallManager.setForceSpeakerphoneOn(true); // Pass true for speaker on, and false for off. Once off audio is always routed through earpiece.
```

If you decide to use the non forcing method, it is important to know that it is supported only for Android.

```tsx
import InCallManager from "react-native-incall-manager";

InCallManager.setSpeakerphoneOn(true);
```

For more information and customization, please visit the official docs of [InCallManager](https://github.com/react-native-webrtc/react-native-incall-manager).

### Audio volume control

We do not support control of the volume of specific audio elements or individual participants through our React Native SDK as React Native WebRTC doesn't support the `setVolume` and `setParticipantVolume` methods from our `SpeakerManager`.

For applications that require volume control functionality in React Native, we recommend using an external library such as [react-native-volume-manager](https://github.com/hirbod/react-native-volume-manager).

---

This page was last updated at 2025-08-15T14:16:44.698Z.

For the most recent version of this documentation, visit [https://getstream.io/video/docs/react-native/guides/camera-and-microphone/](https://getstream.io/video/docs/react-native/guides/camera-and-microphone/).