Platforms, studio, and secrets
What "platform" means in Stream specifically, the five different per-platform configuration surfaces, and the three secrets this product keeps deliberately separate.
"Platform" means a streaming site here, and only that
In Stream's own code, platform always means a streaming/webcam site — Chaturbate,
Stripchat, CAM4, BongaCams, Twitch, Kick, TikTok, Instagram Live, Telegram. That's one of
three unrelated meanings the word carries across the whole codebase; see the
glossary for the other two (a fan's OnlyFans/Fansly platform, and the
Account Platform product). Nothing on this page or elsewhere in Stream's section uses
the word any other way.
Five surfaces, one per platform, each answering a different question
A single connected platform touches five separate configuration rows, and each router's own module docstring states exactly which question it answers — worth reading verbatim rather than guessing from the file name:
| Router | Question it answers | Owner-only? |
|---|---|---|
stream_ingest | Where do we receive video from? | No |
stream_targets | Where do we send video to, and in what layout? | Yes |
stream_overlay | What do we draw in the frame? | Yes |
stream_native | What does the platform show about us, on its own site? | Yes |
stream_studio | Chat connection + auto-messages for this platform | Yes |
stream_native.py's own docstring puts the distinction plainly: the frame is only seen
by someone who already clicked in, while a room's title and category decide whether
they click at all — two different jobs that happen to both be "platform settings."
Targets replaced a shared file for a reason
Fan-out destinations used to live in one platforms.env file next to ffmpeg on the
motor — fine when every creator had their own box, but a shared GPU pod means one file
would let one creator's targets edit another's. StreamVideoTarget is keyed by
owner_id; the pod learns whose targets to use from the publish path itself
(/stream/ingest/resolve), so one pod serves any number of creators safely.
Studio: two connection types, one screen
stream_studio.py handles connecting a platform's chat, and it supports exactly two
mechanisms, chosen by the platform's registry entry:
token— an official API (Chaturbate's Events API today): the panel validates the URL's shape, stores it, and starts a dedicated worker. Live chat with no motor involved at all.session— a webcam site with no official API (Stripchat, CAM4, BongaCams): the panel stores a room/profile and hands it to the registered motor's chat config and auto-message endpoints. If the motor isn't reachable, the connection honestly reportspendingrather than pretending to be connected — logging in and clearing any captcha is still the creator's own job, inside a browser profile, the same shape as OnlyFans login.
Three secrets, never to be confused
| Secret | Field | Scope | What it gates |
|---|---|---|---|
| Overlay token | StreamOverlayToken.token (secrets.token_urlsafe(24), 32 chars) | One per overlay link, rotatable | Who can open the private (or public) second-screen chat overlay |
| Ingest key | StreamIngest.publish_key + slug | One per owner | Whether an encoder's publish attempt is accepted by the door |
| Door secret | settings.stream_door_secret | One, shared by the whole receiving box | Whether MediaMTX's own webhook calls (/auth, /ready, /notready) are trusted at all |
The overlay token is unusual among the three: its own model docstring flags it as "a
credential in itself" — the public overlay resolve path reads it through
skip_tenant with no further check layered on top, so possessing the token is
possessing access. The ingest row deliberately keys its public path on an opaque slug
rather than the owner's own ID, so the receiving box's public URL never reveals an
internal identifier.
What's next
How-to — task-by-task guides for connecting a platform, building a scene, and running the cockpit.