{
  "_": [
    "THE SERIES CARD ALONE, for adding to a 1920x1080 collection that is already configured — and,",
    "specifically, to one that is ON AIR. `obs/stream_1080.json` is the whole layout and carries this",
    "same scene; applying that file rewrites every source it names, which is the right thing when",
    "building a box and the wrong thing at 15:00 on a race day.",
    "",
    "Measured, on the machine this was written on: a dry run of the full layout against a live OBS",
    "reported twelve source rewrites, `programme` among them — the deployed producer's URL carried a",
    "resolution floor and a camera-rotation set the file does not, so the apply would have changed the",
    "picture that was going out. This file names ONE scene, so `apply`'s conservatism does the rest:",
    "a scene the file does not describe is not touched at all.",
    "",
    "Three omissions are the safety, and each is deliberate:",
    "  * NO `profile`  — the canvas belongs to the profile, and this must not be able to move it.",
    "  * NO `program`  — it never cuts. `apply` even restores the operator's programme scene if OBS",
    "                    selects the newly created one by itself.",
    "  * NO `audio_continuity` — the invariant is declared where `programme` is DEFINED, which is the",
    "                    full layout. Here `programme` is borrowed, and a borrowed source with no",
    "                    definition in the same document cannot be validated against one.",
    "",
    "`programme` is still the bottom item, so cutting to the card keeps the commentary running. It has",
    "no settings here on purpose: this file must never be able to re-point the source carrying the",
    "programme picture and its voice.",
    "",
    "  python -m v3.broadcast.live.obs_scenes apply v3/broadcast/live/obs/standings_1080.json \\",
    "      --var standingsbase=http://127.0.0.1:8767",
    "",
    "…where that host is the data-only local standings service installed beside the private feed",
    "relay. Keeping it on 8767 prevents the additive on-air manifest from silently repointing the",
    "card to the IAM-private programme relay on 8766."
  ],
  "collection": "Streaming 1080p",
  "canvas": [
    1920,
    1080
  ],
  "vars": {
    "_standingsbase": "Where the card is served from. Same var, same meaning and the same default as in `obs/stream_1080.json`, so the two files cannot describe the scene differently.",
    "standingsbase": "http://127.0.0.1:8767"
  },
  "scenes": [
    {
      "name": "Standings",
      "items": [
        {
          "source": "programme",
          "enabled": true,
          "transform": {
            "positionX": 0,
            "positionY": 0,
            "alignment": 5,
            "boundsType": "OBS_BOUNDS_SCALE_INNER",
            "boundsAlignment": 5,
            "boundsWidth": 1920,
            "boundsHeight": 1080
          }
        },
        {
          "source": "results:standings",
          "kind": "browser_source",
          "enabled": true,
          "settings": {
            "url": "${standingsbase}/core/web/standings.html",
            "width": 1920,
            "height": 1080,
            "shutdown": false,
            "restart_when_active": false,
            "reroute_audio": false
          },
          "transform": {
            "positionX": 0,
            "positionY": 0,
            "alignment": 5,
            "boundsType": "OBS_BOUNDS_SCALE_INNER",
            "boundsAlignment": 5,
            "boundsWidth": 1920,
            "boundsHeight": 1080
          }
        }
      ]
    }
  ]
}
