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.
Start analyzer
Section titled “Start analyzer”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=valuesuffix; the options are applied to the analyzed input as for a stream input.dvb://a002analyzes a running adapter of the configuration by itsid. Instead of a string the field may carry the parsed form: an object withformat(the scheme) andaddrplus the option fields; advbobject may name the adapter inidinstead ofaddr, then every other option of the object is dropped.
Response:
{ "scan-init": "ok", "id": "scan-731"}id- string, the session identifier forscan-checkandscan-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-scanis 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.
Poll analyzer
Section titled “Poll analyzer”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 previousscan-check, in arrival order. Absent when nothing new arrived. Each call empties the queue. An entry is either a PSI table (it has apsifield) or a status entry (it has ananalyzefield).
Unknown or expired identifier:
{ "scan-check": "ok", "error": "instance not found" }The command name still carries "ok"; check the error field.
Status entry
Section titled “Status entry”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 PIDs0,1,17,18,20and8191always, 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. PID8191counts 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 of8191and of the PIDs no table names count onlypackets,bitrateandpcr_error; their other counters stay0. Fields:pid;packetscounted in the second;bitratein 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 to0for a PID whosepes_erroris0.total.packets- the sum over every row.total.bitrate- the sum of the row bitrates, except that the packets of PID8191and 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_errorsis summed before the per-row reset ofsc_error, so it may exceed the sum of the rows.total.scrambled-truewhen a video or audio PID hassc_errorabove0.total.bitrate_limit- Kbit/s, the threshold applied to the video and audio bitrate:2plus32per video PID and4per audio PID.on_air-falsewhenscrambledistrue, when the video plus audio bitrate is belowbitrate_limit, or when a video or audio PID has more than2PES errors in the second;trueotherwise.
PSI entries
Section titled “PSI entries”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,sdtoreit.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 between1and8190:pnris the program number,pidthe PID of its PMT. The item withpnr0names 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_id9) 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 fromtype_idand the descriptors:VIDEO(0x01,0x02,0x10,0x1B,0x24),AUDIO(0x03,0x04,0x0F,0x11,0x81,0x87, and0x06with an AC-3 or enhanced AC-3 descriptor),TTX(0x06with a teletext descriptor),SUB(0x06with a subtitling descriptor),AIT(0x05with the application signalling descriptor0x6F),DATAotherwise;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 theirdescriptors.
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 itsdescriptors.
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_utandstop_utas Unix time;running_statusandca_modeas coded in the section;descriptors.
Descriptors
Section titled “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.
9cas-caid,pid(the ECM or EMM PID),data- the private bytes as a0xhex string, absent when there are none.10lang-lang.64network_name_descriptor-network_name.67satellite_delivery_system_descriptor-frequency(MHz),orbital_position("019,2E": degrees with a comma decimal andEorW),polarization(H,V,L,R),s2(boolean),rolloff(35,25,20,AUTO, present only whens2istrue),modulation(AUTO,QPSK,8PSK,16-QAM),symbolrate(kSym/s),fec(string).68cable_delivery_system_descriptor-frequency(MHz),modulation(NONE,16-QAM,32-QAM,64-QAM,128-QAM,256-QAM,AUTO),symbolrate(kSym/s),fec(string).72service-service_type_id,service_provider,service_name.77short_event_descriptor-lang,event_name,text_char.78extended_event_descriptor-desc_num,last_desc_num,lang,items(array of{ "item_desc": "...", "item": "..." }, present when the descriptor has items),text.82stream_id-stream_id.83caid-caid.84content_descriptor-items, array of{ "cn_l1": N, "cn_l2": N, "un_l1": N, "un_l2": N }.85parental_rating_descriptor-items, array of{ "country": "...", "rating": N }.86teletext_descriptor-lang.89subtitling_descriptor-lang.90terrestrial_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).91multilingual_network_name_descriptor-network_name, an object keyed by language code.131logical_channel_descriptor-lcn, array of{ "pnr": N, "lcn": N }.- any other tag -
type_nameunknown,data- the whole descriptor as a0xhex string, truncated with... (strip)when longer than the buffer.
Stop analyzer
Section titled “Stop analyzer”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.