{ "openapi": "3.1.0", "info": { "title": "Strom API", "description": "REST and WebSocket API for the Strom pipeline engine", "contact": { "name": "Per Enstedt", "email": "per.enstedt@eyevinn.se" }, "license": { "name": "MIT OR Apache-2.0" }, "version": "0.6.7" }, "paths": { "/api/auth/status": { "get": { "tags": [ "auth" ], "summary": "Get authentication status", "operationId": "auth_status_handler", "responses": { "200": { "description": "Current authentication status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthStatusResponse" } } } } } } }, "/api/blocks": { "get": { "tags": [ "blocks" ], "summary": "List all block definitions (built-in + user-defined).", "operationId": "list_blocks", "responses": { "200": { "description": "List all blocks", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockListResponse" } } } } } }, "post": { "tags": [ "blocks" ], "summary": "Create a new user-defined block.", "operationId": "create_block", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateBlockRequest" } } }, "required": true }, "responses": { "201": { "description": "Block created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/blocks/categories": { "get": { "tags": [ "blocks" ], "summary": "Get all block categories.", "operationId": "get_categories", "responses": { "200": { "description": "List of block categories", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockCategoriesResponse" } } } } } } }, "/api/blocks/{id}": { "get": { "tags": [ "blocks" ], "summary": "Get a specific block definition by ID.", "operationId": "get_block", "parameters": [ { "name": "id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Block found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockResponse" } } } }, "404": { "description": "Block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "put": { "tags": [ "blocks" ], "summary": "Update an existing user-defined block.", "operationId": "update_block", "parameters": [ { "name": "id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockDefinition" } } }, "required": true }, "responses": { "200": { "description": "Block updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "delete": { "tags": [ "blocks" ], "summary": "Delete a user-defined block.", "operationId": "delete_block", "parameters": [ { "name": "id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Block deleted" }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/client-log": { "post": { "tags": [ "whip" ], "summary": "Receive client-side log messages from any browser page (WHIP, WHEP, clocks, …).", "description": "Accepts a JSON array of log entries and writes them to the server log\nprefixed with `[CLIENT]` so they can be correlated with server-side events.", "operationId": "client_log", "responses": { "204": { "description": "Log entries accepted" } } } }, "/api/discovery/announced": { "get": { "tags": [ "discovery" ], "summary": "List streams being announced by this Strom instance.", "operationId": "list_announced", "responses": { "200": { "description": "List of announced streams", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/AnnouncedStreamResponse" } } } } } } } }, "/api/discovery/devices": { "get": { "tags": [ "discovery" ], "summary": "List all discovered devices.", "operationId": "list_devices", "parameters": [ { "name": "category", "in": "query", "description": "Filter by category", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of discovered devices", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/DeviceResponse" } } } } } } } }, "/api/discovery/devices/refresh": { "post": { "tags": [ "discovery" ], "summary": "Refresh discovered devices (trigger re-scan).", "operationId": "refresh_devices", "responses": { "200": { "description": "Devices refreshed" } } } }, "/api/discovery/devices/status": { "get": { "tags": [ "discovery" ], "summary": "Get device discovery status.", "operationId": "device_status", "responses": { "200": { "description": "Device discovery status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceDiscoveryStatus" } } } } } } }, "/api/discovery/devices/{id}": { "get": { "tags": [ "discovery" ], "summary": "Get a specific device by ID.", "operationId": "get_device", "parameters": [ { "name": "id", "in": "path", "description": "Device ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Device details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceResponse" } } } }, "404": { "description": "Device not found" } } } }, "/api/discovery/ndi/refresh": { "post": { "tags": [ "discovery" ], "summary": "Refresh NDI sources (trigger re-scan).", "operationId": "refresh_ndi_sources", "responses": { "200": { "description": "NDI sources refreshed" } } } }, "/api/discovery/ndi/sources": { "get": { "tags": [ "discovery" ], "summary": "List all discovered NDI sources.", "operationId": "list_ndi_sources", "responses": { "200": { "description": "List of discovered NDI sources", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/DeviceResponse" } } } } } } } }, "/api/discovery/ndi/status": { "get": { "tags": [ "discovery" ], "summary": "Get NDI discovery status.", "operationId": "ndi_status", "responses": { "200": { "description": "NDI discovery status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NdiDiscoveryStatus" } } } } } } }, "/api/discovery/streams": { "get": { "tags": [ "discovery" ], "summary": "List all discovered AES67 streams.", "operationId": "list_streams", "responses": { "200": { "description": "List of discovered streams", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/DiscoveredStreamResponse" } } } } } } } }, "/api/discovery/streams/{id}": { "get": { "tags": [ "discovery" ], "summary": "Get a specific discovered stream by ID.", "operationId": "get_stream", "parameters": [ { "name": "id", "in": "path", "description": "Stream ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Stream details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DiscoveredStreamResponse" } } } }, "404": { "description": "Stream not found" } } } }, "/api/discovery/streams/{id}/sdp": { "get": { "tags": [ "discovery" ], "summary": "Get the raw SDP for a discovered stream.", "operationId": "get_stream_sdp", "parameters": [ { "name": "id", "in": "path", "description": "Stream ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "SDP content", "content": { "application/sdp": { "schema": { "type": "string" } } } }, "404": { "description": "Stream not found" } } } }, "/api/elements": { "get": { "tags": [ "elements" ], "summary": "List all available GStreamer elements.", "operationId": "list_elements", "responses": { "200": { "description": "List of available GStreamer elements", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ElementListResponse" } } } } } } }, "/api/elements/{name}": { "get": { "tags": [ "elements" ], "summary": "Get detailed information about a specific element type.\nThis endpoint triggers lazy loading of element properties.\nProperties are introspected on-demand and cached for future requests.", "operationId": "get_element_info", "parameters": [ { "name": "name", "in": "path", "description": "Element type name (e.g., 'videotestsrc')", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Element information with properties", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ElementInfoResponse" } } } }, "404": { "description": "Element not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/elements/{name}/pads": { "get": { "tags": [ "elements" ], "summary": "Get pad properties for a specific element type.\nThis endpoint introspects pad properties on-demand for better safety.", "operationId": "get_element_pad_properties", "parameters": [ { "name": "name", "in": "path", "description": "Element type name (e.g., 'audiomixer')", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Element information with pad properties", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ElementInfoResponse" } } } }, "404": { "description": "Element not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows": { "get": { "tags": [ "flows" ], "summary": "List all flows.", "operationId": "list_flows", "responses": { "200": { "description": "List all flows", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowListResponse" } } } } } }, "post": { "tags": [ "flows" ], "summary": "Create a new flow.", "description": "Creates a flow under the `id` supplied in the body, so a caller can pre-generate an id and then start the flow by it. `id` is a required field: to have the server assign one instead, send the nil uuid (`00000000-0000-0000-0000-000000000000`) and read the assigned id from the `flow.id` of the response. Reusing the id of an existing flow is a 409; use `POST /api/flows/{id}` to update that flow instead.", "operationId": "create_flow", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Flow" } } }, "required": true }, "responses": { "201": { "description": "Flow created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "409": { "description": "A flow with the supplied id already exists", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/animate": { "post": { "tags": [ "flows" ], "summary": "Animate a single input's position and/or size.", "description": "Smoothly animates the specified input from its current position/size\nto the target values over the specified duration.", "operationId": "animate_input", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID (e.g., 'comp_1')", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AnimateInputRequest" } } }, "required": true }, "responses": { "200": { "description": "Animation started successfully" }, "400": { "description": "Invalid parameters", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/dsk": { "post": { "tags": [ "flows" ], "summary": "Toggle a DSK (Downstream Keyer) layer on a vision mixer block.", "operationId": "toggle_dsk", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DskToggleRequest" } } }, "required": true }, "responses": { "200": { "description": "DSK toggled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DskToggleResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/effect": { "post": { "tags": [ "flows" ], "summary": "Set a shader video effect on a vision mixer block (input look or PGM master).", "description": "Requires the shader FX engine (GPU backend with Shader FX enabled) —\nreturns 400 when the engine is not built into the running pipeline.", "operationId": "set_vision_mixer_effect", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetVideoEffectRequest" } } }, "required": true }, "responses": { "200": { "description": "Effect applied", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetVideoEffectResponse" } } } }, "400": { "description": "Invalid request or FX engine unavailable", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/ftb": { "post": { "tags": [ "flows" ], "summary": "Toggle Fade to Black on a vision mixer block.", "operationId": "fade_to_black", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FadeToBlackRequest" } } }, "required": true }, "responses": { "200": { "description": "FTB toggled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FadeToBlackResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/loudness/reset": { "post": { "tags": [ "flows" ], "summary": "Reset accumulated loudness measurements on an EBU R128 meter block.", "operationId": "reset_loudness", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Loudness measurements reset" }, "400": { "description": "Failed to reset", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/multiview-endpoint": { "get": { "tags": [ "vision-mixer" ], "summary": "Get the multiview WHEP endpoint for a vision mixer block.\nGET /api/flows/{flow_id}/blocks/{block_id}/multiview-endpoint", "operationId": "get_multiview_endpoint", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Multiview endpoint info", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MultiviewEndpointResponse" } } } }, "404": { "description": "Flow or block not found" } } } }, "/api/flows/{flow_id}/blocks/{block_id}/overlay-alpha": { "put": { "tags": [ "flows" ], "summary": "Set the multiview overlay alpha on a vision mixer block.", "operationId": "set_overlay_alpha", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OverlayAlphaRequest" } } }, "required": true }, "responses": { "200": { "description": "Overlay alpha set", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OverlayAlphaResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/pip/{pip_idx}": { "get": { "tags": [ "flows" ], "summary": "Get the current composition of a single PiP on a vision mixer block.", "description": "Returns the same per-PiP state as the corresponding entry in\n`VisionMixerState::pips`. Useful for exporting one PiP's composition\n(e.g. to save it as a reusable layout preset); restore it with a `PUT`\nto the same path.", "operationId": "get_pip_config", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } }, { "name": "pip_idx", "in": "path", "description": "PiP index (0-based)", "required": true, "schema": { "type": "integer", "minimum": 0 } } ], "responses": { "200": { "description": "Current PiP composition", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PipState" } } } }, "404": { "description": "Block has no live state (pipeline not running) or PiP index out of range", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "put": { "tags": [ "flows" ], "summary": "Update a PiP composition (background + overlay inputs) on a vision mixer block.", "description": "The change is applied live to all places where the PiP is currently visible:\nthe multiview PiP thumbnail tile, plus PGM/PVW if either bus is showing this PiP.", "operationId": "update_pip_config", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } }, { "name": "pip_idx", "in": "path", "description": "PiP index (0-based)", "required": true, "schema": { "type": "integer", "minimum": 0 } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdatePipConfigRequest" } } }, "required": true }, "responses": { "200": { "description": "PiP config updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdatePipConfigResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/player/control": { "post": { "tags": [ "media_player" ], "summary": "Control the media player (play, pause, stop, next, previous).", "operationId": "control_player", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PlayerControlRequest" } } }, "required": true }, "responses": { "200": { "description": "Action performed" }, "400": { "description": "Action failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Player not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/player/goto": { "post": { "tags": [ "media_player" ], "summary": "Go to a specific file in the playlist.", "operationId": "goto_file", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GotoRequest" } } }, "required": true }, "responses": { "200": { "description": "Goto performed" }, "400": { "description": "Goto failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Player not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/player/playlist": { "post": { "tags": [ "media_player" ], "summary": "Set the playlist for a media player block.", "operationId": "set_playlist", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetPlaylistRequest" } } }, "required": true }, "responses": { "200": { "description": "Playlist set" }, "404": { "description": "Flow or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/player/seek": { "post": { "tags": [ "media_player" ], "summary": "Seek to a position in the current file.", "operationId": "seek_player", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SeekRequest" } } }, "required": true }, "responses": { "200": { "description": "Seek performed" }, "400": { "description": "Seek failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Player not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/player/state": { "get": { "tags": [ "media_player" ], "summary": "Get the current state of a media player block.", "operationId": "get_player_state", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Player state", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PlayerStateResponse" } } } }, "404": { "description": "Player not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/preview": { "put": { "tags": [ "flows" ], "summary": "Select a preview source on a vision mixer block.", "operationId": "select_preview", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SelectPreviewRequest" } } }, "required": true }, "responses": { "200": { "description": "Preview source selected", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SelectPreviewResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/properties": { "get": { "tags": [ "flows" ], "summary": "Get current block-level exposed property values from a running pipeline.", "description": "Returns each live exposed property's current value in block-level (user-facing)\nunits — e.g. a `ch1_pfl` bool, a `fader_db` float in dB — by reading the\nunderlying GStreamer element and applying the declared inverse transform.\nNon-live properties and those bound to the `_block` virtual element are\nomitted.", "operationId": "get_block_properties", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Block properties retrieved", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockPropertiesResponse" } } } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "patch": { "tags": [ "flows" ], "summary": "Update one or more exposed properties on a block instance live.", "description": "Properties are expressed in block-level (user-facing) units — e.g.\n`{\"ch1_pfl\": true, \"fader_db\": -3.0}`. The backend resolves each name to its\nunderlying GStreamer element via the block definition's PropertyMapping,\napplies the declared transform (`bool_to_volume`, `db_to_linear`, …), and\nwrites through the standard live-property path (so `ramp_ms` produces the\nusual anti-click fade where applicable). `ramp_ms_overrides` lets the\ncaller pin a different ramp duration for individual properties in the same\nbatch — useful for crossfades where one fader rises while another falls at\nthe same rate but other properties move instantly.\n\nOnly properties marked `live: true` are accepted. Unknown, non-live, or\ntype-mismatched entries are returned in the `rejected` map without aborting\nthe rest of the batch.", "operationId": "update_block_properties", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateBlockPropertiesRequest" } } }, "required": true }, "responses": { "200": { "description": "Block properties applied (see `rejected` for partial failures)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlockPropertiesResponse" } } } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/recorder/split": { "post": { "tags": [ "flows" ], "summary": "Force an immediate file split on a recorder block.", "operationId": "recorder_split_now", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "File split triggered" }, "400": { "description": "Failed to trigger split (e.g. ts_passthrough mode)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/sdp": { "get": { "tags": [ "flows" ], "summary": "Generate SDP for a specific block in a flow.", "description": "Returns the SDP (Session Description Protocol) data for AES67 output blocks.\nThis SDP can be used by receivers to connect to the audio stream.", "operationId": "get_block_sdp", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "SDP generated successfully", "content": { "application/sdp": {} } }, "400": { "description": "Block type does not support SDP", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/state": { "get": { "tags": [ "flows" ], "summary": "Get the current runtime state of a vision mixer block.", "description": "Reflects the live overlay state — bus inputs, PiP visibility, FTB, DSK,\noverlay alpha, per-PiP composition. Clients use this on (re)connect to\nreconcile state; subsequent changes flow over the `VisionMixerStateChanged`\nWebSocket event.", "operationId": "get_vision_mixer_state", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Vision mixer block instance ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Current vision mixer state", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VisionMixerState" } } } }, "404": { "description": "Block has no live state (pipeline not running)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/blocks/{block_id}/transition": { "post": { "tags": [ "flows" ], "summary": "Trigger a scene transition on a compositor block.", "description": "Animates the transition between two inputs on a compositor/mixer block.\nSupported transition types:\n- `cut`: Instant switch (no animation)\n- `fade`: Cross-fade via alpha blending\n- `slide_left`: New input slides in from the right\n- `slide_right`: New input slides in from the left\n- `slide_up`: New input slides in from the bottom\n- `slide_down`: New input slides in from the top", "operationId": "trigger_transition", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID (e.g., 'comp_1')", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TriggerTransitionRequest" } } }, "required": true }, "responses": { "200": { "description": "Transition triggered successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TransitionResponse" } } } }, "400": { "description": "Invalid transition parameters", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/elements/{element_id}/pads/{pad_name}/properties": { "get": { "tags": [ "flows" ], "summary": "Get current property values from a pad in a running element.", "description": "Returns all readable properties and their current values from a specific pad\non an element in a running pipeline. This is useful for elements like compositor\nwhere you need to control individual sink pad properties (alpha, xpos, ypos, zorder).", "operationId": "get_pad_properties", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "element_id", "in": "path", "description": "Element instance ID", "required": true, "schema": { "type": "string" } }, { "name": "pad_name", "in": "path", "description": "Pad name (e.g., sink_0, sink_1)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Pad properties retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PadPropertiesResponse" } } } }, "404": { "description": "Flow not running, element not found, or pad not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "patch": { "tags": [ "flows" ], "summary": "Update a property on a pad in a running pipeline element.", "description": "Allows live modification of pad properties while the pipeline is running.\nThis is essential for elements like compositor, glvideomixer, and audiomixer\nwhere you need to control individual input pad properties.\nCommon pad properties include:\n- alpha: Opacity/transparency (0.0 to 1.0)\n- xpos, ypos: Position in pixels\n- width, height: Size in pixels\n- zorder: Layer order (higher values are on top)", "operationId": "update_pad_property", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "element_id", "in": "path", "description": "Element instance ID", "required": true, "schema": { "type": "string" } }, { "name": "pad_name", "in": "path", "description": "Pad name (e.g., sink_0, sink_1)", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdatePadPropertyRequest" } } }, "required": true }, "responses": { "200": { "description": "Pad property updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PadPropertiesResponse" } } } }, "400": { "description": "Property cannot be changed in current state or invalid value", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not running, element not found, or pad not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{flow_id}/elements/{element_id}/properties": { "get": { "tags": [ "flows" ], "summary": "Get current property values from a running element.", "description": "Returns all readable properties and their current values from an element\nin a running pipeline. The pipeline must be started for this endpoint to work.", "operationId": "get_element_properties", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "element_id", "in": "path", "description": "Element instance ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Properties retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ElementPropertiesResponse" } } } }, "404": { "description": "Flow not running or element not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "patch": { "tags": [ "flows" ], "summary": "Update a property on a running pipeline element.", "description": "Allows live modification of element properties while the pipeline is running.\nOnly properties marked as mutable in the current pipeline state can be updated.\nThe property mutability flags (mutable_in_playing, etc.) can be checked via\nthe element info endpoint.", "operationId": "update_element_property", "parameters": [ { "name": "flow_id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "element_id", "in": "path", "description": "Element instance ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdatePropertyRequest" } } }, "required": true }, "responses": { "200": { "description": "Property updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ElementPropertiesResponse" } } } }, "400": { "description": "Property cannot be changed in current state or invalid value", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not running or element not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}": { "get": { "tags": [ "flows" ], "summary": "Get a specific flow by ID.", "operationId": "get_flow", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Flow found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "put": { "tags": [ "flows" ], "summary": "Update an existing flow (PUT alias).", "description": "This is an alias for the POST update endpoint, provided for RESTful API conventions.", "operationId": "update_flow_put", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Flow" } } }, "required": true }, "responses": { "200": { "description": "Flow updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "post": { "tags": [ "flows" ], "summary": "Update an existing flow.", "operationId": "update_flow", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Flow" } } }, "required": true }, "responses": { "200": { "description": "Flow updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "400": { "description": "Bad request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "delete": { "tags": [ "flows" ], "summary": "Delete a flow.", "operationId": "delete_flow", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Flow deleted" }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/blocks/{block_id}/thumbnail": { "get": { "tags": [ "flows" ], "summary": "Get a thumbnail image from a block's video tap.", "description": "Works with any block that exposes thumbnail tee elements, including\n`builtin.thumbnail` (index 0) and compositor blocks (one per input).\nThe first request activates the thumbnail branch; subsequent requests\nare served from cache.", "operationId": "get_block_thumbnail", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } }, { "name": "block_id", "in": "path", "description": "Block instance ID (e.g., 'b0')", "required": true, "schema": { "type": "string" } }, { "name": "index", "in": "query", "description": "Tap index (default 0, e.g. compositor input index)", "required": false, "schema": { "type": "integer", "minimum": 0 } } ], "responses": { "200": { "description": "JPEG thumbnail image", "content": { "image/jpeg": {} } }, "404": { "description": "Flow not running or block not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "504": { "description": "Frame capture timed out (retry shortly)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/debug": { "get": { "tags": [ "flows" ], "summary": "Get debug information for a running flow.", "description": "Returns pipeline timing information including base_time, clock_time, and\nrunning_time. This is useful for debugging AES67/RFC 7273 RTP timestamp\nissues where precise clock synchronization is critical.", "operationId": "get_flow_debug_info", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Debug information retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowDebugInfo" } } } }, "404": { "description": "Flow not running", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/debug-graph": { "get": { "tags": [ "flows" ], "summary": "Generate a debug DOT/SVG graph for a flow's pipeline.", "description": "This endpoint generates a GraphViz DOT graph of the GStreamer pipeline\nand converts it to SVG format. The SVG is returned directly and can be\nviewed in a browser.", "operationId": "debug_graph", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "SVG debug graph of the pipeline", "content": { "image/svg+xml": {} } }, "404": { "description": "Flow not found or not running", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Failed to generate graph (Graphviz not installed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/dynamic-pads": { "get": { "tags": [ "flows" ], "summary": "Get runtime dynamic pads for a flow.", "description": "Returns information about dynamic pads (like decodebin outputs) that were\ncreated at runtime and auto-linked to tees. These pads can be connected\nto other elements in the UI.", "operationId": "get_dynamic_pads", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Dynamic pads information", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DynamicPadsResponse" } } } }, "404": { "description": "Flow not found or not running", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/latency": { "get": { "tags": [ "flows" ], "summary": "Get pipeline latency for a running flow.", "description": "Returns the latency information for a running pipeline. The flow must be\nstarted and in PLAYING state for latency information to be available.", "operationId": "get_flow_latency", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Latency retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LatencyResponse" } } } }, "404": { "description": "Flow not running or latency not available", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/pad-caps": { "get": { "tags": [ "flows" ], "summary": "Get negotiated caps for all pads in a running flow's pipeline.", "description": "Returns a JSON map of element_name → [(pad_name, direction, caps_string)].\nUseful for debugging caps negotiation failures.", "operationId": "get_flow_pad_caps", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Pad caps for all elements" }, "404": { "description": "Flow not running", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/probes": { "get": { "tags": [ "probes" ], "summary": "List active probes on a flow.", "operationId": "list_probes", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Active probes", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActiveProbesResponse" } } } }, "404": { "description": "Flow not found or not running" } } }, "post": { "tags": [ "probes" ], "summary": "Activate a buffer age probe on a pad.", "operationId": "activate_probe", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ActivateProbeRequest" } } }, "required": true }, "responses": { "200": { "description": "Probe activated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProbeResponse" } } } }, "400": { "description": "Invalid request" }, "404": { "description": "Flow not found or not running" } } } }, "/api/flows/{id}/probes/{probe_id}": { "delete": { "tags": [ "probes" ], "summary": "Deactivate a probe.", "operationId": "deactivate_probe", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID", "required": true, "schema": { "type": "string" } }, { "name": "probe_id", "in": "path", "description": "Probe ID", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Probe deactivated" }, "404": { "description": "Flow or probe not found" } } } }, "/api/flows/{id}/properties": { "patch": { "tags": [ "flows" ], "summary": "Update flow properties (description, clock type, etc.).", "description": "Updates the configuration properties of a flow. The flow must be stopped\nto change certain properties like the clock type.", "operationId": "update_flow_properties", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateFlowPropertiesRequest" } } }, "required": true }, "responses": { "200": { "description": "Properties updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/rtp-stats": { "get": { "tags": [ "flows" ], "summary": "Get runtime statistics for a flow's pipeline.", "description": "Returns RTP statistics from running pipeline elements, such as jitterbuffer\nstatistics for AES67 input blocks. The flow must be started and running\nfor statistics to be available.", "operationId": "get_flow_rtp_stats", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "RTP statistics retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowStatsResponse" } } } }, "404": { "description": "Flow not running or no RTP statistics available", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/srt-stats": { "get": { "tags": [ "flows" ], "summary": "Get SRT statistics from a running flow.", "description": "Returns statistics for every `srtsink` (output) and `srtsrc` (input) element in\nthe pipeline. Each entry is keyed by element name (e.g. `:srtsink`),\nso the frontend can filter the response per SRT block.", "operationId": "get_srt_stats", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "SRT statistics retrieved", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SrtStatsResponse" } } } }, "404": { "description": "Flow not running", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/start": { "post": { "tags": [ "flows" ], "summary": "Start a flow (pipeline).", "operationId": "start_flow", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Flow started", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/stop": { "post": { "tags": [ "flows" ], "summary": "Stop a flow (pipeline).", "operationId": "stop_flow", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Flow stopped", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FlowResponse" } } } }, "404": { "description": "Flow not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/flows/{id}/webrtc-stats": { "get": { "tags": [ "flows" ], "summary": "Get WebRTC statistics from a running flow.", "description": "Returns statistics from all webrtcbin elements in the pipeline, including\nthose nested in bins like whepclientsrc and whipclientsink. Stats include\nRTP stream information, ICE connection state, and raw stats data.", "operationId": "get_webrtc_stats", "parameters": [ { "name": "id", "in": "path", "description": "Flow ID (UUID)", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "WebRTC statistics retrieved", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebRtcStatsResponse" } } } }, "404": { "description": "Flow not running", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/gst-launch/export": { "post": { "tags": [ "gst-launch" ], "summary": "Export elements and links to gst-launch-1.0 syntax.", "operationId": "export_gst_launch", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExportGstLaunchRequest" } } }, "required": true }, "responses": { "200": { "description": "Pipeline exported successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExportGstLaunchResponse" } } } }, "400": { "description": "Cannot export pipeline", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/gst-launch/parse": { "post": { "tags": [ "gst-launch" ], "summary": "Parse a gst-launch-1.0 pipeline string and extract elements and links.", "description": "This uses GStreamer's native pipeline parser to ensure complete compatibility\nwith the gst-launch-1.0 syntax.", "operationId": "parse_gst_launch", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ParseGstLaunchRequest" } } }, "required": true }, "responses": { "200": { "description": "Pipeline parsed successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ParseGstLaunchResponse" } } } }, "400": { "description": "Invalid pipeline syntax", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/gst-log-level": { "get": { "tags": [ "System" ], "summary": "Get the current GStreamer debug level filter", "operationId": "get_gst_log_level", "responses": { "200": { "description": "Current GStreamer debug level", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GstLogLevelResponse" } } } } } }, "put": { "tags": [ "System" ], "summary": "Set the GStreamer debug level filter at runtime", "operationId": "set_gst_log_level", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetGstLogLevelRequest" } } }, "required": true }, "responses": { "200": { "description": "GStreamer debug level updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GstLogLevelResponse" } } } }, "400": { "description": "Invalid filter string", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/ice-servers": { "get": { "tags": [ "whep" ], "summary": "GET /api/ice-servers - Get configured ICE servers for WebRTC connections.", "operationId": "get_ice_servers", "responses": { "200": { "description": "List of configured ICE servers", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IceServersResponse" } } } } } } }, "/api/log-level": { "get": { "tags": [ "System" ], "summary": "Get the current log level filter", "operationId": "get_log_level", "responses": { "200": { "description": "Current log level", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LogLevelResponse" } } } } } }, "put": { "tags": [ "System" ], "summary": "Set the log level filter at runtime", "operationId": "set_log_level", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetLogLevelRequest" } } }, "required": true }, "responses": { "200": { "description": "Log level updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LogLevelResponse" } } } }, "400": { "description": "Invalid filter string", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/login": { "post": { "tags": [ "auth" ], "summary": "Login handler", "operationId": "login_handler", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } }, "required": true }, "responses": { "200": { "description": "Login attempt result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginResponse" } } } }, "500": { "description": "Internal server error" } } } }, "/api/logout": { "post": { "tags": [ "auth" ], "summary": "Logout handler", "operationId": "logout_handler", "responses": { "200": { "description": "Logout successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginResponse" } } } }, "500": { "description": "Internal server error" } } } }, "/api/mcp": { "get": { "tags": [ "mcp" ], "summary": "GET /api/mcp - Open SSE stream for server-initiated messages.", "description": "Opens a Server-Sent Events stream for receiving server-initiated\nJSON-RPC messages (notifications, requests from server).", "operationId": "mcp_get", "responses": { "200": { "description": "SSE stream for server-initiated messages", "content": { "text/event-stream": {} } }, "400": { "description": "Mcp-Session-Id header required" }, "401": { "description": "Authentication required" }, "403": { "description": "Invalid origin" }, "404": { "description": "Session not found" } } }, "post": { "tags": [ "mcp" ], "summary": "POST /api/mcp - Handle JSON-RPC requests.", "description": "Accepts JSON-RPC requests and returns either:\n- `application/json` for simple responses\n- `text/event-stream` for streaming responses (not implemented yet)\n\nThe `Mcp-Session-Id` header is assigned on initialize and required for subsequent requests.", "operationId": "mcp_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JsonRpcRequest" } } }, "required": true }, "responses": { "200": { "description": "JSON-RPC response", "content": { "application/json": {} } }, "202": { "description": "Notification accepted (no response body)" }, "400": { "description": "Invalid request or session required" }, "401": { "description": "Authentication required" }, "403": { "description": "Invalid origin (DNS rebinding protection)" } } }, "delete": { "tags": [ "mcp" ], "summary": "DELETE /api/mcp - Terminate a session.", "description": "Terminates the session identified by the `Mcp-Session-Id` header.", "operationId": "mcp_delete", "responses": { "204": { "description": "Session terminated successfully" }, "400": { "description": "Mcp-Session-Id header required" }, "401": { "description": "Authentication required" }, "403": { "description": "Invalid origin" }, "404": { "description": "Session not found" } } } }, "/api/media": { "get": { "tags": [ "Media" ], "summary": "List contents of a media directory.", "operationId": "list_media", "parameters": [ { "name": "path", "in": "query", "description": "Directory path relative to media root", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Directory listing", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListMediaResponse" } } } }, "400": { "description": "Invalid path", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Directory not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/media/directory": { "post": { "tags": [ "Media" ], "summary": "Create a directory.", "operationId": "create_directory", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateDirectoryRequest" } } }, "required": true }, "responses": { "200": { "description": "Directory created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaOperationResponse" } } } }, "400": { "description": "Invalid path", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "Directory already exists", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/media/directory/{path}": { "delete": { "tags": [ "Media" ], "summary": "Delete a directory (must be empty).", "operationId": "delete_directory", "parameters": [ { "name": "path", "in": "path", "description": "Directory path relative to media root", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Delete successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaOperationResponse" } } } }, "400": { "description": "Invalid path or directory not empty", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Directory not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/media/file/{path}": { "get": { "tags": [ "Media" ], "summary": "Download a file.", "operationId": "download_file", "parameters": [ { "name": "path", "in": "path", "description": "File path relative to media root", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "File content" }, "400": { "description": "Invalid path", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "File not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "delete": { "tags": [ "Media" ], "summary": "Delete a file.", "operationId": "delete_file", "parameters": [ { "name": "path", "in": "path", "description": "File path relative to media root", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Delete successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaOperationResponse" } } } }, "400": { "description": "Invalid path", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "File not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/media/rename": { "post": { "tags": [ "Media" ], "summary": "Rename a file or directory.", "operationId": "rename_media", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RenameMediaRequest" } } }, "required": true }, "responses": { "200": { "description": "Rename successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaOperationResponse" } } } }, "400": { "description": "Invalid path or name", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "File or directory not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/media/upload": { "post": { "tags": [ "Media" ], "summary": "Upload files to a directory.", "operationId": "upload_files", "parameters": [ { "name": "path", "in": "query", "description": "Directory path to upload to", "required": false, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Upload successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MediaOperationResponse" } } } }, "400": { "description": "Invalid path or upload", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Upload failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/network/interfaces": { "get": { "tags": [ "Network" ], "summary": "List all network interfaces on the system.", "description": "Returns information about all network interfaces including name, MAC address,\nand IP addresses. Useful for selecting which interface to use for multicast\noperations (e.g., AES67 streams).", "operationId": "list_interfaces", "responses": { "200": { "description": "List of network interfaces", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NetworkInterfacesResponse" } } } } } } }, "/api/osc/pat": { "get": { "tags": [ "System" ], "summary": "Get the OSC PAT configuration status", "description": "Reports whether the default PAT is configured and which per-flow credential\nkeys have a PAT registered. Token values are never returned.", "operationId": "get_osc_pat_status", "responses": { "200": { "description": "OSC PAT status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OscAuthStatusResponse" } } } } } } }, "/api/osc/pat/{key}": { "put": { "tags": [ "System" ], "summary": "Set a per-flow OSC Personal Access Token", "description": "Registers a PAT for one credential key (the flow id). Flows resolve their own\nPAT first, falling back to the default — isolating OSC tenants on a shared\ninstance. Held in memory only.", "operationId": "set_osc_pat_keyed", "parameters": [ { "name": "key", "in": "path", "description": "Credential key (flow id) the PAT is scoped to", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetOscPatRequest" } } }, "required": true }, "responses": { "200": { "description": "PAT updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OscAuthStatusResponse" } } } }, "400": { "description": "Empty token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "delete": { "tags": [ "System" ], "summary": "Clear a per-flow OSC Personal Access Token", "operationId": "clear_osc_pat_keyed", "parameters": [ { "name": "key", "in": "path", "description": "Credential key (flow id) to clear", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "PAT cleared", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OscAuthStatusResponse" } } } } } } }, "/api/sources": { "get": { "tags": [ "flows" ], "summary": "Get available source flows for subscription.", "description": "Returns all flows that have InterOutput blocks, along with information\nabout whether each output is currently active (flow is running).\nThis scans all flow definitions, not just running flows.", "operationId": "get_available_sources", "responses": { "200": { "description": "List of available source flows", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AvailableSourcesResponse" } } } } } } }, "/api/system/clock": { "get": { "tags": [ "System" ], "summary": "Get system clock synchronization state", "description": "Returns the current kernel time-discipline state as reported by\n`ntp_adjtime(2)`. This includes the TAI-UTC offset, PLL status,\ncurrent offset being applied, and frequency adjustment — the same\ninformation used by chrony, ntpd and systemd-timesyncd.\n\nUseful for diagnosing flows that use `Realtime` or `Tai` pipeline\nclocks, where the accuracy depends on how the OS clock is being\nsynchronized.", "operationId": "get_system_clock", "responses": { "200": { "description": "System clock state", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SystemClockInfo" } } } }, "500": { "description": "Failed to read system clock state" } } } }, "/api/version": { "get": { "tags": [ "System" ], "summary": "Get version and build information", "description": "Returns comprehensive version information including:\n- Package version from Cargo.toml\n- Git commit hash\n- Git tag (if on a tagged release)\n- Git branch name\n- Working directory status (dirty/clean)\n- Build timestamp", "operationId": "get_version", "responses": { "200": { "description": "Version information", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SystemInfo" } } } } } } }, "/api/whep-streams": { "get": { "tags": [ "whep" ], "summary": "GET /api/whep-streams - List all active WHEP streams (JSON API).", "operationId": "list_whep_streams", "responses": { "200": { "description": "List of active WHEP streams", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WhepStreamsResponse" } } } } } } }, "/api/whip-endpoints": { "get": { "tags": [ "whip" ], "summary": "List active WHIP endpoints (public API, no auth required).", "operationId": "list_whip_endpoints", "responses": { "200": { "description": "List of active WHIP endpoints" } } } }, "/api/ws": { "get": { "tags": [ "websocket" ], "summary": "WebSocket endpoint for real-time bidirectional communication.", "description": "This endpoint establishes a WebSocket connection and:\n- Streams events to the client whenever flows are created, updated, deleted, started, or stopped\n- Sends ping messages every 15 seconds to keep the connection alive\n- Handles pong responses from the client\n\nExample usage from JavaScript:\n```javascript\nconst ws = new WebSocket('ws://localhost:3000/api/ws');\nws.onmessage = (event) => {\n const data = JSON.parse(event.data);\n console.log('Received event:', data);\n};\nws.onclose = () => console.log('Disconnected');\nws.onerror = (error) => console.error('WebSocket error:', error);\n```", "operationId": "websocket_handler", "responses": { "101": { "description": "WebSocket connection upgraded" }, "401": { "description": "Authentication required (use auth_token query param)" } } } }, "/whep/{endpoint_id}": { "post": { "tags": [ "whep" ], "summary": "Proxy POST requests to /whep/{endpoint_id}\nLooks up the internal port from WhepRegistry and forwards to localhost:{port}/whep/endpoint", "operationId": "whep_endpoint_proxy", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHEP endpoint identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "201": { "description": "WHEP session created, SDP answer returned", "content": { "application/sdp": {} } }, "404": { "description": "WHEP endpoint not found" }, "502": { "description": "Proxy error forwarding to internal WHEP server" } } }, "options": { "tags": [ "whep" ], "summary": "Handle OPTIONS preflight for /whep/{endpoint_id}", "operationId": "whep_endpoint_proxy_options", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHEP endpoint identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "CORS preflight response" } } } }, "/whep/{endpoint_id}/resource/{resource_id}": { "delete": { "tags": [ "whep" ], "summary": "Proxy DELETE requests to /whep/{endpoint_id}/resource/{resource_id}", "operationId": "whep_resource_proxy_delete", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHEP endpoint identifier", "required": true, "schema": { "type": "string" } }, { "name": "resource_id", "in": "path", "description": "WHEP resource/session identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "WHEP session deleted" }, "404": { "description": "WHEP endpoint not found" }, "502": { "description": "Proxy error forwarding to internal WHEP server" } } }, "options": { "tags": [ "whep" ], "summary": "Handle OPTIONS preflight for /whep/{endpoint_id}/resource/{resource_id}", "operationId": "whep_resource_proxy_options", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHEP endpoint identifier", "required": true, "schema": { "type": "string" } }, { "name": "resource_id", "in": "path", "description": "WHEP resource/session identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "CORS preflight response" } } }, "patch": { "tags": [ "whep" ], "summary": "Proxy PATCH requests to /whep/{endpoint_id}/resource/{resource_id} for ICE candidates", "operationId": "whep_resource_proxy_patch", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHEP endpoint identifier", "required": true, "schema": { "type": "string" } }, { "name": "resource_id", "in": "path", "description": "WHEP resource/session identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "ICE candidates accepted" }, "404": { "description": "WHEP endpoint not found" }, "502": { "description": "Proxy error forwarding to internal WHEP server" } } } }, "/whip/{endpoint_id}": { "post": { "tags": [ "whip" ], "summary": "Handle WHIP POST request (SDP offer from client).", "description": "Creates a new whipserversrc element for this session, proxies the SDP offer\nto it, and registers the session with the WhipSessionManager.", "operationId": "whip_post", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHIP endpoint identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "201": { "description": "WHIP session created, SDP answer returned", "content": { "application/sdp": {} } }, "404": { "description": "WHIP endpoint not found" }, "502": { "description": "Proxy error forwarding to internal WHIP server" }, "503": { "description": "WHIP element busy, retry in a moment" } } }, "options": { "tags": [ "whip" ], "summary": "Handle CORS preflight for WHIP endpoints.", "operationId": "whip_options", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHIP endpoint identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "CORS preflight response" } } } }, "/whip/{endpoint_id}/resource/{resource_id}": { "delete": { "tags": [ "whip" ], "summary": "Handle WHIP DELETE request (client disconnect).", "description": "Proxies the DELETE to the session's whipserversrc, then tears down the element\nand removes the session from the session manager.", "operationId": "whip_resource_delete", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHIP endpoint identifier", "required": true, "schema": { "type": "string" } }, { "name": "resource_id", "in": "path", "description": "WHIP resource/session identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "WHIP session deleted" }, "404": { "description": "WHIP endpoint or session not found" }, "502": { "description": "Proxy error forwarding to internal WHIP server" } } }, "options": { "tags": [ "whip" ], "summary": "Handle CORS preflight for WHIP resource endpoints.", "operationId": "whip_resource_options", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHIP endpoint identifier", "required": true, "schema": { "type": "string" } }, { "name": "resource_id", "in": "path", "description": "WHIP resource/session identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "CORS preflight response" } } }, "patch": { "tags": [ "whip" ], "summary": "Handle WHIP PATCH request (ICE trickle from client).", "description": "Looks up the session's port by resource_id and proxies the PATCH.", "operationId": "whip_resource_patch", "parameters": [ { "name": "endpoint_id", "in": "path", "description": "WHIP endpoint identifier", "required": true, "schema": { "type": "string" } }, { "name": "resource_id", "in": "path", "description": "WHIP resource/session identifier", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "ICE candidates accepted" }, "404": { "description": "WHIP endpoint or session not found" }, "502": { "description": "Proxy error forwarding to internal WHIP server" } } } } }, "components": { "schemas": { "ActivateProbeRequest": { "type": "object", "description": "Request to activate a buffer age probe on a pad.", "required": [ "element_id" ], "properties": { "element_id": { "type": "string", "description": "Element ID to probe (standalone element or block ID)" }, "sample_interval": { "type": [ "integer", "null" ], "format": "int32", "description": "Measure every Nth buffer (default 1)", "minimum": 0 }, "timeout_secs": { "type": [ "integer", "null" ], "format": "int32", "description": "Auto-remove after this many seconds (default 60)", "minimum": 0 } } }, "ActiveProbesResponse": { "type": "object", "description": "Response listing active probes.", "required": [ "probes" ], "properties": { "probes": { "type": "array", "items": { "$ref": "#/components/schemas/ProbeInfo" }, "description": "List of active probes" } } }, "AnimateInputRequest": { "type": "object", "description": "Request to animate a single input's position/size.", "required": [ "input" ], "properties": { "duration_ms": { "type": "integer", "format": "int64", "description": "Animation duration in milliseconds", "minimum": 0 }, "height": { "type": [ "integer", "null" ], "format": "int32", "description": "Target height (optional)" }, "input": { "type": "integer", "description": "Input index (0-based)", "minimum": 0 }, "width": { "type": [ "integer", "null" ], "format": "int32", "description": "Target width (optional)" }, "xpos": { "type": [ "integer", "null" ], "format": "int32", "description": "Target X position (optional, keeps current if not specified)" }, "ypos": { "type": [ "integer", "null" ], "format": "int32", "description": "Target Y position (optional)" } } }, "AnnouncedStreamResponse": { "type": "object", "description": "Response for announced streams list.", "required": [ "flow_id", "block_id", "origin_ip", "sdp" ], "properties": { "announce_interface": { "type": [ "string", "null" ], "description": "Network interface the stream is announced on (None = all interfaces)." }, "block_id": { "type": "string" }, "flow_id": { "type": "string" }, "origin_ip": { "type": "string" }, "sdp": { "type": "string" } } }, "AuthStatusResponse": { "type": "object", "description": "Authentication status response.", "required": [ "authenticated", "auth_required", "methods" ], "properties": { "auth_required": { "type": "boolean", "description": "Whether authentication is required for this server" }, "authenticated": { "type": "boolean", "description": "Whether the current session is authenticated" }, "methods": { "type": "array", "items": { "type": "string" }, "description": "Available authentication methods (e.g., \"session\", \"api_key\")" } } }, "AvailableOutput": { "type": "object", "description": "Information about an available published output from a source flow.", "required": [ "name", "channel_name", "flow_name", "media_type", "is_active" ], "properties": { "channel_name": { "type": "string", "description": "Channel name for inter-pipeline communication (what InterInput blocks use)" }, "description": { "type": [ "string", "null" ], "description": "Description of the output" }, "flow_name": { "type": "string", "description": "Name of the flow that publishes this output" }, "is_active": { "type": "boolean", "description": "Whether the source flow is currently running (output is active)" }, "media_type": { "$ref": "#/components/schemas/MediaType", "description": "Media type (Audio, Video, Generic)" }, "name": { "type": "string", "description": "Name of the published output (block ID)" } } }, "AvailableSourcesResponse": { "type": "object", "description": "Response containing available source flows for subscription.", "required": [ "sources" ], "properties": { "sources": { "type": "array", "items": { "$ref": "#/components/schemas/SourceFlowInfo" }, "description": "List of flows that have published outputs" } } }, "BlockCategoriesResponse": { "type": "object", "description": "Response containing block categories", "required": [ "categories" ], "properties": { "categories": { "type": "array", "items": { "type": "string" } } } }, "BlockDefinition": { "type": "object", "description": "Block definition - metadata for creating block instances.\n\nNote: Built-in blocks use the BlockBuilder trait to create GStreamer elements directly.\nUser-defined blocks are not yet supported.", "required": [ "id", "name", "description", "category", "exposed_properties", "external_pads", "built_in" ], "properties": { "built_in": { "type": "boolean", "description": "Whether this is a built-in block (read-only) or user-defined" }, "category": { "type": "string", "description": "Category for organization (e.g., \"Inputs\", \"Outputs\", \"Codecs\")" }, "description": { "type": "string", "description": "Description of what this block does" }, "exposed_properties": { "type": "array", "items": { "$ref": "#/components/schemas/ExposedProperty" }, "description": "Exposed properties that users can configure" }, "external_pads": { "$ref": "#/components/schemas/ExternalPads", "description": "External pads exposed by this block" }, "id": { "type": "string", "description": "Unique identifier for this block definition" }, "name": { "type": "string", "description": "Human-readable name (e.g., \"AES67 Input\")" }, "ui_metadata": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/BlockUIMetadata", "description": "Visual representation settings" } ] } } }, "BlockInstance": { "type": "object", "description": "Block instance in a flow", "required": [ "id", "block_definition_id", "properties", "position" ], "properties": { "block_definition_id": { "type": "string", "description": "Reference to the block definition" }, "computed_external_pads": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/ExternalPads", "description": "Computed external pads for this instance based on properties\nIf None, falls back to the pads from the block definition\nThis allows blocks to have dynamic pads based on their configuration" } ] }, "id": { "type": "string", "description": "Unique ID for this instance" }, "name": { "type": [ "string", "null" ], "description": "User-assigned name for this instance" }, "position": { "$ref": "#/components/schemas/Position", "description": "Position in the visual editor" }, "properties": { "type": "object", "description": "Property values for this instance", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } }, "runtime_data": { "type": [ "object", "null" ], "description": "Runtime data (not persisted to storage, only available when flow is running)\nUsed for things like generated SDP for AES67 blocks", "additionalProperties": { "type": "string" }, "propertyNames": { "type": "string" } } } }, "BlockListResponse": { "type": "object", "description": "Response containing a list of blocks", "required": [ "blocks" ], "properties": { "blocks": { "type": "array", "items": { "$ref": "#/components/schemas/BlockDefinition" } } } }, "BlockPropertiesResponse": { "type": "object", "description": "Response containing current block-level exposed property values and any rejections.", "required": [ "block_id", "properties" ], "properties": { "block_id": { "type": "string", "description": "The block instance ID" }, "properties": { "type": "object", "description": "Current values (in block-level units, inverse-transformed from the live elements)", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } }, "rejected": { "type": "object", "description": "Names of properties that could not be applied, mapped to a short reason.\nEmpty on full success. Only populated on PATCH.", "additionalProperties": { "type": "string" }, "propertyNames": { "type": "string" } } } }, "BlockResponse": { "type": "object", "description": "Response containing a block definition", "required": [ "block" ], "properties": { "block": { "$ref": "#/components/schemas/BlockDefinition" } } }, "BlockStats": { "type": "object", "description": "Statistics for a single block instance.", "required": [ "block_instance_id", "block_definition_id", "block_name", "stats", "collected_at" ], "properties": { "block_definition_id": { "type": "string", "description": "The block definition ID (e.g., \"builtin.aes67_input\")" }, "block_instance_id": { "type": "string", "description": "The block instance ID" }, "block_name": { "type": "string", "description": "Human-readable block name" }, "collected_at": { "type": "integer", "format": "int64", "description": "Timestamp when these stats were collected (nanoseconds since epoch)", "minimum": 0 }, "stats": { "type": "array", "items": { "$ref": "#/components/schemas/Statistic" }, "description": "Collection of statistics for this block" } } }, "BlockUIMetadata": { "type": "object", "description": "UI metadata for block rendering", "properties": { "dark_fill_color": { "type": [ "string", "null" ], "description": "Fill/background color in dark mode (hex color)" }, "dark_stroke_color": { "type": [ "string", "null" ], "description": "Stroke/border color in dark mode (hex color)" }, "dark_text_color": { "type": [ "string", "null" ], "description": "Text color in dark mode (hex color)" }, "height": { "type": [ "number", "null" ], "format": "float", "description": "Height in the editor (in grid units)" }, "icon": { "type": [ "string", "null" ], "description": "Icon or visual identifier (emoji or name)" }, "light_fill_color": { "type": [ "string", "null" ], "description": "Fill/background color in light mode (hex color)" }, "light_stroke_color": { "type": [ "string", "null" ], "description": "Stroke/border color in light mode (hex color)" }, "light_text_color": { "type": [ "string", "null" ], "description": "Text color in light mode (hex color)" }, "width": { "type": [ "number", "null" ], "format": "float", "description": "Width in the editor (in grid units)" } } }, "ClientMessage": { "oneOf": [ { "type": "object", "description": "Subscribe to updates for a specific flow", "required": [ "flow_id", "type" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "type": { "type": "string", "enum": [ "subscribe" ] } } }, { "type": "object", "description": "Unsubscribe from updates for a specific flow", "required": [ "flow_id", "type" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "type": { "type": "string", "enum": [ "unsubscribe" ] } } }, { "type": "object", "description": "Ping to keep connection alive", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "ping" ] } } } ], "description": "Messages sent from client to server via WebSocket.", "discriminator": { "propertyName": "type" } }, "ClockSyncStatus": { "type": "string", "description": "Clock synchronization status.", "enum": [ "synced", "not_synced", "unknown" ] }, "CodecStats": { "type": "object", "description": "Codec statistics.", "properties": { "channels": { "type": [ "integer", "null" ], "format": "int32", "description": "Number of channels (for audio)", "minimum": 0 }, "clock_rate": { "type": [ "integer", "null" ], "format": "int32", "description": "Clock rate in Hz", "minimum": 0 }, "mime_type": { "type": [ "string", "null" ], "description": "Codec MIME type (e.g., \"audio/opus\", \"video/VP8\")" }, "payload_type": { "type": [ "integer", "null" ], "format": "int32", "description": "Payload type number", "minimum": 0 } } }, "CpuAffinity": { "type": "string", "description": "CPU affinity strategy for GStreamer streaming threads.\n\nControls whether pipeline threads are pinned to a single CPU core\nfor better cache locality and reduced context switches.", "enum": [ "off", "single_core" ] }, "CreateBlockRequest": { "type": "object", "description": "Request to create a new block definition (currently not supported for user-defined blocks)", "required": [ "name", "description", "category", "exposed_properties", "external_pads" ], "properties": { "category": { "type": "string" }, "description": { "type": "string" }, "exposed_properties": { "type": "array", "items": { "$ref": "#/components/schemas/ExposedProperty" } }, "external_pads": { "$ref": "#/components/schemas/ExternalPads" }, "name": { "type": "string" }, "ui_metadata": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/BlockUIMetadata" } ] } } }, "CreateDirectoryRequest": { "type": "object", "description": "Request to create a directory.", "required": [ "path" ], "properties": { "path": { "type": "string", "description": "Path for new directory (relative to media root)" } } }, "DeviceCategory": { "type": "string", "description": "Device category for filtering.", "enum": [ "audiosource", "audiosink", "videosource", "networksource", "other" ] }, "DeviceCountByCategory": { "type": "object", "description": "Device counts by category.", "required": [ "audio_source", "audio_sink", "video_source", "network_source", "other" ], "properties": { "audio_sink": { "type": "integer", "minimum": 0 }, "audio_source": { "type": "integer", "minimum": 0 }, "network_source": { "type": "integer", "minimum": 0 }, "other": { "type": "integer", "minimum": 0 }, "video_source": { "type": "integer", "minimum": 0 } } }, "DeviceDiscoveryStatus": { "type": "object", "description": "Device discovery status response.", "required": [ "running", "ndi_available", "device_count", "by_category" ], "properties": { "by_category": { "$ref": "#/components/schemas/DeviceCountByCategory", "description": "Number of devices by category." }, "device_count": { "type": "integer", "description": "Total number of discovered devices.", "minimum": 0 }, "ndi_available": { "type": "boolean", "description": "Whether NDI device provider is available." }, "running": { "type": "boolean", "description": "Whether device discovery is running." } } }, "DeviceResponse": { "type": "object", "description": "API response for a discovered device.", "required": [ "id", "name", "device_class", "category", "provider", "properties", "first_seen_secs_ago", "last_seen_secs_ago" ], "properties": { "category": { "$ref": "#/components/schemas/DeviceCategory", "description": "Device category." }, "device_class": { "type": "string", "description": "Device class (e.g., \"Audio/Source\", \"Video/Source\", \"Source/Network\")." }, "first_seen_secs_ago": { "type": "integer", "format": "int64", "description": "Seconds since first discovery.", "minimum": 0 }, "id": { "type": "string", "description": "Unique ID for this device." }, "last_seen_secs_ago": { "type": "integer", "format": "int64", "description": "Seconds since last seen.", "minimum": 0 }, "name": { "type": "string", "description": "Display name of the device." }, "properties": { "type": "object", "description": "Additional properties from the device.", "additionalProperties": { "type": "string" }, "propertyNames": { "type": "string" } }, "provider": { "type": "string", "description": "Provider that discovered this device." } } }, "DiscoveredStreamResponse": { "type": "object", "description": "API response for a discovered AES67 stream.", "required": [ "id", "name", "source", "multicast_address", "port", "channels", "sample_rate", "encoding", "origin_host", "first_seen_secs_ago", "last_seen_secs_ago", "ttl_secs" ], "properties": { "channels": { "type": "integer", "format": "int32", "minimum": 0 }, "encoding": { "type": "string" }, "first_seen_secs_ago": { "type": "integer", "format": "int64", "minimum": 0 }, "id": { "type": "string" }, "last_seen_secs_ago": { "type": "integer", "format": "int64", "minimum": 0 }, "multicast_address": { "type": "string" }, "name": { "type": "string" }, "origin_host": { "type": "string" }, "port": { "type": "integer", "format": "int32", "minimum": 0 }, "received_on_interface": { "type": [ "string", "null" ], "description": "Network interface the stream was discovered on (for SAP)." }, "sample_rate": { "type": "integer", "format": "int32", "minimum": 0 }, "source": { "type": "string" }, "ttl_secs": { "type": "integer", "format": "int64", "minimum": 0 } } }, "DskToggleRequest": { "type": "object", "description": "Request to toggle a DSK (Downstream Keyer) layer on a vision mixer block.", "required": [ "dsk", "enabled" ], "properties": { "dsk": { "type": "integer", "description": "DSK layer number (1 or 2, 1-based)", "minimum": 0 }, "enabled": { "type": "boolean", "description": "Enable or disable the DSK layer" } } }, "DskToggleResponse": { "type": "object", "description": "Response after toggling a DSK layer.", "required": [ "message", "dsk", "enabled" ], "properties": { "dsk": { "type": "integer", "description": "DSK layer number (1-based)", "minimum": 0 }, "enabled": { "type": "boolean" }, "message": { "type": "string" } } }, "DynamicPadsResponse": { "type": "object", "description": "Response containing runtime dynamic pads information.", "required": [ "pads" ], "properties": { "pads": { "type": "object", "description": "Map of element_id -> {pad_name -> tee_element_name}\nThese are pads that appeared at runtime without defined links.", "additionalProperties": { "type": "object", "additionalProperties": { "type": "string" }, "propertyNames": { "type": "string" } }, "propertyNames": { "type": "string" } } } }, "EffectTarget": { "oneOf": [ { "type": "object", "description": "A video input by index — the effect follows the source everywhere\n(PGM, PVW, thumbnails, PiPs).", "required": [ "input" ], "properties": { "input": { "type": "integer", "description": "A video input by index — the effect follows the source everywhere\n(PGM, PVW, thumbnails, PiPs).", "minimum": 0 } } }, { "type": "string", "description": "The PGM master output — applied after composition.", "enum": [ "master" ] } ], "description": "Where a [`VideoEffect`] is applied on a vision mixer block." }, "Element": { "type": "object", "description": "Represents a GStreamer element instance in a flow.", "required": [ "id", "element_type", "position" ], "properties": { "element_type": { "type": "string", "description": "GStreamer element type (e.g., \"videotestsrc\", \"x264enc\", \"filesink\")" }, "id": { "$ref": "#/components/schemas/String", "description": "Unique identifier for this element instance" }, "pad_properties": { "type": "object", "description": "Pad properties (pad_name -> property_name -> value)", "additionalProperties": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } }, "propertyNames": { "type": "string" } }, "position": { "type": "array", "items": { "type": "number", "format": "float" }, "description": "Display position in the visual editor (x, y)" }, "properties": { "type": "object", "description": "Element properties as key-value pairs", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } } } }, "ElementInfo": { "type": "object", "description": "Information about a GStreamer element type (for discovery/palette).", "required": [ "name", "description", "category", "src_pads", "sink_pads", "properties" ], "properties": { "category": { "type": "string", "description": "Element category (e.g., \"Source\", \"Filter\", \"Sink\", \"Codec\")" }, "description": { "type": "string", "description": "Human-readable description" }, "name": { "type": "string", "description": "Element type name" }, "properties": { "type": "array", "items": { "$ref": "#/components/schemas/PropertyInfo" }, "description": "Available properties" }, "sink_pads": { "type": "array", "items": { "$ref": "#/components/schemas/PadInfo" }, "description": "Available sink pads" }, "src_pads": { "type": "array", "items": { "$ref": "#/components/schemas/PadInfo" }, "description": "Available source pads" } } }, "ElementInfoResponse": { "type": "object", "description": "Response containing detailed information about a specific element.", "required": [ "element" ], "properties": { "element": { "$ref": "#/components/schemas/ElementInfo" } } }, "ElementListResponse": { "type": "object", "description": "Response containing information about available elements.", "required": [ "elements" ], "properties": { "elements": { "type": "array", "items": { "$ref": "#/components/schemas/ElementInfo" } } } }, "ElementPropertiesResponse": { "type": "object", "description": "Response containing current property values from a running element.", "required": [ "element_id", "properties" ], "properties": { "element_id": { "type": "string", "description": "The element ID" }, "properties": { "type": "object", "description": "Current property values", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } } } }, "EnumValue": { "type": "object", "description": "Enum value with optional label for display", "required": [ "value" ], "properties": { "label": { "type": [ "string", "null" ], "description": "Optional human-readable label for UI display" }, "value": { "type": "string", "description": "The actual value stored/used" } } }, "ErrorResponse": { "type": "object", "description": "Standard error response.", "required": [ "error" ], "properties": { "details": { "type": [ "string", "null" ] }, "error": { "type": "string" } } }, "ExportGstLaunchRequest": { "type": "object", "description": "Request to convert flow elements/links to gst-launch-1.0 syntax.", "required": [ "elements", "links" ], "properties": { "elements": { "type": "array", "items": { "$ref": "#/components/schemas/Element" }, "description": "Elements to export" }, "links": { "type": "array", "items": { "$ref": "#/components/schemas/Link" }, "description": "Links between elements" } } }, "ExportGstLaunchResponse": { "type": "object", "description": "Response containing the gst-launch-1.0 pipeline string.", "required": [ "pipeline" ], "properties": { "pipeline": { "type": "string", "description": "The generated gst-launch-1.0 pipeline string" } } }, "ExposedProperty": { "type": "object", "description": "Property exposed by a block to the outside", "required": [ "name", "label", "description", "property_type", "mapping" ], "properties": { "default_value": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/PropertyValue", "description": "Default value" } ] }, "description": { "type": "string", "description": "Description for users" }, "label": { "type": "string", "description": "Human-readable label for display in UI (e.g., \"Auth Token\" instead of \"auth_token\")" }, "live": { "type": "boolean", "description": "Whether this property updates the pipeline in real-time without requiring a flow save.\nLive properties show a LIVE badge in the UI and send updates directly to running elements." }, "mapping": { "$ref": "#/components/schemas/PropertyMapping", "description": "Mapping to internal element property" }, "name": { "type": "string", "description": "Name of the exposed property (used as key)" }, "persist": { "type": [ "boolean", "null" ], "description": "Whether live writes to this property should also be persisted to the\nblock instance's properties map (so they survive pipeline restart).\n\n`None` (default) means persist. Set explicitly to `Some(false)` for\ntransient properties — e.g. solo states like `chN_pfl`/`chN_afl` —\nthat should reset on restart and not dirty the flow on every toggle.\n\n`Option` is used here (rather than a bare `bool` with a serde default)\nto keep existing struct-literal call sites compiling — they get the\ndefault behaviour without an added field. Read via `persist()`." }, "property_type": { "$ref": "#/components/schemas/PropertyType", "description": "Type of property" } } }, "ExternalPad": { "type": "object", "required": [ "name", "media_type", "internal_element_id", "internal_pad_name" ], "properties": { "internal_element_id": { "type": "string", "description": "Which internal element and pad this maps to" }, "internal_pad_name": { "type": "string" }, "label": { "type": [ "string", "null" ], "description": "Optional display label (shown in graph editor)" }, "media_type": { "$ref": "#/components/schemas/MediaType", "description": "Media type (audio, video, generic)" }, "name": { "type": "string", "description": "External name for this pad" } } }, "ExternalPads": { "type": "object", "description": "External pads that the block exposes", "required": [ "inputs", "outputs" ], "properties": { "inputs": { "type": "array", "items": { "$ref": "#/components/schemas/ExternalPad" }, "description": "Input pads (mapped to internal element pads)" }, "outputs": { "type": "array", "items": { "$ref": "#/components/schemas/ExternalPad" }, "description": "Output pads (mapped to internal element pads)" } } }, "FadeToBlackRequest": { "type": "object", "description": "Request to toggle Fade to Black on a vision mixer block.", "required": [ "duration_ms" ], "properties": { "duration_ms": { "type": "integer", "format": "int64", "description": "Duration in milliseconds (0 = instant)", "minimum": 0 } } }, "FadeToBlackResponse": { "type": "object", "description": "Response after toggling Fade to Black.", "required": [ "message", "active" ], "properties": { "active": { "type": "boolean" }, "message": { "type": "string" } } }, "Flow": { "type": "object", "description": "A complete GStreamer pipeline definition.\n\nA flow represents a named, configured GStreamer pipeline that can be\nstarted, stopped, and persisted.", "required": [ "id", "name" ], "properties": { "blocks": { "type": "array", "items": { "$ref": "#/components/schemas/BlockInstance" }, "description": "Block instances in this flow" }, "elements": { "type": "array", "items": { "$ref": "#/components/schemas/Element" }, "description": "Elements in this flow" }, "gst_state": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/PipelineState", "description": "Raw GStreamer pipeline state, exposed for diagnostics.\n\nPrefer [`running`](Self::running) for logic and display." } ] }, "id": { "type": "string", "format": "uuid", "description": "Unique identifier for this flow" }, "links": { "type": "array", "items": { "$ref": "#/components/schemas/Link" }, "description": "Links between element pads and/or block external pads" }, "name": { "type": "string", "description": "Human-readable name" }, "properties": { "$ref": "#/components/schemas/FlowProperties", "description": "Flow configuration properties" }, "running": { "type": "boolean", "description": "Whether the pipeline is actively running (data flowing).\n\nThis is the field most callers should use. It is `true` when the\nGStreamer pipeline is in `Playing` *or* in `Paused` due to an\nasync element that has not yet completed its transition." } } }, "FlowDebugInfo": { "type": "object", "description": "Debug information for a running flow's pipeline.\nProvides detailed timing, clock, and state information for troubleshooting.", "required": [ "flow_id", "flow_name" ], "properties": { "base_time_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Pipeline base_time in nanoseconds (reference point for running_time calculation)", "minimum": 0 }, "clock_time_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Current clock time in nanoseconds", "minimum": 0 }, "clock_type": { "type": [ "string", "null" ], "description": "Clock type being used (e.g., \"PTP\", \"Monotonic\", \"Realtime\")" }, "element_count": { "type": [ "integer", "null" ], "format": "int32", "description": "Number of elements in the pipeline", "minimum": 0 }, "flow_id": { "type": "string", "format": "uuid", "description": "The flow ID" }, "flow_name": { "type": "string", "description": "The flow name" }, "is_live": { "type": [ "boolean", "null" ], "description": "Whether this is a live pipeline" }, "latency_formatted": { "type": [ "string", "null" ], "description": "Human-readable latency" }, "latency_max_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Maximum pipeline latency in nanoseconds", "minimum": 0 }, "latency_min_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Minimum pipeline latency in nanoseconds", "minimum": 0 }, "pipeline_state": { "type": [ "string", "null" ], "description": "Pipeline state (Playing, Paused, etc.)" }, "ptp_grandmaster": { "type": [ "string", "null" ], "description": "PTP grandmaster clock ID (only if using PTP clock)" }, "running_time_formatted": { "type": [ "string", "null" ], "description": "Human-readable running_time (how long the pipeline has been playing)" }, "running_time_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Current running time in nanoseconds (clock_time - base_time)", "minimum": 0 } } }, "FlowListResponse": { "type": "object", "description": "Response containing a list of flows.", "required": [ "flows" ], "properties": { "flows": { "type": "array", "items": { "$ref": "#/components/schemas/Flow" } } } }, "FlowProperties": { "type": "object", "description": "Flow configuration properties.", "properties": { "auto_restart": { "type": "boolean", "description": "Whether this flow should be automatically restarted when the backend starts\n(set to true when starting a flow, false when manually stopping it)" }, "clock_sync_status": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/ClockSyncStatus", "description": "Clock synchronization status (updated by backend for running pipelines)" } ] }, "clock_type": { "$ref": "#/components/schemas/GStreamerClockType", "description": "GStreamer clock type to use for this flow" }, "cpu_affinity": { "$ref": "#/components/schemas/CpuAffinity", "description": "CPU affinity for GStreamer streaming threads\nSingleCore pins all threads to one core for better cache locality" }, "created_at": { "type": [ "string", "null" ], "description": "Timestamp when the flow was created\nISO 8601 format with timezone" }, "description": { "type": [ "string", "null" ], "description": "Human-readable description (multiline text)" }, "direct_media_timing": { "type": [ "boolean", "null" ], "description": "Force direct media timing (`base_time=0`, `start_time=NONE`) so buffer\nPTS corresponds to absolute pipeline-clock time.\n\n- `Some(true)`: explicitly on.\n- `Some(false)`: explicitly off.\n- `None` (default): follow the clock-type default — `true` for `Ptp`\n (AES67 contract, RFC 7273 `mediaclk:direct=0`), `false` otherwise.\n\nUse this for narrow pipelines where every element cooperates with\nwall-clock timing (PTP+AES67, or TAI disciplined by `ptp4l`/`phc2sys`\nfeeding AES67 with TAI timestamps). Avoid for general pipelines\n(MPEG-TS demuxers, RTP jitter buffers, WHEP session sinks) that assume\n`running_time` starts near 0." }, "ephemeral": { "type": "boolean", "description": "When true, the flow is not persisted to storage. Useful for temporary or\nAPI-created flows that should not survive a server restart." }, "last_modified": { "type": [ "string", "null" ], "description": "Timestamp when the flow was last modified (any change to flow config)\nISO 8601 format with timezone" }, "ntp_info": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/NtpInfo", "description": "NTP clock information (updated by backend when clock_type is NTP)" } ] }, "ntp_port": { "type": [ "integer", "null" ], "format": "int32", "description": "NTP server port (only used when clock_type is NTP). Defaults to 123.", "minimum": 0 }, "ntp_server": { "type": [ "string", "null" ], "description": "NTP server address (hostname or IP, only used when clock_type is NTP)\nIf not set but clock_type is NTP, will signal as \"ntp=/traceable/\"" }, "ptp_domain": { "type": [ "integer", "null" ], "format": "int32", "description": "PTP domain (0-255, only used when clock_type is PTP)", "minimum": 0 }, "ptp_info": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/PtpInfo", "description": "PTP clock information (updated by backend when clock_type is PTP)" } ] }, "started_at": { "type": [ "string", "null" ], "description": "Timestamp when the flow was started (entered Playing state)\nISO 8601 format with timezone (e.g., \"2024-01-15T14:30:00+01:00\")\nNone if the flow has never been started or is currently stopped" }, "thread_priority": { "$ref": "#/components/schemas/ThreadPriority", "description": "Thread priority for GStreamer streaming threads\nDefault is High (elevated but not realtime)" }, "thread_priority_status": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/ThreadPriorityStatus", "description": "Status of thread priority configuration (updated by backend when pipeline starts)" } ] } } }, "FlowResponse": { "type": "object", "description": "Response containing a single flow.", "required": [ "flow" ], "properties": { "flow": { "$ref": "#/components/schemas/Flow" } } }, "FlowStatsResponse": { "type": "object", "description": "Response containing statistics for a running flow.", "required": [ "flow_id", "flow_name", "blocks", "collected_at" ], "properties": { "blocks": { "type": "array", "items": { "$ref": "#/components/schemas/BlockStats" }, "description": "Statistics for each block in the flow" }, "collected_at": { "type": "integer", "format": "int64", "description": "Timestamp when stats were collected (nanoseconds since UNIX epoch)", "minimum": 0 }, "flow_id": { "type": "string", "format": "uuid", "description": "The flow ID" }, "flow_name": { "type": "string", "description": "The flow name" } } }, "GStreamerClockType": { "type": "string", "description": "GStreamer clock type selection.\n\nMaps to GStreamer's clock implementations:\n- `Monotonic`: SystemClock with GST_CLOCK_TYPE_MONOTONIC (default)\n- `Realtime`: SystemClock with GST_CLOCK_TYPE_REALTIME (UTC wall clock)\n- `Tai`: SystemClock with GST_CLOCK_TYPE_TAI (linear atomic time, no leap seconds)\n- `Ptp`: PtpClock for IEEE 1588 PTP synchronization\n- `Ntp`: NtpClock for NTP synchronization", "enum": [ "monotonic", "realtime", "tai", "ptp", "ntp" ] }, "GlRendererInfo": { "type": "object", "description": "OpenGL renderer information detected from GStreamer's GL context.", "required": [ "renderer", "version", "vendor", "glsl_version" ], "properties": { "glsl_version": { "type": "string", "description": "GLSL version string (e.g. \"4.60 NVIDIA\")" }, "renderer": { "type": "string", "description": "GL renderer string (e.g. \"NVIDIA GeForce RTX 3080/PCIe/SSE2\")" }, "vendor": { "type": "string", "description": "GL vendor string (e.g. \"NVIDIA Corporation\")" }, "version": { "type": "string", "description": "GL version string (e.g. \"4.6.0 NVIDIA 535.183.01\")" } } }, "GotoRequest": { "type": "object", "description": "Request to go to a specific file.", "required": [ "index" ], "properties": { "index": { "type": "integer", "description": "File index (0-based)", "minimum": 0 } } }, "GpuStats": { "type": "object", "description": "GPU statistics for a single GPU device.", "required": [ "index", "name", "utilization", "memory_utilization", "total_memory", "used_memory" ], "properties": { "index": { "type": "integer", "format": "int32", "description": "GPU device index", "minimum": 0 }, "memory_utilization": { "type": "number", "format": "float", "description": "Memory utilization percentage (0-100)" }, "name": { "type": "string", "description": "GPU device name" }, "power_usage": { "type": [ "number", "null" ], "format": "float", "description": "Power usage in watts (if available)" }, "temperature": { "type": [ "number", "null" ], "format": "float", "description": "Temperature in Celsius (if available)" }, "total_memory": { "type": "integer", "format": "int64", "description": "Total memory in bytes", "minimum": 0 }, "used_memory": { "type": "integer", "format": "int64", "description": "Used memory in bytes", "minimum": 0 }, "utilization": { "type": "number", "format": "float", "description": "GPU utilization percentage (0-100)" } } }, "GstLogLevelResponse": { "type": "object", "description": "Response for GStreamer debug level queries and updates.", "required": [ "current", "default" ], "properties": { "current": { "type": "string", "description": "The currently active GST_DEBUG filter string (e.g. \"*:2,webrtcbin:5\")" }, "default": { "type": "string", "description": "The default GST_DEBUG filter the server started with" } } }, "IceCandidateStats": { "type": "object", "description": "ICE candidate statistics.", "properties": { "local_address": { "type": [ "string", "null" ], "description": "Local candidate address" }, "local_candidate_type": { "type": [ "string", "null" ], "description": "Local candidate type (host, srflx, relay)" }, "local_port": { "type": [ "integer", "null" ], "format": "int32", "description": "Local candidate port", "minimum": 0 }, "local_protocol": { "type": [ "string", "null" ], "description": "Local candidate protocol (UDP/TCP)" }, "remote_address": { "type": [ "string", "null" ], "description": "Remote candidate address" }, "remote_candidate_type": { "type": [ "string", "null" ], "description": "Remote candidate type" }, "remote_port": { "type": [ "integer", "null" ], "format": "int32", "description": "Remote candidate port", "minimum": 0 }, "remote_protocol": { "type": [ "string", "null" ], "description": "Remote candidate protocol" }, "state": { "type": [ "string", "null" ], "description": "Connection state" } } }, "IceServer": { "type": "object", "description": "ICE server configuration for WebRTC.\nFor TURN servers, username and credential are extracted from the URL.", "required": [ "urls" ], "properties": { "credential": { "type": [ "string", "null" ], "description": "Credential for TURN server authentication" }, "urls": { "type": "string", "description": "ICE server URL (e.g., \"stun:stun.l.google.com:19302\")" }, "username": { "type": [ "string", "null" ], "description": "Username for TURN server authentication" } } }, "IceServersResponse": { "type": "object", "description": "Response structure for ICE servers endpoint.", "required": [ "ice_servers", "ice_transport_policy" ], "properties": { "ice_servers": { "type": "array", "items": { "$ref": "#/components/schemas/IceServer" }, "description": "List of ICE server configurations (STUN/TURN)" }, "ice_transport_policy": { "type": "string", "description": "ICE transport policy (\"all\" or \"relay\")" } } }, "InputResolution": { "type": "object", "description": "Negotiated resolution of a video input, read from the compositor sink pad\ncaps. Inputs can have arbitrary resolutions and aspect ratios — nothing\nnormalizes them before the mixer.", "required": [ "width", "height" ], "properties": { "height": { "type": "integer", "format": "int32", "minimum": 0 }, "width": { "type": "integer", "format": "int32", "minimum": 0 } } }, "Ipv4AddressInfo": { "type": "object", "description": "IPv4 address information.", "required": [ "address" ], "properties": { "address": { "type": "string", "description": "The IPv4 address" }, "broadcast": { "type": [ "string", "null" ], "description": "Broadcast address (if available)" }, "netmask": { "type": [ "string", "null" ], "description": "Network mask (if available)" } } }, "Ipv6AddressInfo": { "type": "object", "description": "IPv6 address information.", "required": [ "address" ], "properties": { "address": { "type": "string", "description": "The IPv6 address" }, "netmask": { "type": [ "string", "null" ], "description": "Network mask (if available)" } } }, "JsonRpcRequest": { "type": "object", "description": "JSON-RPC 2.0 Request.", "required": [ "jsonrpc", "method" ], "properties": { "id": {}, "jsonrpc": { "type": "string" }, "method": { "type": "string" }, "params": {} } }, "LatencyResponse": { "type": "object", "description": "Response containing pipeline latency information.", "required": [ "min_latency_ns", "max_latency_ns", "live", "min_latency_formatted", "max_latency_formatted" ], "properties": { "live": { "type": "boolean", "description": "Whether the pipeline is a live pipeline" }, "max_latency_formatted": { "type": "string", "description": "Maximum latency formatted as human-readable string" }, "max_latency_ns": { "type": "integer", "format": "int64", "description": "Maximum latency in nanoseconds", "minimum": 0 }, "min_latency_formatted": { "type": "string", "description": "Minimum latency formatted as human-readable string (e.g., \"10.5 ms\")" }, "min_latency_ns": { "type": "integer", "format": "int64", "description": "Minimum latency in nanoseconds", "minimum": 0 } } }, "Link": { "type": "object", "description": "A link between two element pads.\n\nFor API/serialization compatibility, this uses strings. Internally converted to ElementPadRef.", "required": [ "from", "to" ], "properties": { "from": { "type": "string", "description": "Source element and pad (format: \"element_id\" or \"element_id:pad_name\")" }, "to": { "type": "string", "description": "Destination element and pad (format: \"element_id\" or \"element_id:pad_name\")" } } }, "ListMediaResponse": { "type": "object", "description": "Response containing a directory listing.", "required": [ "current_path", "entries" ], "properties": { "current_path": { "type": "string", "description": "Current directory path (relative to media root)" }, "entries": { "type": "array", "items": { "$ref": "#/components/schemas/MediaFileEntry" }, "description": "Directory contents" }, "parent_path": { "type": [ "string", "null" ], "description": "Parent directory path (None if at root)" } } }, "LogLevelResponse": { "type": "object", "description": "Response for log level queries and updates.", "required": [ "current", "default" ], "properties": { "current": { "type": "string", "description": "The currently active log filter string (e.g. \"info,strom::api=debug\")" }, "default": { "type": "string", "description": "The default filter the server started with" } } }, "LoginRequest": { "type": "object", "description": "Login request payload.", "required": [ "username", "password" ], "properties": { "password": { "type": "string", "description": "Password for authentication" }, "username": { "type": "string", "description": "Username for authentication" } } }, "LoginResponse": { "type": "object", "description": "Login response.", "required": [ "success", "message" ], "properties": { "message": { "type": "string", "description": "Human-readable message describing the result" }, "success": { "type": "boolean", "description": "Whether the login was successful" } } }, "MediaFileEntry": { "type": "object", "description": "A file or directory entry in a media directory listing.", "required": [ "name", "path", "is_directory", "size", "modified" ], "properties": { "is_directory": { "type": "boolean", "description": "Whether this is a directory" }, "mime_type": { "type": [ "string", "null" ], "description": "MIME type (None for directories)" }, "modified": { "type": "integer", "format": "int64", "description": "Last modified timestamp (UNIX epoch seconds)", "minimum": 0 }, "name": { "type": "string", "description": "File or directory name" }, "path": { "type": "string", "description": "Full path relative to media root" }, "size": { "type": "integer", "format": "int64", "description": "File size in bytes (0 for directories)", "minimum": 0 } } }, "MediaOperationResponse": { "type": "object", "description": "Response for media operations.", "required": [ "success", "message" ], "properties": { "message": { "type": "string", "description": "Human-readable message" }, "success": { "type": "boolean", "description": "Whether the operation succeeded" } } }, "MediaType": { "type": "string", "description": "Media type classification for pads.", "enum": [ "Generic", "Audio", "Video" ] }, "MultiviewEndpointResponse": { "type": "object", "description": "Response for a vision mixer multiview endpoint query.", "required": [ "endpoint" ], "properties": { "endpoint": { "type": "string", "description": "WHEP endpoint path (e.g. \"/whep/my-endpoint\"), empty if not connected." } } }, "NdiDiscoveryStatus": { "type": "object", "description": "NDI discovery status response.", "required": [ "available", "source_count" ], "properties": { "available": { "type": "boolean", "description": "Whether NDI discovery is available (plugin installed)." }, "source_count": { "type": "integer", "description": "Number of discovered NDI sources.", "minimum": 0 } } }, "NetworkInterfaceInfo": { "type": "object", "description": "Information about a network interface.", "required": [ "name", "index", "ipv4_addresses", "ipv6_addresses", "is_loopback", "is_up" ], "properties": { "index": { "type": "integer", "format": "int32", "description": "Interface index", "minimum": 0 }, "ipv4_addresses": { "type": "array", "items": { "$ref": "#/components/schemas/Ipv4AddressInfo" }, "description": "IPv4 addresses assigned to this interface" }, "ipv6_addresses": { "type": "array", "items": { "$ref": "#/components/schemas/Ipv6AddressInfo" }, "description": "IPv6 addresses assigned to this interface" }, "is_loopback": { "type": "boolean", "description": "Whether this interface is a loopback interface" }, "is_up": { "type": "boolean", "description": "Whether this interface appears to be up (has addresses)" }, "mac_address": { "type": [ "string", "null" ], "description": "MAC address (if available)" }, "name": { "type": "string", "description": "Interface name (e.g., \"eth0\", \"enp0s3\")" } } }, "NetworkInterfacesResponse": { "type": "object", "description": "Response containing list of network interfaces.", "required": [ "interfaces" ], "properties": { "interfaces": { "type": "array", "items": { "$ref": "#/components/schemas/NetworkInterfaceInfo" }, "description": "List of network interfaces" } } }, "NormRect": { "type": "object", "description": "Normalized rectangle in container coordinates. Each component is in `0.0..=1.0`.\n`(x, y)` is the top-left corner; `(w, h)` is the size.\n\nUsed to position a PiP overlay slot anywhere inside its parent region without\ncoupling to the output resolution.", "required": [ "x", "y", "w", "h" ], "properties": { "h": { "type": "number", "format": "float" }, "w": { "type": "number", "format": "float" }, "x": { "type": "number", "format": "float" }, "y": { "type": "number", "format": "float" } } }, "NtpInfo": { "type": "object", "description": "NTP clock information (GStreamer GstNtpClock / NetClientClock).\n\nPopulated at read-time from the running NtpClock instance. Values are snapshots\nfrom the clock's internal state at the moment the flow was queried.", "required": [ "server", "port", "synced", "minimum_update_interval_ns", "round_trip_limit_ns" ], "properties": { "last_update": { "type": [ "integer", "null" ], "format": "int64", "description": "Timestamp of last read (Unix seconds)", "minimum": 0 }, "minimum_update_interval_ns": { "type": "integer", "format": "int64", "description": "Minimum update interval between polls, in nanoseconds (from clock property)", "minimum": 0 }, "offset_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Current offset between external (server) and internal (local) clocks at\nthe calibration reference point, in nanoseconds. Positive = server ahead." }, "port": { "type": "integer", "format": "int32", "description": "Server port", "minimum": 0 }, "rate": { "type": [ "number", "null" ], "format": "double", "description": "Current calibration rate (external clock speed / local speed).\n1.0 = same speed, <1.0 = server slower than local, >1.0 = server faster." }, "round_trip_limit_ns": { "type": "integer", "format": "int64", "description": "Maximum RTT for accepted samples, in nanoseconds (from clock property)", "minimum": 0 }, "server": { "type": "string", "description": "Server hostname/IP the NtpClock is polling" }, "synced": { "type": "boolean", "description": "Whether the clock has collected enough observations to be considered stable" } } }, "OscAuthStatusResponse": { "type": "object", "description": "Status of the OSC Personal Access Token configuration. Token values are never\nreturned.", "required": [ "configured", "keys" ], "properties": { "configured": { "type": "boolean", "description": "Whether the default (fallback) PAT is configured (via env var or the\nkeyless API). Used for single-tenant deployments." }, "keys": { "type": "array", "items": { "type": "string" }, "description": "Credential keys (flow ids) that have a per-flow PAT registered. Used to\nisolate OSC tenants on a shared Strom instance." } } }, "OverlayAlphaRequest": { "type": "object", "description": "Request to set the multiview overlay alpha on a vision mixer block.", "required": [ "alpha" ], "properties": { "alpha": { "type": "number", "format": "double", "description": "Alpha value (0.0 = fully transparent, 1.0 = fully opaque)" } } }, "OverlayAlphaResponse": { "type": "object", "description": "Response after setting the multiview overlay alpha.", "required": [ "message", "alpha" ], "properties": { "alpha": { "type": "number", "format": "double" }, "message": { "type": "string" } } }, "PadInfo": { "type": "object", "description": "Information about an element pad.", "required": [ "name", "caps", "presence", "media_type" ], "properties": { "caps": { "type": "string", "description": "Pad capabilities (simplified)" }, "media_type": { "$ref": "#/components/schemas/MediaType", "description": "Media type classification" }, "name": { "type": "string", "description": "Pad name" }, "presence": { "$ref": "#/components/schemas/PadPresence", "description": "Pad presence type" }, "properties": { "type": "array", "items": { "$ref": "#/components/schemas/PropertyInfo" }, "description": "Properties available on this pad template" } } }, "PadPresence": { "type": "string", "description": "Pad presence type (static, dynamic, or request).", "enum": [ "Always", "Sometimes", "Request" ] }, "PadPropertiesResponse": { "type": "object", "description": "Response containing current property values from a pad.", "required": [ "element_id", "pad_name", "properties" ], "properties": { "element_id": { "type": "string", "description": "The element ID" }, "pad_name": { "type": "string", "description": "The pad name" }, "properties": { "type": "object", "description": "Current property values", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } } } }, "ParseGstLaunchRequest": { "type": "object", "description": "Request to parse a gst-launch-1.0 pipeline string.", "required": [ "pipeline" ], "properties": { "pipeline": { "type": "string", "description": "The gst-launch-1.0 pipeline string to parse\nExample: \"videotestsrc pattern=ball ! videoconvert ! autovideosink\"" } } }, "ParseGstLaunchResponse": { "type": "object", "description": "Response containing parsed pipeline elements and links.", "required": [ "elements", "links" ], "properties": { "elements": { "type": "array", "items": { "$ref": "#/components/schemas/Element" }, "description": "Elements extracted from the parsed pipeline" }, "links": { "type": "array", "items": { "$ref": "#/components/schemas/Link" }, "description": "Links between elements" } } }, "PipState": { "type": "object", "description": "One PiP composition's runtime state (background + zones).", "required": [ "zones" ], "properties": { "bg": { "type": [ "integer", "null" ], "description": "Background input index, or `None` if no bg is set.", "minimum": 0 }, "transforms": { "type": "object", "description": "Per-source crop transforms, keyed by input index.", "additionalProperties": { "$ref": "#/components/schemas/SourceCrop" }, "propertyNames": { "type": "string" } }, "zones": { "type": "array", "items": { "$ref": "#/components/schemas/Zone" }, "description": "Overlay zones (FIFO order, oldest first inside each zone)." } } }, "PipelineState": { "type": "string", "description": "GStreamer pipeline state.\n\nThese states correspond to the GStreamer GST_STATE enum.", "enum": [ "Null", "Ready", "Paused", "Playing" ] }, "PlayerAction": { "type": "string", "description": "Player control action.", "enum": [ "play", "pause", "stop", "next", "previous" ] }, "PlayerControlRequest": { "type": "object", "description": "Request to control the media player.", "required": [ "action" ], "properties": { "action": { "$ref": "#/components/schemas/PlayerAction" } } }, "PlayerState": { "type": "string", "description": "Playback state of a media player.", "enum": [ "playing", "paused", "stopped" ] }, "PlayerStateResponse": { "type": "object", "description": "Response with the current player state.", "required": [ "state", "position_ns", "duration_ns", "current_file_index", "total_files", "playlist", "loop_playlist" ], "properties": { "current_file": { "type": [ "string", "null" ], "description": "Current file path/URI" }, "current_file_index": { "type": "integer", "description": "Current file index (0-based)", "minimum": 0 }, "duration_ns": { "type": "integer", "format": "int64", "description": "Total duration in nanoseconds", "minimum": 0 }, "loop_playlist": { "type": "boolean", "description": "Whether playlist loops" }, "playlist": { "type": "array", "items": { "type": "string" }, "description": "Full playlist" }, "position_ns": { "type": "integer", "format": "int64", "description": "Current position in nanoseconds", "minimum": 0 }, "state": { "$ref": "#/components/schemas/PlayerState", "description": "Current playback state" }, "total_files": { "type": "integer", "description": "Total number of files in playlist", "minimum": 0 } } }, "Position": { "type": "object", "description": "Position in the visual editor", "required": [ "x", "y" ], "properties": { "x": { "type": "number", "format": "float" }, "y": { "type": "number", "format": "float" } } }, "ProbeInfo": { "type": "object", "description": "Information about an active probe.", "required": [ "probe_id", "element_id", "pad_name", "sample_count" ], "properties": { "element_id": { "type": "string", "description": "Element ID being probed" }, "pad_name": { "type": "string", "description": "Pad name being probed" }, "probe_id": { "type": "string", "description": "Unique probe ID" }, "sample_count": { "type": "integer", "format": "int64", "description": "Number of samples collected so far", "minimum": 0 } } }, "ProbeResponse": { "type": "object", "description": "Response after activating a probe.", "required": [ "probe_id" ], "properties": { "probe_id": { "type": "string", "description": "Unique probe ID" } } }, "PropertyInfo": { "type": "object", "description": "Information about an element property.", "required": [ "name", "description", "property_type" ], "properties": { "construct_only": { "type": "boolean", "description": "Property can only be set during construction" }, "controllable": { "type": "boolean", "description": "Property can be controlled over time with GstController" }, "default_value": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/PropertyValue", "description": "Default value" } ] }, "description": { "type": "string", "description": "Human-readable description" }, "mutable_in_null": { "type": "boolean", "description": "Property can be changed in NULL state" }, "mutable_in_paused": { "type": "boolean", "description": "Property can be changed in PAUSED state" }, "mutable_in_playing": { "type": "boolean", "description": "Property can be changed in PLAYING state (live editing!)" }, "mutable_in_ready": { "type": "boolean", "description": "Property can be changed in READY state" }, "name": { "type": "string", "description": "Property name" }, "property_type": { "$ref": "#/components/schemas/PropertyType", "description": "Property type" }, "writable": { "type": "boolean", "description": "Property is writable" } } }, "PropertyMapping": { "type": "object", "description": "Maps an exposed property to one or more internal element properties", "required": [ "element_id", "property_name" ], "properties": { "element_id": { "type": "string", "description": "Which internal element's property to set" }, "property_name": { "type": "string", "description": "Property name on that element" }, "transform": { "type": [ "string", "null" ], "description": "Optional transformation (for future use)" } } }, "PropertyType": { "oneOf": [ { "type": "string", "enum": [ "string" ] }, { "type": "string", "enum": [ "multiline" ] }, { "type": "string", "enum": [ "int" ] }, { "type": "string", "enum": [ "uint" ] }, { "type": "string", "enum": [ "float" ] }, { "type": "string", "enum": [ "bool" ] }, { "type": "object", "required": [ "enum" ], "properties": { "enum": { "type": "object", "required": [ "values" ], "properties": { "values": { "type": "array", "items": { "$ref": "#/components/schemas/EnumValue" } } } } } }, { "type": "string", "description": "Network interface selector - frontend fetches available interfaces from API", "enum": [ "networkinterface" ] }, { "type": "object", "description": "Local capture/playback device selector. Frontend fetches the live\ndevice list from `/api/discovery/devices?category=` and\nrenders a dropdown of `DeviceResponse`s.", "required": [ "device" ], "properties": { "device": { "type": "object", "description": "Local capture/playback device selector. Frontend fetches the live\ndevice list from `/api/discovery/devices?category=` and\nrenders a dropdown of `DeviceResponse`s.", "required": [ "category" ], "properties": { "category": { "$ref": "#/components/schemas/DeviceCategory", "description": "Which `DeviceCategory` to fetch and display (video source,\naudio source, audio sink, network source)." } } } } } ], "description": "Property type enumeration for exposed properties" }, "PropertyValue": { "oneOf": [ { "type": "string" }, { "type": "integer", "format": "int64" }, { "type": "integer", "format": "int64", "minimum": 0 }, { "type": "number", "format": "double" }, { "type": "boolean" } ], "description": "Property value that can be various types.\n\nGStreamer properties can be strings, numbers, booleans, enums, etc." }, "PtpInfo": { "type": "object", "description": "PTP clock information (IEEE 1588).\n\nContains detailed information about the PTP clock state including\ngrandmaster and master clock identities, and synchronization statistics.", "required": [ "domain", "synced" ], "properties": { "domain": { "type": "integer", "format": "int32", "description": "PTP domain currently in use by the running pipeline (0-255)", "minimum": 0 }, "grandmaster_clock_id": { "type": [ "string", "null" ], "description": "Grandmaster clock ID (EUI-64 format as hex string, e.g., \"00:11:22:FF:FE:33:44:55\")" }, "master_clock_id": { "type": [ "string", "null" ], "description": "Master clock ID (EUI-64 format as hex string)" }, "restart_needed": { "type": "boolean", "description": "True if configured domain differs from running domain (restart needed)" }, "stats": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/PtpStats", "description": "PTP synchronization statistics (updated periodically)" } ] }, "synced": { "type": "boolean", "description": "Whether the clock is synchronized with a PTP master" } } }, "PtpStats": { "type": "object", "description": "PTP clock synchronization statistics.\n\nContains measurements from PTP clock synchronization including\npath delay, clock offset, and estimation quality.", "properties": { "clock_offset_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Clock offset/discontinuity in nanoseconds (positive = local clock ahead)\nThis is the correction being applied to keep clocks synchronized" }, "clock_rate": { "type": [ "number", "null" ], "format": "double", "description": "Clock rate ratio (local clock speed relative to PTP master)\n1.0 means clocks run at same speed, <1.0 means local is slower" }, "last_update": { "type": [ "integer", "null" ], "format": "int64", "description": "Timestamp of last statistics update (Unix timestamp in seconds)", "minimum": 0 }, "mean_path_delay_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Mean path delay to master clock in nanoseconds", "minimum": 0 }, "r_squared": { "type": [ "number", "null" ], "format": "double", "description": "R-squared value of clock estimation regression (0.0-1.0, higher is better)\nValues close to 1.0 indicate stable, accurate synchronization" } } }, "RenameMediaRequest": { "type": "object", "description": "Request to rename a file or directory.", "required": [ "old_path", "new_name" ], "properties": { "new_name": { "type": "string", "description": "New name (just the filename, not full path)" }, "old_path": { "type": "string", "description": "Current path (relative to media root)" } } }, "RtpStreamStats": { "type": "object", "description": "RTP stream statistics (inbound or outbound).", "properties": { "bitrate": { "type": [ "integer", "null" ], "format": "int64", "description": "Bitrate in bits per second (calculated)", "minimum": 0 }, "bytes": { "type": [ "integer", "null" ], "format": "int64", "description": "Total bytes sent/received", "minimum": 0 }, "codec": { "type": [ "string", "null" ], "description": "Codec being used" }, "fraction_lost": { "type": [ "number", "null" ], "format": "double", "description": "Fraction of packets lost in last interval (0.0-1.0, inbound only)" }, "jitter": { "type": [ "number", "null" ], "format": "double", "description": "Jitter in seconds (inbound only)" }, "media_type": { "type": [ "string", "null" ], "description": "Media type (audio or video)" }, "packets": { "type": [ "integer", "null" ], "format": "int64", "description": "Total packets sent/received", "minimum": 0 }, "packets_lost": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets lost (inbound only)" }, "round_trip_time": { "type": [ "number", "null" ], "format": "double", "description": "Round-trip time in seconds" }, "ssrc": { "type": [ "integer", "null" ], "format": "int32", "description": "Stream identifier", "minimum": 0 } } }, "SeekRequest": { "type": "object", "description": "Request to seek to a position.", "required": [ "position_ns" ], "properties": { "position_ns": { "type": "integer", "format": "int64", "description": "Position in nanoseconds", "minimum": 0 } } }, "SelectPreviewRequest": { "type": "object", "description": "Request to select a preview source on a vision mixer block.", "required": [ "source" ], "properties": { "source": { "$ref": "#/components/schemas/Source", "description": "Source to place on the PVW bus." } } }, "SelectPreviewResponse": { "type": "object", "description": "Response after selecting a preview source.", "required": [ "message" ], "properties": { "message": { "type": "string" }, "preview_input": { "type": [ "integer", "null" ], "description": "Current PVW input. `None` when PVW is a PiP source.", "minimum": 0 }, "preview_pip": { "type": [ "integer", "null" ], "description": "PiP index currently displayed on PVW, or `None` if PVW is an input.", "minimum": 0 }, "program_input": { "type": [ "integer", "null" ], "description": "Current PGM input. `None` when PGM is a PiP source.", "minimum": 0 }, "program_pip": { "type": [ "integer", "null" ], "description": "PiP index currently displayed on PGM, or `None` if PGM is an input.", "minimum": 0 } } }, "ServerMessage": { "oneOf": [ { "type": "object", "description": "Pipeline state has changed", "required": [ "flow_id", "state", "type" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "state": { "$ref": "#/components/schemas/PipelineState" }, "type": { "type": "string", "enum": [ "state_change" ] } } }, { "type": "object", "description": "An error occurred", "required": [ "message", "type" ], "properties": { "flow_id": { "type": [ "string", "null" ] }, "message": { "type": "string" }, "type": { "type": "string", "enum": [ "error" ] } } }, { "type": "object", "description": "A warning message", "required": [ "message", "type" ], "properties": { "flow_id": { "type": [ "string", "null" ] }, "message": { "type": "string" }, "type": { "type": "string", "enum": [ "warning" ] } } }, { "type": "object", "description": "Informational message", "required": [ "message", "type" ], "properties": { "message": { "type": "string" }, "type": { "type": "string", "enum": [ "info" ] } } } ], "description": "Messages sent from server to client via WebSocket.", "discriminator": { "propertyName": "type" } }, "SetGstLogLevelRequest": { "type": "object", "description": "Request to change the GStreamer debug level at runtime.", "required": [ "filter" ], "properties": { "filter": { "type": "string", "description": "The new GST_DEBUG filter string (e.g. \"*:2,webrtcbin:5\")" } } }, "SetLogLevelRequest": { "type": "object", "description": "Request to change the log level at runtime.", "required": [ "filter" ], "properties": { "filter": { "type": "string", "description": "The new log filter string (e.g. \"info,strom::api=debug\")" } } }, "SetOscPatRequest": { "type": "object", "description": "Request to set the OSC Personal Access Token (PAT) at runtime.\n\nThe PAT is used to mint short-lived Service Access Tokens for OSC-hosted\nservices (e.g. a TAMS gateway). It is held in memory only — not persisted.", "required": [ "pat" ], "properties": { "pat": { "type": "string", "description": "The OSC Personal Access Token." } } }, "SetPlaylistRequest": { "type": "object", "description": "Request to set the playlist.", "required": [ "files" ], "properties": { "files": { "type": "array", "items": { "type": "string" }, "description": "List of file URIs (e.g., \"file:///path/to/video.mp4\")" } } }, "SetVideoEffectRequest": { "type": "object", "description": "Request to set a video effect on a vision mixer block.", "required": [ "target", "effect" ], "properties": { "effect": { "$ref": "#/components/schemas/VideoEffect", "description": "The effect to apply. `{\"type\": \"none\"}` clears." }, "target": { "$ref": "#/components/schemas/EffectTarget", "description": "Where to apply the effect." } } }, "SetVideoEffectResponse": { "type": "object", "description": "Response after setting a video effect.", "required": [ "message", "effect" ], "properties": { "effect": { "$ref": "#/components/schemas/VideoEffect", "description": "The effect as applied (after parameter clamping)." }, "message": { "type": "string" } } }, "Source": { "oneOf": [ { "type": "object", "description": "A regular video input by index.", "required": [ "input" ], "properties": { "input": { "type": "integer", "description": "A regular video input by index.", "minimum": 0 } } }, { "type": "object", "description": "A configured PiP composition by index.", "required": [ "pip" ], "properties": { "pip": { "type": "integer", "description": "A configured PiP composition by index.", "minimum": 0 } } } ], "description": "A source that can be assigned to PGM or PVW.\n\nJSON encoding is externally tagged: `{\"input\": 5}` or `{\"pip\": 1}`.\nThe [`FromStr`] / [`fmt::Display`] impls use a separate compact form\n(`\"input:N\"` / `\"pip:N\"`, case-insensitive) for stored block properties." }, "SourceCrop": { "type": "object", "description": "Normalized per-source crop: the fraction of the source hidden from each\nedge. All components are in `0.0..=1.0`; all zero = no crop.\n\nThe crop selects which part of the source fills its destination rect —\ncombined with a zone rect this gives \"zoom\"/\"punch-in\" framing (the\ncropped region scales to fill the zone box; everything outside is hidden).\nNormalized fractions keep the type resolution-independent; the backend\nconverts to pixels against the negotiated source caps.", "properties": { "bottom": { "type": "number", "format": "float", "description": "Fraction of the source height hidden from the bottom edge." }, "left": { "type": "number", "format": "float", "description": "Fraction of the source width hidden from the left edge." }, "right": { "type": "number", "format": "float", "description": "Fraction of the source width hidden from the right edge." }, "top": { "type": "number", "format": "float", "description": "Fraction of the source height hidden from the top edge." } } }, "SourceFlowInfo": { "type": "object", "description": "Information about a flow that has published outputs.", "required": [ "flow_id", "flow_name", "outputs" ], "properties": { "flow_id": { "type": "string", "format": "uuid", "description": "The flow ID" }, "flow_name": { "type": "string", "description": "The flow name" }, "outputs": { "type": "array", "items": { "$ref": "#/components/schemas/AvailableOutput" }, "description": "Available outputs from this flow" } } }, "SrtCallerStats": { "type": "object", "description": "Stats for a single SRT caller/peer.\n\nFields are grouped by direction so that consumers don't have to guess which\ncounter applies to which role. A `srtsink` populates the sender-side fields\nand leaves the receiver-side ones empty; a `srtsrc` does the opposite. Link\nmetrics (RTT, bandwidth, negotiated latency) apply to both directions.", "properties": { "address": { "type": [ "string", "null" ], "description": "Peer address (`ip:port`), when known." }, "bandwidth_mbps": { "type": [ "number", "null" ], "format": "double", "description": "Estimated link bandwidth between the two endpoints (Mbps)." }, "bytes_received": { "type": [ "integer", "null" ], "format": "int64", "description": "Total bytes received.", "minimum": 0 }, "bytes_sent": { "type": [ "integer", "null" ], "format": "int64", "description": "Total bytes sent.", "minimum": 0 }, "negotiated_latency_ms": { "type": [ "integer", "null" ], "format": "int32", "description": "Negotiated SRT latency (ms).", "minimum": 0 }, "packets_received": { "type": [ "integer", "null" ], "format": "int64", "description": "Total packets received.", "minimum": 0 }, "packets_received_dropped": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets skipped by the receiver due to TSBPD timeout.", "minimum": 0 }, "packets_received_lost": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets the receiver detected as missing.", "minimum": 0 }, "packets_received_retransmitted": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets received that were retransmissions of earlier lost packets.", "minimum": 0 }, "packets_retransmitted": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets the sender retransmitted in response to NAKs.", "minimum": 0 }, "packets_sent": { "type": [ "integer", "null" ], "format": "int64", "description": "Total packets sent.", "minimum": 0 }, "packets_sent_dropped": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets dropped locally before transmission (TLPKTDROP).", "minimum": 0 }, "packets_sent_lost": { "type": [ "integer", "null" ], "format": "int64", "description": "Packets lost on the wire and reported by NAK from the peer.", "minimum": 0 }, "recv_buf_level_ms": { "type": [ "integer", "null" ], "format": "int32", "description": "Receiver buffer fill level (ms).", "minimum": 0 }, "recv_rate_mbps": { "type": [ "number", "null" ], "format": "double", "description": "Instantaneous receive rate (Mbps)." }, "rtt_ms": { "type": [ "number", "null" ], "format": "double", "description": "Smoothed round-trip time (ms)." }, "send_rate_mbps": { "type": [ "number", "null" ], "format": "double", "description": "Instantaneous send rate (Mbps)." }, "snd_buf_level_ms": { "type": [ "integer", "null" ], "format": "int32", "description": "Sender buffer fill level (ms).", "minimum": 0 } } }, "SrtConnectionStats": { "type": "object", "description": "Stats for a single SRT element (srtsrc or srtsink).", "required": [ "role", "connected", "callers" ], "properties": { "callers": { "type": "array", "items": { "$ref": "#/components/schemas/SrtCallerStats" }, "description": "Per-caller stats. Always contains one entry for caller/rendezvous mode and the\nsingle peer of a caller-mode srtsrc; may contain zero or many entries for\nlistener mode (one per connected caller)." }, "connected": { "type": "boolean", "description": "True when at least one caller is exchanging data." }, "mode": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/SrtMode", "description": "Connection mode (`caller`/`listener`/`rendezvous`)." } ] }, "role": { "$ref": "#/components/schemas/SrtRole", "description": "Element role — determines which side of `SrtCallerStats` is populated." } } }, "SrtMode": { "type": "string", "description": "SRT connection mode (matches the `mode` enum nicks exposed by the SRT plugin).", "enum": [ "caller", "listener", "rendezvous" ] }, "SrtRole": { "type": "string", "description": "Direction in which an SRT element transports data.", "enum": [ "sink", "source" ] }, "SrtStats": { "type": "object", "description": "SRT statistics for a flow. Covers both srtsink (outputs) and srtsrc (inputs).", "required": [ "connections" ], "properties": { "connections": { "type": "object", "description": "Stats for each SRT element, keyed by element name (`block_id:srtsrc`/`block_id:srtsink`).", "additionalProperties": { "$ref": "#/components/schemas/SrtConnectionStats" }, "propertyNames": { "type": "string" } } } }, "SrtStatsResponse": { "type": "object", "description": "Response containing SRT statistics.", "required": [ "flow_id", "stats" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "stats": { "$ref": "#/components/schemas/SrtStats" } } }, "StatMetadata": { "type": "object", "description": "Metadata about a statistic.", "required": [ "display_name", "description" ], "properties": { "category": { "type": [ "string", "null" ], "description": "Category for grouping in UI (e.g., \"RTP\", \"Buffer\", \"Network\")" }, "description": { "type": "string", "description": "Description of what this statistic measures" }, "display_name": { "type": "string", "description": "Human-readable name for display" }, "unit": { "type": [ "string", "null" ], "description": "Unit of measurement (e.g., \"packets\", \"ms\", \"bytes\")" } } }, "StatValue": { "oneOf": [ { "type": "object", "description": "Counter - monotonically increasing value (e.g., packets received)", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "Counter" ] }, "value": { "type": "integer", "format": "int64", "description": "Counter - monotonically increasing value (e.g., packets received)", "minimum": 0 } } }, { "type": "object", "description": "Gauge - value that can go up or down (e.g., buffer level)", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "Gauge" ] }, "value": { "type": "integer", "format": "int64", "description": "Gauge - value that can go up or down (e.g., buffer level)" } } }, { "type": "object", "description": "Float value (e.g., average jitter)", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "Float" ] }, "value": { "type": "number", "format": "double", "description": "Float value (e.g., average jitter)" } } }, { "type": "object", "description": "Boolean flag (e.g., is_synced)", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "Bool" ] }, "value": { "type": "boolean", "description": "Boolean flag (e.g., is_synced)" } } }, { "type": "object", "description": "String value (e.g., current SSRC)", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "String" ] }, "value": { "type": "string", "description": "String value (e.g., current SSRC)" } } }, { "type": "object", "description": "Duration in nanoseconds", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "DurationNs" ] }, "value": { "type": "integer", "format": "int64", "description": "Duration in nanoseconds", "minimum": 0 } } }, { "type": "object", "description": "Timestamp in nanoseconds since epoch", "required": [ "value", "type" ], "properties": { "type": { "type": "string", "enum": [ "TimestampNs" ] }, "value": { "type": "integer", "format": "int64", "description": "Timestamp in nanoseconds since epoch", "minimum": 0 } } } ], "description": "A single statistic value with metadata." }, "Statistic": { "type": "object", "description": "A statistic with its current value and metadata.", "required": [ "id", "value", "metadata" ], "properties": { "id": { "type": "string", "description": "Unique identifier for this statistic within the block" }, "metadata": { "$ref": "#/components/schemas/StatMetadata", "description": "Metadata about this statistic" }, "value": { "$ref": "#/components/schemas/StatValue", "description": "Current value" } } }, "String": { "type": "string" }, "StromEvent": { "oneOf": [ { "type": "object", "description": "A flow was created", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow was created", "required": [ "flow_id" ], "properties": { "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "FlowCreated" ] } } }, { "type": "object", "description": "A flow was updated", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow was updated", "required": [ "flow_id" ], "properties": { "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "FlowUpdated" ] } } }, { "type": "object", "description": "A flow was deleted", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow was deleted", "required": [ "flow_id" ], "properties": { "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "FlowDeleted" ] } } }, { "type": "object", "description": "A flow was started", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow was started", "required": [ "flow_id" ], "properties": { "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "FlowStarted" ] } } }, { "type": "object", "description": "A flow was stopped", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow was stopped", "required": [ "flow_id" ], "properties": { "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "FlowStopped" ] } } }, { "type": "object", "description": "A flow's state changed", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow's state changed", "required": [ "flow_id", "state" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "state": { "type": "string" } } }, "type": { "type": "string", "enum": [ "FlowStateChanged" ] } } }, { "type": "object", "description": "Pipeline error occurred", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Pipeline error occurred", "required": [ "flow_id", "error" ], "properties": { "error": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "source": { "type": [ "string", "null" ] } } }, "type": { "type": "string", "enum": [ "PipelineError" ] } } }, { "type": "object", "description": "Pipeline warning message", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Pipeline warning message", "required": [ "flow_id", "warning" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "source": { "type": [ "string", "null" ] }, "warning": { "type": "string" } } }, "type": { "type": "string", "enum": [ "PipelineWarning" ] } } }, { "type": "object", "description": "Pipeline info message", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Pipeline info message", "required": [ "flow_id", "message" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "message": { "type": "string" }, "source": { "type": [ "string", "null" ] } } }, "type": { "type": "string", "enum": [ "PipelineInfo" ] } } }, { "type": "object", "description": "Pipeline reached end of stream", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Pipeline reached end of stream", "required": [ "flow_id" ], "properties": { "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "PipelineEos" ] } } }, { "type": "object", "description": "Element property was changed on a running pipeline", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Element property was changed on a running pipeline", "required": [ "flow_id", "element_id", "property_name", "value" ], "properties": { "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "property_name": { "type": "string" }, "value": { "$ref": "#/components/schemas/PropertyValue" } } }, "type": { "type": "string", "enum": [ "PropertyChanged" ] } } }, { "type": "object", "description": "Pad property was changed on a running pipeline", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Pad property was changed on a running pipeline", "required": [ "flow_id", "element_id", "pad_name", "property_name", "value" ], "properties": { "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "pad_name": { "type": "string" }, "property_name": { "type": "string" }, "value": { "$ref": "#/components/schemas/PropertyValue" } } }, "type": { "type": "string", "enum": [ "PadPropertyChanged" ] } } }, { "type": "object", "description": "Ping event to keep connection alive", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "Ping" ] } } }, { "type": "object", "description": "Audio level meter data from GStreamer level element", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Audio level meter data from GStreamer level element", "required": [ "flow_id", "element_id", "rms", "peak", "decay" ], "properties": { "decay": { "type": "array", "items": { "type": "number", "format": "double" }, "description": "Decay values in dB for each channel" }, "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "peak": { "type": "array", "items": { "type": "number", "format": "double" }, "description": "Peak values in dB for each channel" }, "rms": { "type": "array", "items": { "type": "number", "format": "double" }, "description": "RMS values in dB for each channel" } } }, "type": { "type": "string", "enum": [ "MeterData" ] } } }, { "type": "object", "description": "Audio spectrum analyzer data from GStreamer spectrum element", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Audio spectrum analyzer data from GStreamer spectrum element", "required": [ "flow_id", "element_id", "magnitudes" ], "properties": { "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "magnitudes": { "type": "array", "items": { "type": "array", "items": { "type": "number", "format": "float" } }, "description": "Magnitude values in dB per channel, each inner Vec is one channel's frequency bands" } } }, "type": { "type": "string", "enum": [ "SpectrumData" ] } } }, { "type": "object", "description": "EBU R128 loudness measurement data from GStreamer ebur128level element", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "EBU R128 loudness measurement data from GStreamer ebur128level element", "required": [ "flow_id", "element_id", "momentary", "true_peak" ], "properties": { "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "integrated": { "type": [ "number", "null" ], "format": "double", "description": "Integrated (global) loudness in LUFS (from start)" }, "loudness_range": { "type": [ "number", "null" ], "format": "double", "description": "Loudness range in LU" }, "momentary": { "type": "number", "format": "double", "description": "Momentary loudness in LUFS (400ms window)" }, "shortterm": { "type": [ "number", "null" ], "format": "double", "description": "Short-term loudness in LUFS (3s window)" }, "true_peak": { "type": "array", "items": { "type": "number", "format": "double" }, "description": "True peak per channel in dBTP" } } }, "type": { "type": "string", "enum": [ "LoudnessData" ] } } }, { "type": "object", "description": "Audio latency measurement data from GStreamer audiolatency element", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Audio latency measurement data from GStreamer audiolatency element", "required": [ "flow_id", "element_id", "last_latency_us", "average_latency_us" ], "properties": { "average_latency_us": { "type": "integer", "format": "int64", "description": "Running average latency in microseconds (last 5 measurements)" }, "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "last_latency_us": { "type": "integer", "format": "int64", "description": "Last measured latency in microseconds" } } }, "type": { "type": "string", "enum": [ "LatencyData" ] } } }, { "type": "object", "description": "System monitoring statistics (CPU and GPU)", "required": [ "data", "type" ], "properties": { "data": { "$ref": "#/components/schemas/SystemStats", "description": "System monitoring statistics (CPU and GPU)" }, "type": { "type": "string", "enum": [ "SystemStats" ] } } }, { "type": "object", "description": "Thread CPU statistics for GStreamer streaming threads", "required": [ "data", "type" ], "properties": { "data": { "$ref": "#/components/schemas/ThreadStats", "description": "Thread CPU statistics for GStreamer streaming threads" }, "type": { "type": "string", "enum": [ "ThreadStats" ] } } }, { "type": "object", "description": "PTP clock statistics for a flow", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "PTP clock statistics for a flow", "required": [ "flow_id", "domain", "synced" ], "properties": { "clock_offset_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Clock offset/correction in nanoseconds" }, "clock_rate": { "type": [ "number", "null" ], "format": "double", "description": "Clock rate ratio (local vs master)" }, "domain": { "type": "integer", "format": "int32", "description": "PTP domain", "minimum": 0 }, "flow_id": { "type": "string", "format": "uuid" }, "grandmaster_id": { "type": [ "integer", "null" ], "format": "int64", "description": "Grandmaster clock ID (EUI-64 identifier)", "minimum": 0 }, "master_id": { "type": [ "integer", "null" ], "format": "int64", "description": "Master clock ID (EUI-64 identifier)", "minimum": 0 }, "mean_path_delay_ns": { "type": [ "integer", "null" ], "format": "int64", "description": "Mean path delay to master in nanoseconds", "minimum": 0 }, "r_squared": { "type": [ "number", "null" ], "format": "double", "description": "R-squared (clock estimation quality, 0.0-1.0)" }, "synced": { "type": "boolean", "description": "Whether clock is synchronized" } } }, "type": { "type": "string", "enum": [ "PtpStats" ] } } }, { "type": "object", "description": "A flow's published output became available (flow started)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow's published output became available (flow started)", "required": [ "source_flow_id", "output_name", "channel_name" ], "properties": { "channel_name": { "type": "string" }, "output_name": { "type": "string" }, "source_flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "SourceOutputAvailable" ] } } }, { "type": "object", "description": "A flow's published output became unavailable (flow stopped)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A flow's published output became unavailable (flow stopped)", "required": [ "source_flow_id", "output_name" ], "properties": { "output_name": { "type": "string" }, "source_flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "SourceOutputUnavailable" ] } } }, { "type": "object", "description": "Subscription connection status changed", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Subscription connection status changed", "required": [ "consumer_flow_id", "source_flow_id", "output_name", "connected" ], "properties": { "connected": { "type": "boolean" }, "consumer_flow_id": { "type": "string", "format": "uuid" }, "output_name": { "type": "string" }, "source_flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "SubscriptionStatusChanged" ] } } }, { "type": "object", "description": "Quality of Service statistics (aggregated buffer drop info)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Quality of Service statistics (aggregated buffer drop info)", "required": [ "flow_id", "element_id", "element_name", "event_count", "avg_proportion", "min_proportion", "max_proportion", "avg_jitter", "total_processed", "is_falling_behind" ], "properties": { "avg_jitter": { "type": "integer", "format": "int64", "description": "Average jitter in nanoseconds" }, "avg_proportion": { "type": "number", "format": "double", "description": "Average proportion (< 1.0 = falling behind)" }, "block_id": { "type": [ "string", "null" ], "description": "Block ID if element is inside a block, None if standalone element" }, "element_id": { "type": "string", "description": "Element ID (standalone element ID or block ID if element is in block)" }, "element_name": { "type": "string", "description": "Full GStreamer element name (e.g., \"block_id:element_type\" or \"element_id\")" }, "event_count": { "type": "integer", "format": "int64", "description": "Number of QoS events in aggregation period", "minimum": 0 }, "flow_id": { "type": "string", "format": "uuid" }, "internal_element_type": { "type": [ "string", "null" ], "description": "Internal element type if part of a block (e.g., \"videoconvert\")" }, "is_falling_behind": { "type": "boolean", "description": "Whether pipeline is falling behind (avg_proportion < 1.0)" }, "max_proportion": { "type": "number", "format": "double", "description": "Maximum proportion seen" }, "min_proportion": { "type": "number", "format": "double", "description": "Minimum proportion seen" }, "total_processed": { "type": "integer", "format": "int64", "description": "Total buffers processed", "minimum": 0 } } }, "type": { "type": "string", "enum": [ "QoSStats" ] } } }, { "type": "object", "description": "A new AES67 stream was discovered via SAP or mDNS", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A new AES67 stream was discovered via SAP or mDNS", "required": [ "stream_id", "name", "source" ], "properties": { "name": { "type": "string" }, "source": { "type": "string", "description": "Discovery source: \"sap\" or \"mdns\"" }, "stream_id": { "type": "string" } } }, "type": { "type": "string", "enum": [ "StreamDiscovered" ] } } }, { "type": "object", "description": "A discovered stream was updated (re-announced)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A discovered stream was updated (re-announced)", "required": [ "stream_id" ], "properties": { "stream_id": { "type": "string" } } }, "type": { "type": "string", "enum": [ "StreamUpdated" ] } } }, { "type": "object", "description": "A discovered stream expired or was deleted", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A discovered stream expired or was deleted", "required": [ "stream_id" ], "properties": { "stream_id": { "type": "string" } } }, "type": { "type": "string", "enum": [ "StreamRemoved" ] } } }, { "type": "object", "description": "Media player position update (periodic)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Media player position update (periodic)", "required": [ "flow_id", "block_id", "position_ns", "duration_ns", "current_file_index", "total_files" ], "properties": { "block_id": { "type": "string" }, "current_file_index": { "type": "integer", "description": "Current file index (0-based)", "minimum": 0 }, "duration_ns": { "type": "integer", "format": "int64", "description": "Total duration in nanoseconds", "minimum": 0 }, "flow_id": { "type": "string", "format": "uuid" }, "position_ns": { "type": "integer", "format": "int64", "description": "Current position in nanoseconds", "minimum": 0 }, "total_files": { "type": "integer", "description": "Total number of files in playlist", "minimum": 0 } } }, "type": { "type": "string", "enum": [ "MediaPlayerPosition" ] } } }, { "type": "object", "description": "Media player state changed", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Media player state changed", "required": [ "flow_id", "block_id", "state" ], "properties": { "block_id": { "type": "string" }, "current_file": { "type": [ "string", "null" ], "description": "Current file path (if any)" }, "flow_id": { "type": "string", "format": "uuid" }, "state": { "$ref": "#/components/schemas/PlayerState", "description": "Playback state" } } }, "type": { "type": "string", "enum": [ "MediaPlayerStateChanged" ] } } }, { "type": "object", "description": "A transition was triggered on a compositor block", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A transition was triggered on a compositor block", "required": [ "flow_id", "block_instance_id", "from_input", "to_input", "transition_type", "duration_ms" ], "properties": { "block_instance_id": { "type": "string" }, "duration_ms": { "type": "integer", "format": "int64", "minimum": 0 }, "flow_id": { "type": "string", "format": "uuid" }, "from_input": { "type": "integer", "minimum": 0 }, "to_input": { "type": "integer", "minimum": 0 }, "transition_type": { "type": "string" } } }, "type": { "type": "string", "enum": [ "TransitionTriggered" ] } } }, { "type": "object", "description": "Audio analyzer waveform and vectorscope data from appsink", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Audio analyzer waveform and vectorscope data from appsink", "required": [ "flow_id", "element_id", "waveform_l_min", "waveform_l_max", "waveform_r_min", "waveform_r_max", "vectorscope_l", "vectorscope_r" ], "properties": { "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "vectorscope_l": { "type": "string", "description": "Vectorscope L channel samples (base64-encoded i8 samples)" }, "vectorscope_r": { "type": "string", "description": "Vectorscope R channel samples (base64-encoded i8 samples)" }, "waveform_l_max": { "type": "string", "description": "Waveform max values per column for L channel (base64-encoded i8 samples)" }, "waveform_l_min": { "type": "string", "description": "Waveform min values per column for L channel (base64-encoded i8 samples)" }, "waveform_r_max": { "type": "string", "description": "Waveform max values per column for R channel (base64-encoded i8 samples)" }, "waveform_r_min": { "type": "string", "description": "Waveform min values per column for R channel (base64-encoded i8 samples)" } } }, "type": { "type": "string", "enum": [ "AudioAnalyzerData" ] } } }, { "type": "object", "description": "Recorder block started writing a new file", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Recorder block started writing a new file", "required": [ "flow_id", "block_id", "filename" ], "properties": { "block_id": { "type": "string" }, "filename": { "type": "string", "description": "Full path to the file currently being written" }, "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "RecorderFileChanged" ] } } }, { "type": "object", "description": "Recorder block reached its configured max duration and requests the flow to stop", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Recorder block reached its configured max duration and requests the flow to stop", "required": [ "flow_id", "block_id" ], "properties": { "block_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "RecorderAutoStop" ] } } }, { "type": "object", "description": "TAMS Output block successfully uploaded and registered a media segment", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "TAMS Output block successfully uploaded and registered a media segment", "required": [ "flow_id", "block_id", "tams_flow_id", "object_id", "timerange" ], "properties": { "block_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "object_id": { "type": "string", "description": "TAMS object id of the uploaded media object (`/`)" }, "tams_flow_id": { "type": "string", "description": "TAMS flow UUID the segment was registered on" }, "timerange": { "type": "string", "description": "TAMS timerange string `[:_:)`" } } }, "type": { "type": "string", "enum": [ "TamsSegmentRegistered" ] } } }, { "type": "object", "description": "TAMS Output block failed to upload or register a segment", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "TAMS Output block failed to upload or register a segment", "required": [ "flow_id", "block_id", "error" ], "properties": { "block_id": { "type": "string" }, "error": { "type": "string", "description": "Human-readable error description" }, "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "TamsError" ] } } }, { "type": "object", "description": "Buffer age warning (buffer is older than threshold)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Buffer age warning (buffer is older than threshold)", "required": [ "flow_id", "element_id", "pad_name", "age_ms", "threshold_ms" ], "properties": { "age_ms": { "type": "integer", "format": "int64", "description": "Buffer age in milliseconds", "minimum": 0 }, "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "pad_name": { "type": "string" }, "threshold_ms": { "type": "integer", "format": "int64", "description": "Threshold that was exceeded, in milliseconds", "minimum": 0 } } }, "type": { "type": "string", "enum": [ "BufferAgeWarning" ] } } }, { "type": "object", "description": "Manual buffer age probe measurement", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Manual buffer age probe measurement", "required": [ "flow_id", "probe_id", "element_id", "pad_name", "age_ms", "sample_number" ], "properties": { "age_ms": { "type": "integer", "format": "int64", "description": "Buffer age in milliseconds", "minimum": 0 }, "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "pad_name": { "type": "string" }, "probe_id": { "type": "string" }, "sample_number": { "type": "integer", "format": "int64", "description": "Sequential sample number", "minimum": 0 } } }, "type": { "type": "string", "enum": [ "BufferAgeProbe" ] } } }, { "type": "object", "description": "A manual buffer age probe was activated", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A manual buffer age probe was activated", "required": [ "flow_id", "probe_id", "element_id", "pad_name" ], "properties": { "element_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "pad_name": { "type": "string" }, "probe_id": { "type": "string" } } }, "type": { "type": "string", "enum": [ "BufferAgeProbeActivated" ] } } }, { "type": "object", "description": "A manual buffer age probe was deactivated", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "A manual buffer age probe was deactivated", "required": [ "flow_id", "probe_id", "reason" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "probe_id": { "type": "string" }, "reason": { "type": "string", "description": "Reason: \"manual\", \"timeout\", \"flow_stopped\"" } } }, "type": { "type": "string", "enum": [ "BufferAgeProbeDeactivated" ] } } }, { "type": "object", "description": "Vision mixer PVW/PGM state changed", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Vision mixer PVW/PGM state changed", "required": [ "flow_id", "block_id" ], "properties": { "block_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" }, "preview_input": { "type": [ "integer", "null" ], "description": "Current PVW input. `None` when PVW is a PiP source.", "minimum": 0 }, "preview_pip": { "type": [ "integer", "null" ], "description": "PiP index on PVW, or `None` if PVW is an input.", "minimum": 0 }, "program_input": { "type": [ "integer", "null" ], "description": "Current PGM input. `None` when PGM is a PiP source.", "minimum": 0 }, "program_pip": { "type": [ "integer", "null" ], "description": "PiP index on PGM, or `None` if PGM is an input.", "minimum": 0 } } }, "type": { "type": "string", "enum": [ "VisionMixerStateChanged" ] } } }, { "type": "object", "description": "Vision mixer DSK layer toggled", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Vision mixer DSK layer toggled", "required": [ "flow_id", "block_id", "dsk", "enabled" ], "properties": { "block_id": { "type": "string" }, "dsk": { "type": "integer", "description": "DSK layer number (1-based)", "minimum": 0 }, "enabled": { "type": "boolean" }, "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "VisionMixerDskChanged" ] } } }, { "type": "object", "description": "Vision mixer multiview overlay alpha changed", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Vision mixer multiview overlay alpha changed", "required": [ "flow_id", "block_id", "alpha" ], "properties": { "alpha": { "type": "number", "format": "double" }, "block_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "VisionMixerOverlayAlphaChanged" ] } } }, { "type": "object", "description": "Vision mixer Fade to Black state changed", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Vision mixer Fade to Black state changed", "required": [ "flow_id", "block_id", "active" ], "properties": { "active": { "type": "boolean" }, "block_id": { "type": "string" }, "flow_id": { "type": "string", "format": "uuid" } } }, "type": { "type": "string", "enum": [ "VisionMixerFtbChanged" ] } } }, { "type": "object", "description": "Vision mixer video effect changed (shader FX engine)", "required": [ "data", "type" ], "properties": { "data": { "type": "object", "description": "Vision mixer video effect changed (shader FX engine)", "required": [ "flow_id", "block_id", "target", "effect" ], "properties": { "block_id": { "type": "string" }, "effect": { "$ref": "#/components/schemas/VideoEffect", "description": "The effect as applied (after parameter clamping)." }, "flow_id": { "type": "string", "format": "uuid" }, "target": { "$ref": "#/components/schemas/EffectTarget", "description": "Where the effect was applied (an input or the PGM master)." } } }, "type": { "type": "string", "enum": [ "VisionMixerEffectChanged" ] } } } ], "description": "Event types that can be broadcast to all connected clients.", "discriminator": { "propertyName": "type" } }, "SystemClockInfo": { "type": "object", "description": "System clock synchronization information.\n\nReads the kernel's `ntp_adjtime()` state (same information used by chrony,\nntpd, systemd-timesyncd, etc.) and reports how the system clock is being\ndisciplined. Relevant for flows using Realtime or TAI pipeline clocks.", "required": [ "tai_offset_sec", "state", "synchronized", "pll_active", "offset_ns", "frequency_ppm", "max_error_us", "est_error_us" ], "properties": { "est_error_us": { "type": "integer", "format": "int64", "description": "Estimated error, in microseconds." }, "frequency_ppm": { "type": "number", "format": "double", "description": "Current frequency adjustment in parts-per-million." }, "last_update": { "type": [ "integer", "null" ], "format": "int64", "description": "Timestamp when this info was read (Unix seconds).", "minimum": 0 }, "max_error_us": { "type": "integer", "format": "int64", "description": "Maximum error estimate, in microseconds." }, "offset_ns": { "type": "integer", "format": "int64", "description": "Current time offset being applied to the clock, in nanoseconds." }, "pll_active": { "type": "boolean", "description": "Whether PLL discipline is active (STA_PLL)." }, "state": { "type": "string", "description": "High-level state from `ntp_adjtime()` return value.\nOne of: `ok`, `ins` (leap insert pending), `del`, `oop`, `wait`, `error` (unsynced)." }, "synchronized": { "type": "boolean", "description": "Whether the kernel considers the clock synchronized (STA_UNSYNC not set)." }, "tai_offset_sec": { "type": "integer", "format": "int32", "description": "TAI - UTC offset in seconds (typically 37 as of 2026).\nSet by the clock sync daemon so that `CLOCK_TAI` is correct." } } }, "SystemInfo": { "type": "object", "description": "Server system information: version, build, runtime environment, and host details.", "required": [ "version", "git_hash", "git_tag", "git_branch", "git_dirty", "build_timestamp" ], "properties": { "build_id": { "type": "string", "description": "Unique build ID (UUID) generated at compile time" }, "build_timestamp": { "type": "string", "description": "Build timestamp (ISO 8601 format)" }, "git_branch": { "type": "string", "description": "Git branch name" }, "git_dirty": { "type": "boolean", "description": "Whether the working directory had uncommitted changes" }, "git_hash": { "type": "string", "description": "Git commit hash (short)" }, "git_tag": { "type": "string", "description": "Git tag (if on a tagged commit)" }, "gstreamer_version": { "type": "string", "description": "GStreamer runtime version" }, "hostname": { "type": "string", "description": "Server hostname (for generating external URLs)" }, "in_docker": { "type": "boolean", "description": "Whether running inside a Docker container" }, "os_info": { "type": "string", "description": "Operating system name and version" }, "process_started_at": { "type": "string", "description": "When the Strom server process was started (ISO 8601 format with timezone)" }, "system_boot_time": { "type": "string", "description": "When the system was booted (ISO 8601 format with timezone)" }, "version": { "type": "string", "description": "Package version from Cargo.toml" } } }, "SystemStats": { "type": "object", "description": "System monitoring statistics.", "required": [ "cpu_usage", "num_cores", "total_memory", "used_memory", "gpu_stats", "timestamp" ], "properties": { "cpu_usage": { "type": "number", "format": "float", "description": "CPU usage percentage (0-100)" }, "gl_renderer": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/GlRendererInfo", "description": "OpenGL renderer info from GStreamer (if available)" } ] }, "gpu_stats": { "type": "array", "items": { "$ref": "#/components/schemas/GpuStats" }, "description": "GPU statistics (if available)" }, "num_cores": { "type": "integer", "description": "Number of CPU cores available to this process (cgroup-aware)", "minimum": 0 }, "timestamp": { "type": "integer", "format": "int64", "description": "Timestamp of the measurement" }, "total_memory": { "type": "integer", "format": "int64", "description": "Total system memory in bytes", "minimum": 0 }, "used_memory": { "type": "integer", "format": "int64", "description": "Used system memory in bytes", "minimum": 0 } } }, "ThreadCpuStats": { "type": "object", "description": "CPU statistics for a single GStreamer streaming thread.", "required": [ "thread_id", "cpu_usage", "element_name", "flow_id" ], "properties": { "block_id": { "type": [ "string", "null" ], "description": "Block ID if the element is inside a block" }, "cpu_usage": { "type": "number", "format": "float", "description": "CPU usage percentage (0-100%)" }, "element_name": { "type": "string", "description": "Name of the GStreamer element that owns this thread" }, "flow_id": { "type": "string", "format": "uuid", "description": "Flow ID this thread belongs to" }, "pinned_cpus": { "type": [ "array", "null" ], "items": { "type": "integer", "minimum": 0 }, "description": "Logical CPUs this thread is pinned to (None if affinity is off).\nContains all sibling hyperthreads of the allocated physical core." }, "thread_id": { "type": "integer", "format": "int64", "description": "Native thread ID (OS-specific)", "minimum": 0 } } }, "ThreadPriority": { "type": "string", "description": "Thread priority level for GStreamer streaming threads.\n\nControls the scheduling priority of GStreamer's internal streaming threads.\nHigher priorities help ensure smooth media processing under system load.", "enum": [ "normal", "high", "realtime" ] }, "ThreadPriorityStatus": { "type": "object", "description": "Status of thread priority configuration for a running pipeline.", "required": [ "requested", "achieved", "threads_configured" ], "properties": { "achieved": { "type": "boolean", "description": "Whether the requested priority was successfully applied" }, "error": { "type": [ "string", "null" ], "description": "Error message if priority could not be set (empty if achieved)" }, "requested": { "$ref": "#/components/schemas/ThreadPriority", "description": "The requested thread priority level" }, "threads_configured": { "type": "integer", "format": "int32", "description": "Number of threads that had priority set", "minimum": 0 } } }, "ThreadStats": { "type": "object", "description": "Aggregated thread statistics for all GStreamer streaming threads.", "required": [ "threads", "timestamp" ], "properties": { "threads": { "type": "array", "items": { "$ref": "#/components/schemas/ThreadCpuStats" }, "description": "Statistics for all active streaming threads" }, "timestamp": { "type": "integer", "format": "int64", "description": "Timestamp when this snapshot was taken (Unix timestamp in milliseconds)" } } }, "TransitionResponse": { "type": "object", "description": "Response after triggering a transition.\n\nReports *what was done*, not the resulting bus state — for the latter,\nlisten to the `VisionMixerStateChanged` WebSocket event, which is\nbroadcast immediately after the take completes.", "required": [ "message", "transition_type", "actual_transition_type", "duration_ms" ], "properties": { "actual_transition_type": { "type": "string", "description": "The transition type that was actually executed. Differs from\n`transition_type` when the engine downgraded the request — e.g.\nSlide/Push across heterogeneous PiP/input sources downgrades to \"fade\"." }, "duration_ms": { "type": "integer", "format": "int64", "description": "Duration of the transition in milliseconds", "minimum": 0 }, "message": { "type": "string", "description": "Success message" }, "transition_type": { "type": "string", "description": "The transition type requested by the client." } } }, "TransportStats": { "type": "object", "description": "Transport statistics.", "properties": { "bytes_received": { "type": [ "integer", "null" ], "format": "int64", "description": "Total bytes received", "minimum": 0 }, "bytes_sent": { "type": [ "integer", "null" ], "format": "int64", "description": "Total bytes sent", "minimum": 0 }, "packets_received": { "type": [ "integer", "null" ], "format": "int64", "description": "Total packets received", "minimum": 0 }, "packets_sent": { "type": [ "integer", "null" ], "format": "int64", "description": "Total packets sent", "minimum": 0 } } }, "TriggerTransitionRequest": { "type": "object", "description": "Request to trigger a transition on a compositor block.", "required": [ "from_input", "to_input" ], "properties": { "duration_ms": { "type": "integer", "format": "int64", "description": "Duration of the transition in milliseconds (ignored for \"cut\")", "minimum": 0 }, "from_input": { "type": "integer", "description": "Index of the currently active input (0-based)", "minimum": 0 }, "to_input": { "type": "integer", "description": "Index of the input to transition to (0-based)", "minimum": 0 }, "transition_type": { "type": "string", "description": "Type of transition: \"cut\", \"fade\", \"slide_left\", \"slide_right\", \"slide_up\", \"slide_down\"" } } }, "UpdateBlockPropertiesRequest": { "type": "object", "description": "Request to update one or more exposed properties on a block instance live.\n\nValues are expressed in the block-level (user-facing) units defined by the block\n— e.g. `ch1_pfl: true` (Bool), `fader_db: -3.0` (dB). The backend resolves each\nproperty to its underlying GStreamer element via the block's PropertyMapping and\napplies the declared transform (`bool_to_volume`, `db_to_linear`, …) before\nwriting.\n\nOnly properties marked `live: true` in the block definition can be patched via\nthis endpoint. Non-live properties must go through the regular flow update.", "required": [ "properties" ], "properties": { "properties": { "type": "object", "description": "Map of exposed property name → new value (in block-level units).", "additionalProperties": { "$ref": "#/components/schemas/PropertyValue" }, "propertyNames": { "type": "string" } }, "ramp_ms": { "type": [ "integer", "null" ], "format": "int32", "description": "Optional default ramp duration in ms applied to every property in this\nbatch (honored for volume-element writes — produces anti-click fades for\nbool/dB toggles that map to a `volume` property). Acts as the fallback\nwhen no per-property override is set in `ramp_ms_overrides`.", "minimum": 0 }, "ramp_ms_overrides": { "type": [ "object", "null" ], "description": "Optional per-property ramp duration overrides, keyed by exposed\nproperty name. When a property in `properties` has an entry here, that\nduration is used instead of the batch-level `ramp_ms`. Entries for\nnames not present in `properties` are silently ignored. Only effective\nfor properties whose underlying write goes through the ramp path\n(currently audio `volume`-element `volume` and `mute`); for other\nproperties the override is accepted but has no effect, matching the\nbehavior of the batch-level `ramp_ms`. Enables crossfades where\nindividual faders ramp at different rates within a single PATCH.", "additionalProperties": { "type": "integer", "format": "int32", "minimum": 0 }, "propertyNames": { "type": "string" } } } }, "UpdateFlowPropertiesRequest": { "type": "object", "description": "Request to update flow properties.", "required": [ "properties" ], "properties": { "properties": { "$ref": "#/components/schemas/FlowProperties" } } }, "UpdatePadPropertyRequest": { "type": "object", "description": "Request to update a property on a pad in a running pipeline.", "required": [ "property_name", "value" ], "properties": { "property_name": { "type": "string", "description": "The name of the property to update" }, "value": { "$ref": "#/components/schemas/PropertyValue", "description": "The new value for the property" } } }, "UpdatePipConfigRequest": { "type": "object", "description": "Request to update a PiP composition (background source + zones).\n\nA PiP is a background source plus zero or more zones. Each zone is a\nsub-region with its own current sources (FIFO, oldest first) that\nauto-tile inside the zone's rect. See [`crate::vision_mixer::Zone`].", "properties": { "bg": { "type": [ "integer", "null" ], "description": "Background input index. Omit/null for no bg.", "minimum": 0 }, "transforms": { "type": "object", "description": "Per-source crop (\"zoom\"/\"punch-in\"), keyed by input index. Applies to\nthe source wherever it renders inside this PiP (bg or zone). Missing\nkey = no crop. Entries for sources currently *outside* the PiP are\nretained and re-apply when the source returns (swap-zone workflow);\nremoving a crop is explicit — omit/delete its entry while the source\nis present. See [`crate::vision_mixer::SourceCrop`].", "additionalProperties": { "$ref": "#/components/schemas/SourceCrop" }, "propertyNames": { "type": "string" } }, "zones": { "type": "array", "items": { "$ref": "#/components/schemas/Zone" }, "description": "Zones in z-order (zone 0 lowest, last zone on top). Sources within a\nzone are also in z-order (oldest first)." } } }, "UpdatePipConfigResponse": { "type": "object", "description": "Response after updating a PiP composition.", "required": [ "message", "pip_idx", "zones" ], "properties": { "bg": { "type": [ "integer", "null" ], "minimum": 0 }, "message": { "type": "string" }, "pip_idx": { "type": "integer", "minimum": 0 }, "transforms": { "type": "object", "description": "Authoritative per-source crop state. Identical to the request except\nthat crop fractions are clamped (see `SourceCrop::clamped`).", "additionalProperties": { "$ref": "#/components/schemas/SourceCrop" }, "propertyNames": { "type": "string" } }, "zones": { "type": "array", "items": { "$ref": "#/components/schemas/Zone" }, "description": "Authoritative zone state. Identical to the request except that\n`NormRect`s are clamped to `[0,1]`. Duplicate sources or out-of-range\nindices are rejected with 400 rather than silently sanitized." } } }, "UpdatePropertyRequest": { "type": "object", "description": "Request to update a property on a running pipeline element.", "required": [ "property_name", "value" ], "properties": { "property_name": { "type": "string", "description": "The name of the property to update" }, "ramp_ms": { "type": [ "integer", "null" ], "format": "int32", "description": "Optional ramp duration in milliseconds. Currently honored for audio\n`volume`-element `volume` and `mute` updates — when set, `volume` is\ninterpolated per-sample over the given duration (anti-zipper / fade)\nand `mute=true` is preceded by a fade-out of the same length while\n`mute=false` is followed by a 0→pre_mute fade-in. Useful for\nbroadcast-style on-air / off-air route transitions (e.g. 500 ms).\nWhen omitted, a short default ramp is used for `volume`/`mute`; other\nproperties are set immediately.", "minimum": 0 }, "value": { "$ref": "#/components/schemas/PropertyValue", "description": "The new value for the property" } } }, "VideoEffect": { "oneOf": [ { "type": "object", "description": "No effect (identity passthrough).", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "none" ] } } }, { "type": "object", "description": "Chroma key: pixels close to `key_color` become transparent.", "required": [ "type" ], "properties": { "key_color": { "type": "string", "description": "Key color as `#RRGGBB` (typically green `#00B140` or blue)." }, "similarity": { "type": "number", "format": "float", "description": "Chroma distance below which pixels are fully keyed (0..1)." }, "smoothness": { "type": "number", "format": "float", "description": "Soft edge width added above `similarity` (0..1)." }, "spill": { "type": "number", "format": "float", "description": "Spill suppression amount — desaturates key-colored fringes (0..1)." }, "type": { "type": "string", "enum": [ "chroma_key" ] } } }, { "type": "object", "description": "Mosaic pixelation (privacy or stylization).", "required": [ "type" ], "properties": { "block_size": { "type": "number", "format": "float", "description": "Block size in source pixels (2..200)." }, "type": { "type": "string", "enum": [ "pixelate" ] } } }, { "type": "object", "description": "Disc-bokeh defocus blur (24-tap Vogel spiral, single pass).", "required": [ "type" ], "properties": { "radius": { "type": "number", "format": "float", "description": "Blur radius in source pixels (0..40)." }, "type": { "type": "string", "enum": [ "blur" ] } } }, { "type": "object", "description": "Two-color luma mapping. `low`=black point color, `high`=white point\ncolor. Grayscale = `#000000`/`#FFFFFF`, sepia = `#2B1D0E`/`#FFF1DF`.", "required": [ "type" ], "properties": { "high": { "type": "string" }, "low": { "type": "string" }, "mix": { "type": "number", "format": "float", "description": "Blend between original (0) and duotone (1)." }, "type": { "type": "string", "enum": [ "duotone" ] } } }, { "type": "object", "description": "Darkened corners.", "required": [ "type" ], "properties": { "amount": { "type": "number", "format": "float", "description": "Strength of the darkening (0..1)." }, "softness": { "type": "number", "format": "float", "description": "Falloff softness (0.01..1)." }, "type": { "type": "string", "enum": [ "vignette" ] } } }, { "type": "object", "description": "Animated VHS look: chroma shift, scanlines, tape noise.", "required": [ "type" ], "properties": { "intensity": { "type": "number", "format": "float", "description": "Overall intensity (0..1)." }, "type": { "type": "string", "enum": [ "vhs" ] } } }, { "type": "object", "description": "Animated old-film look: grain, flicker, scratches, warm tone.", "required": [ "type" ], "properties": { "intensity": { "type": "number", "format": "float", "description": "Overall intensity (0..1)." }, "type": { "type": "string", "enum": [ "old_film" ] } } }, { "type": "object", "description": "Edge detection glow added on top of the image.", "required": [ "type" ], "properties": { "color": { "type": "string", "description": "Glow color as `#RRGGBB`." }, "intensity": { "type": "number", "format": "float", "description": "Glow strength (0..1)." }, "type": { "type": "string", "enum": [ "edge_glow" ] } } }, { "type": "object", "description": "CRT monitor: barrel distortion, scanlines, RGB grille.", "required": [ "type" ], "properties": { "intensity": { "type": "number", "format": "float", "description": "Overall intensity (0..1)." }, "type": { "type": "string", "enum": [ "crt" ] } } }, { "type": "object", "description": "Newspaper-print halftone dots.", "required": [ "type" ], "properties": { "dot_size": { "type": "number", "format": "float", "description": "Dot grid size in pixels (3..40)." }, "type": { "type": "string", "enum": [ "halftone" ] } } }, { "type": "object", "description": "Thermal-camera false color over luma.", "required": [ "type" ], "properties": { "intensity": { "type": "number", "format": "float", "description": "Blend between original (0) and thermal (1)." }, "type": { "type": "string", "enum": [ "thermal" ] } } }, { "type": "object", "description": "Night-vision scope: green phosphor, lifted shadows, grain, vignette.", "required": [ "type" ], "properties": { "intensity": { "type": "number", "format": "float", "description": "Blend between original (0) and night vision (1)." }, "type": { "type": "string", "enum": [ "night_vision" ] } } }, { "type": "object", "description": "Color quantization into bands (screen-print / toon).", "required": [ "type" ], "properties": { "levels": { "type": "number", "format": "float", "description": "Number of levels per channel (2..16)." }, "type": { "type": "string", "enum": [ "posterize" ] } } }, { "type": "object", "description": "Underwater: wavy refraction, blue-green grade, caustic shimmer.", "required": [ "type" ], "properties": { "intensity": { "type": "number", "format": "float", "description": "Overall intensity (0..1)." }, "type": { "type": "string", "enum": [ "underwater" ] } } }, { "type": "object", "description": "Primary color correction + white balance — the camera-matching tool.\nEvery control is neutral at its default, so an untouched correction is\nan identity pass. Applied in a fixed order: white balance, brightness,\ncontrast, hue, saturation, gamma.", "required": [ "type" ], "properties": { "brightness": { "type": "number", "format": "float", "description": "Additive brightness offset (-1..1, neutral 0)." }, "contrast": { "type": "number", "format": "float", "description": "Contrast multiplier around mid-gray (0..2, neutral 1)." }, "gamma": { "type": "number", "format": "float", "description": "Midtone gamma curve (0.1..3, neutral 1)." }, "hue": { "type": "number", "format": "float", "description": "Hue rotation: -1..1 maps to -180..180 degrees (neutral 0)." }, "saturation": { "type": "number", "format": "float", "description": "Saturation: 0 = grayscale, 1 = unchanged, up to 2 (0..2, neutral 1)." }, "temperature": { "type": "number", "format": "float", "description": "White balance temperature: warm (+) / cool (-) (-1..1, neutral 0)." }, "tint": { "type": "number", "format": "float", "description": "White balance tint: magenta (+) / green (-) (-1..1, neutral 0)." }, "type": { "type": "string", "enum": [ "color_correct" ] } } } ], "description": "A persistent video effect (\"look\") applied to a vision mixer input or to\nthe PGM master output.\n\nJSON encoding is internally tagged on `type`:\n`{\"type\": \"pixelate\", \"block_size\": 24.0}`.\n\nAll numeric parameters are clamped server-side (see [`VideoEffect::sanitized`]);\ncolors are `#RRGGBB` hex strings." }, "VisionMixerState": { "type": "object", "description": "Current runtime state of a vision mixer block.\n\nThis is the snapshot a client uses to reconcile on (re)connect when WS\nevents have not yet arrived. Static config (input count, labels, DSK\ncount) is *not* included — that lives on the block resource itself.", "required": [ "ftb_active", "dsk_enabled", "overlay_alpha", "pips" ], "properties": { "dsk_enabled": { "type": "array", "items": { "type": "boolean" }, "description": "DSK on/off state, one entry per configured DSK input." }, "ftb_active": { "type": "boolean", "description": "Whether Fade to Black is currently active." }, "fx_available": { "type": "boolean", "description": "Whether the shader FX engine is built into this pipeline (GPU backend\nwith Shader FX enabled). When `false`, effect endpoints reject and\nshader transitions downgrade to Fade." }, "input_effects": { "type": "array", "items": { "$ref": "#/components/schemas/VideoEffect" }, "description": "Current per-input video effects (length = configured `num_inputs`).\nEmpty when the FX engine is unavailable." }, "input_resolutions": { "type": "array", "items": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/InputResolution" } ] }, "description": "Negotiated resolution per input (length = configured `num_inputs`).\n`None` for inputs whose caps are not negotiated yet. Inputs can have\narbitrary resolutions/aspects — clients must not assume the PGM aspect\n(the crop editor needs the real source aspect for its window math)." }, "master_effect": { "$ref": "#/components/schemas/VideoEffect", "description": "Current master (PGM) video effect." }, "overlay_alpha": { "type": "number", "format": "double", "description": "Multiview overlay alpha (0.0–1.0)." }, "pips": { "type": "array", "items": { "$ref": "#/components/schemas/PipState" }, "description": "Per-PiP runtime state (length = configured `num_pips`)." }, "preview_input": { "type": [ "integer", "null" ], "description": "Current PVW input. `None` when PVW is a PiP source.", "minimum": 0 }, "preview_pip": { "type": [ "integer", "null" ], "description": "PiP index currently displayed on PVW, or `None` if PVW is an input.", "minimum": 0 }, "program_input": { "type": [ "integer", "null" ], "description": "Current PGM input. `None` when PGM is a PiP source.", "minimum": 0 }, "program_pip": { "type": [ "integer", "null" ], "description": "PiP index currently displayed on PGM, or `None` if PGM is an input.", "minimum": 0 } } }, "WebRtcConnectionStats": { "type": "object", "description": "Stats for a single WebRTC connection (webrtcbin element).", "required": [ "inbound_rtp", "outbound_rtp", "codecs", "raw" ], "properties": { "codecs": { "type": "array", "items": { "$ref": "#/components/schemas/CodecStats" }, "description": "Codec statistics (keyed by codec ID)" }, "ice_candidates": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/IceCandidateStats", "description": "ICE candidate pair statistics" } ] }, "inbound_rtp": { "type": "array", "items": { "$ref": "#/components/schemas/RtpStreamStats" }, "description": "Inbound RTP stream statistics" }, "outbound_rtp": { "type": "array", "items": { "$ref": "#/components/schemas/RtpStreamStats" }, "description": "Outbound RTP stream statistics" }, "raw": { "type": "object", "description": "Raw stats as key-value pairs (for debugging/extensibility)", "additionalProperties": { "type": "string" }, "propertyNames": { "type": "string" } }, "transport": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/TransportStats", "description": "Transport statistics" } ] } } }, "WebRtcStats": { "type": "object", "description": "WebRTC statistics for a flow.", "required": [ "connections" ], "properties": { "connections": { "type": "object", "description": "Stats for each WebRTC connection (keyed by element name)", "additionalProperties": { "$ref": "#/components/schemas/WebRtcConnectionStats" }, "propertyNames": { "type": "string" } } } }, "WebRtcStatsResponse": { "type": "object", "description": "Response containing WebRTC statistics.", "required": [ "flow_id", "stats" ], "properties": { "flow_id": { "type": "string", "format": "uuid" }, "stats": { "$ref": "#/components/schemas/WebRtcStats" } } }, "WhepStreamInfo": { "type": "object", "description": "Response structure for a WHEP stream.", "required": [ "endpoint_id", "num_audio_tracks", "num_video_tracks" ], "properties": { "endpoint_id": { "type": "string", "description": "Unique identifier for the WHEP endpoint" }, "num_audio_tracks": { "type": "integer", "description": "Number of independent audio tracks exposed by this endpoint (0 = audio\ndisabled). Clients should add this many recvonly audio transceivers in\ntheir offer.", "minimum": 0 }, "num_video_tracks": { "type": "integer", "description": "Number of independent video tracks exposed by this endpoint (0 = video\ndisabled). Clients should add this many recvonly video transceivers in\ntheir offer.", "minimum": 0 } } }, "WhepStreamsResponse": { "type": "object", "description": "Response structure for the streams list endpoint.", "required": [ "streams" ], "properties": { "streams": { "type": "array", "items": { "$ref": "#/components/schemas/WhepStreamInfo" }, "description": "List of active WHEP streams" } } }, "Zone": { "type": "object", "description": "A sub-region of a PiP that hosts one or more overlay sources.\n\nSources inside a zone auto-tile within its `rect` (using\n[`compute_pip_overlay_rects`]) so the zone behaves like a \"mini-PiP\"\nnested inside the parent PiP region. The `capacity` puts a cap on how\nmany sources can occupy the zone; pushing a new source into a full zone\nis expected to evict the oldest (client-side FIFO).", "properties": { "border": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/ZoneBorder", "description": "Border drawn around each source box in this zone (None = no border).\nRendered live on the PGM overlay — follows morphs/takes/punch-ins." } ] }, "capacity": { "type": [ "integer", "null" ], "description": "Max sources allowed in the zone. `None` = unlimited (up to\n[`MAX_PIP_OVERLAYS`]). A capacity of 1 is \"swap mode\": replacing\nthe source animates a cross-fade.", "minimum": 0 }, "rect": { "oneOf": [ { "type": "null" }, { "$ref": "#/components/schemas/NormRect", "description": "Where the zone sits within the parent PiP region.\n`None` = fill the entire PiP region." } ] }, "sources": { "type": "array", "items": { "type": "integer", "minimum": 0 }, "description": "Current sources (FIFO, oldest first). Sources auto-tile within `rect`." } } }, "ZoneBorder": { "type": "object", "description": "Border drawn around each source box in a zone.\n\nRendered by the mixer itself on a PGM-side overlay — borders are a\nfunction of the mixer's own live geometry (boxes move with morphs, takes\nand punch-ins), so no external graphics source could stay in sync.", "required": [ "color", "width" ], "properties": { "color": { "type": "string", "description": "Border color as `#RRGGBB` or `#RRGGBBAA` hex." }, "width": { "type": "number", "format": "float", "description": "Border width in PGM canvas pixels, drawn outward from the box edge.\nEvery render target scales it by `region_width / pgm_width`, so the\nborder looks proportionally identical on PGM, the PVW big display and\nthe PiP thumbnails regardless of resolution." } } } } }, "tags": [ { "name": "flows", "description": "GStreamer flow management endpoints" }, { "name": "elements", "description": "GStreamer element discovery endpoints" }, { "name": "blocks", "description": "Reusable block management endpoints" }, { "name": "gst-launch", "description": "gst-launch-1.0 import/export endpoints" }, { "name": "Network", "description": "Network interface discovery endpoints" }, { "name": "System", "description": "System information endpoints" }, { "name": "Media", "description": "Media file management endpoints" }, { "name": "auth", "description": "Authentication endpoints" }, { "name": "whep", "description": "WHEP WebRTC playback endpoints" }, { "name": "whip", "description": "WHIP WebRTC ingest endpoints" }, { "name": "mcp", "description": "Model Context Protocol (MCP) endpoints" }, { "name": "discovery", "description": "AES67 stream and device discovery endpoints" }, { "name": "media_player", "description": "Media player control endpoints" }, { "name": "probes", "description": "Buffer age probe endpoints" }, { "name": "websocket", "description": "WebSocket real-time communication" } ] }