# Agora Video Recording API Documentation

## Base URL

```
http://127.0.0.1:8000/api/agora
```

**Note: All recording APIs are public and do not require authentication.**

---

## 1. Start Recording

### Endpoint

```
POST /api/agora/recording/start
```

### Headers

```json
{
  "Content-Type": "application/json"
}
```

### Request Body

```json
{
  "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
  "uid": "1001",
  "schedule_id": "675812ab3f4e5a0b1c234567"
}
```

### Parameters

| Parameter    | Type   | Required | Description                           |
| ------------ | ------ | -------- | ------------------------------------- |
| channel_name | string | Yes      | The Agora channel name (max 64 chars) |
| uid          | string | Yes      | User ID for the recording bot         |
| schedule_id  | string | No       | Interview schedule ID for tracking    |

### Success Response (200)

```json
{
  "status": 200,
  "message": "Cloud recording started successfully",
  "data": {
    "resourceId": "JyvK8nXHuV1BE64GDkAaBGEscvtHW7v8BrQoRPCHxmeVxwY22-x-kv4GdPcjZeMzoCBUCOr9q-k6wBWMC7SaAkZ_4nO3JLqYwM1bL1n6wKnnD9EC9waxJbuslbVEDMLz",
    "sid": "38f8e3cfdc474cd56fc1cde2fcb39c7d",
    "channelName": "interview_1733845678_a1b2c3d4e5f6g7h8",
    "uid": "1001"
  }
}
```

### Error Response (422 - Validation Error)

```json
{
  "status": 422,
  "message": "Validation failed",
  "data": {
    "errors": {
      "channel_name": ["The channel name field is required."]
    }
  }
}
```

### Error Response (500 - Server Error)

```json
{
  "status": 500,
  "message": "Failed to start cloud recording",
  "data": {
    "error": "Failed to acquire resource"
  }
}
```

---

## 2. Stop Recording

### Endpoint

```
POST /api/agora/recording/stop
```

### Headers

```json
{
  "Content-Type": "application/json"
}
```

### Request Body

```json
{
  "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
  "uid": "1001",
  "resource_id": "JyvK8nXHuV1BE64GDkAaBGEscvtHW7v8BrQoRPCHxmeVxwY22-x-kv4GdPcjZeMzoCBUCOr9q-k6wBWMC7SaAkZ_4nO3JLqYwM1bL1n6wKnnD9EC9waxJbuslbVEDMLz",
  "sid": "38f8e3cfdc474cd56fc1cde2fcb39c7d",
  "schedule_id": "675812ab3f4e5a0b1c234567"
}
```

### Parameters

| Parameter    | Type   | Required | Description                               |
| ------------ | ------ | -------- | ----------------------------------------- |
| channel_name | string | Yes      | The Agora channel name                    |
| uid          | string | Yes      | User ID used when starting recording      |
| resource_id  | string | Yes      | Resource ID from start recording response |
| sid          | string | Yes      | Session ID from start recording response  |
| schedule_id  | string | No       | Interview schedule ID                     |

### Success Response (200)

```json
{
  "status": 200,
  "message": "Cloud recording stopped successfully",
  "data": {
    "resourceId": "JyvK8nXHuV1BE64GDkAaBGEscvtHW7v8BrQoRPCHxmeVxwY22-x-kv4GdPcjZeMzoCBUCOr9q-k6wBWMC7SaAkZ_4nO3JLqYwM1bL1n6wKnnD9EC9waxJbuslbVEDMLz",
    "sid": "38f8e3cfdc474cd56fc1cde2fcb39c7d",
    "serverResponse": {
      "fileListMode": "json",
      "fileList": [
        {
          "filename": "recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.m3u8",
          "trackType": "audio_and_video",
          "uid": "1001",
          "mixedAllUser": true,
          "isPlayable": true,
          "sliceStartTime": 1733845780000
        },
        {
          "filename": "recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.mp4",
          "trackType": "audio_and_video",
          "uid": "1001",
          "mixedAllUser": true,
          "isPlayable": true,
          "sliceStartTime": 1733845780000
        }
      ],
      "uploadingStatus": "uploaded"
    }
  }
}
```

---

## 3. Query Recording Status

### Endpoint

```
POST /api/agora/recording/query
```

### Headers

```json
{
  "Content-Type": "application/json"
}
```

### Request Body

```json
{
  "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
  "uid": "1001",
  "resource_id": "JyvK8nXHuV1BE64GDkAaBGEscvtHW7v8BrQoRPCHxmeVxwY22-x-kv4GdPcjZeMzoCBUCOr9q-k6wBWMC7SaAkZ_4nO3JLqYwM1bL1n6wKnnD9EC9waxJbuslbVEDMLz",
  "sid": "38f8e3cfdc474cd56fc1cde2fcb39c7d"
}
```

### Parameters

| Parameter    | Type   | Required | Description                          |
| ------------ | ------ | -------- | ------------------------------------ |
| channel_name | string | Yes      | The Agora channel name               |
| uid          | string | Yes      | User ID used when starting recording |
| resource_id  | string | Yes      | Resource ID from start recording     |
| sid          | string | Yes      | Session ID from start recording      |

### Success Response (200)

```json
{
  "status": 200,
  "message": "Recording status retrieved successfully",
  "data": {
    "resourceId": "JyvK8nXHuV1BE64GDkAaBGEscvtHW7v8BrQoRPCHxmeVxwY22-x-kv4GdPcjZeMzoCBUCOr9q-k6wBWMC7SaAkZ_4nO3JLqYwM1bL1n6wKnnD9EC9waxJbuslbVEDMLz",
    "sid": "38f8e3cfdc474cd56fc1cde2fcb39c7d",
    "serverResponse": {
      "status": "5",
      "sliceStartTime": 1733845780000,
      "fileListMode": "json",
      "fileList": []
    }
  }
}
```

### Recording Status Codes

| Status | Description               |
| ------ | ------------------------- |
| 0      | Recording has not started |
| 1      | Initialization complete   |
| 2      | Recorder is starting      |
| 3      | Uploader is ready         |
| 4      | Recorder is ready         |
| 5      | Recording in progress     |
| 6      | Recording paused          |
| 7      | Recording stopped         |
| 8      | Recording exited          |
| 20     | Recording abnormal exit   |

---

## 4. Get Interview Recordings

### Endpoint

```
GET /api/agora/recording/interview/{schedule_id}
```

### Headers

```json
{
  "Content-Type": "application/json"
}
```

### URL Parameters

| Parameter   | Type   | Required | Description           |
| ----------- | ------ | -------- | --------------------- |
| schedule_id | string | Yes      | Interview schedule ID |

### Example Request

```
GET /api/agora/recording/interview/675812ab3f4e5a0b1c234567
```

### Success Response (200)

```json
{
  "status": 200,
  "message": "Interview recordings retrieved successfully",
  "data": {
    "schedule_id": "675812ab3f4e5a0b1c234567",
    "total_count": 2,
    "s3_bucket": "drjobscv-replication",
    "s3_region": "us-east-2",
    "s3_base_url": "https://drjobscv-replication.s3.us-east-2.amazonaws.com",
    "recordings": [
      {
        "_id": "675812cd3f4e5a0b1c234568",
        "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
        "uid": "1001",
        "resource_id": "JyvK8nXHuV1BE64GDkAaBGEscvtHW7v8BrQoRPCHxmeVxwY22-x-kv4GdPcjZeMzoCBUCOr9q-k6wBWMC7SaAkZ_4nO3JLqYwM1bL1n6wKnnD9EC9waxJbuslbVEDMLz",
        "sid": "38f8e3cfdc474cd56fc1cde2fcb39c7d",
        "schedule_id": "675812ab3f4e5a0b1c234567",
        "status": "completed",
        "started_at": "2025-12-10T10:30:00.000Z",
        "stopped_at": "2025-12-10T11:00:00.000Z",
        "recording_url": "https://drjobscv-replication.s3.us-east-2.amazonaws.com/recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.mp4",
        "file_list": [
          {
            "filename": "recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.m3u8",
            "s3_url": "https://drjobscv-replication.s3.us-east-2.amazonaws.com/recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.m3u8",
            "trackType": "audio_and_video",
            "uid": "1001",
            "mixedAllUser": true,
            "isPlayable": true,
            "sliceStartTime": 1733845780000
          },
          {
            "filename": "recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.mp4",
            "s3_url": "https://drjobscv-replication.s3.us-east-2.amazonaws.com/recordings/2025-12-10/interview_1733845678_a1b2c3d4e5f6g7h8.mp4",
            "trackType": "audio_and_video",
            "uid": "1001",
            "mixedAllUser": true,
            "isPlayable": true,
            "sliceStartTime": 1733845780000
          }
        ],
        "created_at": "2025-12-10T10:30:00.000Z",
        "updated_at": "2025-12-10T11:00:00.000Z"
      }
    ]
  }
}
```

---

## Database Collections

### 1. interview_recordings (mongodb)

Stores recording metadata:

```json
{
  "_id": "ObjectId",
  "channel_name": "string",
  "uid": "string",
  "resource_id": "string",
  "sid": "string",
  "schedule_id": "string",
  "status": "recording|completed",
  "started_at": "datetime",
  "stopped_at": "datetime",
  "server_response": "object",
  "file_list": "array",
  "created_at": "datetime",
  "updated_at": "datetime"
}
```

### 2. interview_schedule_requests (mongodb)

Updated with recording_data field:

```json
{
  "_id": "ObjectId",
  "job_id": "string",
  "member_id": "int",
  "screening_id": "string",
  "interview_schedule": "datetime",
  "recording_data": {
    "resource_id": "string",
    "sid": "string",
    "status": "recording|completed",
    "started_at": "datetime",
    "stopped_at": "datetime",
    "file_list": "array"
  }
}
```

---

## Example Usage Flow

### 1. Start Interview Recording

```bash
curl -X POST http://127.0.0.1:8000/api/agora/recording/start \
  -H "Content-Type: application/json" \
  -d '{
    "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
    "uid": "1001",
    "schedule_id": "675812ab3f4e5a0b1c234567"
  }'
```

### 2. Query Recording Status (During Interview)

```bash
curl -X POST http://127.0.0.1:8000/api/agora/recording/query \
  -H "Content-Type: application/json" \
  -d '{
    "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
    "uid": "1001",
    "resource_id": "RESOURCE_ID_FROM_START",
    "sid": "SID_FROM_START"
  }'
```

### 3. Stop Recording (Interview Ends)

```bash
curl -X POST http://127.0.0.1:8000/api/agora/recording/stop \
  -H "Content-Type: application/json" \
  -d '{
    "channel_name": "interview_1733845678_a1b2c3d4e5f6g7h8",
    "uid": "1001",
    "resource_id": "RESOURCE_ID_FROM_START",
    "sid": "SID_FROM_START",
    "schedule_id": "675812ab3f4e5a0b1c234567"
  }'
```

### 4. Get All Recordings for Interview

```bash
curl -X GET http://127.0.0.1:8000/api/agora/recording/interview/675812ab3f4e5a0b1c234567 \
  -H "Content-Type: application/json"
```

---

## Recording Configuration

### Video Settings

- Resolution: 1280x720
- FPS: 15
- Bitrate: 2000 kbps
- Layout: Best fit (mixed video)

### Output Formats

- HLS (.m3u8) - For streaming playback
- MP4 (.mp4) - For download and local playback

### Storage

- Vendor: 1 (Amazon S3)
- Region: 9 (us-east-2)
- Bucket: drjobscv-replication
- Base URL: https://drjobscv-replication.s3.us-east-2.amazonaws.com
- File Path: `recordings/YYYY-MM-DD/filename`
- Max Idle Time: 30 seconds (recording stops if no user in channel)
- **Full S3 URLs**: Each file in the response includes both `filename` (relative path) and `s3_url` (full S3 URL) for direct access
- **Recording URL**: Each recording includes `recording_url` field with direct link to the MP4 file - use this URL to open/download the recording directly

---

## Error Codes

| Status Code | Description                    |
| ----------- | ------------------------------ |
| 200         | Success                        |
| 422         | Validation error               |
| 500         | Server error / Agora API error |

---

## Notes

1. **No Authentication Required**: All recording APIs are public and can be called without JWT token
2. **Resource & SID**: Save the `resourceId` and `sid` from start response - needed for stop/query
3. **Schedule ID**: Optional but recommended for tracking recordings by interview
4. **S3 Storage**: Using Amazon S3 (vendor 1) in us-east-2 region - recordings stored in `drjobscv-replication` bucket
5. **Full URLs**: Each file includes `s3_url` field with complete S3 path for direct download/streaming
6. **Recording URL**: Use the `recording_url` field to directly open/play the MP4 recording in browser or video player
7. **File List**: Available in stop response and getInterviewRecordings endpoint
8. **Auto Update**: Recording data automatically updates in `interview_schedule_requests` collection
9. **Access Files**: Simply use the `recording_url` or individual `s3_url` from file_list to access recordings

---

## Testing Tips

1. Start recording when interview begins
2. Store resourceId and sid in your frontend state
3. Optionally query status during interview to check recording health
4. Stop recording when interview ends
5. Retrieve recording details using schedule_id
6. Access recording files from the file_list array

---

## Environment Variables

Required in `.env`:

```env
# Agora Configuration
AGORA_APP_ID=859a5bfd0b834751b88d7510680a5a6b
AGORA_APP_CERTIFICATE=your-agora-app-certificate
AGORA_CUSTOMER_ID=your-agora-customer-id
AGORA_CUSTOMER_SECRET=your-agora-customer-secret

# S3 Storage Configuration
AGORA_STORAGE_VENDOR=1
AGORA_STORAGE_REGION=9
AWS_ACCESS_KEY_ID=your-aws-access-key-id
AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
AWS_DEFAULT_REGION=us-east-2
AWS_BUCKET=your-s3-bucket-name
AWS_URL=https://your-bucket-name.s3.us-east-2.amazonaws.com
```

**Storage Vendor Codes:**

- 0 = Agora Cloud Backup (temporary)
- 1 = Amazon S3
- 2 = Alibaba Cloud
- 3 = Tencent Cloud

**Region Codes for S3:**

- 0 = us-east-1
- 1 = us-east-2
- 2 = us-west-1
- 3 = us-west-2
- 9 = us-east-2 (Ohio)
