# Lumi Companion

Lumi Companion is the Windows streaming-computer client for Lumi. It provides a
single paired-device shell for Companion plugins, including server-hosted
transcription, Song Overlay capture, and the native Lumi monitor overlay. The app
is single-instance, installs per Windows user, closes to the notification area,
and preserves pairing and settings across updates.

## Install and pair

From Lumi, open **Admin > Companion** and choose **Download Companion**. The
private ZIP contains:

- the checksum-pinned per-user Windows installer;
- a one-time `.lumi-pairing.json` package;
- a Host Operator notice and start instructions.

Extract the ZIP and run `Lumi.Companion-Setup.exe`. Setup installs to
`%LocalAppData%\Programs\Lumi Companion`, displays the licence and privacy
notices, identifies the paired Lumi host, imports the adjacent pairing package,
and opens the installed copy. The extracted download can then be deleted.

Existing portable or installed builds retain the current Windows user's
DPAPI-protected device identity, so reinstalling does not create a duplicate
paired device. Pairing packages expire after 15 minutes, work once, and must not
be shared or committed.

## Security boundaries

- Companion plugins inherit the shell's paired-device authentication. Plugins do
  not store or request separate Lumi credentials.
- Production Companion traffic requires HTTPS. Plain HTTP/WebSocket traffic is
  accepted only when the device was paired from the exact matching loopback Lumi
  origin and the request remains on loopback.
- The OBS integration communicates with Companion through a same-user named pipe.
- Transcription audio is normalized to 16 kHz mono signed 16-bit PCM, kept in
  bounded memory, and sent to the paired Lumi host. Companion does not perform
  local speech recognition.
- Installing or repairing the OBS integration requests elevation only while OBS
  is closed and only to copy the verified managed component into OBS's shared
  ProgramData plugin directory.

## Updates

Companion checks after connecting and every six hours. Updates are
user-approved, size- and checksum-verified, and refused while OBS is streaming or
recording. Applying an update replaces the installed executable, bundled
components, and legal bundle, then restarts Companion. Pairing credentials,
settings, and plugin state remain in the per-user data directory.

If the paired Lumi host is temporarily unavailable, Companion remains paired and
reconnects quietly in the background with bounded backoff. The Overview and
Connection pages show the offline state without repeated dialogs; **Retry now**
remains available for an immediate manual attempt.

Localhost development builds can also receive checksum-addressed same-version
updates without publishing a release. See
[Localhost development updates](../docs/local-development-updates.md).

## Transcription control

The Transcription page has a persistent **Generate and include captions** switch,
also available from the tray menu. Turning it off stops the active transcription
session, excludes captions from live and private-test output, and stops sending
microphone audio to Lumi for speech recognition. Private Stream Testing remains
available as a video-only test. Turning the switch back on restores automatic
caption startup with OBS and can start captions while a private test is already
running.

## Private Stream Testing

The core **Stream Testing** page asks the paired Lumi host for an expiring
destination, then uses the managed OBS Bridge to snapshot the complete current
OBS streaming service before installing that destination. OBS sends its ordinary
encoded video and audio to the existing paired Lumi hostname on the configured
RTMP/RTMPS port; Companion does not need a second login, destination editor, or
local media runtime.

While a private test is active, Companion exposes **Open stream viewer**, which
opens the paired Lumi host directly at **Admin > Stream testing**.

Lumi owns and verifies the MediaMTX receiver. MediaMTX remuxes the source stream
for same-origin Admin playback without transcoding or recording it. In v0.3.3,
`Source` is therefore the normal and only quality choice unless a future
provider supplies genuine additional representations.

Stopping the test, losing the Lumi connection, receiver failure, Companion
exit, expiry, or an OBS restart all enter the same recovery path. Companion
keeps the DPAPI-protected recovery record until the OBS Bridge confirms that the
exact saved service type and settings were restored and saved. If automatic
restoration cannot finish while OBS is unavailable, the recovery remains
visible and can be retried after OBS and the bridge reconnect.

## Build and verify

Requirements:

- Windows x64;
- a current .NET SDK with the .NET 8 targeting pack;
- CMake and Visual Studio C++ tools for the native OBS bridge;
- Inno Setup 6 for the installer.

Build the managed solution:

```powershell
dotnet build companion/Lumi.Companion.sln -c Release -p:EnableWindowsTargeting=true
```

Build the pinned OBS bridge, self-contained archive, legal bundle, and installer:

```powershell
companion/scripts/publish-companion.ps1
```

The publish script generates the shared application/tray icon, verifies the OBS
payload inside the published executable, collects NuGet notices, and packages the
corresponding source for the GPL-licensed OBS bridge.

Run Song Overlay's focused verification with:

```powershell
companion/scripts/verify-song-overlay.ps1
```

Run the native Lumi Overlay feed, layout/lifecycle, settings, and full managed
build verification with:

```powershell
companion/scripts/verify-lumi-overlay.ps1
```

Native overlay behavior and capture-exclusion limitations are documented in
[`docs/companion-native-overlay.md`](../docs/companion-native-overlay.md).

Generated installers, pairing packages, credentials, build output, and logs must
not be committed.

## Distribution and legal notices

The release is currently unsigned, so Windows may show an unknown-publisher
warning. The installer and installed `legal` directory include the Companion
licence, default privacy notice, third-party notices, exact licence texts, and
the corresponding OBS bridge source bundle.

Self-hosters should set `LUMI_OPERATOR_NAME`, `LUMI_OPERATOR_CONTACT`, and
`LUMI_OPERATOR_PRIVACY_URL`. Those values identify the Host Operator responsible
for its hosted service and server-side processing; OokamiKunTV is the software
developer and is not automatically the operator of an independently hosted Lumi
installation.
