# FFmpeg Stream

OmniScope supports **real-time monitoring of video delivered via FFmpeg** over UDP or named pipe, using the NUT container format.

The **FFmpeg Stream** source (previously two separate sources — *UDP/NUT* and *Pipe/NUT*) is a unified input that auto-detects the connection type from the URL you provide:

| URL format             | Behavior                                                   |
| ---------------------- | ---------------------------------------------------------- |
| `udp://…`              | UDP socket; NUT container forced (FFmpeg cannot probe UDP) |
| `\\.\pipe\…` (Windows) | Named pipe via NUT bridge                                  |
| Other paths / URLs     | Auto-detect container format                               |

{% hint style="info" %}
**SRT Stream** remains a separate, dedicated source type optimised for low-latency secure streaming. Use FFmpeg Stream for UDP and pipe-based workflows.
{% endhint %}

## Connecting via UDP

1. Open OmniScope and go to **Input > Connect to…**
2. Select **FFmpeg Stream**
3. Enter a `udp://` URL, for example:

   ```
   udp://0.0.0.0:5000
   ```
4. Click **Connect**

When a UDP URL is detected, advanced UDP options are shown (packet size, FIFO size, etc.).

## Connecting via Named Pipe (Windows)

Named-pipe transport requires a small Python relay script — the **NUT bridge** — that sits between your FFmpeg sender and OmniScope.

### Prerequisites

* Python 3.x with `pywin32`: `pip install pywin32`
* FFmpeg in PATH

### Step 1 — Start the NUT bridge

```bash
python nut_bridge.py
```

The bridge creates two pipes and waits for connections:

* `\\.\pipe\ffmpeg_in` — FFmpeg writes here
* `\\.\pipe\ffmpeg_out` — OmniScope reads here

### Step 2 — Send video to the bridge

```bash
# Remux without re-encoding (fastest, preserves quality):
ffmpeg -i input.mov -c copy -f nut \\.\pipe\ffmpeg_in

# From a capture device:
ffmpeg -f dshow -i video="My Webcam" -c:v libx264 -f nut \\.\pipe\ffmpeg_in

# From an RTMP stream:
ffmpeg -i rtmp://server/live/stream -c copy -f nut \\.\pipe\ffmpeg_in
```

### Step 3 — Connect OmniScope

1. Go to **Input > Connect to…** and select **FFmpeg Stream**
2. Enter the pipe path: `\\.\pipe\ffmpeg_out` (pre-filled by default)
3. Click **Connect**

### Hot-connect

The NUT bridge supports connecting and reconnecting at any time:

* OmniScope can join **after** the sender is already streaming — the bridge replays the NUT header to synchronise
* The sender can restart without disconnecting OmniScope
* OmniScope can disconnect and reconnect; the bridge handles this gracefully

To stop: terminate the Python script (Ctrl+C) — the pipes are removed automatically.

## Why NUT container?

NUT is ideal for pipe and UDP transport because:

* **Low overhead** — minimal container framing
* **Simple header** — can be captured and replayed for mid-stream joins
* **Codec-agnostic** — supports any codec FFmpeg knows
* **No index required** — unlike MP4/MKV, no seek table needed
* **Byte-stream friendly** — designed for streaming scenarios where seeking is not possible

## Migrating from UDP/NUT or Pipe/NUT

If you previously used the separate **UDP/NUT** or **Pipe/NUT** source types, your saved configurations are automatically migrated to **FFmpeg Stream** on first load. No manual changes are needed.

## Related

* [SRT Stream](https://docs.timeinpixels.com/nobe-omniscope/sources/srt-stream) — Low-latency secure streaming
* [NDI®](https://docs.timeinpixels.com/nobe-omniscope/sources/ndi-r) — Network Device Interface source
* [Multiple Input Sources](https://docs.timeinpixels.com/nobe-omniscope/sources/multiple-input-sources) — Use several sources simultaneously
