cloudflare / cloudflare/realtimekit-web-examples

Recording starts before startRecording() when autoStart:false — is joining the meeting yourself supported?

Open
#95 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
67
Forks
23
PR merge metrics
No merged PRs in 30d

Description

## What we're trying to achieve

We record two-person conversations with a custom recording app. The stored MP4 is
the deliverable — people watch it back — so we want it to **open directly on both
participants' video**, with none of the startup sequence in front of it.

Concretely, we want to avoid a recording that begins like this:

```
0.0 - 3.5s our "preparing the conversation" loading screen (nobody in the roster yet)
3.5 - 4.5s two named tiles showing avatar placeholders, no video
4.5s both tiles finally live
```

…and instead have frame zero already show the finished composition. Everything
before both video tracks are attached is startup scaffolding that we don't want
in the artifact.

That is why we reached for `autoStart: false` — so our app could decide when the
picture was actually ready and only then begin capture. It works when our
`startRecording()` call lands in time, and doesn't when it doesn't, which is what
this issue is about.

If there's a better-supported way to get a clean opening — including "this isn't
what the recording SDK is for, do X instead" — that answer is just as useful to
us as a fix.

## Summary

The recording guide documents `autoStart: false` + a manual `startRecording()` call as the way to delay capture until your recording app's UI is ready. We rely on that, and we're seeing the recording worker begin capture **before** `startRecording()` is called, if that call arrives more than roughly 3.5–4 s after the recording is invoked.

We'd like to understand whether the pattern we're using is supported, because none of the examples in this repo demonstrate it.

## What the docs say

> "you can manually call the `startRecording()` function when you are ready to begin the recording. For example, you want to start a recording after you have loaded your UI content in the app and `autoStart` is not set to true."

— [Create Custom Recording App Using Recording SDKs](https://developers.cloudflare.com/realtime/realtimekit/recording-guide/create-record-app-using-sdks/)

## What every example in this repo does instead

All eight recording examples (4 React, 4 Angular) are identical in shape:

```ts
const recordingSDK = new RealtimeKitRecording({}); // autoStart defaults to true
const meetingObj = await initClient({ authToken, defaults: { audio: false, video: false } });
await recordingSDK.init(meetingObj!);
```

None of them passes `autoStart`, calls `startRecording()`, or calls `join()` — `startRecording()` performs the join internally. So the documented manual-start path has no reference implementation here.

## Our usage, and the warning it produces

Our recorder needs to observe the meeting composition before deciding when to start, so it joins itself:

```ts
new RealtimeKitRecording({ autoStart: false, autoStop: true })
await RealtimeKitClient.init({ authToken, defaults: { audio: false, video: false } })
await recording.init(client)
await client.join()
// …later, when our UI is ready:
await recording.startRecording()
```

Because we've already joined, `startRecording()` hits this guard in the SDK:

```
"Meeting already joined. Cannot start recording. SDK will call meeting.join() automatically."
```

It logs a warning and proceeds — but it throws under `devMode`, which suggests this is not an intended path.

## Observed behaviour

Comparing our own `startRecording()` call against the recording's `started_time` from the REST API, over ~40 recordings. Two runs of **identical code**, three minutes apart, offsets relative to `invoked_time`:

**Honoured** — good opening:

| event | offset |
|---|---|
| page joined meeting | +2.75 s |
| our `startRecording()` | **+4.11 s** |
| `started_time` | **+4.06 s** |

`started_time` matches our call to within 50 ms.

**Not honoured** — recording opens on ~4 s of our loading UI:

| event | offset |
|---|---|
| `started_time` | **+3.61 s** |
| page joined meeting | +4.47 s |
| our `startRecording()` | +6.01 s |

Capture began 0.85 s *before the page had joined the meeting at all*, and 2.4 s before we asked for it.

Across all recordings the rule held with no exceptions in either direction: the opening is correct **iff** the page joins the meeting before `started_time`. Observed `started_time` lands 3.4–6.0 s after `invoked_time`.

## Questions

1. Is calling `client.join()` yourself supported, given the SDK warns about it and throws under `devMode`? If not, what is the supported way to delay capture until the recording app's UI is ready — which is what the docs describe `autoStart: false` as being for?
2. Is there a worker-side timeout after which capture starts regardless of `startRecording()`? What is it measured from, and is it configurable?
3. If that fallback is intended, is there a way for the recording app to detect that it fired? Right now it's only inferrable from the frame content of the finished asset.

## Environment

- `@cloudflare/realtimekit` 2.0.1
- `@cloudflare/realtimekit-recording-sdk` 0.0.3
- Custom recording app, deployed to Cloudflare Pages, invoked via the Start Recording REST API with a `url` parameter.

Happy to supply recording IDs and account details privately via a support ticket if that's more useful — I've kept them out of here deliberately.

Contributor guide

Open the contributing guide

Research direction

Start with the eight React and Angular recording examples and compare their RealtimeKitRecording initialization with the documented autoStart:false flow. Trace the init(), join(), and startRecording() entry points against the observed invoked_time and started_time offsets, then establish whether self-joining and the delayed capture behavior are supported and how completion should be verified.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
audio-video-rtc
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.