> ## Documentation Index
> Fetch the complete documentation index at: https://api-tools.memories.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Start Video Stream Moderation

> Start video stream content moderation and logo detection with real-time processing.

<Info>
  **Product**: Visual Intelligence — Live Video Content Moderation
  **Use case**: Real-time NSFW / violence / logo detection on a live video stream (RTMP/RTSP), results pushed to your callback every 5s
  **Mode**: Server-Pull (you give us a stream URL → we pull → results to your callback)
  **Host**: `https://mavi-backend.memories.ai/serve/api/v2`
  **Auth**: `Authorization: sk-mavi-...` (no `Bearer` prefix)
</Info>

<Warning>
  **Access Required**: To use this API endpoint, please contact us at [contact@memories.ai](mailto:contact@memories.ai) to enable stream processing features for your account.
</Warning>

This endpoint starts real-time video stream processing for content moderation and logo detection. The stream is automatically segmented every 5 seconds, with results sent via webhook callbacks.

<Note>
  **Pricing:**

  The pricing varies based on the features enabled:

  **Content Moderation + Logo Detection:**

  ```
  Cost (USD) = duration × 2 × (1 + (fps - 1) × 0.5) / 3600
  ```

  * Base rate: \$2.00/hour
  * Example (FPS=2): $3.00/hour ($0.00417 per 5-second segment)

  **Content Moderation Only:**

  ```
  Cost (USD) = duration × 1.5 × (1 + (fps - 1) × 0.5) / 3600
  ```

  * Base rate: \$1.50/hour
  * Example (FPS=2): $2.25/hour ($0.00313 per 5-second segment)

  **Logo Detection Only:**

  ```
  Cost (USD) = duration × 1.5 × (1 + (fps - 1) × 0.5) / 3600
  ```

  * Base rate: \$1.50/hour
  * Example (FPS=2): $2.25/hour ($0.00313 per 5-second segment)

  Where:

  * `duration`: Video duration in seconds (5 seconds per segment)
  * `fps`: Frames per second
  * Charges occur at start (pre-charge for one segment) and per segment processed
</Note>

## Supported Protocols

* RTMP (Recommended)
* RTSP

## Key Features

* ✅ Real-time stream processing
* ✅ Automatic 5-second segmentation
* ✅ Asynchronous webhook callbacks
* ✅ Content moderation (adult content, violence, etc.)
* ✅ Logo detection and tracking
* ✅ Automatic resource management

### Code Example

<CodeGroup>
  ```python Python theme={null}
  import requests

  BASE_URL = "https://mavi-backend.memories.ai/serve/api/v2"
  API_KEY = "sk-mavi-..."
  HEADERS = {
      "Authorization": f"{API_KEY}",
      "Content-Type": "application/json"
  }

  def start_video_stream(stream_url: str, fps: int = 2):
      url = f"{BASE_URL}/stream/start"
      data = {
          "url": stream_url,
          "enable_content_moderation": True,
          "enable_logo_detection": True,
          "fps": fps,
          "max_logos": 10
      }
      resp = requests.post(url, json=data, headers=HEADERS)
      return resp.json()

  # Usage example
  result = start_video_stream("rtmp://example.com/live/stream", fps=2)
  print(result)
  print(f"Task ID: {result['data']['task_id']}")
  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');

  const BASE_URL = 'https://mavi-backend.memories.ai/serve/api/v2';
  const API_KEY = 'sk-mavi-...';

  const headers = {
      'Authorization': API_KEY,
      'Content-Type': 'application/json'
  };

  async function startVideoStream(streamUrl, fps = 2) {
      const response = await axios.post(
          `${BASE_URL}/stream/start`,
          {
              url: streamUrl,
              enable_content_moderation: true,
              enable_logo_detection: true,
              fps: fps,
              max_logos: 10
          },
          { headers }
      );
      return response.data;
  }

  // Usage example
  startVideoStream('rtmp://example.com/live/stream', 2)
      .then(result => {
          console.log(result);
          console.log(`Task ID: ${result.data.task_id}`);
      });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://mavi-backend.memories.ai/serve/api/v2/stream/start" \
    -H "Authorization: sk-mavi-..." \
    -H "Content-Type: application/json" \
    -d '{
      "url": "rtmp://example.com/live/stream",
      "enable_content_moderation": true,
      "enable_logo_detection": true,
      "fps": 2,
      "max_logos": 10
    }'
  ```
</CodeGroup>

### Response

Returns the task information for the started video stream.

<ResponseExample>
  ```json Response theme={null}
  {
    "code": 200,
    "message": "success",
    "data": {
      "task_id": "550e8400-e29b-41d4-a716-446655440000",
      "message": "Stream processing started successfully"
    }
  }
  ```

  ```json Callback Response - Success theme={null}
  {
    "code": 200,
    "message": "SUCCESS",
    "data": {
      "status": 0,
      "message": "Segment processed successfully",
      "data": {
        "segment_index": 9,
        "start_time": "45",
        "end_time": "50",
        "video_url": "https://storage.googleapis.com/memories-cache/video-stream/f9c9b4caf3184ac4bcc46727d802e3d4/segment_0009.mp4",
        "content_moderation": {
          "has_unsafe_content": false,
          "frames_processed": 10
        },
        "logo_detection": {
          "has_logo": false,
          "logos": [],
          "frames_processed": 10
        },
        "processing_time_ms": "9594"
      },
      "token": {
        "input": 2946,
        "output": 25,
        "total": 2971,
        "video_tokens": 2946,
        "text_tokens": 25
      }
    },
    "task_id": "f9c9b4caf3184ac4bcc46727d802e3d4"
  }
  ```

  ```json Callback Response - Insufficient Balance theme={null}
  {
    "code": 200,
    "message": "SUCCESS",
    "data": {
      "status": 402,
      "message": "You don't have enough points.",
      "data": null,
      "token": null
    },
    "task_id": "f9c9b4caf3184ac4bcc46727d802e3d4"
  }
  ```

  ```json Callback Response - User Stopped theme={null}
  {
    "code": 200,
    "message": "SUCCESS",
    "data": {
      "status": 14,
      "message": "Stream stopped by user",
      "data": null,
      "token": null
    },
    "task_id": "f9c9b4caf3184ac4bcc46727d802e3d4"
  }
  ```

  ```json Callback Response - No Data theme={null}
  {
    "code": 200,
    "message": "SUCCESS",
    "data": {
      "status": 15,
      "message": "Stream ended: no video data received",
      "data": null,
      "token": null
    },
    "task_id": "f9c9b4caf3184ac4bcc46727d802e3d4"
  }
  ```

  ```json Callback Response - Capacity Reached theme={null}
  {
    "code": 200,
    "message": "SUCCESS",
    "data": {
      "status": 16,
      "message": "Server capacity reached. Please try again later.",
      "data": null,
      "token": null
    },
    "task_id": "f9c9b4caf3184ac4bcc46727d802e3d4"
  }
  ```
</ResponseExample>

### Request Parameters

| Parameter                   | Type    | Required | Default | Description                               |
| --------------------------- | ------- | -------- | ------- | ----------------------------------------- |
| url                         | string  | Yes      | -       | Video stream URL (supports RTMP/RTSP/HLS) |
| enable\_content\_moderation | boolean | No       | false   | Enable content moderation                 |
| enable\_logo\_detection     | boolean | No       | false   | Enable logo detection                     |
| fps                         | integer | No       | 1       | Frames per second to process              |
| max\_logos                  | integer | No       | 5       | Maximum number of logos to detect (1-50)  |

### Response Parameters

| Parameter     | Type   | Description                                      |
| ------------- | ------ | ------------------------------------------------ |
| code          | string | Response code (200 indicates success)            |
| message       | string | Response message describing the operation result |
| data          | object | Response data object containing task information |
| data.task\_id | string | Unique identifier of the stream processing task  |
| data.message  | string | Status message about the stream start            |

### Callback Response Parameters

Callbacks are sent to your configured webhook URL every time a 5-second segment is processed.

| Parameter                                          | Type    | Description                                          |
| -------------------------------------------------- | ------- | ---------------------------------------------------- |
| code                                               | string  | Response code (200 indicates success)                |
| message                                            | string  | Response message ("SUCCESS")                         |
| task\_id                                           | string  | The task ID associated with this stream              |
| data                                               | object  | Wrapper object containing processing results         |
| data.status                                        | integer | Status code (see Status Codes section below)         |
| data.message                                       | string  | Status message describing the result                 |
| data.data                                          | object  | Segment processing results (null for error statuses) |
| data.data.segment\_index                           | integer | Index of the processed segment (starts from 0)       |
| data.data.start\_time                              | string  | Segment start time in seconds                        |
| data.data.end\_time                                | string  | Segment end time in seconds                          |
| data.data.video\_url                               | string  | URL of the processed video segment                   |
| data.data.content\_moderation                      | object  | Content moderation results                           |
| data.data.content\_moderation.has\_unsafe\_content | boolean | Whether unsafe content was detected                  |
| data.data.content\_moderation.frames\_processed    | integer | Number of frames processed                           |
| data.data.logo\_detection                          | object  | Logo detection results                               |
| data.data.logo\_detection.has\_logo                | boolean | Whether logos were detected                          |
| data.data.logo\_detection.logos                    | array   | Array of detected logos (empty if none)              |
| data.data.logo\_detection.frames\_processed        | integer | Number of frames processed                           |
| data.data.processing\_time\_ms                     | string  | Processing time in milliseconds                      |
| data.token                                         | object  | Token usage statistics (null for error statuses)     |
| data.token.input                                   | integer | Number of input tokens used                          |
| data.token.output                                  | integer | Number of output tokens generated                    |
| data.token.total                                   | integer | Total tokens used                                    |
| data.token.video\_tokens                           | integer | Tokens from video processing                         |
| data.token.text\_tokens                            | integer | Tokens from text processing                          |

### Status Codes

| Status | Name                 | Description                      | Stream Stopped |
| ------ | -------------------- | -------------------------------- | -------------- |
| 0      | Success              | Segment processed successfully   | No             |
| -1     | Error                | Processing failed                | No             |
| 14     | User Stopped         | User manually stopped the stream | Yes            |
| 15     | No Data              | Stream has no video data         | Yes            |
| 16     | Capacity Reached     | Server capacity limit reached    | Yes            |
| 402    | Insufficient Balance | User balance insufficient        | Yes            |

### Callback Flow

```
User Request → Start Stream → Process Segment (every 5s) → Webhook Callback
                    ↓
            Pre-charge for first segment
                    ↓
            Charge per segment processed
```

### Important Notes

<Note>
  * **Webhook Configuration**: Configure your webhook URL in user settings before using this API
  * **No callback parameter needed**: The system uses a unified asynchronous callback mechanism
  * **Automatic segmentation**: Every 5 seconds triggers a callback
  * **Pre-charge mechanism**: Balance is checked and pre-charged at start
  * **Per-segment charging**: Each processed segment is charged immediately
  * **Auto-stop on insufficient balance**: Stream automatically stops if balance is insufficient (status 402)
  * **Concurrent stream limit**: Each user has a maximum concurrent stream limit
  * **Retry mechanism**: Failed callbacks are automatically retried
</Note>

### Rate Limiting

* **Maximum concurrent streams**: Each user can run N concurrent stream tasks (video + audio combined)
* **Capacity check**: Returns status 16 if server capacity is reached
* **Balance check**: Returns HTTP 402 if insufficient balance at start


## OpenAPI

````yaml visual-intelligence/stream/openapi.json POST /stream/start
openapi: 3.0.0
info:
  title: Stream Processing API
  version: 2.0.0
  description: Real-time video and audio stream processing APIs
servers:
  - url: https://mavi-backend.memories.ai/serve/api/v2
    description: Production server
security: []
paths:
  /stream/start:
    post:
      tags:
        - Video Stream
      summary: Start Video Stream Moderation
      description: >-
        Start real-time video stream processing for content moderation and logo
        detection
      operationId: startVideoStream
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - url
              properties:
                url:
                  type: string
                  description: Video stream URL (supports RTMP/RTSP)
                  example: rtmp://example.com/live/stream
                enable_content_moderation:
                  type: boolean
                  description: Enable content moderation
                  default: false
                enable_logo_detection:
                  type: boolean
                  description: Enable logo detection
                  default: false
                fps:
                  type: integer
                  description: Frames per second to process
                  minimum: 1
                  default: 1
                max_logos:
                  type: integer
                  description: Maximum number of logos to detect (1-50)
                  minimum: 1
                  maximum: 50
                  default: 5
      responses:
        '200':
          description: Stream started successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                    example: 200
                  message:
                    type: string
                    example: success
                  data:
                    type: object
                    properties:
                      task_id:
                        type: string
                        example: 550e8400-e29b-41d4-a716-446655440000
                      message:
                        type: string
                        example: Stream processing started successfully
        '400':
          description: Bad request
        '401':
          description: Unauthorized
        '402':
          description: Insufficient balance
      security:
        - ApiKeyAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization

````