# MeetStream Guide: Per-Participant Video Streams

This guide explains how to capture **individual video recordings per participant** in a meeting. Instead of a single composite screen recording, you receive a separate WebM video file for each participant's webcam and any screen shares.

Supported platforms: **Google Meet, Zoom, Microsoft Teams**.

---

## 1) What you need

1. A MeetStream API key (see the [Quickstart Guide](/guides/get-started/create-your-first-bot)).
2. A meeting link (Google Meet, Zoom, or Microsoft Teams).
3. Set `video_separate_streams: true` in your Create Bot request.

---

## 2) Create a bot with per-participant video

Use the **Create Agent** endpoint:
https://docs.meetstream.ai/api-reference/api-reference/bot-endpoints/create-agent

### Minimal example

```bash
curl -X POST "https://api.meetstream.ai/api/v1/bots/create_agent" \
  -H "Authorization: Token <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "meeting_link": "<YOUR_MEETING_LINK>",
    "bot_name": "RecorderBot",
    "video_separate_streams": true
  }'
```

### Full example with recording config

```json
{
  "meeting_link": "https://meet.google.com/abc-defg-hij",
  "bot_name": "RecorderBot",
  "video_required": true,
  "video_separate_streams": true,
  "recording_config": {
    "transcript": {
      "provider": {
        "deepgram": {
          "model": "nova-3",
          "language": "en"
        }
      }
    }
  },
  "automatic_leave": {
    "everyone_left_timeout": 5
  }
}
```

### Parameter reference

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `video_separate_streams` | boolean | `false` | Enable per-participant video capture |
| `video_required` | boolean | `false` | Enable composite screen recording (single MP4). Can be used alongside `video_separate_streams` |

> **Tip:** You can also pass `video_separate_streams` nested inside `recording_config`:
> ```json
> "recording_config": {
>   "video_separate_streams": true
> }
> ```
> The top-level parameter takes precedence if both are set.

---

## 3) What happens during the meeting

Once the bot joins, it automatically:

- Captures each participant's **webcam feed** as a separate video stream.
- Captures **screen shares** as separate streams.
- Records up to **6 concurrent webcam streams**. If more than 6 participants have cameras on, additional cameras are queued and start recording when a slot frees up.
- Screen shares are always captured (1 concurrent on Teams/Zoom, multiple possible on Google Meet).

No additional configuration is needed per participant -- the bot handles everything.

---

## 4) Retrieve per-participant video streams

After the bot leaves and video processing completes, call:

```bash
curl -X GET "https://api.meetstream.ai/api/v1/bots/<BOT_ID>/get_recording_streams" \
  -H "Authorization: Token <YOUR_API_KEY>"
```

### Response when processing is complete

```json
{
  "bot_id": "f923cd21-da86-4d77-b37b-0707d37751c8",
  "video_status": "Success",
  "recording_streams_available": true,
  "participants": [
    {
      "participant_name": "John Doe",
      "streams": [
        {
          "stream_id": "user_456",
          "segments": [
            {
              "segment_index": 0,
              "url": "https://s3.amazonaws.com/...?X-Amz-Signature=...",
              "filename": "John_Doe_456_0.webm",
              "duration_seconds": 125.5,
              "width": 640,
              "height": 360,
              "codec": "vp8"
            }
          ]
        }
      ]
    },
    {
      "participant_name": "Jane Smith",
      "streams": [
        {
          "stream_id": "user_789",
          "segments": [
            {
              "segment_index": 0,
              "url": "https://s3.amazonaws.com/...?X-Amz-Signature=...",
              "filename": "Jane_Smith_789_0.webm",
              "duration_seconds": 130.2,
              "width": 854,
              "height": 480,
              "codec": "vp8"
            }
          ]
        }
      ]
    }
  ],
  "screenshares": [
    {
      "participant_name": "John Doe",
      "streams": [
        {
          "stream_id": "source_101",
          "segments": [
            {
              "segment_index": 0,
              "url": "https://s3.amazonaws.com/...?X-Amz-Signature=...",
              "filename": "John_Doe_101_0.webm",
              "duration_seconds": 60.0,
              "width": 1280,
              "height": 720,
              "codec": "vp8"
            }
          ]
        }
      ]
    }
  ],
  "summary": {
    "total_participants": 2,
    "total_screenshares": 1,
    "total_segments": 3
  }
}
```

### Response when processing is still in progress

```json
{
  "video_status": "processing",
  "stage": "Core Processing",
  "message": "Video is being processed. Try again later."
}
```

HTTP status **202** is returned when processing is not yet complete. The `stage` field indicates the current processing step. Poll again after 10-30 seconds.

---

## 5) Download the video files

Each segment in the response contains a `url` field -- a **presigned S3 URL** that allows direct download without additional authentication.

```bash
# Download a participant's video
curl -o "John_Doe.webm" "<PRESIGNED_URL_FROM_RESPONSE>"
```

> **Important:** Presigned URLs expire after **10 minutes**. If a URL has expired, call `get_recording_streams` again to get fresh URLs.

### File format

| Property | Value |
|----------|-------|
| Container | WebM |
| Video codec | VP8 |
| Frame rate | 15 FPS |
| Audio | None (video-only files) |

Audio is available separately via the standard **Get Bot Audio** endpoint.

---

## 6) Understanding segments

A participant may have **multiple segments**. A new segment is created when:

- A **screen share resolution changes** (e.g., switching from fullscreen 1080p to a smaller window) on Teams or Zoom.
- A participant **shares their screen multiple times** (each share session is a separate segment).
- A **webcam video dimension change** occurs on Teams.

Camera off/on does **not** create a new segment -- the bot maintains a continuous recording file per participant across camera toggles.

Segments are ordered by `segment_index` and are chronologically sequential. Use the `duration_seconds` field to determine segment timing.

---

## 7) Video resolution by platform

Webcam and screen share resolutions differ by platform:

| Platform | Webcam | Webcam Bitrate | Screen share | Screen share Bitrate |
|----------|--------|---------------|-------------|---------------------|
| Google Meet | Up to 854x480 | 800 kbps | Up to 1280x720 | 2 Mbps |
| Microsoft Teams | Up to 854x480 | 800 kbps | Up to 1280x720 | 2 Mbps |
| Zoom | 640x360 (fixed) | 300 kbps | Native resolution | 1.5 Mbps |

---

## 8) Using both composite and per-participant video

You can enable both `video_required` and `video_separate_streams` simultaneously:

```json
{
  "meeting_link": "<MEETING_LINK>",
  "video_required": true,
  "video_separate_streams": true
}
```

This produces:
- A **composite MP4** (single screen recording of the meeting view) -- retrieve via the **Get Bot Video** endpoint.
- **Per-participant WebM files** -- retrieve via the **Get Recording Streams** endpoint.

---

## 9) Webhook notifications

If you have webhooks configured, you will receive notifications when video processing starts and completes. Use the `video_status` field in webhook payloads or poll `get_recording_streams` until `video_status` is `"Success"`.

---

## 10) Troubleshooting

- **`recording_streams_available: false` with `video_status: "Success"`?**
  - The bot may have been in the meeting but no participant had their camera on. Per-participant streams are only produced for participants whose cameras were active.

- **Missing a participant's video?**
  - The bot captures up to **6 concurrent webcam streams**. If more than 6 cameras were active, some participants may not have been captured.
  - Participants who never turned on their camera will not appear in the response.

- **Getting `video_status: "processing"`?**
  - Video processing takes a short time after the bot exits. Poll again after 10-30 seconds.

- **Presigned URL returns 403 Forbidden?**
  - The URL has expired (10-minute lifetime). Call `get_recording_streams` again for fresh URLs.

- **Video file has no audio?**
  - Per-participant video files are **video-only**. Use the **Get Bot Audio** endpoint to retrieve the meeting audio separately.
