Skip to content

Scan API

The scan methods run the MPEG-TS analyzer on any input address for a short time: scan-init starts an analyzer session, scan-check collects what it found since the previous call and keeps the session alive, scan-kill stops it. The interface uses them for the DVB scan and for the stream analyzer page. All three are served on the POST /control/ entry point with the command name in cmd and are control only; an observer receives 404. See How to call API methods for the entry points, authentication and roles. Every method answers 200 with a JSON body; a failure is reported inside the body.

A session does not touch the configuration and sends no WebSocket notification.

Request: POST /control/. Control only.

{
"cmd": "scan-init",
"scan": "udp://239.255.1.1:1234"
}
  • scan - string, required. The input address in the Media Address Format, with the usual #option&option=value suffix; the options are applied to the analyzed input as for a stream input. dvb://a002 analyzes a running adapter of the configuration by its id. Instead of a string the field may carry the parsed form: an object with format (the scheme) and addr plus the option fields; a dvb object may name the adapter in id instead of addr, then every other option of the object is dropped.

Response:

{
"scan-init": "ok",
"id": "scan-731"
}
  • id - string, the session identifier for scan-check and scan-kill: scan- followed by a random number between 100 and 999 that is not in use.

Error replies:

{ "scan-init": "er", "error": "failed to get address" }
  • failed to get address - scan is absent, or a string without ://.
  • input initialization failed - the input could not be created.

An address with an unknown scheme, or a dvb:// address whose adapter is not running, is written to the log; the session is still created and answers "ok", but delivers no PSI entries, only a status entry every second with every counter 0 and on_air false.

Lifetime: the session is checked every 10 seconds and stopped when no scan-check arrived since the previous check, so poll at least every 10 seconds to keep it alive. A session never polled stops 10 seconds after scan-init; a polled one stops between 10 and 20 seconds after its last scan-check. The input is started for the session; a DVB adapter is shared with the streams that use it.

Request: POST /control/. Control only.

{
"cmd": "scan-check",
"id": "scan-731"
}
  • id - string, required. Session identifier.

Response:

{
"scan-check": "ok",
"scan": [
{ "psi": "pat", "pid": 0, "table_id": 0, "version": 3, "crc32": 2718450225, "tsid": 1, "programs": [ { "pnr": 1, "pid": 32 } ] },
{ "analyze": [ { "pid": 0, "packets": 10, "bitrate": 15, "cc_error": 0, "pes_error": 0, "pcr_error": 0, "sc_error": 0 } ], "total": { "bitrate": 4200, "packets": 2793, "cc_errors": 0, "pes_errors": 0, "sc_errors": 0, "pcr_errors": 0, "scrambled": false, "bitrate_limit": 38 }, "on_air": true }
]
}
  • scan - array of the entries collected since the previous scan-check, in arrival order. Absent when nothing new arrived. Each call empties the queue. An entry is either a PSI table (it has a psi field) or a status entry (it has an analyze field).

Unknown or expired identifier:

{ "scan-check": "ok", "error": "instance not found" }

The command name still carries "ok"; check the error field.

Produced once per second with the counters of that second, also while no data arrives (every counter 0, on_air false).

{
"analyze": [
{ "pid": 0, "packets": 10, "bitrate": 15, "cc_error": 0, "pes_error": 0, "pcr_error": 0, "sc_error": 0 },
{ "pid": 256, "packets": 2650, "bitrate": 3985, "cc_error": 0, "pes_error": 0, "pcr_error": 0, "sc_error": 0 },
{ "pid": 8191, "packets": 120, "bitrate": 180, "cc_error": 0, "pes_error": 0, "pcr_error": 0, "sc_error": 0 }
],
"total": {
"bitrate": 4200,
"packets": 2793,
"cc_errors": 0,
"pes_errors": 0,
"sc_errors": 0,
"pcr_errors": 0,
"scrambled": false,
"bitrate_limit": 38
},
"on_air": true
}
  • analyze - array with one row per PID, in ascending PID order. A PID a table names has a row every second, with packets or not: the PIDs 0, 1, 17, 18, 20 and 8191 always, the NIT, PMT, elementary stream, PCR and CA PIDs once the tables name them. A named PID keeps its row until the next PAT change, also when a new PMT version drops it. A PID no table names has a row of its own in the seconds it carries packets. PID 8191 counts the null packets and the packets without a sync byte. A row counts every packet of its PID in the second, also those that arrived before the table that names it. The rows of 8191 and of the PIDs no table names count only packets, bitrate and pcr_error; their other counters stay 0. Fields: pid; packets counted in the second; bitrate in Kbit/s (packets * 188 * 8 / 1000); cc_error - continuity counter errors, not counted when the packet carries the discontinuity indicator; pes_error - video and audio packets whose payload start does not begin with a PES header, a packet with the transport error indicator is not judged; pcr_error - PCR values that deviate by more than 500 ns from the value extrapolated from the previous PCR interval and the packet count since the last PCR; the first two PCRs of a PID set the rate; the extrapolation assumes a constant packet rate between two PCRs, so a variable bitrate stream reports errors even when its PCR is correct; sc_error - scrambled packets, reset to 0 for a PID whose pes_error is 0.
  • total.packets - the sum over every row.
  • total.bitrate - the sum of the row bitrates, except that the packets of PID 8191 and of the PIDs no table names are converted to Kbit/s as one sum, so it may be a few Kbit/s above the sum of the rows.
  • total.cc_errors, total.pes_errors, total.sc_errors, total.pcr_errors - sums of the row counters; total.sc_errors is summed before the per-row reset of sc_error, so it may exceed the sum of the rows.
  • total.scrambled - true when a video or audio PID has sc_error above 0.
  • total.bitrate_limit - Kbit/s, the threshold applied to the video and audio bitrate: 2 plus 32 per video PID and 4 per audio PID.
  • on_air - false when scrambled is true, when the video plus audio bitrate is below bitrate_limit, or when a video or audio PID has more than 2 PES errors in the second; true otherwise.

Produced once per table change. The first section of each table and section number is sent; after that a section is sent only when its checksum differs from the previous one of the same table and section number. A new table version is sent section by section as it arrives. The PAT follows the same rule as every other table. An unchanged table is not sent again, however long it is absent. A table is told apart by table_id and its identifier: tsid of a PAT (only the latest PAT is kept, so a PAT with an earlier tsid is sent again), pnr of a PMT, network_id of a NIT, tsid and the original network of an SDT, sid, tsid and onid of an EIT. Every PSI entry carries:

  • psi - string, the table name: pat, cat, pmt, nit, sdt or eit.
  • pid - number, the PID the section arrived on.
  • table_id - number.
  • version - number, the table version.
  • crc32 - number, the section checksum.

The remaining fields depend on the table.

{
"psi": "pat",
"pid": 0,
"table_id": 0,
"version": 3,
"crc32": 2718450225,
"tsid": 1,
"programs": [
{ "pnr": 0, "pid": 16 },
{ "pnr": 1, "pid": 32 }
]
}
  • tsid - transport stream identifier.
  • programs - list of the PAT items with a PID between 1 and 8190: pnr is the program number, pid the PID of its PMT. The item with pnr 0 names the NIT PID.

A PAT change does not reset the counters: counting goes on in the same rows. The PIDs are named again from the new PAT, the CAT and the PMTs of the programs whose PAT item stays the same. The PIDs of a program the new PAT drops become PIDs no table names: they have a row only in the seconds they carry packets. The PMTs of the programs that stay are not sent again. A PMT or NIT PID whose PAT items change starts over: its next sections are sent again while a PAT lists it. A client that clears its program list on a PAT entry should keep the PMTs of the programs the new PAT still lists.

{
"psi": "cat",
"pid": 1,
"table_id": 1,
"version": 0,
"crc32": 1234567890,
"descriptors": [
{ "type_id": 9, "type_name": "cas", "caid": 2600, "pid": 1000 }
]
}
  • descriptors - the CAT descriptors, see Descriptors. The PID of every CA descriptor (type_id 9) is added to the analyzed PIDs.
{
"psi": "pmt",
"pid": 32,
"table_id": 2,
"version": 5,
"crc32": 3456789012,
"pnr": 1,
"pcr": 256,
"descriptors": [],
"streams": [
{
"pid": 256,
"type_id": 27,
"type_name": "VIDEO",
"descriptors": []
},
{
"pid": 257,
"type_id": 4,
"type_name": "AUDIO",
"descriptors": [
{ "type_id": 10, "type_name": "lang", "lang": "eng" }
]
}
]
}
  • pnr - program number.
  • pcr - PID that carries the PCR of the program.
  • descriptors - program level descriptors.
  • streams - elementary streams: pid; type_id - the stream type of the PMT; type_name - the class derived from type_id and the descriptors: VIDEO (0x01, 0x02, 0x10, 0x1B, 0x24), AUDIO (0x03, 0x04, 0x0F, 0x11, 0x81, 0x87, and 0x06 with an AC-3 or enhanced AC-3 descriptor), TTX (0x06 with a teletext descriptor), SUB (0x06 with a subtitling descriptor), AIT (0x05 with the application signalling descriptor 0x6F), DATA otherwise; descriptors - the stream descriptors.

Only the actual network table (table_id 64) is reported.

{
"psi": "nit",
"pid": 16,
"table_id": 64,
"version": 2,
"crc32": 4567890123,
"section_number": 0,
"last_section_number": 0,
"network_id": 1,
"descriptors": [
{ "type_id": 64, "type_name": "network_name_descriptor", "network_name": "ASTRA" }
],
"streams": [
{
"tsid": 1,
"onid": 1,
"descriptors": [
{ "type_id": 67, "type_name": "satellite_delivery_system_descriptor", "frequency": 11913, "orbital_position": "019,2E", "polarization": "H", "s2": true, "rolloff": "35", "modulation": "8PSK", "symbolrate": 27500, "fec": "3/4" }
]
}
]
}
  • section_number, last_section_number - the section counters; a multi-section NIT arrives as one entry per section.
  • network_id - network identifier.
  • descriptors - network level descriptors.
  • streams - transport streams of the network: tsid, onid (original network identifier) and their descriptors.

Only the table of the actual transport stream (table_id 66) is reported, and once a PAT has arrived only the one whose tsid equals the PAT tsid. An SDT that arrives before the first PAT is reported whatever its tsid.

{
"psi": "sdt",
"pid": 17,
"table_id": 66,
"version": 1,
"crc32": 5678901234,
"section_number": 0,
"last_section_number": 0,
"tsid": 1,
"services": [
{
"sid": 1,
"descriptors": [
{ "type_id": 72, "type_name": "service", "service_type_id": 1, "service_provider": "Provider", "service_name": "Channel 1" }
]
}
]
}
  • section_number, last_section_number - the section counters.
  • tsid - transport stream identifier.
  • services - one item per service: sid (the service identifier, equal to the program number) and its descriptors.

Event information tables with a table_id from 78 (0x4E) to 111 (0x6F): present/following and schedule, actual and other transport stream.

{
"psi": "eit",
"pid": 18,
"table_id": 78,
"version": 9,
"crc32": 6789012345,
"sid": 1,
"section_number": 0,
"last_section_number": 1,
"tsid": 1,
"onid": 1,
"events": [
{
"event_id": 1001,
"start_ut": 1758240000,
"stop_ut": 1758243600,
"running_status": 4,
"ca_mode": 0,
"descriptors": [
{ "type_id": 77, "type_name": "short_event_descriptor", "lang": "eng", "event_name": "News", "text_char": "Evening news" }
]
}
]
}
  • sid - service identifier.
  • section_number, last_section_number - the section counters.
  • tsid, onid - transport stream and original network identifiers.
  • events - one item per event: event_id; start_ut and stop_ut as Unix time; running_status and ca_mode as coded in the section; descriptors.

Every descriptors item is an object with type_id (the descriptor tag) and type_name, plus the fields of the recognized tags below. Text fields are decoded to UTF-8. Language codes are three lower-case letters.

  • 9 cas - caid, pid (the ECM or EMM PID), data - the private bytes as a 0x hex string, absent when there are none.
  • 10 lang - lang.
  • 64 network_name_descriptor - network_name.
  • 67 satellite_delivery_system_descriptor - frequency (MHz), orbital_position ("019,2E": degrees with a comma decimal and E or W), polarization (H, V, L, R), s2 (boolean), rolloff (35, 25, 20, AUTO, present only when s2 is true), modulation (AUTO, QPSK, 8PSK, 16-QAM), symbolrate (kSym/s), fec (string).
  • 68 cable_delivery_system_descriptor - frequency (MHz), modulation (NONE, 16-QAM, 32-QAM, 64-QAM, 128-QAM, 256-QAM, AUTO), symbolrate (kSym/s), fec (string).
  • 72 service - service_type_id, service_provider, service_name.
  • 77 short_event_descriptor - lang, event_name, text_char.
  • 78 extended_event_descriptor - desc_num, last_desc_num, lang, items (array of { "item_desc": "...", "item": "..." }, present when the descriptor has items), text.
  • 82 stream_id - stream_id.
  • 83 caid - caid.
  • 84 content_descriptor - items, array of { "cn_l1": N, "cn_l2": N, "un_l1": N, "un_l2": N }.
  • 85 parental_rating_descriptor - items, array of { "country": "...", "rating": N }.
  • 86 teletext_descriptor - lang.
  • 89 subtitling_descriptor - lang.
  • 90 terrestrial_delivery_system_descriptor - frequency (MHz), bandwidth ("8 MHz", "7 MHz", …), priority, modulation (QPSK, 16-QAM, 64-QAM), hierarchy (0, 1, 2, 4), code_rate_hp, code_rate_lp (strings), guard_interval (1/32, 1/16, 1/8, 1/4), transmission (2k, 8k, 4k).
  • 91 multilingual_network_name_descriptor - network_name, an object keyed by language code.
  • 131 logical_channel_descriptor - lcn, array of { "pnr": N, "lcn": N }.
  • any other tag - type_name unknown, data - the whole descriptor as a 0x hex string, truncated with ... (strip) when longer than the buffer.

Request: POST /control/. Control only.

{
"cmd": "scan-kill",
"id": "scan-731"
}
  • id - string, required. Session identifier.

Response:

{ "scan-kill": "ok" }

The input is stopped and the session with its collected entries is dropped. An unknown or already expired identifier changes nothing and is still answered "ok"; a following scan-check reports instance not found.