> 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/reference/hi/inference/inference-sdk/webrtc.md).

# WebRTC Streaming

का उपयोग करें `inference-sdk` मॉडल या वर्कफ़्लो के माध्यम से वीडियो स्ट्रीम करने के लिए WebRTC क्लाइंट। वीडियो फ़्रेम एक कनेक्शन के जरिए Inference Server तक जाते हैं, और प्रोसेस किए गए फ़्रेम तथा प्रेडिक्शन डेटा लगातार वापस प्रवाहित होते हैं।

वही क्लाइंट self-hosted Inference Server और Serverless Video Streaming API दोनों के साथ काम करता है। सेट करें `api_url` को उस runtime पर जिसे आप चाहते हैं:

* Self-hosted: `http://localhost:9001`
* Serverless: `https://serverless.roboflow.com`

WebRTC स्ट्रीमिंग के लिए अतिरिक्त dependencies की आवश्यकता होती है:

```bash
pip install "inference-sdk[webrtc]"
```

## मॉडल स्ट्रीम करें

पास करें एक `model_id` एक मॉडल के माध्यम से वीडियो स्ट्रीम करने के लिए। SDK आवश्यक single-model Workflow बनाता है, और आपका `on_frame` हैंडलर प्रत्येक वीडियो फ़्रेम को उसकी prediction data के साथ प्राप्त करता है:

```python
import cv2
import supervision as sv
from inference_sdk import InferenceHTTPClient, InferenceConfiguration
from inference_sdk.webrtc import WebcamSource

# ROBOFLOW_API_KEY को अपने Roboflow API Key से बदलें
client = InferenceHTTPClient(
    api_url="http://localhost:9001",
    api_key="ROBOFLOW_API_KEY",
).configure(InferenceConfiguration(api_key_transport="header"))

session = client.webrtc.stream(
    source=WebcamSource(),
    model_id="rfdetr-nano",
)

box_annotator = sv.BoxAnnotator()

@session.on_frame
def show(frame, data):
    # data कच्चा predictions dict है, बिल्कुल वैसे ही जैसा सर्वर द्वारा लौटाया गया है
    # (जब इस फ़्रेम के लिए predictions उपलब्ध न हों तब None)
    if data is None:
        return
    detections = sv.Detections.from_inference(data)
    annotated = box_annotator.annotate(frame.copy(), detections)
    cv2.imshow("Preview", annotated)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        session.close()

session.run()  # स्ट्रीम समाप्त होने तक या session.close() कॉल होने तक ब्लॉक करता है
```

`model_id` एक generic Workflow model block के साथ किसी भी task type के लिए काम करता है। मॉडल का task type Roboflow API lookup के माध्यम से स्वतः हल किया जाता है, और मिलान करने वाला model block आपके लिए चुना जाता है। समर्थित task types:

* `object-detection`
* `instance-segmentation`
* `semantic-segmentation`
* `classification`
* `multi-label-classification`
* `keypoint-detection`

`data` serialized predictions dict को ज्यों का त्यों पास किया जाता है - इसका आकार task type के अनुसार होता है। detection-family models के लिए यह inference-response के समान होता है, इसलिए आप इसे matching [`supervision`](https://supervision.roboflow.com/) helper - `sv.Detections.from_inference(data)` object detection और instance segmentation के लिए, `sv.KeyPoints.from_inference(data)` keypoint models के लिए। Classification predictions में `top`/`confidence` keys होते हैं, और semantic-segmentation predictions में run-length-encoded masks (`rle_mask`) होते हैं, जिन्हें आपको स्वयं decode करना होता है।

जब किसी फ़्रेम के लिए predictions उपलब्ध न हों (उदाहरण के लिए, live stream फ़्रेम के लिए paired prediction message कभी नहीं आया), `data` है `None` - उपयोग से पहले अपने handler में इसकी जाँच करें।

VLMs `model_id` mode में समर्थित नहीं हैं (हर VLM family का अपना dedicated Workflow block होता है, इसलिए उन्हें wrap करने के लिए कोई generic block नहीं है) - इसके बजाय उन्हें एक पूर्ण [`वर्कफ़्लो`](#streaming-a-workflow) के साथ स्ट्रीम करें।

**task-type lookup छोड़ना:** पास करें `task_type` स्पष्ट रूप से ताकि network call से बचा जा सके - air-gapped या self-hosted deployments के लिए उपयोगी:

```python
session = client.webrtc.stream(
    source=WebcamSource(),
    model_id="my-project/3",
    task_type="object-detection",
)
```

में `model_id` mode, `on_frame` handlers इनमें से कोई भी ले सकते हैं `(frame, data)` या `(frame, data, metadata)` - तीसरा तर्क [`VideoMetadata`](#frame-metadata) है, जो फ़्रेम के लिए है।

## एक Workflow स्ट्रीम करें

multi-step pipelines के लिए, एक `वर्कफ़्लो` के बजाय एक `model_id`पास करें। अपने Roboflow workspace में सहेजे गए Workflow को ID द्वारा संदर्भित करें, या एक पूर्ण specification dict प्रदान करें:

{% tabs %}
{% tab title="Workflow ID" %}

```python
import cv2
from inference_sdk import InferenceHTTPClient
from inference_sdk.webrtc import WebcamSource, StreamConfig

client = InferenceHTTPClient(
    api_url="http://localhost:9001",
    api_key="ROBOFLOW_API_KEY",
)

session = client.webrtc.stream(
    source=WebcamSource(),
    workflow="my-workflow-id",
    workspace="my-workspace-name",
    config=StreamConfig(
        stream_output=["output_image"],   # workflow output वीडियो के रूप में वापस स्ट्रीम होता है
        data_output=["predictions"],      # workflow outputs data channel के माध्यम से दिए जाते हैं
    ),
)

@session.on_frame
def show(frame, metadata):
    cv2.imshow("Preview", frame)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        session.close()

@session.on_data("predictions")
def handle_predictions(predictions, metadata):
    print(f"Frame {metadata.frame_id}: {predictions}")

session.run()
```

{% endtab %}

{% tab title="Workflow specification" %}

```python
import cv2
from inference_sdk import InferenceHTTPClient
from inference_sdk.webrtc import WebcamSource, StreamConfig

client = InferenceHTTPClient(
    api_url="http://localhost:9001",
    api_key="ROBOFLOW_API_KEY",
)

workflow_spec = {
    "version": "1.0",
    "inputs": [{"type": "InferenceImage", "name": "image"}],
    "steps": [
        {
            "type": "roboflow_core/roboflow_object_detection_model@v2",
            "name": "model",
            "images": "$inputs.image",
            "model_id": "rfdetr-nano",
        }
    ],
    "outputs": [
        {
            "type": "JsonField",
            "name": "predictions",
            "selector": "$steps.model.predictions",
        },
        {"type": "JsonField", "name": "image", "selector": "$inputs.image"},
    ],
}

session = client.webrtc.stream(
    source=WebcamSource(),
    workflow=workflow_spec,
    config=StreamConfig(
        stream_output=["image"],
        data_output=["predictions"],
    ),
)

@session.on_frame
def show(frame, metadata):
    cv2.imshow("Preview", frame)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        session.close()

session.run()
```

{% endtab %}
{% endtabs %}

नोट्स:

* `वर्कफ़्लो` और `model_id` परस्पर अनन्य हैं - केवल एक ही पास करें।
* `workspace` तब आवश्यक है जब `वर्कफ़्लो` एक ID string हो; specification dict के लिए इसकी आवश्यकता नहीं है।
* `image_input` (default `"image"`) उस Workflow image input का नाम देता है जिससे वीडियो फ़्रेम जुड़े होते हैं।
* workflow mode में, `on_frame` handlers प्राप्त करते हैं `(frame, metadata)` - prediction data अलग से [`on_data`](#receiving-data-on_data) handlers के माध्यम से आती है, जिसे `data_output` names द्वारा `StreamConfig`.

## वीडियो स्रोत

का पहला तर्क `stream()` यह चुनता है कि वीडियो कहाँ से आएगा:

```python
from inference_sdk.webrtc import (
    WebcamSource,
    RTSPSource,
    LocalStreamSource,
    MJPEGSource,
    VideoFileSource,
    ManualSource,
)
```

### WebcamSource

स्थानीय कैमरा डिवाइस से फ़्रेम कैप्चर करता है और उन्हें सर्वर को भेजता है:

```python
source = WebcamSource()                                    # default camera
source = WebcamSource(device_id=1, resolution=(1920, 1080))
```

कैमरे का FPS स्वतः पता लगाया जाता है और सर्वर को रिपोर्ट किया जाता है।

### RTSPSource

The **server** RTSP कैमरा से कनेक्ट करता है और प्रोसेस किया गया वीडियो आपको वापस स्ट्रीम करता है - इसका उपयोग तब करें जब कैमरा सर्वर से पहुंच योग्य हो:

```python
source = RTSPSource("rtsp://user:pass@camera.local/stream")
```

### LocalStreamSource

एक RTSP/RTMP स्ट्रीम को **स्थानीय रूप से** (क्लाइंट मशीन पर) कैप्चर करता है और फ़्रेम सर्वर को भेजता है - इसका उपयोग तब करें जब कैमरा केवल आपकी मशीन से पहुंच योग्य हो, सर्वर से नहीं:

```python
source = LocalStreamSource("rtsp://192.168.1.10/stream")   # साथ ही rtsps://, rtmp://, rtmps://
```

### MJPEGSource

जैसे `RTSPSource`लेकिन सर्वर द्वारा कैप्चर की गई MJPEG streams के लिए:

```python
source = MJPEGSource("http://camera.local/mjpeg")
```

### VideoFileSource

एक वीडियो फ़ाइल को data channel के माध्यम से सर्वर पर अपलोड करता है; सर्वर इसे प्रोसेस करता है और परिणाम वापस स्ट्रीम करता है। पहले से रिकॉर्ड किए गए वीडियो के लिए frame-by-frame streaming से अधिक कुशल:

```python
source = VideoFileSource("video.mp4")

# अपलोड प्रगति को ट्रैक करें और मूल FPS पर प्रोसेस करें (live-preview pacing)
source = VideoFileSource(
    "video.mp4",
    on_upload_progress=lambda uploaded, total: print(f"{uploaded}/{total} chunks"),
    realtime_processing=True,   # default False = जितनी जल्दी हो सके प्रोसेस करें
)
```

डिफ़ॉल्ट रूप से फ़्रेम data channel के माध्यम से वापस आते हैं (क्रम और गुणवत्ता की गारंटी के साथ)। पास करें `use_datachannel_frames=False` उन्हें इसके बजाय hardware-accelerated WebRTC video track के माध्यम से प्राप्त करने के लिए (कम bandwidth)।

### ManualSource

फ़्रेम प्रोग्रामmatically भेजें - उपयोगी जब फ़्रेम किसी custom pipeline से आते हों:

```python
import threading
import time

import cv2
from inference_sdk.webrtc import ManualSource, StreamConfig

source = ManualSource()
session = client.webrtc.stream(
    source=source,
    model_id="rfdetr-nano",
    config=StreamConfig(declared_fps=30),
)

@session.on_frame
def handle(frame, data):
    print(data)

# run() कनेक्शन स्थापित करता है और handlers को dispatch करता है; इसे
# background thread में शुरू करें ताकि यह thread फ़्रेम भेज सके।
threading.Thread(target=session.run, daemon=True).start()

cap = cv2.VideoCapture("video.mp4")
while True:
    ret, frame = cap.read()
    if not ret:
        break
    try:
        source.send(frame)   # BGR numpy array
    except RuntimeError:
        pass                 # session अभी भी connect हो रहा है - फ़्रेम छोड़ दिया गया
    time.sleep(1 / 30)       # भेजने की गति declared FPS के अनुसार रखें

session.close()
```

`send()` उठाता है `RuntimeError` जब तक कनेक्शन स्थापित नहीं हो जाता, और यदि आप stream के उपभोग की गति से तेज़ भेजते हैं तो queued frames oldest-first क्रम में हटा दिए जाते हैं। `ManualSource` में FPS auto-detection नहीं है, इसलिए frame rate को `StreamConfig(declared_fps=...)`.

## परिभाषित करें

### session lifecycle

`stream()` एक `WebRTCSession`लौटाता है। कनेक्शन पहले उपयोग पर lazily शुरू होता है (`run()`, `video()`या `wait()`) और resources मुक्त करने के लिए बंद किया जाना चाहिए। तीन समान पैटर्न:

```python
# 1. run() - बाहर निकलने पर auto-close होता है (handlers के साथ अनुशंसित)
session.run()

# 2. Context manager - exit पर auto-close होता है (video() iterator के साथ अनुशंसित)
with client.webrtc.stream(source=source, model_id="rfdetr-nano") as session:
    for frame, data in session.video():
        ...

# 3. Manual - आपको स्वयं close() कॉल करनी होगी
session = client.webrtc.stream(source=source, model_id="rfdetr-nano")
for frame, data in session.video():
    ...
session.close()
```

`session.close()` idempotent है और किसी handler के अंदर से कॉल करना सुरक्षित है - यह समाप्त करता है `run()` और `video()` iterator को। `session.wait(timeout=None)` फ़्रेम स्वयं consume किए बिना stream समाप्त होने तक ब्लॉक करता है।

### फ़्रेम प्राप्त करना: `on_frame` और `video()`

`@session.on_frame` को उपयोग करते समय हर प्रोसेस किए गए वीडियो फ़्रेम के लिए invok होने वाला handler पंजीकृत करता है `run()`. `session.video()` iterator समकक्ष है - वही data, pull-based:

```python
# model_id mode: (frame, data) - data कच्चा predictions dict है
# (जब फ़्रेम के लिए predictions उपलब्ध न हों तब None)
for frame, data in session.video():
    ...

# workflow mode: (frame, metadata)
for frame, metadata in session.video():
    ...
```

फ़्रेम BGR numpy arrays होते हैं। यदि आपका handler realtime mode में पीछे रह जाता है, तो सबसे पुराने फ़्रेम हटा दिए जाते हैं ताकि stream live बनी रहे।

### डेटा प्राप्त करना: `on_data`

में सूचीबद्ध Workflow outputs `StreamConfig.data_output` data channel के माध्यम से आते हैं। प्रति output name handler पंजीकृत करें, या पूरे payload के लिए एक global handler:

```python
@session.on_data("predictions")           # एक single output field
def handle_predictions(predictions, metadata):
    print(f"Frame {metadata.frame_id}: {predictions}")

@session.on_data                          # global: full output dict
def handle_all(data, metadata):
    print(data)
```

Handlers इनमें से स्वीकार कर सकते हैं `(value, metadata)` या केवल `(value)` - signature स्वतः पहचानी जाती है।

### त्रुटियों को संभालना: `on_error`

सर्वर प्रत्येक data channel message के साथ प्रति-फ़्रेम त्रुटियाँ (workflow execution failures, output serialization failures) रिपोर्ट करता है। `on_error` handlers केवल उन फ़्रेमों के लिए चलते हैं जिनमें non-empty error list हो:

```python
@session.on_error
def on_err(errors, metadata):
    print(f"Frame {metadata.frame_id} failed: {errors}")
    session.close()   # उदाहरण: पहली त्रुटि पर बाहर निकलें
```

ये server-side per-frame failures हैं; connection और setup errors `run()` से exceptions के रूप में सामने आते हैं। त्रुटियाँ `metadata.errors` से भी हर फ़्रेम पर जुड़ी होती हैं, इसलिए `on_frame` / `on_data` handlers उनकी सीधे जाँच कर सकते हैं।

### फ़्रेम metadata

`VideoMetadata` प्रत्येक फ़्रेम और data message के साथ आती है:

| विशेषता                         | विवरण                                                                                            |
| ------------------------------- | ------------------------------------------------------------------------------------------------ |
| `frame_id`                      | स्ट्रीम में फ़्रेम का अद्वितीय पहचानकर्ता                                                        |
| `received_at`                   | जब सर्वर ने फ़्रेम प्राप्त किया                                                                  |
| `pts` / `time_base`             | वीडियो स्ट्रीम का प्रस्तुति टाइमस्टैम्प                                                          |
| `declared_fps` / `measured_fps` | घोषित बनाम मापा गया stream FPS                                                                   |
| `errors`                        | सर्वर द्वारा रिपोर्ट की गई प्रति-फ़्रेम त्रुटियाँ (जब फ़्रेम बिना समस्या प्रोसेस हो जाए तो खाली) |

## StreamConfig

`StreamConfig` output routing, processing behavior, और network settings को नियंत्रित करता है:

```python
from inference_sdk.webrtc import StreamConfig

config = StreamConfig(
    stream_output=["output_image"],
    data_output=["predictions"],
    realtime_processing=True,
)
session = client.webrtc.stream(source=source, workflow="...", workspace="...", config=config)
```

| फ़ील्ड                | डिफ़ॉल्ट | विवरण                                                                                                  |
| --------------------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `stream_output`       | `[]`     | Workflow output names जिन्हें वीडियो के रूप में वापस स्ट्रीम किया जाता है                              |
| `data_output`         | `[]`     | Workflow output names जिन्हें data channel के माध्यम से दिया जाता है                                   |
| `realtime_processing` | `True`   | real time में साथ बने रहने के लिए फ़्रेम छोड़ें; सेट करें `False` ताकि हर फ़्रेम queue होकर प्रोसेस हो |
| `declared_fps`        | `None`   | auto-detection के बिना स्रोतों के लिए FPS घोषणा (उदा. `ManualSource`)                                  |
| `turn_server`         | `None`   | TURN server config: `{"urls": "turn:...", "username": "...", "credential": "..."}`                     |
| `workflow_parameters` | `{}`     | वर्कफ़्लो निष्पादन को दिए गए पैरामीटर                                                                  |
| `requested_plan`      | `None`   | Roboflow सर्वरलेस एंडपॉइंट्स के लिए कंप्यूट प्लान (उदा. `"webrtc-gpu-small"`)                          |
| `requested_region`    | `None`   | सर्वरलेस एंडपॉइंट्स के लिए प्रोसेसिंग क्षेत्र (उदा. `"us"`, `"eu"`)                                    |
| `processing_timeout`  | `None`   | सर्वर-साइड सत्र समय-सीमा सेकंड में (सर्वरलेस एंडपॉइंट्स)                                               |

में `model_id` मोड, खाली `stream_output` / `data_output` स्वतः भरे जाते हैं (`["image"]` और `["predictions"]`); आपके द्वारा प्रदान की गई कोई भी अन्य सेटिंग्स सुरक्षित रहती हैं।

**TURN सर्वर:** Roboflow-होस्टेड एंडपॉइंट्स से कनेक्ट करते समय, TURN कॉन्फ़िगरेशन अपने आप प्राप्त हो जाता है। प्रतिबंधित NATs या फ़ायरवॉल के पीछे स्थित self-hosted सर्वरों के लिए, प्रदान करें `turn_server` स्पष्ट रूप से; जब यह सेट नहीं होता, तब सीधे कनेक्शन का प्रयास किया जाता है।

## चलाने योग्य उदाहरण

पूर्ण कार्यशील स्क्रिप्टें यहाँ उपलब्ध हैं: [`examples/webrtc_sdk/`](https://github.com/roboflow/inference/tree/main/examples/webrtc_sdk) Inference रिपॉज़िटरी की निर्देशिका में:

* [`webcam_basic.py`](https://github.com/roboflow/inference/blob/main/examples/webrtc_sdk/webcam_basic.py) - बुनियादी वेबकैम स्ट्रीमिंग
* [`rtsp_basic.py`](https://github.com/roboflow/inference/blob/main/examples/webrtc_sdk/rtsp_basic.py) - RTSP स्ट्रीम प्रोसेसिंग
* [`mjpeg_basic.py`](https://github.com/roboflow/inference/blob/main/examples/webrtc_sdk/mjpeg_basic.py) - MJPEG स्ट्रीम प्रोसेसिंग
* [`video_file_basic.py`](https://github.com/roboflow/inference/blob/main/examples/webrtc_sdk/video_file_basic.py) - आउटपुट सहेजने के साथ वीडियो फ़ाइल प्रोसेसिंग

आप Roboflow Serverless Hosted API (`https://serverless.roboflow.com`) के साथ बिना किसी सेटअप के, या विकास के लिए एक स्थानीय सर्वर के साथ स्ट्रीम कर सकते हैं:

```bash
# CPU
docker run -p 9001:9001 roboflow/roboflow-inference-server-cpu:latest

# GPU
docker run --gpus all -p 9001:9001 roboflow/roboflow-inference-server-gpu:latest
```
