Editing, checking and carrying the settings

The procedure for editing pss.json by hand, for carrying the settings to another version of Perfect Streamer and for reusing the settings on another node.

Read The pss.json settings file first — at the very least the sections on the sparseness of the file, on reading the file and on the invisible rules. This page says what to do; that one says why, and the reasons are not obvious. In short: the file holds only the differences from the defaults, the service ignores an unknown key without stopping, and a single unacceptable value discards the whole file.

Editing the file changes the next start. To change a running service, use the web interface or the HTTP API (Managing the node over the HTTP API).

What you will need

The schema

Two files are supplied with the documentation: the strict schema pss.schema.json and the permissive pss.compat.schema.json. How they differ and what each of them checks is in Two schema files; the same place says why a permissive check on its own is not enough.

The schemas are part of the documentation, not of the product. They are not on the node, and there is no copy in the settings directory: looking for one there is pointless. Both are on the documentation site, in the directory of their own version:

https://doc2.pstreamer.tv/schema/

Take the schema for your version and keep it on the machine where you edit the file.

Check the version line inside the schema before relying on it. A check against the schema of another release gives confident and wrong answers.

The validator

Any JSON Schema validator with draft 2020-12 support will do. The schema uses conditional constructs, so a validator limited to earlier drafts will accept a file it should have refused; that is worth checking when choosing a different tool.

The recommended one is jv, a standalone open-source program under the Apache 2.0 licence; builds are published on the releases page of the jsonschema project.

Take the archive for your platform, unpack it and put the program into a directory that is already in PATH:

$ tar xzf jv-v<version>-linux-amd64.tar.gz
$ sudo install -m 0755 jv /usr/local/bin/jv
$ jv --version

Builds are published for Linux, Windows and macOS.

Note

The Linux build requires a reasonably fresh set of system libraries: it works on RHEL, AlmaLinux and Rocky 9, Debian 12, Ubuntu 22.04 and newer, and on an older distribution it does not start at all. That is no obstacle: check the file on a workstation and carry an already checked one to the node. It is the better way round anyway — the file is small, and the node does not need a validator.

A tool for the checks the schema does not do

Two rules cannot be expressed in JSON Schema at all: the uniqueness of identifiers and the equal length of paired arrays. The commands in The checks the schema does not do use jq, which is in the repository of every distribution:

On RHEL, AlmaLinux and Rocky:

$ sudo dnf install jq

On Debian and Ubuntu:

$ sudo apt install jq

Changing a parameter

Carry out the sequence in full. The steps usually skipped are 5 and 7 — and they are exactly the ones that catch the silent errors.

  1. Stop the service.

    $ sudo systemctl stop pss
    

    The file of a running node must not be edited: the service overwrites pss.json on a schedule of its own with what it holds in memory, and the edit will disappear without a single message.

  2. Save a copy — under a name that does not exist yet.

    $ cp pss.json pss.json.$(date +%Y%m%d_%H%M%S)
    

    That is the only way back: the service keeps no automatic backup of the working configuration. Do not use the same copy name twice: on a second pass through this sequence you would overwrite the only sound file with what an unsuccessful attempt left behind.

  3. Edit.

    Change the values in place. Do not move keys and do not move array entries — for why, see The order of the keys inside an object matters and The order of entries in an array is not preserved. When adding an entry to an array, give it an explicit and unique id: nobody will assign one for you (Identifiers are set by hand). Give the entry its anchor keys as well — stream-name for a stream, type and the address for an input and an output, name for a card and a storage, and so on (The structure of the document): without them the file will be refused whole.

  4. Remove your comments. The reading admits only block /* ... */, strict JSON tools do not accept even those, and the service will erase the comments at the first save anyway (Comments are read but not preserved).

  5. Check the file against the schema.

    $ jv pss.schema.json pss.json
    

    A zero return code means the check has passed. Otherwise one line is printed per error, and each names the exact place:

    jsonschema validation failed with 'pss.schema.json#'
      - at '/stream/3/input/1/passphrase': false schema
    

    It reads like this: the second input of the fourth stream has a passphrase key that does not belong to the transport chosen by its type key. Positions are counted from zero.

  6. Run the checks from The checks the schema does not do.

  7. Start the service and read the log.

    $ sudo systemctl start pss
    $ grep -iE 'ignore|clamped|config' /var/log/pss/main.log
    

    The service writes the log to a file; the directory is set by the log-dir key of pss.properties, by default /var/log/pss. These lines will not be in journalctl -u pss until log-to-console or log-to-syslog is turned on in pss.properties.

    A line about an ignored key means the schema does not match the installed build — usually it is older or newer. A line about a clamped value means a number went out of range and was silently corrected, and the file has already been re-saved with the corrected value.

    If the service did not start, look in the bad/ directory — Recovering after a refused file.

  8. Check the result through the interface, not by the file. The file does not show the settings left at their default, so nothing can be confirmed by it. Read the configuration back over the HTTP API: there every key is returned.

Carrying the settings to another version

There is no version mark in the file, and the service performs no conversion. A configuration from another release is applied as it is: keys that no longer exist are ignored; keys that did not exist yet take their default values. Neither is reported. The procedure below makes both visible.

  1. Take pss.schema.json for the target version — the one that will read the file, not the one that wrote it.

  2. First pass, permissive. It checks types, ranges and required keys, but tolerates the keys the target version has dropped:

    $ jv pss.compat.schema.json pss.json
    

    Everything reported here is a genuine problem: a value out of range, a key that changed shape, a missing identifier.

  3. Second pass, strict. It lists the keys the target version no longer knows:

    $ jv pss.schema.json pss.json
    

    Every complaint that is new compared with the second step is a key the new version will silently ignore. Decide for each one whether the setting was renamed, replaced by another mechanism or abolished, and in every case delete the key from the file: left in place it costs nothing at run time, but it hides the fact that the setting no longer does anything.

    The strict pass also answers for the belonging of a key to a variant, which the permissive schema does not check — which is why a permissive pass alone is not enough.

  4. Compare the defaults of the two versions.

    The file holds only the differences from the defaults, so a setting you have never touched is absent from the file — and if its default has changed, the behavior will change with the update, silently. The file and the schema are blind to this by construction: the schema of the target version will not show such a change.

    It is visible only in the effective configuration, because the HTTP API returns every key, including the ones left at their default. Read it on the source node before the update and on a node of the target version: the differences in the keys you have never set are the defaults that changed.

  5. Continue from step 4 of Changing a parameter.

Warning

Do not carry pss.json backwards, to an older version. A key that appeared later will be ignored, but a value that is admissible now and was not before will be clamped to the edge or will discard the whole file.

Carrying the settings to another node

A configuration is portable, but some keys identify the node or open access to it, and copying them unchanged is at best confusing and at worst a leak.

  1. Replace every secret. The list of them is Values that must not be passed on. Do not blank them: some keys do not accept an empty value and will discard the whole file. Substitute an obvious replacement of a plausible length, and set the real values through the web interface after the first start.

  2. Change the identifying data of the node: the node name must be unique within the domain, and the note, the role and the region describe this machine, not the one they were copied from.

  3. Look through everything that names a particular machine: listening addresses, interface names, storage paths, card numbers. A non-existent path and an uninstalled card the schema will not catch.

  4. Look through the Meshwork section. The addresses, names and secrets of the peers are paired arrays matched by position (Paired arrays are matched by position): when deleting an entry, delete the corresponding entry from every array. Here a difference in length discards the file whole, so check them in advance — The equal length of paired arrays.

  5. Compare the licenses of the two nodes. The settings of anything the target license does not include will turn out to be unknown keys: the section will leave the file with a single warning in the log. This is most noticeable with DVB reception.

  6. Continue from step 4 of Changing a parameter.

The checks the schema does not do

Duplicated identifiers

Two entries of one array with the same id discard the whole file. The uniqueness of a key among the entries of an array cannot be expressed in JSON Schema, so it is checked separately:

$ jq '[paths(type=="array") as $p
       | {at: ($p|join(".")),
          duplicated: (getpath($p)
                       | map(select(type=="object") | (.id // 0))
                       | group_by(.) | map(select(length>1)) | map(.[0]))}
       | select(.duplicated|length>0)]' pss.json

An empty result is what you want. Anything else names the array and the identifiers repeated in it. A missing id the command counts as zero: that is how the service reads it in the stream array, where two entries without an identifier collide. In any other array an entry without an id discards the file by itself, so a zero identifier outside stream is already a find.

The equal length of paired arrays

Where arrays are matched by position, the number of entries in them must be the same. For the Meshwork section:

$ jq '.cluster | {addresses: (.["cluster-node-address"]|length),
                  names:     (.["cluster-node-name"]|length),
                  secrets:   (.["cluster-node-secret"]|length)}' pss.json

The three numbers must be equal. The check here is not a matter of hygiene: the service detects a difference in length itself and discards the whole file — for the Meshwork peers, for the environment variables, for the “was — became” lists when PIDs are reassigned (mpegts-pid-old and mpegts-pid-new), for the language-change lists (mpegts-lang-set-pid and mpegts-lang-set) and for the pair biss-pnr and biss-key. For the four RIST addresses (rist-addr-*) the file is not discarded, but the input does not open and the reason goes to the log.

The order of the keys

The schema does not see the order of the keys, and it matters in three places — The order of the keys inside an object matters. There is no command for this: the rule is to move nothing, and in a new entry added by hand to put type, mpts and mode first.

References between sections

The numbers that point to another part of the file — a storage, a program-guide source, a receiver card, a source stream — are not checked by the schema. If the target does not exist, the service will say so at startup.

Recovering after a refused file

If pss.json could not be read, the service moves it into the bad/ directory under a name with the date and time and comes up on the previously restored configuration, or, in its absence, on the default settings (pss_default.json, Behavior at startup and on configuration errors). Those contain no streams at all, so in this state the node runs empty. An alert at startup reports that the settings could not be loaded and that the node is running on the fallback ones.

  1. Do not restart the node again. A restart does no harm to the archived copy, but the working configuration right now is the default settings, and there is no reason to let them be saved over anything.

  2. Find the archived file in the bad/ directory. The most recent one is your configuration.

  3. Find out what is wrong with it:

    $ jv pss.schema.json bad/pss_20260809_101500.json
    

    The log of the failed start also names the key and the reason.

  4. Fix it, check until the result is clean, copy it back over pss.json and start.

If the archived copy is gone or is damaged as well, the last hope is the copy made at step 2 of Changing a parameter. That is what the step is for.

Hints in the editor

Most editors will suggest key names, show the admissible values and underline an error as you type, if you point them at the schema.

Bind the schema by file name, in the settings of the editor itself: in editors that work through the JSON language server this is the json.schemas entry, mapping the name pss.json to the schema. The schema can be given either as a local file or as the address of the published version. A local file is preferable: it works without a network and pins the version hard, whereas in an address the wrong version is easy to type.

Warning

Do not add a $schema key inside pss.json itself. It looks as though it works: the service accepts it as an unknown key, with a warning in the log — but at the very first save the key disappears, because the document is built anew from memory. Everything the product did not declare lives in the file exactly until the next save.

In short

  • Stop the service before editing: the file of a running node will be overwritten from memory.

  • Save a copy: there is no automatic backup of the working configuration.

  • Do not move keys or array entries.

  • Give every added entry an explicit and unique identifier.

  • Check the file against the schema of the version that will read it.

  • Check duplicated identifiers and the lengths of paired arrays separately.

  • Read the log after the first start: ignored keys and clamped values are visible only there.

  • Confirm the result through the interface, not by re-reading the file.