# media_inspect

Inspect streamed audio/video, measure silence and RMS levels, or extract requested JPEG images.

## What it does

Receives media as BEGIN/WRITE/END streams and processes it when the input object closes. Temporary files are private to that object and are released after processing, failure or cancellation cleanup. The node never calls account storage, fetches URLs, or keeps a persistent source cache. Connect downstream nodes to persist results.

## Lanes

| Lane in | Lane out | Description |
| --- | --- | --- |
| `video` | `text` | JSON measurement/report (plus image-name markers for stills) |
| `video` | `answers` | Structured result manifest |
| `video` | `image` | Named JPEG streams |
| `audio` | `text` | JSON measurement/report (plus image-name markers for stills) |
| `audio` | `answers` | Structured result manifest |
| `audio` | `image` | Named JPEG streams |

## Configuration

Set overrides in the selected profile block. `chunk_kb` controls output chunk size (clamped to 64–8192 KB); input bytes are spooled incrementally to temporary disk. `event_type` names progress events; progress is not written to a file.

### Request

`request` is a JSON object encoded as a string. `mode` selects the operation. `input_name` optionally selects the incoming media descriptor name. The defaults are `probe`. A source must arrive on a media lane: a storage path alone is not input. Top-level `write_to`, `probe_to`, `status_to` and `report_to` are rejected.

- `probe`: duration, display/coded dimensions, pixel aspect, codecs, frame rate, audio channels and sample rate.
- `levels`: `range` is `start_ms-end_ms`; `ranges` measures selected RMS windows; `scan: "no"` skips whole-range scans; `scan_scenes: "no"` skips transition scanning. `silence_db`, `silence_ms` and `peak_ms` configure measurements; `scene_threshold` overrides the transition score.
- `stills`: `stills` is an array of `{id, t_ms, crop, width}`; crop is `[x,y,width,height]` in display pixels. `quality` sets JPEG quantization (clamped to 2–31; missing or zero uses the default). JPEGs always stream on `image`; connect an image sink. Invalid entries are returned in `failed`; other entries continue.

Example: `{"mode":"stills","stills":[{"id":"poster","t_ms":1000,"width":320}]}`.

## Notes

### Stream lifecycle and limits

`ROCKETRIDE_MEDIA_FFMPEG_TIMEOUT` bounds each FFmpeg encode (default 3600 seconds, configurable from above 0 to 86400). Metadata subprocesses have a maximum 60-second timeout. Invalid timeout values fail explicitly.

Each descriptor should declare `size` and a unique `name`. `max_input_mb` limits cumulative incoming bytes across all streams in an object (default 16384 MiB / 16 GiB, clamped to 1–1048576 MiB). It is enforced before writing each chunk, including when `size` is absent; declared sizes above the remaining budget fail at BEGIN. This ingress limit does not bound decoded/intermediate output size. Empty, truncated, oversized-relative-to-declaration and duplicate inputs fail. At most 128 streams are accepted per object. This processor accepts exactly one media stream per object. Media ingress uses bounded stream chunks. Decoders, analysis and speech models have additional memory requirements; temporary disk usage scales with input and intermediate outputs. Abrupt process termination may leave scratch files for host cleanup.

No browser download/re-upload relay is required by the node contract. The stock `filestore_source` currently rejects saved files above 100 MiB; direct webhook uploads avoid that source limit. These nodes do not change the stock source or sink. Durable progress, recovery and output naming belong to pipeline/application orchestration.

### Verification

Tests are in `nodes/test/media_inspect`: stream lifecycle, isolation, path validation, real FFmpeg operations and live engine integration. The shipped `example.pipe` uses webhook → parse → this node → response and stock file-store sinks; configure each sink destination before running. Its default `probe` request returns metadata; the image sink is used when the request is changed to `stills`. This node does not load a speech model.

<!-- ROCKETRIDE:GENERATED:PARAMS START -->
<!-- Generated by nodes:docs-generate. Do not edit by hand. -->

## Schema

| Field | Type | Description | Default |
|---|---|---|---|
| `media_inspect.chunk_kb` | `number` | **Stream chunk size (KB)** | `1024` |
| `media_inspect.event_type` | `string` | **Name of the progress event this pipeline emits** | `"media_inspect"` |
| `media_inspect.max_input_mb` | `number` | **Maximum cumulative input per object (MiB)**<br/>Total incoming media bytes, including all assets. Clamped to 1–1048576 MiB; enforced even when stream size is undeclared. | `16384` |
| `media_inspect.peak_ms` | `number` | **Length of one loudness bucket (ms)** | `100` |
| `media_inspect.profile` | `string` | **Profile** | `"default"` |
| `media_inspect.request` | `string` | **Operation request (JSON)**<br/>JSON request: probe, levels (range, ranges, scan, scan_scenes) or stills (stills array). Sources arrive as media streams. | `"{}"` |
| `media_inspect.scene_threshold` | `number` | **Scene score a shot change has to cross** | `0.35` |
| `media_inspect.silence_db` | `number` | **Silence threshold (dB)** | `-40` |
| `media_inspect.silence_ms` | `number` | **Shortest silence worth reporting (ms)** | `700` |

## Dependencies

- `av` `>=18,<19`
- `imageio-ffmpeg` `>=0.6,<0.7`
- `numpy` `>=2,<3`

## Source

[<svg viewBox="0 0 16 16" width="15" height="15" fill="currentColor" aria-hidden="true" style="vertical-align:-0.15em;margin-right:0.35em"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg> View source](https://github.com/rocketride-org/rocketride-server/tree/develop/nodes/src/nodes/media_inspect)
<!-- ROCKETRIDE:GENERATED:PARAMS END -->
