# Pre-call test recording

The loopback recording API lets you record a short self-test of the local participant's media as it travels through Stream's SFU. The local video file is written to the device — nothing is uploaded.

This is different from [server-side recording](/video/docs/react-native/advanced/recording/), which records the full call on Stream's infrastructure. Use the loopback API for **local, pre-call diagnostics**.

## When to use it

- **Pre-call device check** — verify the user's microphone, camera, and network path end-to-end before they join a real call.
- **Diagnostics builds** — capture a short reference clip when users report audio or video quality issues, so you have a reproducible artifact to inspect.

## How it works

The hook records your published media after it has made a full round trip through Stream's servers — capturing what other participants would actually see and hear, not just your local camera and microphone. Any problem along that path shows up in the recording.

Recordings are written to a Stream-managed directory inside your app's private storage (iOS temporary storage, Android cache). Files stay there until you remove them — clearing the directory is your responsibility, and the API exposes `clearRecordings()` for that.

## Requirements

The component must be rendered inside `<StreamCall>`, and the call must be joined with `allowOwnTracksLoopback: true`.

<admonition type="warning">

No other participants can be present. The hook will not start recording when the call is shared.

</admonition>

## API reference

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

const {
  startRecording,
  stopRecording,
  clearRecordings,
  getRecordings,
  recordingState,
  loopbackVideoStream,
  loopbackAudioStream,
} = useLoopbackRecording();
```

| Field                      | Description                                                                                                                                                                                                                                                                                                                                                                                                         |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `startRecording(options?)` | Starts a recording. Returns a promise that resolves with the `file://` URI of the produced video file once recording finishes, or `null` if no file was produced (for example, you stopped the recording before any data arrived). Pass `{ includeVideo: false }` for an audio-only recording, or `{ maxDurationMs }` to override the default 10-second cap (clamped to a 5-second minimum and a 2-minute maximum). |
| `stopRecording()`          | Stops the recording early. During `'awaiting-streams'` it aborts the pending wait; during `'recording'` it finalises the file.                                                                                                                                                                                                                                                                                      |
| `clearRecordings()`        | Recursively deletes every file under the SDK's local recordings directory.                                                                                                                                                                                                                                                                                                                                          |
| `getRecordings()`          | Returns every `file://` URI in that directory, sorted most-recent first.                                                                                                                                                                                                                                                                                                                                            |
| `recordingState`           | One of `'idle'`, `'awaiting-streams'`, or `'recording'`.                                                                                                                                                                                                                                                                                                                                                            |
| `loopbackVideoStream`      | The video `MediaStream` echoed back by the SFU, when present. Render it with `RTCView` to give the user live feedback while recording.                                                                                                                                                                                                                                                                              |
| `loopbackAudioStream`      | The audio `MediaStream` echoed back by the SFU, when present.                                                                                                                                                                                                                                                                                                                                                       |

## Minimal example

```tsx
import React, { useCallback, useEffect, useMemo } from "react";
import { Button, View } from "react-native";
import {
  Call,
  StreamCall,
  useLoopbackRecording,
  useStreamVideoClient,
} from "@stream-io/video-react-native-sdk";

export function PreCallTest() {
  const client = useStreamVideoClient();
  const call = useMemo<Call | undefined>(() => {
    if (!client) return undefined;
    return client.call("default", "self-test-" + Date.now());
  }, [client]);

  useEffect(() => {
    if (!call) return;
    call.getOrCreate();
    return () => {
      call.leave();
    };
  }, [call]);

  if (!call) return null;

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

function RecordButton({ call }: { call: Call }) {
  const { startRecording, recordingState } = useLoopbackRecording();

  const onPress = useCallback(async () => {
    await call.join({ create: true, allowOwnTracksLoopback: true });
    const uri = await startRecording();
    call.leave();
    if (uri) {
      // You now have a local video file on disk. Play it back or share it.
      console.log("Recording saved at", uri);
    }
  }, [call, startRecording]);

  return (
    <View>
      <Button title={recordingState} onPress={onPress} />
    </View>
  );
}
```

## Lifecycle and limits

- Recordings **auto-stop after 10 seconds** by default. Override via `startRecording({ maxDurationMs })` — values outside the `[5 seconds, 2 minutes]` range snap to the nearest bound.
- `startRecording()` waits up to **10 seconds** for the SFU to echo the loopback tracks back. If the wait times out the promise rejects.
- The recording auto-stops and finalises if the call leaves or the screen unmounts mid-recording — the file is still produced.

## See also

- [Pre-call self-test cookbook](/video/docs/react-native/ui-cookbook/pre-call-self-test/) — a complete two-screen UI recipe (record → play back → share).
- [Server-side recording](/video/docs/react-native/advanced/recording/) — cloud-hosted recording of the full call.
- [Call Stats Report](/video/docs/react-native/advanced/stats/) — surface latency, jitter, and bitrate during the loopback test for richer diagnostics.


---

This page was last updated at 2026-06-26T15:47:36.513Z.

For the most recent version of this documentation, visit [https://getstream.io/video/docs/react-native/advanced/loopback-recording/](https://getstream.io/video/docs/react-native/advanced/loopback-recording/).