NoSignal MPEG-TS operator control plane
EN RO

NoSignal Documentation

Complete usage manual for operators, integrators, and system administrators running NoSignal in production broadcast and IPTV environments.

Introduction

NoSignal is a pure-Rust Linux application for MPEG-TS stream processing. It ingests transport streams from multiple sources, maintains channel health with automatic failover, optionally transforms the stream (PID remapping, PSI rewriting, CBR pacing), and delivers to multiple outputs simultaneously.

Key characteristics:

  • Single binary — no C library dependencies, no runtime installations
  • Embedded web UI — operator console baked into the binary, served on the API port
  • Embedded data store — uses redb (pure Rust key-value store), no external database
  • Multi-input failover — automatic switchover with anti-flap, probe-based revert
  • Stream conditioning — VBR passthrough or CBR null-packet padding, PID remapping, SI rewriting
  • EPG support — EIT extraction from inputs and XMLTV import, standalone SPTS multiplex output
  • Prometheus telemetry — per-channel bitrate, CC errors, PCR jitter with historical charts
  • External API — full REST API with API key authentication for third-party integrations

Key Concepts

Before diving in, here are the core concepts used throughout this manual:

ConceptDescription
ChannelA logical stream unit with one or more inputs, zero or more outputs, optional failover and pipeline configuration. Each channel runs independently.
InputA source of MPEG-TS data. Each input has a priority (0 = primary). Supported types: UDP multicast, HTTP TS, HLS, SRT.
OutputA destination for the processed stream. Same transport types as inputs. All outputs receive identical post-pipeline data.
PipelineOptional per-channel processing: PID remapping via slot configuration, CBR pacing, SI rewriting, time table injection.
FailoverAutomatic switching from a failed input to the next healthy backup, with configurable thresholds and anti-flap protection.
SlugURL-friendly identifier auto-generated from the channel name (e.g., "BBC One HD" becomes bbc-one-hd). Used in API paths.

Installation

Prerequisites

  • Linux server (Ubuntu 20.04+ or similar)
  • ffmpeg (for offline banner image-to-MPEG-TS conversion)
  • ImageMagick (for offline banner image resizing)
  • nginx with Let's Encrypt (for TLS reverse proxy, recommended)

Download

Download the latest binary from download.nosignal.ro. The binary is a statically-linked executable that runs on any Linux system.

wget https://download.nosignal.ro/nosignal
chmod +x nosignal

Fresh Install

The binary includes a built-in installer that creates everything needed for a production deployment:

sudo ./nosignal --install-service

This command:

  • Creates the nosignal system user
  • Sets up /srv/nosignal/ with correct permissions
  • Generates a JWT secret at /srv/nosignal/.env
  • Installs a hardened systemd service unit
  • Sets up daily backup cron job
  • Creates two fixed accounts — admin (full access) and user (read-only viewer) — each with a randomly generated 16-character password

Then start the service:

sudo systemctl start nosignal
sudo systemctl enable nosignal

Directory Layout

/srv/nosignal/
├── nosignal              # runtime binary
├── nosignal.redb         # data store
├── .env                  # runtime secrets (JWT secret, tuning)
├── backups/              # automatic redb backups (max 10 rotating)
├── credentials.txt       # initial admin + user passwords (delete after first login)
└── slate/                # custom offline banner images

Systemd Service

The service runs as the unprivileged nosignal user with hardened security settings:

  • ProtectSystem=strict — read-only filesystem except /srv/nosignal
  • CAP_NET_RAW and CAP_NET_ADMIN — for UDP multicast socket operations
  • Automatic restart on failure with 5-second delay
  • Logs to journald
# Check status
sudo systemctl status nosignal

# View logs
sudo journalctl -u nosignal -f

# Restart after update
sudo systemctl restart nosignal

Nginx Reverse Proxy

NoSignal binds to localhost only (default 127.0.0.1:8080). Use nginx for TLS termination:

server {
    listen 443 ssl http2;
    server_name nosignal.example.com;

    ssl_certificate     /etc/letsencrypt/live/nosignal.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/nosignal.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # SSE events — disable buffering
    location ~ ^/api/v1/channels/.*/events$ {
        proxy_pass http://127.0.0.1:8080;
        proxy_buffering off;
        proxy_cache off;
        proxy_set_header Connection '';
        proxy_http_version 1.1;
        chunked_transfer_encoding off;
    }

    # Restrict Prometheus metrics to localhost
    location = /metrics {
        allow 127.0.0.1;
        deny all;
        proxy_pass http://127.0.0.1:8080;
    }
}

Firewall

Required network access (nftables example):

# Allow nginx (HTTP/HTTPS)
nft add rule inet filter input tcp dport { 80, 443 } accept

# Allow multicast UDP (adjust port ranges to your setup)
nft add rule inet filter input ip daddr 239.0.0.0/8 udp dport 1000-65535 accept

First Login

On first startup, NoSignal creates two fixed accounts — admin (full access) and user (read-only viewer) — each with a randomly generated 16-character password. Both passwords are written to /srv/nosignal/credentials.txt (mode 0600) and printed to the journal:

sudo cat /srv/nosignal/credentials.txt

Open the web UI in your browser (e.g., https://nosignal.example.com) and log in with username admin and the generated password.

Important: Change both passwords immediately after first login via the user menu (top right) → Change Password. Then delete /srv/nosignal/credentials.txt.

User Roles

NoSignal ships with exactly two fixed accounts — this is the complete user model. There is no user CRUD; the only way to alter the user account is the admin-only password reset.

AccountRolePermissions
adminFull accessCreate/modify/delete channels, manage license, API keys, config backup/restore, reset the user password
userRead-only viewerSee all channel status, telemetry, and logs — cannot make changes

Dashboard

The dashboard is the landing page after login. It provides an at-a-glance view of your system health:

  • Channel counts — total channels, running, stopped, errored
  • License status — current license state and expiry
  • Alerts — offline channels, offline always-on inputs, and recent failover events
  • System health — quick access to performance and resource usage

Channel Management

Channels are the core unit in NoSignal. Each channel represents a single MPEG-TS service with its own inputs, outputs, failover, and pipeline configuration.

Creating a Channel

Navigate to Channels in the sidebar and click New Channel. Fill in:

  1. Name — a display name (e.g., "BBC One HD"). A URL slug is auto-generated.
  2. Description — optional free-text note for your team.
  3. Inputs — add one or more inputs with priorities (0 = primary). See Input Types below.
  4. Outputs — add one or more outputs. See Output Types below.
  5. Failover — configure failover behavior (thresholds, hold times, auto-revert). See Failover section.
  6. Pipeline — optional stream processing (CBR, slots, SI overrides). See Pipeline section.

Click Save to create the channel. If enabled, it starts automatically.

Input Types

UDP Multicast

Standard MPEG-TS over UDP multicast, the most common delivery method in IPTV headends.

FieldExampleDescription
Addressudp://[email protected]:1234Multicast group and port. Prefix with interface@ to bind to a specific NIC.
PNR1Optional program number to extract a single service from an MPTS.

HTTP Transport Stream

Pull a persistent HTTP stream. Useful for remote contribution feeds or HTTP-based encoders.

FieldExampleDescription
Addresshttp://source.example.com:8080/streamFull HTTP or HTTPS URL.

SRT (Secure Reliable Transport)

Low-latency, encrypted transport for contribution over the public internet.

FieldExampleDescription
Addresssrt://source.example.com:9000SRT endpoint address.
Modecaller / listenerCaller connects out; listener waits for connections.
Latency120 msSRT latency buffer. Higher values tolerate more jitter.
Passphrase(optional)AES encryption passphrase. Both ends must match.

HLS (HTTP Live Streaming)

Pull an HLS playlist and reconstruct a live MPEG-TS stream. Useful for ingesting from OTT sources or CDN-fronted feeds that only publish HLS.

FieldExampleDescription
Addresshttps://cdn.example.com/live/bbc/master.m3u8Master or media playlist URL. HTTPS supported.

NoSignal follows the latest rendition of the playlist and splices TS segments into a continuous stream with monotonic PCR. Suitable as an input for full-pipeline processing (failover, CBR pacing, PSI rewrite, and any output type).

Common Input Options

These options apply to all input types:

FieldDescription
PriorityInteger (0 = primary, higher = lower priority). Determines failover order.
Source NameOptional friendly label (e.g., "Telekom Primary", "SRT Backup"). Shown in the UI and event log for easier identification.
Always ActiveWhen enabled, this input runs as an auxiliary feed even when not the active input. Useful for monitoring a backup source's telemetry (bitrate, CC errors) continuously without waiting for a probe.

Channel Logos

Each channel can have a custom logo image. Upload a PNG or JPG via the channel detail page. Logos appear in the channel list, explorer, and overview pages for quick visual identification.

Output Types

UDP Multicast

Standard multicast output for local network distribution.

FieldExampleDescription
Address239.2.1.1:5000Multicast group and port.
Interfaceeth0Optional: bind to a specific NIC.
TTL16Multicast time-to-live (hop count).

HTTP Transport Stream

HTTP server that clients can connect to and pull a live TS stream.

FieldExampleDescription
Address0.0.0.0:8085Bind address and port.

SRT Output

SRT output for reliable delivery over lossy networks.

FieldExampleDescription
Address0.0.0.0:9100Bind address for listener mode, or target for caller.
Modelistener / callerListener waits for connections; caller connects out.
Latency200 msSRT latency buffer.
Passphrase(optional)AES encryption passphrase.

HLS is not in this list. Starting with v0.8.56, HLS is a top-level origin subsystem rather than a per-channel output type — see HLS Origin below.

Channel Operations

  • Start / Stop — click the play/stop button on the channel list or detail page. Starting begins ingesting from the highest-priority available input.
  • Edit — modify any channel configuration. Running channels are automatically restarted when saved — no manual restart needed.
  • Delete — stops the channel and removes it along with all inputs, outputs, and configuration.
  • Bulk actions — select multiple channels for batch start/stop from the channels list.

Failover

Each channel can have multiple inputs ordered by priority. NoSignal automatically switches between inputs based on health, with configurable thresholds and protection against oscillation.

Failover Triggers

Silence (No Data)

If no TS packets arrive for source_timeout_ms (default 5000 ms), the input is marked as down and failover begins.

Sustained CC Errors

If the continuity counter error rate exceeds cc_error_rate errors/sec and remains above that threshold for the full cc_error_window_ms window (default 10 s), failover is triggered. Brief spikes that drop back below threshold within the window do not trigger failover.

Fast Failover

Background probing continuously checks backup health. If the next backup has already been confirmed healthy by a recent probe, the switch is near-instant. If no cached-healthy backup exists, NoSignal probes each backup in priority order sequentially.

Hold Time

After any switch, the channel stays on the new input for at least hold_time_ms (default 30 s) before another switch is allowed. This prevents rapid oscillation.

Failback (Auto-Revert)

When auto_revert is enabled (default), NoSignal automatically returns to a higher-priority input when it recovers. Three gates must be passed:

  1. Probe gate — the higher-priority input must pass revert_after_probes (default 3) consecutive successful background probes.
  2. Quality gate — a deep probe receives data for ~3 seconds and checks CC error rate. If errors are above threshold, the failback is deferred.
  3. Minimum delay — failback will not happen before revert_delay_ms (default 60 s) has elapsed since the original failover.

Anti-Flap Protection

Input Lockout

If a specific input fails 3 or more times within 10 minutes, it is locked out for 30 minutes. During lockout the input is skipped during failover, but background probes continue. Lockout clears automatically after 30 minutes or with a manual channel restart.

Escalating Hold Time

If more than 2 failovers occur within 5 minutes, the hold time automatically doubles on each subsequent switch, up to a maximum of 10 minutes. It resets after 10 minutes of stability.

Failover Configuration Reference

FieldDefaultDescription
source_timeout_ms5000Silence duration before triggering failover
cc_error_rate10CC errors/sec threshold
cc_error_window_ms10000Duration errors must sustain above threshold
hold_time_ms30000Minimum time on any input after a switch
revert_delay_ms60000Minimum floor before failback can occur
auto_reverttrueAutomatically switch back to higher-priority input
revert_after_probes3Consecutive healthy probes needed before failback
probe_interval_ms60000Background probe frequency (base, ±20% jitter)
probe_timeout_ms10000How long a probe waits for data
no_signal_slatefalseShow offline banner when all inputs are exhausted

HLS Origin

NoSignal acts as an HLS origin: each enabled channel publishes a media playlist plus rotating .ts segments, all served by a small HTTP server that binds once globally (--hls-bind, default 127.0.0.1:8090). Manage HLS from the HLS → Origin page in the operator UI.

HLS is not a per-channel output — it's a top-level subsystem with its own toggle. Toggling it on or off is hot: the HLS subscriber attaches to (or detaches from) the channel's broadcast bus without restarting the pipeline.

Enabling HLS for a channel

Open the HLS → Origin page, find the channel and flip its toggle. The page shows the live state of every channel side-by-side with its HLS toggle, playlist URL, master URL, and current output bitrate.

  • Toggling on a running channel: subscriber attaches immediately; the first segment lands after ~6 seconds.
  • Toggling off: subscriber is cancelled and the segment directory is wiped to keep disk clean.
  • Channel start/stop: HLS state is preserved. A toggled-on channel re-attaches its HLS subscriber automatically on every (re)start.
  • Bulk action: select multiple rows and use the bulk toggle to enable or disable HLS across many channels at once.

HLS publishing is opt-in. Channels never pay HLS CPU or disk cost unless explicitly enabled.

Endpoints

The origin server exposes five endpoint families. All return Access-Control-Allow-Origin: *.

EndpointPurpose
GET /hls/{slug}/index.m3u8Media playlist for one channel. Updates as new segments are cut.
GET /hls/{slug}/seg<NNNNNN>.tsIndividual MPEG-TS segment, ~6 seconds, immutable.
GET /hls/{slug}/master.m3u8Single-variant master playlist. Required by some strict clients.
GET /playlist.m3uIPTV bouquet listing every enabled, running, HLS-enabled channel. Served as audio/x-mpegurl so VLC and IPTV apps treat it as a regular playlist (not an HLS multivariant). Carries tvg-id / tvg-name / tvg-logo / group-title attributes and a url-tvg pointer to /epg.xml. /index.m3u8 is kept as an alias.
GET /epg.xmlXMLTV export for IPTV-client EPG. Channel IDs match the tvg-id in /playlist.m3u (= channel slug). Programmes come from the imported XMLTV catalogue for epg_mode=xmltv channels and from the per-channel live EIT scanner for epg_mode=input channels. Cached for 60 s.

Segment rotation is automatic. The playlist carries the last PLAYLIST_DEPTH (10) segments; the segmenter keeps an extra GRACE_SEGMENTS (2) on disk for in-flight downloads. Disk usage per channel is bounded at 12 segments while HLS is running.

Per-channel master playlist

The master playlist at /hls/{slug}/master.m3u8 declares one variant pointing at index.m3u8, with a BANDWIDTH attribute derived from the running channel's measured output bitrate. Strict HLS clients that require a multivariant playlist (rather than a bare media playlist) should hit the master URL.

The master is generated on demand from runtime state — there is no separate persisted file. If HLS is disabled for the slug, the master endpoint returns 404.

Origin channel index

Loading http://<hls-bind>/playlist.m3u in VLC, an IPTV app, or any M3U-aware player yields the full bouquet — every channel that is currently HLS-enabled and running, with #EXTINF entries pointing at each channel's media playlist. The link host adapts to the inbound Host header so the bouquet keeps working unchanged behind nginx.

The bouquet is served with Content-Type: audio/x-mpegurl (generic M3U) rather than application/vnd.apple.mpegurl (HLS). The HLS content type would push players into the HLS demuxer, which then mis-parses each per-channel playlist URL as a TS segment. /index.m3u8 is kept as an alias for backwards compatibility with v0.8.56 docs.

The HLS Origin page in the app shows the bouquet URL prominently with a copy-to-clipboard button — share it with downstream operators to give them a single-URL entry point to all channels.

IPTV EPG (XMLTV)

The bouquet pairs with an XMLTV export at /epg.xml on the same host:port. The playlist's #EXTM3U header declares url-tvg="http://<host>/epg.xml", which most modern IPTV clients (Tivimate, IPTV Smarters, Kodi, TVHeadend) auto-discover — so loading just the bouquet gives the client both the channel list and the EPG.

tvg-id in the M3U equals <channel id="..."> in the XMLTV, both set to the channel's slug. No per-client mapping step is needed.

Programme data sources, per channel:

  • epg_mode = xmltv channels: full schedule from the imported XMLTV catalogue (typically 7 days).
  • epg_mode = input channels: present + following + whatever schedule sections the upstream EIT carried (usually 1–2 days).
  • epg_mode = none channels: appear in the channel list but with no programme entries (clients show a blank EPG row).

The response is cached for 60 seconds (Cache-Control: public, max-age=60) so high-volume IPTV-client polls don't rebuild the document every request.

Stream Processing Pipeline

The pipeline is an optional per-channel processing stage between input and output. When no pipeline is configured, packets pass through unmodified (VBR passthrough).

Output Modes

VBR Passthrough (Default)

Packets are forwarded as-is. The output bitrate follows the input bitrate. This is the simplest mode and introduces no additional latency.

CBR (Constant Bitrate)

Set target_bitrate_kbps to enable CBR output. NoSignal inserts null packets (PID 0x1FFF) to pad the stream to the target bitrate. The P-controller pacing ensures smooth, DVB-compliant output timing.

Tip: The channel detail page shows a Suggested CBR value based on the observed peak bitrate + 5% headroom. Use this as a starting point.

On-Demand Mode

When enabled, the channel defers input activation until a consumer connects to one of its unicast outputs (HTTP TS or SRT listener). Output ports bind immediately so clients can connect at any time — only the input and processing pipeline are deferred. When the last consumer disconnects, a configurable grace period (default 30 seconds, NOSIGNAL_ON_DEMAND_GRACE_S) elapses before the input is stopped. The channel shows Standby status while idle.

On-demand works with channels that have no outputs (telemetry-only) or only unicast outputs (HTTP TS, SRT listener). If any UDP multicast or SRT caller output is configured, on-demand is ignored and the channel runs normally. Enabling the HLS origin for a channel is independent of on-demand — when consumers wake the channel, the HLS subscriber attaches and starts producing segments. Enable on-demand in the Add Channel form or the channel edit form under On-Demand Mode.

While in standby, the channel generates no telemetry at all — no input bitrate, no CC error counters, no PCR metrics, no Prometheus samples. Telemetry resumes the moment a consumer connects and the input activates.

Preview, Analyse, and Extended Analysis all work with standby channels — opening any of them temporarily wakes the input. When closed, the 30-second grace period starts and the channel returns to standby if no other consumers are connected. When no consumers are connected, the output pipeline skips serialization and bus publishing entirely (zero CPU overhead).

Slot Configuration (PID Remapping)

Slots define semantic PID mappings — you specify what you want (e.g., "the first video stream") and NoSignal resolves it against the actual input PMT at runtime.

Slot Types

TypeDescription
videoVideo elementary stream (H.264, H.265, MPEG-2, etc.)
audioAudio elementary stream (AAC, AC-3, MP2, etc.)
subtitleDVB subtitles or teletext
dataData broadcast or application streams
scte35SCTE-35 ad insertion cue messages

Match Strategies

StrategyDescription
firstFirst stream of the matching category (default)
by_languageMatch by ISO 639 language code (e.g., eng, fra)
by_stream_typeMatch by MPEG stream type byte (e.g., 0x1B for H.264)
by_pidMatch a specific input PID number

Each slot also specifies an output_pid (the PID number in the output stream), and can be marked optional (if the match fails, the slot is simply omitted rather than causing an error).

Service Information Overrides

Override the service metadata in the output stream:

FieldDescription
override_pnrChange the output program number (service ID)
override_tsidChange the transport stream ID
service_providerOverride the service provider name in SDT
service_nameOverride the service name in SDT
inject_time_tablesInject TDT/TOT from system UTC on PID 0x14
pmt_guard_max_msSafety PMT re-inject interval if source goes silent (100–400 ms)

Electronic Program Guide (EPG)

The EPG subsystem ingests programme schedules from two sources — XMLTV feeds and live EIT scraped from each channel's input — and re-emits a unified guide on a standalone DVB SPTS multiplex that downstream SI-injection headends (Teleste Luminato and similar) bind into the QAM output. The same data also powers the /epg.xml export consumed by IPTV clients (see IPTV EPG (XMLTV)).

Open the EPG sidebar entry. Six tabs run top-to-bottom in a typical workflow:

TabPurpose
Active InputLive EIT scraped from each channel right now — present + following + 7-day schedule sections, grouped by channel. Read-only.
XMLTVBrowse the entire imported XMLTV catalogue (every channel + programme). Filter by locale. Channel names are non-clickable here — these rows are XMLTV entries, not platform channels.
XMLTV SourcesCRUD for upstream XMLTV feeds. RO + HU iptv-epg.org are seeded on first boot. Each source carries an optional locale tag.
EPG MapperPer-channel EPG configuration — EPG mode, language preference, XMLTV mapping, SID/TSID editor. The control surface for everything below.
SPTS OutputStandalone DVB SPTS multiplex carrying the consolidated EIT. Bind the multicast targets here.
ScanningTune the background EIT sweep cadence + parallelism.

EPG modes

Each channel picks one of three modes (column EPG Mode in the Mapper). The mode decides what — if anything — that channel contributes to the SPTS multiplex and to /epg.xml.

ModeBehaviour
noneNot in EPG. The channel still streams, but no EIT carries its events. It appears in /playlist.m3u with an empty EPG row.
inputUse active input. The per-channel scanner reads EIT from the upstream feed, filters to this channel's effective service_id, and re-emits those sections. Best for upstreams that already publish EIT (DVB, Romanian DTT, etc.).
xmltvUse XMLTV. NoSignal synthesises EIT sections from the imported XMLTV programme list, keyed to this channel's service_id. Best for channels whose upstream carries no EIT (HLS, HTTP, SRT pull-from-CDN).

The full carousel is delivered only through the SPTS multiplex — per-channel TS outputs never carry the consolidated EIT. /epg.xml re-uses the same data so IPTV clients get the same view that downstream QAMs do.

XMLTV sources

The XMLTV Sources tab lists each configured upstream feed: an ID, the URL, a locale tag, the cron schedule, last-fetch timestamp, event count, and HTTP status. Click Add Source to add another.

  • URL — plain XML or gzipped .xml.gz. Most community feeds (iptv-epg.org, iptv-org/epg) publish gzip; both are detected from the gzip magic byte.
  • Locale — short language code (e.g. ro, hu, en). Used by the Mapper's Map all channels action to restrict auto-match candidates to feeds in the language a given channel prefers. Optional — leaving it empty makes the source eligible for every channel.
  • Schedule — currently informational. The fetcher always runs once daily at 06:00 local time; the cron field is forward-compatibility for per-source schedules.

Fresh installs are seeded with two default rows: ro-iptv-epg (epg-ro.xml.gz) and hu-iptv-epg (epg-hu.xml.gz) from iptv-epg.org. Delete or replace them if your region uses a different feed; iptv-org/epg's per-country files are a common fallback.

Failure handling. If a fetch fails (network error, HTTP 5xx, empty body, parser error), the existing in-memory catalogue and DB rows are kept untouched and the fetcher retries in 1 hour. An XMLTV file with zero channels is also rejected — refusing to overwrite a known-good catalogue with empty is intentional. Deleting a source removes both its config row and every channel + programme it imported (no orphans).

Manual fetch. The Fetch now button (top right of both the XMLTV and XMLTV Sources tabs) wakes the fetcher immediately and polls the import status for up to 60 s. Status badges flip to ok on success or carry the error text on failure.

XMLTV browse

The XMLTV tab is a read-only browser over the entire imported catalogue — every channel from every configured source, regardless of whether it's mapped to a platform channel. Use it to confirm a fetch landed, to look up a specific xmltv_id before pasting it into the Mapper, or to verify a feed's coverage for a given day.

  • The Table view is a paginated list — expand a row to see that channel's full schedule.
  • The Grid view is the 24-hour timeline. Programme tiles tied to a mapped platform channel navigate to the channel detail's EPG tab; unmapped tiles are read-only (the tooltip still shows the programme details).
  • Channel names are intentionally non-clickable here — XMLTV channels are catalogue entries, not platform channels, and clicking them used to land on a 404. Use the Mapper to bind one to a platform channel.
  • The Locale dropdown appears once you have sources tagged in more than one language; filtering shrinks both the browse list and the background fetch.

EPG Mapper — per-channel configuration

The Mapper is where most operators spend their EPG time. It shows every configured platform channel on one screen with four editable columns and two bulk-action buttons in the header. Every change applies live — the affected channel hot-reloads its EPG configuration; no manual restart is ever required.

Columns

ColumnWhat it does
ChannelChannel name. The grey badges underneath are SID:<n> (effective service_id) and TSID:<n> (transport_stream_id the EIT will carry). Click either badge to edit it inline. A yellow ⚠ TSID means it's inherited from the live input PAT — set an override to match the QAM where this channel lives downstream.
EPG ModeThe three-mode dropdown above (none / input / xmltv). A yellow warning appears when the mode is xmltv but no mapping is set — the channel would emit nothing without one.
Preferred XMLTV LangPer-channel hint used only by the Map all channels button. With ro set, the auto-matcher only considers XMLTV sources tagged ro for that channel. Does not restrict what you can pick manually — the dropdown still shows every catalogue entry.
XMLTV mappingThe XMLTV channel to use when EPG Mode is xmltv. Type to search by display name or xmltv_id. (auto-match) defers to the name-normaliser at every run; an explicit pick wins over auto. The greyed placeholder shows what auto would pick — a ~ prefix means a fuzzy (sub-1.0) score.

The two bulk-action buttons

Map all channels. Iterates every channel and runs the auto-matcher against the XMLTV catalogue. For each channel:

  • If Preferred XMLTV Lang is set, candidates are restricted to sources tagged with that locale.
  • Matching ignores common cosmetic noise — leading/trailing locale codes (RO -, HU), trailing format suffixes (HD, FHD, 4K, HEVC, DVB), the trailing word TV, and all non-alphanumerics. So RO - TVR 1 HD matches TVR 1; AMC RO matches RO - AMC; Agro TV RO matches Agro. Names with no separator are protected — rotor never collapses to tor.
  • A unique exact match (score 1.0) wins unambiguously. A prefix match wins only if score ≥ 0.7 AND no other candidate also scores ≥ 0.7 (so HBO vs HBO 2 + HBO 3 is rejected as ambiguous).
  • When a match is found and the channel is currently none, its EPG Mode flips to xmltv so it joins the carousel automatically. Channels already on input or xmltv keep their chosen mode; only the mapping is updated.
  • Typed CONFIRM gate — bulk updates can churn many channels and the operator needs to acknowledge before they fire.

Fix output service IDs. Resolves duplicate or missing SIDs across the platform. The button counter shows how many channels need attention; the yellow banner above the table lists which SIDs are colliding.

  • The oldest channel in each collision group keeps its SID. Every newer collider — and every channel with no resolvable SID — is assigned the next free value.
  • This applies regardless of EPG mode. A channel with epg_mode=none still needs a unique SID so its PAT/PMT don't clash with another channel's on the same QAM.
  • Running channels are restarted to publish the new PAT/PMT.

The (ONID, TSID, SID) triplet

Receivers bind EIT events to services by matching the triplet (original_network_id, transport_stream_id, service_id) against the QAM's PAT/SDT. If the EIT we emit carries the wrong ONID or TSID, the events arrive on the wire but the STB silently drops them — they don't match any service. So:

  • ONID is set per-multiplex on the SPTS Output tab (Network ID field). It must equal the ONID the downstream headend advertises in its SDT. The factory default 1 is rarely correct in real deployments.
  • TSID is set per-channel from the Mapper. Yellow ⚠ means it's inheriting from the live input PAT — fine for a passthrough, dangerous for a downstream QAM that asserts its own ts_id. Click and type the ts_id of the QAM where that channel will land. Empty input clears the override and reverts to the live PAT.
  • SID is set per-channel. Click the SID badge to type a new value, or use Fix output service IDs to bulk-resolve collisions.

How the effective SID is computed

For every channel, NoSignal walks this chain to pick the SID the EIT will reference:

  1. override_pnr from the slot config (typed in the SID badge).
  2. The program_number from a single-service input PAT carve.
  3. The PAT of the running channel as observed by the manager.

If none yield a value, the channel is skipped in the EPG carousel with a warning in the log — emitting EIT with a default SID would corrupt the downstream multiplex. Set an explicit override_pnr from the Mapper to fix this.

SPTS output

The standalone EPG SPTS is a small DVB-spec transport stream that carries the consolidated EIT for every participating channel, plus optional SDT-other / PAT / PMT framing. It binds one or more multicast targets at 239.255.1.100:5100 by default and runs at a configurable minimum bitrate (200 kbps default — enough for ~60 channels at default cadences; the stream pads with NULL packets below this floor so receivers stay locked even on a quiet catalogue).

Output mode picks the wire shape:

ModeWhat goes on the wireUse when
raw_eit_pidPure EIT on PID 18 + NULL padding. No PAT, no SDT, no PMT.You feed an SI-injection multiplexer (Teleste Luminato, cherryEpg-compatible chains) that re-emits your EIT into its own QAM. Cleanest possible input.
full_dvb_tsPAT + PMT + SDT-actual + per-channel SDT-other + EIT.You feed a receiver that auto-detects the input against a full multiplex (binds EIT by service triplet rather than ingesting raw PID 18).

Cadences — pf_cycle_s (present/following repetition, default 2 s) and sched_cycle_s (full schedule repetition, default 30 s) — control how often each event window is re-emitted. The Sizing card under the form estimates the wire rate at the current cadences and warns when it exceeds the floor (so the operator can raise the floor or relax cadences).

The SDT advertises a single service per multiplex — name (EPG) and provider (NoSignal) are configurable. Per-channel events ride inside as EIT, referenced by service_id.

Operator pitfall — Luminato PID 18 binding. Adding the SPTS as an input to a Teleste Luminato gives it the wire content immediately, but the Luminato does not bind PID 18 to its outgoing QAM until you explicitly add a passthrough rule per QAM. This is a manual one-time step in the Luminato UI and is independent of NoSignal config.

Scanning cadence

The background EIT sweep runs on every channel on a fixed schedule (default every 6 hours, 60 s after daemon start). Each sweep refreshes the per-channel monitor's EIT snapshot — the data that feeds the Active Input tab, the epg_mode=input contribution to the SPTS carousel, and the input branch of /epg.xml.

  • Sweep Interval (hours) — 1–72, default 6. Higher = less load, more stale EIT. Lower = fresher EIT, more on-demand wakes (sweep scans every channel including standby).
  • Parallel Channels — 1–64, default 10. Cap on concurrent per-channel scans inside one sweep. Also the default for the manual Scan All button on the EPG page.

Manual Scan All (top-right of the Active Input tab) resets the sweep timer to now + interval. Useful right after editing channel inputs to confirm the new feed publishes valid EIT.

Monitoring & Telemetry

NoSignal provides extensive real-time and historical monitoring for every channel.

Metrics

Per-channel telemetry includes:

Per-Input Metrics

MetricDescription
bitrate_bpsCurrent ingress bitrate
cc_errors_per_secContinuity counter errors per second
pcr_bitrate_bpsBitrate derived from PCR deltas (sanity cross-check)
pcr_jitter_usPCR jitter in microseconds
pmt_cadence_mean_msMean interval between PMT sections
pmt_cadence_max_msMaximum observed PMT interval (DVB spec: ≤500 ms)
psi_changes_totalTotal PSI version changes since start

Post-Pipeline Output Metrics

MetricDescription
output_bitrate_bpsEgress bitrate after pipeline processing
output_cc_errors_per_secCC errors on the emitted stream (should be 0)
output_pcr_jitter_usPCR jitter on the output stream

Channel States

StateMeaning
stoppedChannel is not running
startingChannel is initializing
runningNormal operation on primary or backup input
degradedRunning on a backup input (failover active)
errorAll inputs failed
slateShowing offline banner (all inputs exhausted, slate enabled)
standbyOn-demand mode: waiting for a consumer to connect before activating input

Live Preview

The channel detail page includes a live stream preview. This uses server-side FFmpeg transcoding to provide a browser-playable preview of the MPEG-TS stream. Both input (unprocessed) and output (post-pipeline) previews are available.

Event Log

Every channel maintains a structured event log (up to 200 events per channel in memory). Event types include:

EventSeverityDescription
startedinfoChannel started
stoppedinfoChannel stopped
failoverwarningSwitched to backup input
revertinfoReturned to higher-priority input
cc_errorwarningContinuity counter errors detected
no_datawarningInput silence detected
pid_changewarningPID set changed in the input stream
pat_changeinfoPAT table version change
pmt_changeinfoPMT table version change
sdt_changeinfoSDT table version change
probeinfoBackground probe result
errorerrorChannel error (lockout, socket failure, etc.)

Events with identical type and message are merged — a count field shows how many times the event repeated.

Prometheus Integration

NoSignal exposes a /metrics endpoint in Prometheus exposition format. Prometheus scrapes this endpoint and stores historical data with 30-day retention. The web UI charts query Prometheus through the NoSignal API proxy.

Setup

# Install Prometheus
sudo apt-get install -y prometheus

# Use the provided config template
sudo cp /opt/nosignal/docs/prometheus.yml /etc/prometheus/prometheus.yml

# Set 30-day retention and localhost binding
# In /etc/default/prometheus:
ARGS="--web.listen-address=127.0.0.1:9090 --storage.tsdb.retention=30d"

# Restart
sudo systemctl restart prometheus
sudo systemctl enable prometheus
Note: The scrape_interval in prometheus.yml must match NOSIGNAL_METRICS_INTERVAL_S in .env (default: 60 seconds). If you change one, update the other.

Prometheus Metric Families

MetricLabelsDescription
nosignal_channel_input_bitrate_bpschannel, inputPer-input bitrate
nosignal_channel_input_cc_errors_per_secchannel, inputPer-input CC errors/sec
nosignal_channel_input_pcr_jitter_uschannel, inputPer-input PCR jitter
nosignal_channel_output_bitrate_aggregate_bpschannelPost-pipeline output bitrate
nosignal_channel_output_cc_errors_per_secchannelOutput CC errors/sec
nosignal_channel_output_pcr_jitter_uschannelOutput PCR jitter

Multicast Scanner

The scanner discovers active multicast streams on your network interfaces.

Running a Scan

  1. Navigate to Scanner in the sidebar.
  2. Select the network interface to scan on.
  3. Optionally specify a multicast range (e.g., 239.0.0.0/8). Leave blank for passive blind scan.
  4. Click Start Scan.

The scan runs for up to 5 minutes. Results show each discovered multicast group with:

  • Multicast address and port
  • Detected services (program names from SDT/PAT)
  • Bitrate
  • Whether the stream is already configured as a channel
Note: Only one scan can run at a time. Results are ephemeral (in-memory) and remain available until the next scan replaces them.

Channel Explorer

The Explorer provides a compact table view of all channels with their multicast addresses, service IDs, input/output mapping, and current state. It is designed for quick lookups — "which multicast group does this channel use?" — and includes:

  • Channel name with logo, service ID badge, and status pill
  • Input and output addresses at a glance
  • Search and filter by name, address, or state
  • Sortable columns
  • Copy any address to clipboard with a single click

Overview (Live Data)

The Overview page shows a real-time summary of all running channels on a single screen. For each channel it displays:

  • Current state and active input
  • Input and output bitrate
  • CC error rate
  • PCR jitter

Values update in real time. This is the go-to page for NOC operators monitoring a headend at a glance.

Consumers

The Consumers page shows all currently connected output subscribers — HTTP TS clients and SRT peers. For each consumer you can see:

  • Client IP address and port
  • Connected channel
  • Connection duration
  • Bytes delivered

This is useful for monitoring who is pulling streams and diagnosing delivery issues.

System

Performance

The Performance page shows real-time system resource usage: CPU usage, memory consumption, and process statistics. Use this to ensure your server has enough headroom for the number of channels you're running.

Network Interfaces

View all network interfaces with per-interface statistics: RX/TX bitrate, packet drops, and errors. You can also set friendly descriptions for each interface to identify them in the channel configuration.

Settings

The Settings page provides:

  • API Keys — create, list, and revoke API keys for external integrations. Each key has a label, permission level (ro/rw), and optional IP whitelist.
  • Multicast defaults — configure default multicast output settings (next available address suggestion).
  • EPG tuning — sweep cadence and XMLTV fetch intervals.
  • Public status page — master on/off switch and CC-error reporting toggle for the /status page (see below).

Config Backup & Restore

Export your entire configuration (all channels, inputs, outputs, failover, pipeline, EPG mappings) as a JSON file:

  • Export — Settings → Config Backup → Download. Saves everything needed to rebuild the instance.
  • Import — Settings → Config Backup → Upload. Replaces the current configuration with the imported JSON.
Warning: Import replaces all existing configuration. Export a backup first.

Offline Banner (Slate)

When all inputs for a channel are exhausted and no_signal_slate is enabled, NoSignal can display a custom offline banner image as a looping MPEG-TS stream.

  • Upload a custom PNG or JPG image via Slate Settings.
  • The image is automatically converted to MPEG-TS using FFmpeg.
  • If no custom image is uploaded, a built-in default slate is used.
  • Preview the current slate image in the settings page.

Public Status Page

NoSignal ships with an unauthenticated status surface at /status that subscribers can bookmark to check for outages. Only channels with the public flag are ever exposed — private channels are invisible regardless of state so internal channel names don't leak.

The underlying endpoint is GET /api/v1/public/status. It returns the total count of public channels, an ok_count, and an issues[] array of the ones considered affected. The response is cached in-process for 60 seconds — every visitor within a cache window sees an identical snapshot and an identical generated_at timestamp, so hitting refresh does not reset the "updated Ns ago" counter.

Issue rule

By default a channel is listed as an issue only when it is in the stopped state. Channels that fell back to a secondary input are state degraded and are not flagged — the viewer still sees a working signal. Turn on Also report CC errors (Settings → Public status page) to additionally flag channels with cc_errors_per_sec > 0.

Disabling the page

Operators who don't want a subscriber-facing status surface at all can flip Enable public status page off. With the toggle off, both /status and /api/v1/public/status return 404; the page then renders a polite "not available" notice instead. The toggle is read on every recompute, so changes take effect at the next 60-second cache refresh.

Logs

The Logs page aggregates events from all channels into a single searchable, filterable timeline. Filter by event type, channel, severity, or free-text search.

License Management

NoSignal instances run in one of two licensing modes. Both use Ed25519-signed leases, but behave very differently at runtime.

Modes

ModeNetworkRenewalBinding
SubscriptionRequires a live TLS connection to the license server.Heartbeats every ~1 h with a multi-day grace window on transient outages.Keypair + soft fingerprint (machine-id, interfaces, hostname).
PerpetualFully offline. Never contacts the license server after install.Never — the lease has no expiry.2-of-3 quorum over machine-id + primary MAC + hostname, plus a major.minor version pin.

License States

StateApplies ToBehavior
NoLeaseBothNo lease installed. Channel starts are blocked.
LicensedSubscriptionValid lease. Full operation.
GraceSubscriptionLicense server unreachable but lease still valid. Channels continue running normally.
OfflineExpiredSubscriptionGrace window ended without a successful heartbeat. New starts blocked; running channels keep going but are read-only until reconnection.
RestrictedSubscriptionServer returned a soft reject (e.g. instance converted to perpetual, binary mismatch). Mutations blocked; existing channels unaffected.
PerpetualPerpetualQuorum ≥ 2/3 and version line matches. Full operation, no network dependency.
LockedBothHard stop. All channels are stopped. Triggered by failed perpetual quorum, version mismatch, or explicit server revoke (subscription only — perpetual leases are non-revocable by design).

Subscription Configuration

Navigate to License in the sidebar and fill in:

  • Instance ID — unique identifier for this installation (generated when you register with the license server).
  • License server URL — e.g. https://license.nosignal.ro.
  • Server public key — the license server's Ed25519 public key (base64) used to verify lease signatures. Modern builds ship with the production key baked in, so this is only needed for staging or self-hosted license servers.

You can regenerate the instance's Ed25519 keypair from this page; the new public key must be registered with the license server before the next heartbeat.

Perpetual Install

A perpetual license is delivered as a single text block (the NSL1 key) — everything the instance needs is in that text, including the signature. No server round-trip is ever made.

  1. The operator (or Cloud Craft sales) generates the key on the license server by entering the customer's /etc/machine-id, primary MAC, hostname, allowed version line (e.g. 0.8), and max channels.
  2. The customer installs the key by one of three routes:
    • GUI — paste the entire NSL1 block into the License page textarea and submit. Surrounding email text is tolerated; the parser finds the BEGIN/END markers.
    • CLInosignal --install-license /path/to/key.txt (persists and exits; does not start the server).
    • Drop-in file — place the key text at license.txt next to the nosignal data file. It is picked up on the next startup.
  3. On install, the instance verifies the Ed25519 signature, checks the 2-of-3 machine-identifier quorum, and confirms the binary's major.minor version matches bind_version. A quorum < 2 or a version mismatch rejects the install.

To pre-flight a key without committing to install, run nosignal --verify-license /path/to/key.txt. It prints mode, bind_version, max channels, and the local quorum (N/3) without touching state.

Perpetual Runtime Behavior

  • Offline forever — no heartbeat task is spawned. The license server may be decommissioned without affecting the instance.
  • 24-hour re-check — a background task re-evaluates machine-identifier quorum and version pin once per day. Quorum < 2 or a version upgrade to a new minor line transitions the instance to Locked.
  • Bugfix upgrades are free — a lease bound to 0.8 accepts any 0.8.x build. Upgrading to 0.9.0 or 1.0.0 requires a new key from sales.
  • Non-revocable — by design there is no kill-switch. To relocate a perpetual instance (hardware swap, hostname change) the admin re-mints the key with the new bound identifiers; the old key is replaced on the target machine.

External API Reference

The external API allows third-party systems (monitoring dashboards, automation scripts, broadcast controllers) to interact with NoSignal. All endpoints live under /api/v1/ext/.

Authentication

API keys are created in Settings → API Keys. Each key has a label, permission level (ro or rw), and optional IP whitelist.

Pass the key in the X-API-Key header:

curl -H "X-API-Key: nsk_xxxxx" https://nosignal.example.com/api/v1/ext/channels

Key format: nsk_ prefix + 48 random alphanumeric characters. Keys are SHA-256 hashed before storage and cannot be retrieved after creation.

IP Whitelisting

Each key can have an IP whitelist. Supported formats: exact IP (192.168.1.50), CIDR (10.0.0.0/24), or comma-separated. Empty whitelist allows all IPs.

Channel Endpoints

List All Channels

GET /api/v1/ext/channels

Returns all channels with current status and summary metrics.

Channel Status

GET /api/v1/ext/channels/{slug}/status

Returns channel state, active input, and per-input health.

Combined Status + Live Telemetry

GET /api/v1/ext/channels/{slug}/live

Returns both status and live telemetry in a single response. Recommended for dashboard polling.

Telemetry Endpoints

Live Telemetry Snapshot

GET /api/v1/ext/channels/{slug}/telemetry

Historical Telemetry

GET /api/v1/ext/channels/{slug}/telemetry?range=1h|6h|1d|7d|30d

Returns time-series data from Prometheus. Step sizes: 1h→30s, 6h→60s, 1d→5m, 7d→15m, 30d→1h.

Event Endpoints

GET /api/v1/ext/channels/{slug}/events?limit=50&search=failover&since=2026-01-01T00:00:00Z
ParameterTypeDescription
limitintMax events to return (default 50)
offsetintPagination offset
event_typestringFilter by type (e.g., failover, cc_error)
searchstringFree-text search in event messages
sinceISO 8601Events after this timestamp
untilISO 8601Events before this timestamp

Write Operations (rw keys only)

Create Channel

POST /api/v1/ext/channels
Content-Type: application/json

{
  "name": "BBC One HD",
  "enabled": true,
  "inputs": [
    {"type": "udp_multicast", "address": "udp://[email protected]:1234", "priority": 0},
    {"type": "srt", "address": "srt://backup.example.com:9000", "priority": 1,
     "config": {"latency_ms": 200}}
  ],
  "outputs": [
    {"type": "udp_multicast", "address": "239.2.1.1:5000", "config": {"ttl": 16}}
  ],
  "failover": {
    "source_timeout_ms": 5000,
    "auto_revert": true
  }
}

Update Channel

PUT /api/v1/ext/channels/{slug}

Same body as create. Running channels are automatically restarted.

Delete Channel

DELETE /api/v1/ext/channels/{slug}

Stops the channel if running, then deletes it with all associated configuration.

Input & Output CRUD

# Add input
POST /api/v1/ext/channels/{slug}/inputs

# Update input
PUT /api/v1/ext/channels/{slug}/inputs/{id}

# Delete input
DELETE /api/v1/ext/channels/{slug}/inputs/{id}

# Add output
POST /api/v1/ext/channels/{slug}/outputs

# Update output
PUT /api/v1/ext/channels/{slug}/outputs/{id}

# Delete output
DELETE /api/v1/ext/channels/{slug}/outputs/{id}

Start / Stop Channel

POST /api/v1/ext/channels/{slug}/start
POST /api/v1/ext/channels/{slug}/stop

Error Codes

StatusMeaning
401Missing or invalid API key
403Permission denied (ro key on write endpoint, IP not whitelisted)
404Resource not found (channel, input, or output)
422Validation error (invalid request body)
502Upstream unavailable (Prometheus unreachable)

Recommended Polling Intervals

Use CaseIntervalEndpoint
Live dashboard2–5 secondsGET .../live
Status monitoring10–30 secondsGET .../status
Event ingestion30–60 secondsGET .../events?since=...
Periodic reporting5–15 minutesGET .../telemetry?range=1h

Download API Reference

The full API reference is also available as a Markdown download from any running instance:

GET /api/v1/ext/docs

No API key required. Returns text/markdown.

CLI Reference

nosignal [OPTIONS]

Options

FlagDefaultDescription
--data <PATH>./nosignal.redbPath to the redb data store
--api-bind <ADDR>127.0.0.1:8080API and web UI bind address
--hls-bind <ADDR>127.0.0.1:8090HLS server bind address
--log-level <LEVEL>infoLog level: trace, debug, info, warn, error
--jwt-secret <SECRET>randomJWT secret for session tokens. Random if absent (tokens won't survive restart).
--install-serviceInstall systemd service, create user, directories, and cron backup (requires root). Fresh installs only.
--update-serviceRefresh the systemd unit + sysctl drop-in on an existing install. Backs up the old unit, runs daemon-reload, restarts the service. Does not touch .env, the data store, or credentials. Use after upgrading the binary to a release that needs new capabilities (v0.8.71+ requires CAP_SYS_NICE + LimitRTPRIO=40 for SCHED_FIFO promotion of the UDP pacer threads).
--generate-prometheus-confWrite prometheus.yml to current directory
--generate-sysctl-confWrite multicast sysctl config to /etc/sysctl.d/ (requires root)
--reset-passwordReset admin password, print new credentials, and exit
--install-license <FILE>Install a perpetual license from an NSL1 text key file, then exit. Does not start the server.
--verify-license <FILE>Verify a perpetual license key without installing. Prints mode, bind_version, max channels, and local quorum N/3. Read-only.
--suggest-network-tuningInspect NIC ring buffers and print an advisory on recommended ethtool -G settings for high channel counts. Read-only.

Environment Variables

Defaults aim for lowest PCR jitter on the wire (what TVs downstream of professional re-multiplexers see). Trade CPU for jitter only when the downstream tolerates it. All vars are read from /srv/nosignal/.env; restart the service for changes to take effect.

General

VariableDefaultDescription
NOSIGNAL_API_BIND127.0.0.1:8080Override --api-bind
NOSIGNAL_JWT_SECRETOverride --jwt-secret
NOSIGNAL_WORKER_THREADS8Cap tokio worker threads
NOSIGNAL_METRICS_INTERVAL_S60Prometheus scrape interval (10–300). Must match prometheus.yml.
NOSIGNAL_PROMETHEUS_URLhttp://127.0.0.1:9090Prometheus URL for telemetry query proxy

UDP Output Pacer (DVB-critical, v0.8.71+)

The pacer determines PCR arrival jitter at downstream re-multiplexers (Teleste Luminato, Cisco RX-1, professional headends). Default is one dedicated OS thread per UDP output, promoted to SCHED_FIFO priority 20. CPU cost is roughly 1.5–2× the async pacer; turn knobs down only if measurements warrant.

VariableDefaultDescription
NOSIGNAL_UDP_PACER_ASYNCunsetSet to 1 to revert to the tokio-async pacer (shared workers). Lower CPU, higher PCR jitter under load.
NOSIGNAL_UDP_PACER_LEGACY_THREADunset (= dedicated thread)Set to 0/false/no/off to opt out of the dedicated thread (same as ASYNC=1). Back-compat env name with inverted semantics.
NOSIGNAL_UDP_PACER_RTPRIO20SCHED_FIFO priority for the pacer thread. 0 skips RT promotion (still dedicated thread but SCHED_OTHER). Range 1..=49. Requires CAP_SYS_NICE + LimitRTPRIO=40 in the systemd unit.
NOSIGNAL_UDP_PACER_BATCH1Datagrams coalesced per sendmmsg(2) (1–16). K=1 paces every datagram individually. K>1 trades K×datagram_interval of intra-burst smear for fewer syscalls.
NOSIGNAL_UDP_PACER_CPUSETunsetPin pacer threads to a CPU set (e.g. 2-5). Multi-NUMA only.

UDP Input + Monitor

VariableDefaultDescription
NOSIGNAL_UDP_RX_BATCH8Datagrams drained per recvmmsg(2) on UDP input (1–32). K=1 ≈ legacy recv.
NOSIGNAL_UDP_RX_LEGACYunsetSet to 1 to force pre-0.8.11 single-recv UDP input loop (per-host rollback).
NOSIGNAL_DISABLE_PCR_JITTERunsetSet to 1 to skip per-packet PCR jitter sampling on the monitor hot path.

Verifying the pacer is at SCHED_FIFO

ps -eLo pid,tid,nice,rtprio,policy,comm | grep udp-out
# Expect: POL=FF (SCHED_FIFO), RTPRIO=20 on every udp-out-* thread

If you see POL=TS instead of FF, the systemd unit is missing CAP_SYS_NICE / LimitRTPRIO=40. Run sudo /srv/nosignal/nosignal --update-service to refresh it.

Troubleshooting

Channel keeps flapping between two inputs

Symptoms: Repeated failover/revert events every few minutes.

Cause: Both inputs are marginal — primary recovers just long enough to pass the probe gate, then fails again.

Fix:

  • Increase revert_after_probes (e.g., to 5) to require longer proof of stability.
  • Increase revert_delay_ms to give the primary more settling time.
  • Check the underlying transport (packet loss, jitter) on both inputs.

Failover is too slow

Symptoms: Several seconds of dead air before the backup activates.

Fix:

  • Lower source_timeout_ms (e.g., 2000–3000 ms).
  • Reduce probe_interval_ms (e.g., 10000–30000 ms for critical channels) so backup health is always fresh.

Backup never activates despite primary being down

Symptoms: Channel shows no_data warnings but stays on the failed primary.

Fix:

  • Check backup input URL and network connectivity.
  • Review probe events in the channel log — look for consecutive probe failures.
  • Verify firewall rules (backup source IP/port reachable from the NoSignal server).

Failback never happens

Symptoms: Channel stays on backup even though primary is working again.

Fix:

  • Confirm auto_revert is true.
  • Check probe and cc_error events — if the primary has CC errors during deep probe, it won't pass the quality gate.
  • Investigate the primary source for intermittent CC errors.

No historical telemetry charts

Symptoms: Telemetry page shows "No data" for historical ranges.

Fix:

  • Verify Prometheus is running: sudo systemctl status prometheus
  • Check the scrape target is healthy: curl -s http://127.0.0.1:9090/api/v1/targets | jq '.data.activeTargets[].health'
  • Ensure NOSIGNAL_METRICS_INTERVAL_S matches scrape_interval in prometheus.yml.

Input locked out

Symptoms: Event log shows "input locked out" error.

Fix:

  • The lockout clears automatically after 30 minutes.
  • To clear immediately, restart the channel (stop + start).
  • Investigate and fix the underlying input issue.

Cannot start channels

Symptoms: Start button is disabled or returns an error.

Fix:

  • Check license status — Expired or Locked states block new starts.
  • Navigate to License page and verify the configuration.

Lost admin password

sudo /srv/nosignal/nosignal --reset-password

This prints a new random password and exits. The service does not need to be stopped.

Glossary

TermDefinition
MPEG-TSMPEG Transport Stream — the packet-based container format used in digital television broadcast and IPTV.
PIDPacket Identifier — a 13-bit field in each TS packet header identifying the stream it belongs to.
PATProgram Association Table — maps program numbers to their PMT PIDs. Always on PID 0.
PMTProgram Map Table — lists the elementary streams (video, audio, etc.) belonging to a program.
SDTService Description Table — carries service names, provider names, and service type.
EITEvent Information Table — carries programme schedule data (now/next and schedule).
NITNetwork Information Table — describes the physical network (transport streams, frequencies).
PSIProgram Specific Information — collective term for PAT, PMT, CAT, and NIT.
PCRProgram Clock Reference — timestamp in the TS adaptation field used for decoder clock synchronization.
CCContinuity Counter — 4-bit counter in each TS packet. Discontinuities indicate packet loss.
SPTSSingle Program Transport Stream — a TS carrying exactly one service.
MPTSMulti Program Transport Stream — a TS carrying multiple services.
CBRConstant Bitrate — output mode where null packets pad the stream to a fixed rate.
VBRVariable Bitrate — output mode where packets pass through at their natural rate.
SRTSecure Reliable Transport — open-source protocol for low-latency video over unreliable networks.
HLSHTTP Live Streaming — Apple's playlist-based adaptive streaming protocol (RFC 8216). NoSignal supports HLS as an input (pull a remote playlist and splice TS segments) and as a top-level origin subsystem (per-channel .m3u8 + ~6 s segments served from --hls-bind). See HLS Origin.
XMLTVXML-based format for exchanging TV programme schedule data.
PerpetualA fully offline license mode — the instance never contacts the license server after install. Lease is bound to machine identifiers and a major.minor version line.
QuorumThe perpetual license match policy: at least 2 of 3 identifiers (machine-id, primary MAC, hostname) must match the bound hashes for the license to hold.
NSL1NoSignal License v1 — the ASCII key block format for perpetual licenses. PEM-style wrapper around a signed JSON payload.
PNRProgram Number — identifies a service within a transport stream (used in PAT/PMT).
TTLTime To Live — multicast packet hop count limit.
TDT/TOTTime and Date Table / Time Offset Table — carry UTC time in the transport stream.