---
title: MPTS Migrate Perfect Streamer Toolkit v1.0 — MPTS identity migration
url: https://doc.pstreamer.tv/en/manual/mpts_migrate.html
lang: en
product: Perfect Streamer
version: 1.13.3.445
---

# MPTS Migrate Perfect Streamer Toolkit v1.0 — MPTS identity migration

Part of the **Perfect Streamer Toolkit** — [https://pstreamer.tv](https://pstreamer.tv)

Capture the DVB SI/PSI identity of a live MPEG-TS multiprogram stream (MPTS) and reproduce it on a Perfect Streamer (PSS) instance running on the same host. The result: consumer receivers (STB / TV) keep working **without a channel re-scan** after a migration or failover.

## Pre-conditions

Before running the utility verify that:

- **PSS is running** on the same host (or a host reachable via `--pss-base`). The utility queries `/proc` for `pss` and reads `pss.json` for the admin port (default `43971`).
- **Source MPTS is reachable** if you intend to capture (modes 1, 2, save+apply): the URL passed as the positional `<input>` argument must deliver an MPEG-TS stream. For UDP multicast — IGMP / firewall must allow it; for files — the path must exist.
- **Target MPTS is configured in PSS**: the utility never creates new streams. An MPTS object plus at least as many SPTS feeders as the inventory has services must already exist. Services without an available feeder are surfaced in the dialog and can be skipped.
- **HTTP admin API is open on localhost** for reading `/data/stream` (used by verify) and writing `/config/stream` (apply).

## What gets migrated

Every receiver-visible identifier on the transport-stream and per-service level:

- **Transport stream**: TSID, ONID, network ID, network name, **provider name** (auto-applied as mux-wide `sdt-provider-name` when all source services share one), delivery descriptor (terrestrial / cable / satellite parameters), PAT/SDT/NIT versions
- **Per service**: `service_id`, `pmt_pid`, `pcr_pid`, `service_type`, service name, logical channel number (LCN), free-CA mode, EIT-present/EIT-schedule flags
- **Elementary streams**: PIDs (identity remap applied — see *Limitations*), stream types, language tags
- **Conditional access**: program-level and ES-level CA descriptors

Service / provider names in non-ASCII DVB character sets (e.g. ISO-8859-5 Cyrillic) are decoded into UTF-8 automatically.

Per-service ES PID remap is built as identity pairs (`mpegts-pid-old` ≡ `mpegts-pid-new`) for every PCR / video / audio / teletext / data PID, so the resulting muxed output keeps source PIDs **byte-exact**. Legacy receivers that cache PMT after first scan continue to work without re-tune.

## Use cases

- **Failover**: switch decoders from primary to backup MPTS, keeping every receiver locked on the same channel numbers
- **Hardware migration**: move a working mux from one PSS host to another without operator instructions to viewers
- **Pre-/post-update snapshot**: capture the mux before a PSS upgrade, re-apply after to guarantee bit-identical SI/PSI
- **Manual edit & re-apply**: capture, edit `migrate.json` (rename services, change LCN, fix `service_type`), re-apply
- **Dry-run review**: print every HTTP POST that *would* be sent, without touching PSS

## Quick start

```bash
# Capture from a live stream and apply to local PSS in one run
mpts_migrate udp://239.1.1.1:1234

# Capture, save to migrate.json and apply
mpts_migrate -s udp://239.1.1.1:1234

# Capture only — write to file, do not apply
mpts_migrate -o backup.json udp://239.1.1.1:1234

# Apply a previously saved JSON
mpts_migrate -i backup.json

# No arguments — load ./migrate.json and apply
mpts_migrate

# Preview what apply would do, without changes
mpts_migrate -i backup.json --dry-run
```

## Workflow

1. **Capture** — utility opens the stream, parses PAT / PMT / SDT / NIT / EIT for up to `-t` seconds (default 30) and builds an inventory; total stream bitrate is measured.
2. **(Optional) Save** — with `-s` or `-o` writes the inventory to JSON for later reuse.
3. **Discover PSS** — locates the running PSS instance via `/proc` scan, reads `pss.json` to find its admin port (default `43971`); `--pss-base http://host:port` overrides discovery.
4. **Confirm mapping** — interactive dialog asks how to map each captured service to an existing SPTS feeder; `--non-interactive` accepts suggestions and aborts on conflict; `--target-mpts <id>` skips the MPTS-choice prompt.
5. **Auto-unpause feeders** — for each mapped SPTS / muxer-output the utility issues `{"pause":false}` if it was paused, so the muxer actually receives data after apply.
6. **Auto-adjust bitrate** — if `captured_bitrate × (1 + headroom%)` exceeds the target MPTS `mpegts-output-bitrate`, the utility raises that limit on PSS in a single POST (rounded up to the nearest 1000 kbps). Disable with `--no-bitrate-adjust`.
7. **Plan** — diffs the inventory against PSS’s current `/config/stream` tree, prepares HTTP POST requests only for fields that differ. ES PID remap is generated as identity pairs (`mpegts-pid-old` ≡ `mpegts-pid-new`) so the muxed output keeps every source PID unchanged — including PCR, video, audio, teletext, SCTE-35, DSM-CC.
8. **Apply** — sends the planned POST requests, then triggers a pause/unpause of the MPTS so PSS reloads config; with `--dry-run` only prints the plan.
9. **Verify** (default on, even when the plan is empty) — captures the resulting MPTS through one of the PSS UDP outputs and diffs against the goal; critical mismatches (TSID, ONID, service_id, name, type, LCN) → exit 5.

Re-running the whole pipeline is **idempotent**: a second run reports `no changes needed` if PSS already matches the inventory, and verify still confirms via a fresh capture.

## CLI options

### Mode selection

| Option | Description | Default |
| --- | --- | --- |
| `-f, --file <path>` | Migration JSON path (used as default import without `-i`, and as save target with `-s`) | `./migrate.json` |
| `-s, --save` | Save captured inventory to migration file (combines with stream input; still applies) | — |
| `-o, --output <file>` | Capture-only: write to file, do not apply | — |
| `-i, --input <file>` | Apply-only: load file, do not capture | — |

### Capture

| Option | Description | Default |
| --- | --- | --- |
| `-t, --time <sec>` | Maximum capture duration | `30` |
| `-b, --bitrate <Mbps>` | TS bitrate hint for file-mode pacing | `38.8` |

### Apply / Verify

| Option | Description | Default |
| --- | --- | --- |
| `--target-mpts <id>` | Skip MPTS choice prompt; apply to this PSS stream id | — |
| `--non-interactive` | Auto-accept dialog suggestions; abort on conflict | — |
| `--dry-run` | Print planned POSTs, send nothing | — |
| `--pss-base <url>` | Override PSS discovery (e.g. `http://host:43971`) | auto-discovered |
| `--no-verify` | Skip post-apply self-capture and diff | verify on |
| `--verify-time <s>` | Verification capture window | `10` |
| `--no-bitrate-adjust` | Do not auto-raise `mpegts-output-bitrate` on the target MPTS | adjust on |
| `--bitrate-headroom <pct>` | Safety headroom above measured bitrate when adjusting | `15` |

### Misc

| Option | Description |
| --- | --- |
| `-v, --verbose` | Verbose log (every HTTP POST and dialog branch) |
| `-h, --help` | Show usage and exit |

## Migration file (`migrate.json`)

Human-readable JSON with `format_version: 1`. Default location `./migrate.json`; override with `-f`. Example shape:

```json
{
  "format_version": 1,
  "tool": "mpts_migrate",
  "capture": {
    "source": "udp://239.1.1.1:1234",
    "captured_at_utc": "2026-04-30T08:15:00Z",
    "duration_s": 8.2,
    "packets": 109344
  },
  "transport_stream": {
    "transport_stream_id": 1234,
    "original_network_id": 8442,
    "network_name": "Operator",
    "delivery": { "type": "terrestrial", "frequency_khz": 522000 }
  },
  "services": [
    {
      "service_id": 1, "pmt_pid": 256, "pcr_pid": 256,
      "service_type": 1, "service_name": "Channel 1",
      "provider_name": "MyProvider", "logical_channel_number": 101,
      "free_ca_mode": false,
      "elementary_streams": [
        { "pid": 256, "stream_type": 27, "language": "rus" }
      ]
    }
  ]
}
```

Edit it before re-apply: rename services, change LCN, flip `service_type`, adjust `network_name` — `mpts_migrate -i migrate.json` will push only the changed fields.

## PSS connection

- **Auto-discovery**: scans `/proc/<pid>/comm` for `pss`, reads its `--config` file, picks `web-server.bind-port` (default `43971`).
- **Manual**: `--pss-base http://host:port` skips discovery entirely. Useful for remote PSS or when `--dry-run` should produce a plan without a live PSS.
- The admin REST API requires no authentication on `localhost`.

## Verification

When `--no-verify` is **not** specified (default), after applying the plan the utility:

1. Looks for a localhost UDP output of the target MPTS, or temporarily adds one on `127.0.0.1:<auto>` (annotated `added by mpts_migrate for verification`).
2. Captures the live MPTS through that output for `--verify-time` seconds (default 10).
3. Diffs the captured inventory against the goal: - **Critical** mismatch (TSID, ONID, service_id, name, type, LCN) → exit code **5**. - **Soft** mismatch (PMT PID, PCR PID, ES PID) → printed as warning, exit code 0.
4. If the target MPTS is overloaded (output bitrate ≥ configured `mpegts-output-bitrate`), prints `WARNING: target MPTS is overloaded` — see *Bitrate adjust* below.

## Dry-run

`--dry-run` prints every HTTP request the utility *would* send (path, JSON body) but issues none. Useful for:

- Reviewing the plan with the operator before commit.
- Generating reproducible change-sets in a CI / change-management workflow.
- Working when PSS is offline (combine with `--pss-base http://host:port`).

Dry-run does not run verification.

## Bitrate adjust

By default, if `captured_bitrate × (1 + headroom%)` exceeds the target MPTS `mpegts-output-bitrate`, the utility raises that limit on PSS before applying SI/PSI changes. Without enough headroom an overloaded MPTS drops low-priority data — typical symptoms: missing audio on radio services, intermittent EIT CRC errors. Disable with `--no-bitrate-adjust`, tune the safety margin with `--bitrate-headroom <pct>` (default `15`).

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success — apply and (if enabled) verification both clean. Also returned by successful `--dry-run`. |
| `1` | Argument / file / discovery error |
| `2` | No PAT seen in source — input is not a valid MPEG-TS, or capture window too short |
| `3` | One or more apply HTTP POSTs failed |
| `4` | Apply succeeded but the target MPTS did not return to *Running* state |
| `5` | Verification failed — captured stream differs from the goal in critical fields |

## Limitations & gotchas

- **PSS must already host the target MPTS and feeders**: the utility does not create new streams. The target MPTS plus at least as many SPTS feeders as the inventory has services must already exist; services that have no available feeder are skipped in the dialog.
- **Source MPTS must be reachable** when capturing (modes 1, 2, save+apply): the URL passed as the positional `<input>` argument has to deliver an MPEG-TS stream; for UDP multicast IGMP / firewall must allow it.
- **ES PID remap is applied automatically**: per-service identity remap (`mpegts-pid-old` ≡ `mpegts-pid-new`) is generated for every PCR/video/audio/teletext/data PID so the muxed output keeps source PIDs byte-exact. PMT layout stays stable across migration — even legacy receivers (pre-2015 STBs, Samsung pre-H, LG pre-WebOS 3.0) that cache PIDs do not need re-scan.
- **Delivery descriptors must match the real carrier** for receivers that re-tune via NIT (DVB-T/T2/C/S). A mismatched `delivery` block can send the receiver to a wrong frequency.
- **LCN consistency** between primary and backup MPTS is essential for failover — if they differ, channel positions move in the receiver’s list after the switch.
- **Provider name is mux-wide on PSS** (single `sdt-provider-name` on the MPTS muxer-input). The utility applies it automatically when all captured services share one provider; if different services have different `provider_name` values, a warning is printed and the field is left untouched — the operator must decide which one wins.
- **Not a configuration tool for PSS itself**: `mpts_migrate` only touches SI/PSI identity fields, the per-feeder `pause` flag, and (optionally) `mpegts-output-bitrate`. It does not configure encoders, inputs, encryption, scheduling, etc.

## Troubleshooting

| Symptom | Likely cause / fix |
| --- | --- |
| `Error: no PAT seen in stream` | source is not MPEG-TS, IGMP/firewall blocks the multicast, or `-t` is too short |
| `Error: cannot reach PSS` | use `--pss-base http://host:port` to bypass auto-discovery |
| Apply succeeds but MPTS stays paused | check PSS log; re-run with `-v` to see the full POST plan |
| Verification reports critical diff | compare goal vs capture in JSON; usually a feeder is mistakenly mapped to the wrong service in the dialog |
| `WARNING: target MPTS is overloaded` | raise `mpegts-output-bitrate` on PSS or `--bitrate-headroom <higher %>`; without headroom radio audio and PSI tables corrupt |
