Phantasy Stream Studio — OBS browser sources, multi-destination RTMP, companion live booth
  • TypeScript 95.2%
  • CSS 4.4%
  • HTML 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-31 07:42:30 -04:00
data feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00
docs feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00
packages feat: add companion presence controls and overlays 2026-08-31 07:42:30 -04:00
vendor/plugin-twitch-patches feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00
.env.example fix: harden Stream Studio auth, frames, encoder, and overlays 2026-08-07 12:28:46 -04:00
.gitignore feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00
package.json feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00
pnpm-lock.yaml feat: add companion presence controls and overlays 2026-08-31 07:42:30 -04:00
pnpm-workspace.yaml feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00
README.md feat: auction overlay and ingest for live desk 2026-08-10 01:14:21 -04:00
tsconfig.base.json feat: extract Stream Studio live booth app 2026-08-07 11:22:56 -04:00

Stream Studio

Optional live booth for Phantasy companions: transparent OBS browser sources, multi-destination go-live (Twitch, Kick, YouTube, custom RTMP), and a path to in-app RTMP encoding.

This app is adjacent to the CMS admin shell — like Party, it is not part of the default companion install.

Architecture

Package Port Role
@stream-studio/overlay 5100 Pure browser sources (transparent by default)
@stream-studio/operator 5200 Operator control deck
@stream-studio/server 5300 Control API + WebSocket state
@stream-studio/shared — Destination contracts, overlay URL builders

Phantasy runtime (:2000) remains the source of truth for character identity, avatar assets, and platform plugins.

Quick start

From a Phantasy monorepo checkout:

# If installed as a submodule:
git submodule update --init --recursive apps/stream-studio

cd apps/stream-studio
pnpm install
cp .env.example .env
# Set CHARACTER_RUNTIME_API_KEY to match the Phantasy runtime
pnpm dev

Then:

  1. Open operator: http://127.0.0.1:5200
  2. Copy the Avatar browser source URL
  3. In OBS: Sources → Browser → paste URL → enable transparency / custom CSS if needed
  4. Configure destinations (Twitch / Kick / custom RTMP) under Destinations

Recommended OBS browser source settings:

  • Width / height matching your canvas (e.g. 1920x1080 or avatar-only crop)
  • Shutdown source when not visible: off
  • Background: transparent (Stream Studio defaults to bg=transparent)

Browser sources

Path Purpose
/source/avatar Character only (PNGTuber first; Live2D/VRM later)
/source/chat Platform chat panel
/source/alerts Follow / sub / raid / tip alerts
/source/auction Live Desk lot / high bid / soft-close (Phantasy push)
/source/starting-soon Pre-roll interstitial

Query params:

  • bg=transparent|chroma|#RRGGBB
  • key=#00FF00 (with bg=chroma)
  • anchor=bottom-left|bottom-right|center
  • scale=0.1–2
  • flip=1

Destinations

Destination kinds: twitch, kick, youtube, facebook, tiktok, custom_rtmp.

Stream keys stay on the Studio server disk / secret refs — never embedded in overlay URLs.

Video paths

  1. OBS-first (default): transparent sources + RTMP keys for OBS/Streamlabs
  2. In-app encoder: local ffmpeg multi-RTMP from avatar still / test pattern (Go live tab)

Event ingest

# Direct to Studio
curl -X POST http://127.0.0.1:5300/api/events/chat \
  -H 'Content-Type: application/json' \
  -d '{"platform":"twitch","username":"viewer","message":"hi"}'

# Live Desk auction overlay snapshot (from Phantasy or manual)
curl -X POST http://127.0.0.1:5300/api/events/auction \
  -H 'Content-Type: application/json' \
  -d '{"lotTitle":"Vintage pin","startBidUsd":5,"highBidUsd":12,"highBidder":"alice","updatedAtMs":0}'

# Via Phantasy runtime bridge
curl -X POST http://127.0.0.1:2000/api/v1/stream/events \
  -H "X-API-Key: $CHARACTER_RUNTIME_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"chat":[{"platform":"twitch","username":"viewer","message":"hi"}]}'

Layout profiles

Operator Go live can save/apply layout profiles (scene + avatar/chat/alert toggles) under data/profiles.json.

Avatar modes

Mode Overlay behavior
PNGTuber Idle still + talking frame cycle on talking events
Live2D Loads Cubism/pixi assets from Phantasy /admin/* public paths
VRM CDN three + three-vrm transparent canvas

Talking is driven by:

  • Runtime assistant replies (auto pulse)
  • POST /api/events/talking or operator Events → Pulse talking

Encoder lip-sync

When talking frames resolve, Path B ffmpeg uses a frame sequence loop (avatar-sequence) instead of a single still.

plugin-twitch

See docs/PLUGIN_TWITCH_STREAM_BRIDGE.md and vendor/plugin-twitch-patches/.

Submodule extract

See docs/SUBMODULE.md.

Relation to Phantasy

  • Character APIs: GET /api/v1/character-runtime, GET /api/v1/character-card
  • Chat/events: platform plugins on the runtime (@phantasy/plugin-twitch, Kick, …)
  • Roleplay livestream is a separate multi-viewer stage product — do not merge control planes

Submodule note

This tree may live in-repo during development and extract to phantasy-bot/stream-studio as an optional git submodule (same pattern as apps/party).