> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/deployment/ko/self-hosted/enterprise/stream-management-api.md).

# Stream Management API

{% hint style="warning" %}
**독립형 서비스로는 중단되었습니다.** Inference SDK WebRTC 클라이언트를 다음과 함께 사용하세요 [Inference Server](/deployment/ko/self-hosted/inference-server.md) 현재 비디오 스트리밍 배포에 사용하세요. 동일한 클라이언트는 셀프 호스티드 및 Serverless 런타임에서 모델과 워크플로를 실행합니다. 자세한 내용은 [비디오 처리](https://docs.roboflow.com/workflows/deploy/video-processing).
{% endhint %}

{% hint style="warning" %}
**엔터프라이즈 기능입니다.** 이 페이지의 독립형 서비스를 프로덕션에서 사용하려면 Roboflow Enterprise 라이선스가 필요합니다. 참조: [Roboflow 라이선싱](https://roboflow.com/licensing) 자세한 내용은 참조하세요. 이는 위에서 설명한 통합 비디오 관리 API에는 적용되지 않습니다.
{% endhint %}

## 소개

Stream Management API는 온라인 비디오 스트림에서 Roboflow 객체 감지 모델의 예측을 생성했습니다. 원격으로 비디오 작업자를 제어할 수 있는 HTTP 관리 계층을 추가했습니다.

다음을 포함하되 이에 국한되지 않는 시나리오에 유용합니다:

* 여러 온라인 비디오 스트림에서 동시에 추론을 수행합니다.
* 조정이 필요한 여러 장치에서 추론을 실행합니다.
* 비디오 처리를 감독하기 위한 모니터링 계층을 구축합니다.

![Stream Management 설계](https://storage.googleapis.com/com-roboflow-marketing/inference/stream_management_api_design.jpg)

### 사용 예시

Joe는 공장에 설치된 IP 카메라 여러 대가 촬영한 영상을 모니터링하고자 합니다. Roboflow 플랫폼에서 객체 감지 모델을 학습한 후 배포할 준비가 되었습니다. 공장에 카메라가 네 대 있으므로, Joe는 Jetson 장치에서 초당 30회 이상의 추론을 처리할 수 있을 만큼 작은 모델을 선택합니다. 장치당 해당 연산 예산을 고려할 때, 그는 모든 카메라의 영상을 처리하기 위해 두 대의 Jetson 장치가 필요하며, 비디오 소스당 대략 초당 15프레임으로 처리합니다.

배포를 간소화하기 위해 Joe는 로컬 네트워크의 모든 Jetson 장치에 Stream Management 컨테이너를 배포합니다. 이를 통해 각 장치와 HTTP로 통신하여 처리 작업을 조율할 수 있습니다. 그는 각 비디오 스트림의 상태에 대한 메트릭을 보내고 가져오는 웹 앱을 만듭니다. 마지막으로, 그는 예측을 수신하는 UDP 서버를 구현하며, 다음을 `supervision` 영상에서 객체를 추적하기 위한 package.

## 실행 방법

### Docker에서 다음과 함께 `docker compose`

가장 일반적인 사용 사례는 Docker Compose 구성으로 패키징되어 있습니다. 카메라 장치를 전달하는 것처럼 컨테이너 내부에서 사용자 지정 구성이 필요한 경우에는 아래의 별도 컨테이너 옵션이 더 적합할 수 있습니다.

{% tabs %}
{% tab title="CPU" %}

```bash
docker compose -f ./docker/dockerfiles/stream-management-api.compose-cpu.yaml up
```

{% endtab %}

{% tab title="GPU" %}

```bash
docker compose -f ./docker/dockerfiles/stream-management-api.compose-gpu.yaml up
```

{% endtab %}

{% tab title="Jetson (JetPack 5.1.1)" %}

```bash
docker compose -f ./docker/dockerfiles/stream-management-api.compose-jetson.5.1.1.yaml up
```

Jetson 장치에서는 컨테이너 부트스트랩이나 모델 초기화와 같은 일부 작업이 다른 플랫폼보다 더 오래 걸립니다. Docker Compose 정의는 현재 Stream Manager TCP 소켓 포트가 열릴 때까지 기다리지 않으므로, HTTP API에 대한 초기 요청은 HTTP 503으로 응답될 수 있습니다.
{% endtab %}
{% endtabs %}

### Docker에서 API와 stream manager를 별도로 실행

{% tabs %}
{% tab title="CPU" %}

```bash
docker run -d --name stream_manager --network host roboflow/roboflow-inference-stream-manager-cpu:latest
docker run -d --name stream_management_api --network host roboflow/roboflow-inference-stream-management-api:latest
```

{% endtab %}

{% tab title="GPU" %}

```bash
docker run -d --name stream_manager --network host --runtime nvidia roboflow/roboflow-inference-stream-manager-gpu:latest
docker run -d --name stream_management_api --network host roboflow/roboflow-inference-stream-management-api:latest
```

{% endtab %}

{% tab title="Jetson (JetPack 5.1.1)" %}

```bash
docker run -d --name stream_manager --network host --runtime nvidia roboflow/roboflow-inference-stream-manager-jetson-5.1.1:latest
docker run -d --name stream_management_api --network host roboflow/roboflow-inference-stream-management-api:latest
```

{% endtab %}
{% endtabs %}

#### 구성 매개변수

**스트림 관리 API**

* `STREAM_MANAGER_HOST` - stream manager 컨테이너의 호스트 이름입니다. \`--network host\` `--network host` 을 사용하지 않거나 원격 머신을 대상으로 하는 경우에는 컨테이너 이름으로 변경하세요.
* `STREAM_MANAGER_PORT` - stream manager와 통신하는 데 사용되는 포트입니다. stream manager 컨테이너와 일치해야 합니다.

**Stream Manager**

* `PORT` - 서버가 실행되는 포트입니다.
* 컨테이너의 `/tmp/cache` 에 볼륨을 마운트하여 모델을 영구 저장하면 추론 파이프라인 초기화를 더 빠르게 할 수 있습니다.
* 카메라 연결은 이 컨테이너 수준에서 활성화해야 하므로, 장치를 Docker에 전달해야 한다면 여기에서 수행하세요.

#### 이미지 빌드하기(선택 사항)

```bash
# Stream Management API
docker build -t roboflow/roboflow-inference-stream-management-api:dev -f docker/dockerfiles/Dockerfile.stream_management_api .

# Stream Manager
docker build -t roboflow/roboflow-inference-stream-manager-{device}:dev -f docker/dockerfiles/Dockerfile.onnx.{device}.stream_manager .
```

### 베어메탈 배포

경우에 따라 애플리케이션을 호스트 수준에서 배포해야 할 수 있습니다. 이는 가능하지만, 플랫폼에 맞게 Stream Manager와 Stream Management API Dockerfile이 처리하는 방식으로 환경을 구성해야 합니다. 그렇게 한 다음 실행하세요:

```bash
python -m inference.enterprise.stream_management.manager.app  # manager를 실행합니다
python -m inference.enterprise.stream_management.api.app      # management API를 실행합니다
```

## 통합 방법

실행한 후 `roboflow-inference-stream-management-api` 컨테이너에서 HTTP API는 `http://127.0.0.1:8080` 기본 구성으로.

호출하세요 `wget http://127.0.0.1:8080/openapi.json` API의 OpenAPI 명세를 가져올 수 있으며, 이는 [Swagger 편집기](https://editor.swagger.io/).

Python 클라이언트 예시:

```python
import requests
from typing import Optional

URL = "http://127.0.0.1:8080"

def list_pipelines() -> dict:
    response = requests.get(f"{URL}/list_pipelines")
    return response.json()


def get_pipeline_status(pipeline_id: str) -> dict:
    response = requests.get(f"{URL}/status/{pipeline_id}")
    return response.json()


def pause_pipeline(pipeline_id: str) -> dict:
    response = requests.post(f"{URL}/pause/{pipeline_id}")
    return response.json()


def resume_pipeline(pipeline_id: str) -> dict:
    response = requests.post(f"{URL}/resume/{pipeline_id}")
    return response.json()


def terminate_pipeline(pipeline_id: str) -> dict:
    response = requests.post(f"{URL}/terminate/{pipeline_id}")
    return response.json()


def initialise_pipeline(
    video_reference: str,
    model_id: str,
    api_key: str,
    sink_host: str,
    sink_port: int,
    max_fps: Optional[int] = None,
) -> dict:
    response = requests.post(
        f"{URL}/initialise",
        json={
            "type": "init",
            "sink_configuration": {
                "type": "udp_sink",
                "host": sink_host,
                "port": sink_port,
            },
            "video_reference": video_reference,
            "model_id": model_id,
            "api_key": api_key,
            "max_fps": max_fps,
        },
    )
    return response.json()
```

{% hint style="info" %}
`initialise_pipeline()` 다음이 주어져야 합니다: `video_reference` 및 `sink_configuration` 모든 리소스(비디오 파일 또는 카메라 장치)와 URI(스트림 참조, 싱크 참조)가 **Stream Manager 환경에서 접근 가능해야 합니다**. 예를 들어, Docker 컨테이너 내부에서는 `localhost` 호스트 머신의 localhost가 아니라 컨테이너의 localhost에 바인딩됩니다.
{% endhint %}

## 개발자 노트

구현의 핵심 요소는 단일 스레드 TCP 서버로 동작하는 Stream Manager 구성 요소입니다. 이는 TCP 소켓에서 받은 요청을 처리하고 비디오 작업자 프로세스를 감독합니다. 멀티프로세싱 큐가 작업자와 Stream Manager 사이에서 명령과 결과를 전달합니다.

Stream Manager에 대한 요청은 차단 모드로 순차 처리되므로, 각 요청은 다음 요청이 시작되기 전에 완료되어야 합니다.

### 통신 프로토콜: 요청

Stream Manager는 다음 이진 프로토콜을 허용합니다. 각 페이로드에는 다음이 포함됩니다:

```
[HEADER: 4B, big-endian, unsigned - int value with message size][MESSAGE: utf-8 serialised json of size dictated by header]
```

디코딩 후 메시지는 유효한 JSON이어야 하며, 유효한 명령을 나타내야 합니다.

**`list_pipelines`**

```json
{
  "type": "list_pipelines"
}
```

**`init`**

```json
{
  "type": "init",
  "model_id": "some/1",
  "video_reference": "rtsp://192.168.0.1:554",
  "sink_configuration": {
    "type": "udp_sink",
    "host": "192.168.0.3",
    "port": 9999
  },
  "api_key": "YOUR_API_KEY",
  "max_fps": 16,
  "model_configuration": {
    "type": "object-detection",
    "class_agnostic_nms": true,
    "confidence": 0.5,
    "iou_threshold": 0.4,
    "max_candidates": 300,
    "max_detections": 3000
  },
  "video_source_properties": {
    "frame_width": 1920,
    "frame_height": 1080,
    "fps": 30
  }
}
```

{% hint style="info" %}
모델 ID는 다음 문자열로 구성됩니다 `<project_id>/<version_id>`. 전체 가이드는  [모델 ID](https://docs.roboflow.com/models/model-ids) 이러한 값을 찾으세요.
{% endhint %}

**`종료`**

```json
{
  "type": "terminate",
  "pipeline_id": "my_pipeline"
}
```

**`일시 중지`**

```json
{
  "type": "mute",
  "pipeline_id": "my_pipeline"
}
```

**`재개`**

```json
{
  "type": "resume",
  "pipeline_id": "my_pipeline"
}
```

**`상태`**

```json
{
  "type": "status",
  "pipeline_id": "my_pipeline"
}
```

### 통신 프로토콜: 응답

처리 가능한 각 요청(타임아웃이나 소스 연결 끊김 없이)에 대해 Stream Manager는 다음 형식으로 결과를 반환합니다:

```
[HEADER: 4B, big-endian, unsigned - int value with result size][RESULT: utf-8 serialised json of size dictated by header]
```

결과에는 다음이 포함됩니다:

* `request_id` - 디버깅을 쉽게 하기 위해 Stream Manager가 할당한 요청 ID를 나타내는 임의의 문자열입니다.
* `pipeline_id` - 해당되는 경우 명령이 연결된 파이프라인입니다.
* `response` - 작업 응답의 페이로드입니다.

각 `response` 하나의 `상태` 다음 두 값 중 하나를 가진 키가 있습니다: `성공` 또는 `실패`. 실패한 각 응답에는 `error_type` 키가 있어 오류 처리를 분기하며, 추가로 선택적 `error_class` 및 `error_message` 필드에 오류의 내부 세부 정보가 포함됩니다. 성공한 응답의 내용은 작업 유형에 따라 다릅니다.

## 향후 작업

* 안전한 원격 제어를 가능하게 하기 위해 API 연결 계층을 보호합니다.
* Stream Manager의 TCP 소켓을 보호합니다.
