Streams
A stream is the live object you broadcast into and viewers watch. It owns three things you will use in most integrations:
| Field | What it is | Safe to expose? |
|---|---|---|
id | GraphQL object ID for API mutations and queries | Backend only |
streamKey | Secret ingest credential for push streams | No |
playbackId | Public viewer identifier for /play and Player | Yes |
Use streamKey only where media is being uploaded. Use playbackId everywhere viewers need to
watch.
Stream Types
Section titled “Stream Types”FrameWorks supports two ingest models:
| Model | How media arrives | Creation path |
|---|---|---|
| Push | Your encoder opens RTMP/E-RTMP, SRT, or WHIP to FrameWorks | Dashboard or GraphQL createStream |
| Pull | FrameWorks opens RTSP, SRT, RIST, HLS, DTSC, or TS to you | Dashboard or GraphQL createStream |
Most builders start with push streams. Pull-input streams are useful for cameras, venue feeds, and upstream origins that cannot push into FrameWorks. See Pull-input streams for supported source schemes, private-source rules, and lifecycle visibility. Note that RTMP and FLV-over-HTTP pull are not supported today — open a ticket if you need them.
Experimental media-engine discovery exists locally today. On the roadmap: packaging that into FrameWorks Edge, Tray, CLI, API, and dashboard workflows for venues and studios that want camera pickup without hand-wiring RTSP URLs.
Create a Push Stream in the Dashboard
Section titled “Create a Push Stream in the Dashboard”- Open Content -> Streams.
- Click Create Stream.
- Give it a name and optional description.
- Copy the Stream Key for your encoder.
- Copy the Playback ID for players and embeds.
For the fastest end-to-end setup, follow Quick Start.
Create a Push Stream with GraphQL
Section titled “Create a Push Stream with GraphQL”Most mutations return a union. Always check __typename.
mutation { createStream(input: { name: "Main Stage", record: true }) { __typename ... on Stream { id name streamKey playbackId record } ... on ValidationError { field message } ... on AuthError { message } }}record: true enables DVR recording from the start. For event channels, this gives late viewers
seekback while the stream is live. For 24/7 channels, the live stream keeps running while replay
is served from chapter artifacts that segment the session timeline — no forced stream restart at
a duration boundary. You can also toggle recording later with updateStream. See
Live and DVR Streams for what that creates.
Live and DVR Streams
Section titled “Live and DVR Streams”Setting record: true at create time (or calling startDVR(streamId) later) creates a separate
stream entity for the recording, with its own internal name and playbackId, distinct from the
live stream:
- Live stream — segments live in a shared-memory ring buffer of about 50 seconds. Right for
real-time playback and
CLIP_NOWof recent moments. - DVR stream — segments are written to disk and archived under one recording artifact. Right for seek-back, longer clips, and post-event playback. The live DVR window is bounded for player performance; historical replay uses finalized chapter artifacts over the same segment archive.
The live ring is configurable — private deployments often want a longer window — but every extra second costs cluster RAM, so the default stays tight. Open an in-app ticket if your deployment needs a non-default size.
Practical consequences:
- Players use the DVR
playbackId(withcontentType="dvr") to seek back beyond the live ring within the live DVR window. - Clip creation runs against the entity that holds the moment you want — see Clips. Use the live stream for the live ring and the DVR recording for archived ranges.
- Access control, multistream targets, thumbnails, and analytics attach per stream entity.
For 24/7-style streams, the recording can continue as one DVR artifact for the full stream session. Replay viewers navigate that archive through chapters or explicit time ranges, while the live player still receives a bounded seekback window. See Recordings, Clips & VOD.
Go Live
Section titled “Go Live”After creating a push stream, send media to one of the ingest endpoints shown on the stream detail page:
| Protocol | Typical use | Guide |
|---|---|---|
| RTMP/E-RTMP | OBS, hardware encoders, FFmpeg | Encoder Setup |
| SRT | Unreliable or long-haul networks | Encoder Setup |
| WHIP | Browser or WebRTC-native broadcast | StreamCrafter |
The stream becomes live once the media edge accepts the input and MistServer reports an active session.
Watch the Stream
Section titled “Watch the Stream”Use playbackId with the FrameWorks Player or raw /play URLs:
import { Player } from "@livepeer-frameworks/player-react";
<Player contentType="live" contentId="<PLAYBACK_ID>" options={{ autoplay: true, muted: true }} />;https://foghorn.frameworks.network/play/<PLAYBACK_ID>/hls/index.m3u8https://foghorn.frameworks.network/play/<PLAYBACK_ID>/webrtcSee Playback & Embedding for protocols, players, and custom source resolution.
Lifecycle
Section titled “Lifecycle”- Offline - The stream exists, but no encoder or pull input is currently active.
- Live - The media edge is receiving or pulling source media.
- Recording - If recording is enabled, DVR assets are produced while the stream is live.
- Idle pull input - Pull streams do not fetch upstream media until a viewer requests playback.
Playback access policies, multistream targets, recordings, thumbnails, and analytics attach to the stream regardless of whether the media arrives by push or pull. The difference is only how the source media gets into the platform.