Skip to content

Streams API

The stream methods read and modify the stream list of the configuration, start and stop streams, switch their inputs and report their status. Most of them are served on the POST /control/ entry point with the command name in cmd; the read-only status and info methods and the output group method are served on the path entry point. See How to call API methods for the entry points, authentication and roles. Every method on this page answers 200 with a JSON body: a failed command reports the failure inside the body, either as the value "er" under the command name or as an error field, never with an HTTP error status.

A stream is a JSON object in the make_stream list of the configuration. The API stores the object as sent; only the fields below are read by the methods on this page, every other option is passed through to the stream when it starts. For the full option set see the stream configuration articles: SPTS Service Settings, SPTS Backup Settings and MPTS General Settings.

{
"id": "a001",
"name": "Channel 1",
"type": "spts",
"enable": true,
"input": [
"udp://239.255.1.1:1234"
],
"output": [
"udp://239.255.2.1:1234"
]
}
  • id - string. Unique stream identifier, the id of every method below. A stream stored without an id cannot be addressed afterwards.
  • name - string, required to start the stream. A stream without a name is stored but not started.
  • type - string, spts or mpts. Selects the pipeline and the version fields the API maintains (see below).
  • enable - boolean. true starts the stream when it is set; a stream with false or without the field is stored only.
  • input - array, required to start the stream. Each item is an URL string or an object with an url field and further options. An item whose scheme is not a known input kind is logged and skipped.
  • output - array, optional. Same item forms as input.
  • backup_type - string, optional. active when absent; passive and disable are the modes in which Switch active input works.
  • no_event - boolean, optional. true disables statistics collection for the stream, so Get stream status reports monitoring disabled.

Table version fields: set-stream maintains the PSI table version numbers inside the stored object, so that players notice a changed configuration. For spts streams pmt_version and sdt_version are set to 1 on the first save and incremented modulo 32 on every following save; for mpts streams pat_version, cat_version, sdt_version and nit_version are set to 0 on the first save and incremented modulo 32 afterwards. Send the object back as it was read, so that the counters continue.

Request: POST /control/. Control and observer.

{
"cmd": "get-stream",
"id": "a001"
}
  • id - string, required. Stream identifier.

Response:

{
"get-stream": "ok",
"stream": { "id": "a001", "name": "Channel 1", "type": "spts", "enable": true, "input": [ "..." ] }
}
  • stream - the stored stream configuration object.

Unknown identifier:

{ "get-stream": "er", "error": "stream not found" }

Request: GET /api/stream-info or GET /api/stream-info/{id}. Control only; an observer receives 404.

Without an identifier the reply lists every stream:

{
"instance": "server-1",
"streams": [
{ "id": "a001", "name": "Channel 1", "type": "spts", "enable": true, "input": [ "..." ] }
]
}
  • instance - the instance_name setting, or the host name of the server when the setting is not defined.
  • streams - array of the stored stream configuration objects, [] when there are none.

With an identifier the reply is the stored stream configuration object itself:

{ "id": "a001", "name": "Channel 1", "type": "spts", "enable": true, "input": [ "..." ] }

Unknown identifier:

{ "error": "stream not found" }

Request: POST /control/. Control only.

{
"cmd": "set-stream",
"id": "a001",
"stream": {
"id": "a001",
"name": "Channel 1",
"type": "spts",
"enable": true,
"input": [ "udp://239.255.1.1:1234" ]
}
}
  • id - string, optional. Identifier of the stream to replace. When a stored stream has this identifier it is stopped and removed from the list before the new object is inserted; when none has it, the new object is added. Without id the object is always added, so repeating such a request stores a second object with the same stream.id.
  • stream - object, required. The stream configuration; its own id field is the identifier the stream is stored under, so keep it equal to id. The handler does not check that the two match.
  • gid - number, optional. Identifier generator counter of the interface: when present it is stored as gid in the configuration and echoed in the notification, so that every interface client continues the same sequence.

Response:

{ "set-stream": "ok" }

Without the stream field the reply is { "set-stream": "er" } and nothing changes.

Side effects:

  • The stream object is appended to the end of the make_stream list, so a replaced stream changes its position.
  • The table version fields are set or incremented as described in Stream configuration.
  • For mpts streams the object is registered with the MPTS registry under its id.
  • With enable set to true the stream is started. A start failure (missing name, empty input, another running stream with the same id) is written to the log; the reply is still "ok" and the object is saved.
  • The configuration is saved.
  • WebSocket clients receive one or two notifications. When an existing stream was replaced: {"scope": "set-stream", "stream": {"id": "a001", "remove": true, "up": true}}, where up is true for a replacement and false for a removal. Then, for the inserted object: {"scope": "set-stream", "gid": 466561, "stream": { ... }} with the stored object including the version fields; gid is absent when the configuration holds none.

Request: POST /control/. Control only.

{
"cmd": "set-stream",
"id": "a001",
"stream": {
"remove": true
}
}
  • id - string, required. Identifier of the stream to delete.
  • stream.remove - boolean, true. Other fields of stream are not stored; stream.enable set to true still triggers a start attempt of the removal object, which fails with a log line.

Response:

{ "set-stream": "ok" }

The running stream is stopped, the object is removed from the make_stream list, an mpts stream is unregistered from the MPTS registry, the configuration is saved and WebSocket clients receive {"scope": "set-stream", "stream": {"id": "a001", "remove": true, "up": false}}. An unknown id changes nothing and is still answered "ok".

Turn a stream on or off. Request: POST /control/. Control only.

{
"cmd": "toggle-stream",
"id": "a001"
}
  • id - string, required. Stream identifier.

Response:

{ "toggle-stream": "ok" }

Unknown identifier:

{ "toggle-stream": "er", "error": "stream not found" }

Side effects: enable is inverted in the stored object (a missing enable becomes true); an enabled stream is started, a disabled one is stopped; the object moves to the end of the make_stream list; the configuration is saved; WebSocket clients receive {"scope": "set-stream", "stream": { ... }} with the updated object.

Request: POST /control/. Control only.

{
"cmd": "restart-stream",
"id": "a001"
}
  • id - string, required. Stream identifier.

Response:

{ "restart-stream": "ok" }

Unknown identifier:

{ "restart-stream": "er", "error": "stream not found" }

An enabled stream is stopped and started again from its stored configuration. A disabled stream is left alone and still answered "ok". The configuration is not changed and no notification is sent.

Runtime status of a running stream. Request: POST /control/. Control and observer.

{
"cmd": "check-stream",
"id": "a001",
"status": true
}
  • id - string, required. Stream identifier. The stream must be running: a disabled stream is answered stream not found.
  • status - boolean, optional. true adds the status object to the reply.
  • eit - boolean, optional. Accepted, but the stream keeps no EIT data, so the reply never carries an eit field.

Response:

{
"check-stream": "ok",
"status": {
"active_input": 1,
"onair": true,
"input": [
{
"bitrate": 4200,
"packets": 27931,
"scrambled": false,
"cc_error": 0,
"pes_error": 0,
"sc_error": 0,
"pcr_error": 0
}
]
}
}
  • active_input - number of the input selected as active, 1 for the first input. 0 while none is selected: before the first analyzer report and, with the default backup type, while no input is on air.
  • onair - true while the active input works without errors.
  • input - array indexed by input number with the last analyzer sample of each input: bitrate in Kbit/s, packets counted in the sample, scrambled, and the cc_error, pes_error, sc_error and pcr_error counters of the sample. An input that is starting or was stopped holds {"bitrate": 0} only; an input that was never started has no entry. The value is a JSON array while the entries are numbered from 1 without gaps; otherwise it is a JSON object with the input numbers as string keys, for example {"0": {"bitrate": 0}, "1": { ... }, "2": { ... }} after Switch active input was called while no input was on air.
  • no_active_input - true while no input is on air; absent otherwise.

The status fields are filled for spts streams whose inputs run. An spts stream without outputs is started on demand, when the first HTTP client connects, and until then keeps the initial values active_input: 0, onair: false, input: []; an mpts stream keeps them always.

Unknown or not running identifier:

{ "check-stream": "er", "error": "stream not found" }

Statistics of a running stream from the monitoring module. Request: GET /api/stream-status/{id} with an optional query ?t={time}. Control only; an observer receives 404.

  • id - string, required in the path. Stream identifier; the stream must be running.
  • t - number, optional query parameter. 1 (default) returns the statistics of the last completed monitoring interval, 0 the latest analyzer sample. Any other number is answered {"error": "not implemented"}; a value that is not a number counts as 1.

The monitoring interval is the tsdb_interval setting, 60 seconds when not defined.

Response:

{
"instance": "server-1",
"name": "Channel 1",
"input_id": 1,
"timestamp": 1758240000,
"active": true,
"onair": true,
"sessions": 0,
"pes_error": 0,
"sc_error": 0,
"cc_error": 0,
"sync_error": 0,
"bitrate": 4200,
"video_count": 1,
"audio_count": 1
}
  • instance - the instance_name setting; absent when the setting is not defined.
  • name - stream name.
  • input_id - number of the input on air, 1 for the first input. 0 in an interval report of an inactive stream.
  • timestamp - Unix time. For t=1 the end of the reported interval, for t=0 the current time.
  • active - true if the stream is active. false when it works on demand and is inactive, and in an interval report with no collected samples; then input_id, sessions and every counter are 0.
  • onair - true if the active input works without errors.
  • sessions - number of active client sessions on the stream.
  • pes_error - PES errors as a percentage of the PES packets, over the interval for t=1 or in the latest sample for t=0.
  • sc_error - scrambled TS packets as a percentage of all TS packets, over the same span. If the stream is protected by a conditional access system sc_error and pes_error are greater than 0; a stream descrambled with a wrong key shows sc_error equal to 0 and pes_error greater than 0.
  • cc_error - continuity counter errors, summed over the interval for t=1, of the latest sample for t=0. Caused by packet loss or duplication.
  • sync_error - not filled by the stream analyzer, always 0.
  • bitrate - Kbit/s. Average over the interval for t=1, the latest sample for t=0.
  • video_count - number of video streams.
  • audio_count - number of audio streams.

Error replies, all with status 200:

  • {"error": "stream id not defined"} - no identifier in the path.
  • {"error": "stream not found"} - the stream is not running (unknown identifier or disabled stream).
  • {"error": "monitoring disabled"} - the stream has no monitoring slot: mpts streams and streams with no_event set.
  • {"error": "not implemented"} - t is a number other than 0 and 1.

Choose the active input. Works only for streams with the backup type passive or disable. Request: POST /control/. Control only.

{
"cmd": "set-stream-input",
"id": "a001",
"input": 2
}
  • id - string, required. Stream identifier; the stream must be running.
  • input - number, optional. Input number, numbering starts from 1; a numeric string is accepted. When the field is absent or names an input that is not in the stream’s input list, the input after the active one is chosen, wrapping around to the first.

Response:

{ "set-stream-input": "ok" }

A stream that is not running, or whose backup_type is neither passive nor disable, is answered { "set-stream-input": "er" } without an error field.

The chosen number is compared with active_input of the stream status (see Check stream). When they differ, the input numbered active_input is destroyed and the chosen input is started unless it already runs; when they are equal nothing changes. While no input is on air active_input is 0, so the running input keeps running, the chosen one is started next to it and status.input gets a "0" entry. The configuration is not changed and the command sends no notification of its own; the analyzer’s regular stream_event messages, one per running input, show which inputs run.

Push a picture URL for a stream to the connected interface clients. Request: POST /control/. Control only.

{
"cmd": "set-stream-image",
"id": "a001",
"url": "http://server/images/a001.png"
}
  • id - string, required. Stream identifier; the stream must exist in the configuration, running or not.
  • url - string, optional. Sent to the clients as src; absent in the notification when omitted.

Response:

{ "set-stream-image": true }

Unknown identifier:

{ "set-stream-image": false, "error": "stream not found" }

The only effect is the WebSocket notification {"scope": "stream_image", "channel_id": "a001", "src": "http://server/images/a001.png"}. Nothing is stored. The Channel Screenshots on Dashboard script uses this method to put screenshots on the stream tiles.

Create, replace or remove a named output group in the output list of the configuration. Request: POST /api/output-group to create a group, POST /api/output-group/{name} to replace or remove the group with that name. Control only; an observer receives 404.

{
"group": {
"name": "Cable head-end"
},
"remove": false
}
  • name in the path - string. Name of an existing group; group not found when no stored group has it.
  • group - object. The group to store; name is the only field the handler reads, the rest is stored as sent. Required to create or replace a group.
  • remove - boolean, optional. true together with a name in the path removes that group.

Response:

{ "ok": true }

Error replies, all with status 200:

  • {"error": "invalid data"} - the body is not valid JSON.
  • {"error": "group not found"} - the name in the path matches no stored group.
  • {"error": "group name already exists"} - another stored group already has group.name: a duplicate name on create, or a rename onto an existing name. Replacing a group under its own name passes.

Side effects: the output list of the configuration is updated (a new group is appended, a replaced group keeps its position, the list is dropped when the last group is removed), the configuration is saved and WebSocket clients receive {"scope": "post-output-group", "index": 0, "remove": false, "group": { ... }}, where index is the zero-based position of the replaced or removed group and absent for a new one, and remove and group echo the request fields and are absent when the request did not carry them. Astra stores the groups for the interface; no stream or output is started from them.