Skip to content

StreamCrafter — React

Terminal window
npm install @livepeer-frameworks/streamcrafter-react

Import the CSS once in your app:

import "@livepeer-frameworks/streamcrafter-react/streamcrafter.css";

The <StreamCrafter /> component is fully self-contained with video preview, controls, and connection management.

Direct WHIP Mode:

<StreamCrafter whipUrl="https://edge-ingest.frameworks.network/webrtc/stream-key" initialProfile="broadcast" />

Gateway Resolution Mode:

import { StreamCrafter } from "@livepeer-frameworks/streamcrafter-react";
import "@livepeer-frameworks/streamcrafter-react/streamcrafter.css";
function BroadcastPage() {
return (
<StreamCrafter
gatewayUrl="https://bridge.frameworks.network/graphql"
streamKey="<YOUR_STREAM_KEY>"
initialProfile="broadcast"
onStateChange={(state) => console.log(state)}
/>
);
}

Gateway resolution calls the public resolveIngestEndpoint GraphQL field from the publisher’s browser. Use direct whipUrl unless that resolver is enabled in your environment, and prefer the dashboard DNS ingest URL for backend or encoder-side publishing.

Pass children to <StreamCrafter> to replace the default UI with your own layout using the provided sub-components:

import {
StreamCrafter,
StudioPreview,
StudioMixer,
StudioActionBar,
StudioSettings,
StudioStatusBadge,
} from "@livepeer-frameworks/streamcrafter-react";
import "@livepeer-frameworks/streamcrafter-react/streamcrafter.css";
function CustomStudio() {
return (
<StreamCrafter whipUrl="https://edge-ingest.frameworks.network/webrtc/my-key">
<div className="my-layout">
<StudioStatusBadge />
<StudioPreview />
<div className="sidebar">
<StudioMixer />
<StudioSettings />
</div>
<StudioActionBar />
</div>
</StreamCrafter>
);
}

When children are provided, the built-in UI is entirely replaced. Sub-components auto-connect to the parent <StreamCrafter> via React context.

ComponentPurpose
StudioPreviewVideo preview with optional compositor overlay and live badge
StudioMixerSource list with volume sliders, mute, and remove buttons
StudioActionBarCamera, Screen Share, Settings, and Go Live buttons
StudioSettingsQuality profile selector popup
StudioStatusBadgeState badge (Idle, Capturing, Live, Connecting, etc.)

All sub-components accept optional prop overrides for any value they normally read from context.

For complete UI control, use useStreamCrafterV2 directly:

import { useStreamCrafterV2 } from "@livepeer-frameworks/streamcrafter-react";
function FullyCustomBroadcaster() {
const {
state,
isStreaming,
isCapturing,
sources,
mediaStream,
startCamera,
startScreenShare,
startStreaming,
stopStreaming,
removeSource,
setSourceVolume,
setSourceMuted,
qualityProfile,
setQualityProfile,
} = useStreamCrafterV2({
whipUrl: "https://edge-ingest.frameworks.network/webrtc/key",
profile: "broadcast",
reconnection: { enabled: true },
});
return (
<div>
<video
ref={(el) => {
if (el) el.srcObject = mediaStream;
}}
autoPlay
muted
/>
<p>State: {state}</p>
<p>Sources: {sources.length}</p>
<button onClick={() => startCamera()}>Add Camera</button>
<button onClick={() => startScreenShare({ audio: true })}>Share Screen</button>
<button onClick={() => (isStreaming ? stopStreaming() : startStreaming())}>
{isStreaming ? "Stop" : "Go Live"}
</button>
</div>
);
}
PropertyTypeDescription
stateIngestStateCurrent lifecycle state
isStreamingbooleanWhether currently live
isCapturingbooleanWhether media is captured
isReconnectingbooleanWhether reconnecting
sourcesMediaSource[]Active media sources
mediaStreamMediaStream | nullCombined output stream
qualityProfileQualityProfileCurrent quality settings
startCamera(opts?)() => Promise<MediaSource>Add camera source
startScreenShare(opts?)() => Promise<MediaSource | null>Add screen share source
startStreaming()() => Promise<void>Go live
stopStreaming()() => Promise<void>Stop streaming
removeSource(id)(id: string) => voidRemove a source
setSourceVolume(id, vol)(id, number) => voidSet source volume (0-1)
setSourceMuted(id, muted)(id, boolean) => voidMute/unmute source
setQualityProfile(profile)(profile: QualityProfile) => Promise<void>Change quality profile
getController()() => IngestControllerV2 | nullDirect controller access
<StreamCrafter
whipUrl="..."
onStateChange={(state, context) => {
if (state === "streaming") showLiveBadge();
if (state === "error") showError(context?.error);
}}
/>