---
title: MPTS Migrate Perfect Streamer Toolkit v1.1 — MPTS identity migration
url: https://doc2.pstreamer.tv/en/manual/toolkit/mpts_migrate.html
lang: en
product: Perfect Streamer
version: 2.0.2.362
---

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

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

Captures the DVB SI/PSI identity of a running multi-programme MPEG-TS stream (MPTS) and reproduces it on a Perfect Streamer (PSS) instance on the same host. As a result, subscriber receivers (STB / TV) keep working **without a channel rescan** after a migration or a switchover to the backup.

The tool is part of the **pstreamer** package and is located at `/opt/pss/tools/mpts_migrate` after installation — no separate installation is required.

## Prerequisites

Before running the utility, make sure that:

- **PSS is running** on the same host (or on a host reachable via `--pss-base`). The utility looks for `pss` in `/proc` and reads `pss.json` to obtain the admin port (`43971` if the configuration does not contain it).
- **The source MPTS is reachable** if a capture is intended (modes 1, 2, save+apply): the URL passed as the positional argument `<input>` must deliver an MPEG-TS stream. For UDP multicast, IGMP / firewall must permit reception; for files, the path must exist.
- **The target MPTS is already configured in PSS**: the utility does not create new streams. The MPTS object and at least as many SPTS feeders as there are services in the inventory must exist beforehand. Services with no free feeder are shown in the dialogue and may be skipped.
- **The HTTP admin API is available on localhost** for reading `/data/stream` (used during verify) and writing `/config/stream` (apply).

## What is migrated

All receiver-visible identifiers at transport stream and service level:

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

Service / provider names in non-ASCII DVB character encodings (for example ISO-8859-5 for Cyrillic) are decoded to UTF-8 automatically.

For every service the ES PID remap is built as identity pairs (`mpegts-pid-old` ≡ `mpegts-pid-new`) for each PCR / video / audio / teletext / data PID, so the resulting multiplexed output preserves the original PIDs **byte-exact**. Legacy receivers that cache the PMT after the first scan keep working without reconfiguration.

On PSS 2.0.0.193 and later the plan additionally enables, on the muxer input of the target MPTS, the native original-PID preservation mode (Automatic PID mapping disabled) and sets for each service the captured programme order in the PAT (program order) — the on-air programme order survives the migration. Support is detected automatically from the configuration of the target streamer; on older versions these keys are not sent (the utility prints a warning), identity pairs remain the only mechanism that pins the PIDs, and the programme order in the PAT is not preserved.

## Use cases

- **Failover**: switching decoders from the primary MPTS to the backup one while preserving the channels on the receiver side
- **Hardware migration**: moving a running multiplex from one PSS host to another without any instructions to the viewers
- **Before / after upgrade snapshot**: capturing the multiplex before a PSS upgrade and re-applying it afterwards to guarantee bit-identical SI/PSI
- **Manual editing and re-apply**: capture, edit `migrate.json` (rename services, change LCNs, adjust `service_type`), re-apply
- **Dry-run check**: printing every HTTP POST that *would* be sent, without affecting 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** — the utility opens the stream, parses PAT / PMT / SDT / NIT / EIT for `-t` seconds (30 by default) and builds the inventory; the total stream bitrate is measured.
2. **(Optional) Save** — with `-s` or `-o` the inventory is written to JSON for later reuse.
3. **PSS discovery** — detects the running PSS by scanning `/proc` and reads `pss.json` to obtain the admin port (`43971` if the configuration does not contain it); `--pss-base http://host:port` bypasses auto-discovery.
4. **Mapping confirmation** — an interactive dialogue asks how each captured service is to be mapped to an existing SPTS feeder; `--non-interactive` accepts the proposals and exits on a conflict; `--target-mpts <id>` skips the MPTS selection prompt.
5. **Automatic feeder un-pause** — for every mapped SPTS / muxer-output the utility sends `{"pause":false}` if the feeder was paused, so that the multiplexer actually receives data after apply.
6. **Automatic bitrate adjustment** — if `captured_bitrate × (1 + headroom%)` exceeds the `mpegts-output-bitrate` of the target MPTS, the utility raises that limit on PSS with a single POST (rounded up to the nearest 1000 kbps). Disabled with `--no-bitrate-adjust`.
7. **Planning** — compares the inventory with the current `/config/stream` tree on PSS and prepares HTTP POST requests only for the fields that differ. The ES PID remap is generated as identity pairs (`mpegts-pid-old` ≡ `mpegts-pid-new`) so that the multiplexed output keeps every original PID unchanged — including PCR, video, audio, teletext, SCTE-35, DSM-CC. On PSS 2.0.0.193 and later the plan additionally enables the original-PID preservation mode on the target muxer input and sets the programme order in the PAT (see *What is migrated*).
8. **Apply** — sends the planned POST requests, then toggles the MPTS pause/unpause so that PSS re-reads the configuration; with `--dry-run` the plan is only printed.
9. **Verify** (enabled by default, even if the plan is empty) — captures the resulting MPTS through one of the PSS UDP outputs and compares it with the target; critical mismatches (TSID, ONID, service_id, name, type, LCN) → exit code 5.

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

## CLI options

### Mode selection

| Option | Description | Default |
| --- | --- | --- |
| `-f, --file <path>` | Path to the migration JSON (used as the default import when `-i` is absent and as the save target with `-s`) | `./migrate.json` |
| `-s, --save` | Save the captured inventory to the migration file (combined with a stream input; apply is still performed) | — |
| `-o, --output <file>` | Capture only: write to file, no apply | — |
| `-i, --input <file>` | Apply only: load the file, no capture | — |

### Capture

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

### Apply / Verify

| Option | Description | Default |
| --- | --- | --- |
| `--target-mpts <id>` | Skip the MPTS selection prompt; apply to this stream id on PSS | — |
| `--non-interactive` | Auto-accept the dialogue proposals; exit on a conflict | — |
| `--dry-run` | Print the plan of POSTs, send nothing | — |
| `--pss-base <url>` | Override PSS auto-discovery (for example, `http://host:8808`) | auto |
| `--no-verify` | Skip the post-apply capture and diff | verify enabled |
| `--verify-time <s>` | Capture window for verification | `10` |
| `--no-bitrate-adjust` | Do not raise `mpegts-output-bitrate` on the target MPTS | adjustment enabled |
| `--bitrate-headroom <pct>` | Bitrate headroom above the measured value when adjusting | `15` |

### Miscellaneous

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

## Migration file (`migrate.json`)

Human-readable JSON with `format_version: 1`. The default location is `./migrate.json`; it is overridden with `-f`. Example of the layout:

```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,
      "program_order": 1,
      "free_ca_mode": false,
      "elementary_streams": [
        { "pid": 256, "stream_type": 27, "language": "rus" }
      ]
    }
  ]
}
```

The file may be edited before a re-apply: rename services, change LCNs, change `service_type`, adjust `network_name` — `mpts_migrate -i migrate.json` sends only the modified fields.

## Connecting to PSS

- **Auto-discovery**: scanning `/proc/<pid>/comm` for `pss`, reading its `--config` file and taking `web-server.bind-port` (`43971` if the key is absent).
- **Manually**: `--pss-base http://host:port` bypasses auto-discovery entirely. Useful for a remote PSS or when `--dry-run` has to produce a plan without a live PSS.
- The admin REST API requires no authentication on `localhost`.

## Verification

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

1. Looks for a localhost UDP output on the target MPTS, or temporarily adds one on `127.0.0.1:<auto>` (labelled `added by mpts_migrate for verification`).
2. Captures the live MPTS through that output for `--verify-time` seconds (10 by default).
3. Compares the captured inventory with the target:

   - A **critical** mismatch (TSID, ONID, network name, service_id, name, type, LCN) → exit code **5**.
   - A **soft** mismatch (PMT PID, number of ES, provider name, programme order in the PAT) → reported as a warning, exit code 0.
4. If the target MPTS is overloaded (output bitrate ≥ the configured `mpegts-output-bitrate`), `WARNING: target MPTS is overloaded` is printed — see *Bitrate adjust* below.

## Dry-run

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

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

Dry-run does not run verification.

## Bitrate adjust

By default, if `captured_bitrate × (1 + headroom%)` exceeds the `mpegts-output-bitrate` of the target MPTS, the utility raises that limit on PSS before applying the SI/PSI changes. Without sufficient headroom an overloaded MPTS drops low-priority data — the typical symptoms are audio dropouts on radio services and intermittent EIT CRC errors. Disabled with `--no-bitrate-adjust`; the headroom is set with `--bitrate-headroom <pct>` (`15` by default).

## Exit codes

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

## Limitations and pitfalls

- **PSS must already hold the target MPTS and the feeders**: the utility does not create new streams. The target MPTS and at least as many SPTS feeders as there are services in the inventory must exist beforehand; services with no free feeder are skipped in the dialogue.
- **The source MPTS must be reachable** during a capture (modes 1, 2, save+apply): the URL passed as the positional argument `<input>` must deliver an MPEG-TS stream; for UDP multicast, IGMP / firewall must permit it.
- **The ES PID remap is applied automatically**: for every service an identity remap (`mpegts-pid-old` ≡ `mpegts-pid-new`) is generated for each PCR/video/audio/teletext/data PID, so that the multiplexed output preserves the original PIDs byte-exact. The PMT layout stays stable across migrations — even legacy receivers (STBs made before 2015, Samsung sets before the H series, LG sets before WebOS 3.0) that cache PIDs need no rescan.
- **The delivery descriptor must match the actual carrier** for receivers that retune via the NIT (DVB-T/T2/C/S). A mismatched `delivery` block may send the receiver to the wrong frequency.
- **LCN consistency** between the primary and the backup MPTS is critical for failover — if they differ, the channel positions in the receiver list shift after the switchover.
- **The provider name in PSS is mux-wide** (a single `sdt-provider-name` per MPTS muxer input). The utility applies it automatically if all captured services share one value; if different services carry different `provider_name` values, a warning is printed and the field is left untouched — the choice is up to the operator.
- **Not a PSS configuration tool**: `mpts_migrate` touches only the SI/PSI identity fields, the `pause` flag on each feeder, (optionally) `mpegts-output-bitrate`, and, on PSS 2.0.0.193 and later, the PID-preservation-mode and programme-order keys. It does not configure encoders, inputs, encryption, schedules and the like.
- **On PSS older than 2.0.0.193** the muxer original-PID preservation mode and the programme order in the PAT are not supported: the utility prints a warning, the PIDs are pinned by identity pairs alone, and the programme order after the migration may differ from the original one.

## Troubleshooting

| Symptom | Probable cause / remedy |
| --- | --- |
| `Error: no PAT seen in stream` | the 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 succeeded, but the MPTS stays paused | check the PSS log; re-run with `-v` to see the full plan of POSTs |
| Verification reports a critical mismatch | compare the target and the captured stream in JSON; usually a feeder was mapped to the wrong service in the dialogue |
| `WARNING: target MPTS is overloaded` | raise `mpegts-output-bitrate` on PSS or use `--bitrate-headroom <higher %>`; without headroom the audio of radio services and the PSI tables are corrupted |
