navig-obs
Control OBS Studio from navig — scenes, sources, streams, recording, studio mode, whole obs-websocket v5 surface — its own navig-obs command, and
navig obsinside navig.
Works on its own — its own CLI, no navig required · v0.6.0 · not on PyPI yet (install from source below)
On its own (no navig needed)
pip install "git+https://github.com/navig-run/plugins#subdirectory=navig-obs"
navig-obs --help # no navig needed
With navig
pip install "git+https://github.com/navig-run/plugins#subdirectory=navig-obs"
navig obs --help
Commands
| Command | What it does |
|---|---|
navig obs clips |
Cut the Grid Pigeon's moments from a recording into 9:16 clips, captions burned in. |
navig obs doctor |
Local OBS health check: install, websocket config, plugin load errors, missing files. |
navig obs events |
Stream OBS events live (scene changes, output state, media, …). |
navig obs marker |
Append a marker to the session's recording clock (OBS must be recording). |
navig obs request |
Send any obs-websocket v5 request and print its responseData. |
navig obs screenshot |
Capture a source/scene image from OBS and save it locally (proof shot). |
navig obs stats |
OBS resource stats: CPU, memory, FPS, render/output frame health. |
navig obs status |
Live OBS state: version, current scene, stream/record/replay/vcam/studio. |
Control OBS Studio from NAVIG — locally or on any machine on your LAN — over
OBS's built-in obs-websocket v5 protocol (port 4455). One command surface,
two front doors: navig obs … inside navig, navig-obs … standalone.
No agent on the OBS machine is required: OBS ≥ 28 ships the websocket server itself. You only need it enabled (Tools → WebSocket Server Settings).
Quick start
navig obs doctor # local health: websocket, plugins, missing files, log errors
navig obs status # version, current scene, stream/record/vcam/studio state
navig obs scenes list
navig obs scenes activate "BRB"
navig obs stream start
navig obs screenshot "Program" --out proof.png
Remote machine: navig obs --host 192.168.1.50 status or NAVIG_OBS_HOST=….
Connection & auth
Resolution order per field: --host/--port/--password flags → NAVIG_OBS_HOST /
NAVIG_OBS_PORT / NAVIG_OBS_PASSWORD env → navig config obs.host / obs.port /
obs.password → OBS's own local config file (loopback only, read-only) → defaults
127.0.0.1:4455. The password is never printed or logged. The v5 challenge/
response handshake is implemented in navig_obs/engine/client.py (stdlib +
websockets, no third-party OBS wrapper).
Verbs
| Group | Actions |
|---|---|
status · doctor · stats · events · screenshot |
top-level probes |
request |
top-level — raw obs-websocket v5 request: request GetVersion (its availableRequests lists every valid name) · --data '{…}' |
scenes |
list · current · create · remove · activate |
items |
list · visible · transform · remove · duplicate |
sources |
list · kinds · add · remove · settings · active · defaults · refresh (browser source, no cache) |
audio |
monitor — read, or --type none|monitor|both |
filters |
list · add · remove · settings · enable |
transitions |
list · current · set · settings |
stream |
status · start · stop · pause · resume · settings |
record |
status · start · stop · pause · resume · directory |
replay |
status · start · stop · save |
vcam |
status · start · stop |
studio |
status · enable · disable · to-program |
collections |
list · current · create · use |
profiles |
list · current · use |
media |
status · play · pause · restart · stop |
show |
status · setup · cue · toast · poll · pigeon · civic · say — deploy toasts, store-sale ring, the Grid Pigeon (below) |
hotkeys |
list · send |
session |
start · stop |
marker |
top-level — append to the session's recording clock |
Every verb accepts --json for scripts/agents. Exit codes are part of the
contract: usage errors exit 2, operation failures exit 1, and an unreachable
OBS on status is a skip (exit 0) — "not running" is an answer, not a failure.
Destructive verbs (scenes remove, items remove, sources remove) confirm
unless -y.
stream settings masks the stream key in every rendering (including --json)
unless --reveal; writes go through --set-key / --set-server and never echo
the key.
Integration contract (for SCHEMA BROADCAST and other consumers)
Consumers drive OBS through this CLI (or the same verbs through the agent). Stable mapping for the SCHEMA BROADCAST integration spec:
| Consumer intent | NAVIG OBS action |
|---|---|
| Select broadcast scene | navig obs scenes activate "<scene>" |
| Trigger transition | scenes activate … (applies the current transition); studio mode: studio to-program |
| Set scene data (overlay payload) | navig obs sources settings <browser-source> --set '{"url":"…"}' (or any source's settings) |
| Display mission alert / Disorder Protocol / BRB / Emergency Cut | scenes activate "<pack scene name>" — names come from the scene pack, no hardcoding here |
| Read OBS connection status | navig obs status --json → {"reachable": true, …} (exit 0 + reachable:false when down) |
| Read recording status | navig obs record status --json |
| Start/stop stream & recording | stream start|stop, record start|stop |
| Anchor a recording session (clock, scene, canvas) | navig obs session start --lang fr → prints the session dir (default ~/.navig/obs-sessions/<id>/, override --dir / NAVIG_OBS_SESSIONS) |
| Mark an event during a recording | navig obs marker <label> --kind cue|character|scene|mission|anomaly|bookmark|incident (needs an active recording; --session <dir> or NAVIG_OBS_SESSION) |
| Close a session + locate the file | navig obs session stop (sets endEpoch, finds the newest recording since startEpoch) |
| Archive a session + cut clips from its markers | navig obs session archive --clip → obs.archive_dir/<id>/ (sha256-verified copy + edl.json → navig video cut) |
| React to OBS state changes | navig obs events --json (JSONL stream: scene changes, output state, media, …; --topics filters, --timeout bounds it) |
Guarantees for consumers:
- All verbs and their
--jsonshapes are stable within a major version; new verbs are additive. --hosttargets any OBS on the network; auth per the resolution order above.- The controller never mutates the scene pack — scene names are data supplied by the consumer.
- Sessions are the writer of SCHEMA broadcast contract 7
(
session.json+markers.jsonl, shapes frozen in the SCHEMA repo underdesign/broadcast/contracts/): media never enters a repository; the session dir is the hand-off unit for ingest and the EDL. - Designed for adapter-style consumption: run the CLI, parse
--json, branch on exit code (0ok/skip,1failed,2usage).
Show events — deploys, sales and the Grid Pigeon on the stream
navig_obs.show puts three off-stream moments on the stream; it is off until
obs.show.enabled is true, then the gateway runs it (restart the gateway):
- A deploy — polls
obs.show.patch_feed(default Schema's public Source log,https://api.schema.cx/api/source/patches, everyobs.show.poll_seconds= 60): a deploy landing (compiling) or a published patch becomes anobs-browseremit_eventnamedobs.show.toast_event(schema-toast) that the broadcast overlay draws, plus thepatch-landedcue. The first look only seeds the position (~/.navig/obs-show/feed-state.json); after downtime only the newest patch shows. - A store sale — navig's
salenotification (navig-msstore) plays thesale-ringcue. Sound only. - A civic event — polls
obs.show.civic_feed(default Schema's public civic feed,https://api.schema.cx/api/civic/events, same interval): each new row becomes anemit_eventnamedobs.show.civic_event(pigeonCivic) carrying the row; the Grid Pigeon overlay reacts to itskind. Same seeding rule (civic-state.json); after downtime at most three fire, oldest first. The overlay is a local file (originnull) the API does not admit — reading the feed here is what lets it react without loosening the API's CORS. An emptycivic_feedturns it off.
By hand: navig obs show pigeon <beat> [--mode observer|chaos|courier] sends
the pigeon page event (obs.show.pigeon_event) — any beat of the overlay;
navig obs show civic [--fire] reads the civic feed once.
A spoken line — navig obs show say [TEXT] [--title T] [--kicker K]
[--tone deploy|game|live|passport|info] [--lang en|fr|ru] [--template deploy]
[--image https://…] [--provider P] [--voice V] [--fresh] [--no-voice] [--dry-run]
[--json].
- The stage's language decides the voice. The loaded collection names it
(
SCHEMA BROADCAST (ru)→ru;--langoverrides; elseobs.show.say_lang, defaulten). Each language has its own voice —obs.show.say_voices{lang: {provider, voice, style, fx}}overvoices.DEFAULTS(en MiMo Dean with the pigeon's style note, fr Edge Henri, ru Edge Dmitry).--provider/--voiceoverride one line;obs.show.say_provider/say_voice, when set, force one voice for every language (the old behaviour). - Names are said the language's way: synthesis is
navig voice speak TEXT --provider P [--voice V] --lang L [--style S] --output FILE --no-play, and navig-audio's lexicon rewrites the SPOKEN text only (SCHEMA → Skeema / schéma / Схема;audio.tts.lexicon.<lang>adds your own). The card keeps the text. fx(pitch=<±semitones>,tempo=<factor>) is the pigeon's character, applied by ffmpeg after synthesis (pitch keeps the speed; loudness evened).- The clip is cached at
~/.navig/obs-show/tts/<sha16(provider,voice,text,lang, style,fx)>.mp3and never synthesized again (--freshforces it); measured with ffprobe (fallbackmax(3500, words × 380)ms). Then, in one OBS session: theschema-toastalert card{kind:"alert", tone, kicker, title, text, ms, image?}(cardms= clip + 1 s;imageonly an https URL), thepigeon{act:"speak", ms}event, and the clip through the cue input. - A failed synthesis still shows the card (warning, exit 0). A dry run never
touches OBS. With
obs.show.civic_sayon (default off — TTS can bill), each civic beat is spoken the same way, in the stage's language, coloured by kind (flash_liveamber,passport_forgedpassport,ignitionlive).
Deploys, spoken — with obs.show.deploy_say on, a published patch that changed something a citizen can see is SAID in the stage's language instead of the silent card + sting (one cue input: the sting would cut the voice). English reads the patch's world-voiced headline; French and Russian name the layers it touched (voices.LAYER_NAMES, the app's own translations; at most three, then "and N more"). An internal-only patch keeps the plain card. On air only: obs.show.say_on_air_only (default on) lets the bridge speak — deploys and civic beats alike — only while OBS is streaming or recording; off air the cards and the pigeon still react, silently. A hand-run show say always speaks.
Voices — navig obs show voices lists each language's voice; --sample
[--play] renders (and plays on stream, one by one) four directions × three
languages; --use <direction> keeps one (writes obs.show.say_voices).
Flash on air — navig obs show flash <zone-slug> [--api URL] calls the
Architects' flash door (POST /api/admin/flash/deal) with the session in the
vault (schema_operator_session, or NAVIG_SCHEMA_SESSION). It deals a REAL
mission and notifies that Zone — an operator act, never automatic. Refusals are
printed in plain words (exit 1).
Voice remote (Alexa) — a voice assistant drives the stage through NAVIG's
signed ingest door. navig signals add alexa creates the source (URL + secret,
shown once); the gateway checks the HMAC, timestamp window and replays, then
hands the verified intent to navig_obs.show.remote (an ingest action, so it
never rings as a notification). The menu is fixed: SwitchScene{scene} (a
number or the closest name), EmergencyCut, Say{text}, RecordStart,
RecordStop, Status, FreeGames, OpenPage{page} (allow-listed https pages,
obs.show.voice_pages). Going live is not on it. The reply (speech) is in
the request's locale (en/fr). Source name: obs.show.voice_source (default
alexa). No source = the door stays closed.
Cues come from a contract-04 cue book (obs.show.cues_file, default
~/.navig/obs-show/cues.json; provenance required, cooldownMs honoured) and
play through ONE media input, obs.show.cue_input (SCHEMA · Cue) — set the
file, restart the input. navig obs show setup --all-scenes creates that input
and places it in every scene (monitor + output). An OBS that is closed is a
logged no-op. GET /api/deck/obs/show reports the running bridge.
Layout
navig_obs/
engine/client.py obs-websocket v5 protocol (handshake, auth, requests, keepalives, events)
engine/config.py target resolution (flags > env > navig config > local OBS file)
doctor.py local health checks (install, websocket config, plugins, logs, missing files)
commands/obs.py top-level verbs + group mounts; sibling modules = resource groups
show/ show-events bridge: feed watcher, cue book, OBS moves, gateway service
skills/obs-control/SKILL.md agent routing
Install (dev)
pip install -e plugins/navig-obs # from the navig repo root
navig obs doctor
Metadata
Release files for navig-obs 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| navig_obs-0.6.0.tar.gz | 130.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| navig_obs-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 240.3 kB
Security for navig-obs 0.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.