# IRecordingClient

<Badge tone="type">interface</Badge> <Badge>thread-safe</Badge>

```csharp
namespace AR51.Net;

public interface IRecordingClient
```

Records camera video and tracking data on the AR 51 servers. Use it through [`IAR51Client.Recording`](/docs/sdk-api/csharp-api/classes/iar51client/).

Recordings are saved on the servers, in a folder named after the recording. `IsRecording` follows the system live, whoever started the recording. All members are safe to use from any thread.

:::tip[How-to]
This page is **reference** (facts only). For a walkthrough with a complete sample, see the [Recording guide](/docs/csharp-api/recording/).
:::

## Properties

<div className="apiPropTable apiTable">

| Property | Type | Access | Description |
|---|---|---|---|
| `IsRecording` | `bool` | `get` | Whether the system is recording, whoever started it. |

</div>

## Method summary

<div className="apiTable">

| Method | Returns | |
|---|---|---|
| [`StartRecordingAsync`](#startrecordingasync) | [`Task`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task) |  |
| [`StopRecordingAsync`](#stoprecordingasync) | [`Task`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task) |  |

</div>

→ Full descriptions in [Method details](#method-details) below.

## Events

Standard .NET events (`EventHandler<T>`): subscribe with `+=`, unsubscribe with `-=`. They are raised on a background thread.

<div className="apiTable">

| Event | Args | Raised when |
|---|---|---|
| `RecordingStateChanged` | [`RecordingStateEventArgs`](#recordingstateeventargs) | Raised when recording starts or stops, whoever started it. Raised on a background thread. Checked about once a second. |

</div>

## Method details

### StartRecordingAsync

<ApiBody kind="method">

```csharp
Task StartRecordingAsync(RecordingOptions options, CancellationToken cancellationToken = default);
```

Starts recording tracking data and, from the chosen cameras, video.

<Params>
<Param name="options" type="RecordingOptions" typeHref="#recordingoptions">The recording's name and cameras.</Param>
<Param name="cancellationToken" type="CancellationToken" typeHref="https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken">Cancels the request. Optional.</Param>
</Params>

<Returns type="Task" typeHref="https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task">A task that completes when every chosen camera and the tracking data are recording.</Returns>

<Throws>
<Throw type="ArgumentException" typeHref="https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception">[`RecordingOptions.Name`](#recordingoptions) is empty or not a valid folder name.</Throw>
<Throw type="AR51Exception" typeHref="/docs/sdk-api/csharp-api/classes/ar51exception/">A recording is already running, started by this or another app, or a camera does not exist or failed to start ([`AR51ErrorCode.Rejected`](/docs/sdk-api/csharp-api/classes/ar51exception/#ar51errorcode)), or a server could not be reached. A running recording is never touched, and nothing is left half-started: the parts that did start are stopped again.</Throw>
</Throws>

<Example>

```csharp
await ar51.Recording.StartRecordingAsync(new RecordingOptions
{
    Name = "take-01",
    CameraIds = new[] { camera.Id },   // empty = tracking data only
});
await Task.Delay(TimeSpan.FromSeconds(5));
await ar51.Recording.StopRecordingAsync();
```

</Example>

</ApiBody>

### StopRecordingAsync

<ApiBody kind="method">

```csharp
Task StopRecordingAsync(CancellationToken cancellationToken = default);
```

Stops the recording, whoever started it. Does nothing if nothing is recording.

<Params>
<Param name="cancellationToken" type="CancellationToken" typeHref="https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken">Cancels the request. Optional.</Param>
</Params>

<Returns type="Task" typeHref="https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task">A task that completes when the servers have stopped recording.</Returns>

<Throws>
<Throw type="AR51Exception" typeHref="/docs/sdk-api/csharp-api/classes/ar51exception/">A server could not be reached.</Throw>
</Throws>

:::caution[Affects every app using the system]
Stops the recording **whoever started it** — including one started from Mocap Studio or another app.
:::

</ApiBody>

## Related types

Small types used by this interface, documented here.

### RecordingOptions

<Badge tone="type">record · sealed</Badge>

```csharp
public sealed record RecordingOptions
```

Options for [`IRecordingClient.StartRecordingAsync`](#startrecordingasync).

:::note
Video is recorded at each camera's own resolution and frame rate.
:::

<div className="apiPropTable apiTable">

| Property | Type | Access | Default | Description |
|---|---|---|---|---|
| `Name` | `string` | `get · init` | — | **Required.** The recording's name, also the name of its folder on the servers. |
| `CameraIds` | [`IReadOnlyList<string>`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlylist-1) | `get · init` | `[]` | The cameras to record video from, by [`CameraInfo.Id`](/docs/sdk-api/csharp-api/classes/camerainfo/). Empty = tracking data only, no video. |

</div>

### RecordingStateEventArgs

<Badge tone="type">class · sealed</Badge>

```csharp
public sealed class RecordingStateEventArgs : EventArgs
```

Data for `IRecordingClient.RecordingStateChanged`.

<div className="apiPropTable apiTable">

| Property | Type | Access | Description |
|---|---|---|---|
| `IsRecording` | `bool` | `get` | Whether the system is recording now. |

</div>

<details>
<summary>Constructor</summary>

```csharp
public RecordingStateEventArgs(bool isRecording);
```

Creates the event data.

</details>

## See also

- [Recording guide](/docs/csharp-api/recording/) — walkthrough with a complete, compiled sample
- [Class index](/docs/sdk-api/csharp-api/classes/) — every AR51.Net type
- [Data conventions, threading and errors](/docs/csharp-api/conventions/)
