Skip to content

Choosing Your Integration

Both the Player (playback) and StreamCrafter (ingest) offer four integration levels. This guide helps you choose the right one.

If you are still deciding what to create first, start with Streams for the basic object model: stream keys, playback IDs, push ingest, and pull-input streams.

FrameworkPlayer PackageStudio Package
React 17+@livepeer-frameworks/player-react@livepeer-frameworks/streamcrafter-react
Svelte 5@livepeer-frameworks/player-svelte@livepeer-frameworks/streamcrafter-svelte
Vue, Angular, etc.@livepeer-frameworks/player-wc@livepeer-frameworks/streamcrafter-wc
No framework / CDN@livepeer-frameworks/player-wc (IIFE)@livepeer-frameworks/streamcrafter-wc (IIFE)
Custom / headless@livepeer-frameworks/player-core@livepeer-frameworks/streamcrafter-core

Level 1: Drop-in Component

Use the component as-is. No custom UI work required.

// Player
<Player contentId="pk_..." contentType="live" />
// Studio
<StreamCrafter whipUrl="..." />

Best for: Quick integration, prototyping, default look is acceptable.


Level 2: Composable Components

Replace the default layout with framework sub-components. Mix our components with your own.

// Player — custom control bar
<Player contentId="pk_..." contentType="live">
<PlayButton />
<VolumeControl />
<SettingsMenu />
<FullscreenButton />
<MyCustomOverlay />
</Player>
// Studio — custom layout
<StreamCrafter whipUrl="...">
<StudioPreview />
<div className="my-sidebar">
<StudioMixer />
<MyCustomPanel />
</div>
<StudioActionBar />
</StreamCrafter>

Best for: Custom layouts, adding your own UI around standard controls, brand-specific styling.


Level 3: Hooks / Stores / Controller

Build your own UI entirely using the provided state management primitives.

// React hooks
const { state, togglePlay, setVolume } = usePlayerController({ ... });
// Svelte stores
const crafter = createStreamCrafterContextV2();
crafter.startCamera();
// Vanilla reactive state
player.subscribe.on("volume", (v) => updateSlider(v));
studio.reactiveState.on("streaming", (live) => updateButton(live));
// WC controller
document.querySelector("fw-player").controller.play();

Best for: Fully custom UI, unique design requirements, embedding in complex applications.


Level 4: Headless / No UI

Run the media engine without any visual UI. Full programmatic control.

// Vanilla player (no built-in UI)
const player = createPlayer({
target: "#player",
contentId: "pk_...",
skin: false,
});
// Vanilla studio — no target
const studio = createStreamCrafter({ whipUrl: "..." });
// WC — provide your own controls slot content
<fw-player content-id="pk_..."><div slot="controls"></div></fw-player>
<fw-streamcrafter whip-url="..." controls="false"></fw-streamcrafter>

Best for: Custom renderers, audio-only, data extraction, automated testing.

PlayerStreamCrafter
DirectionPlayback (viewer)Ingest (broadcaster)
ProtocolsHLS, LL-HLS, DASH, WebRTC (WHEP), WebSocketWebRTC (WHIP)
SourcesRemote stream endpointsLocal camera, screen, custom MediaStream
Key featuresABR, multi-engine, protocol negotiationMulti-source mixing, compositor, reconnection
Use caseWatching streamsBroadcasting streams
@livepeer-frameworks/player-core ← Headless player engine
@livepeer-frameworks/player-react ← React bindings (depends on core)
@livepeer-frameworks/player-svelte ← Svelte bindings (depends on core)
@livepeer-frameworks/player-wc ← Web Components (depends on core)
@livepeer-frameworks/streamcrafter-core ← Headless ingest engine
@livepeer-frameworks/streamcrafter-react ← React bindings (depends on core)
@livepeer-frameworks/streamcrafter-svelte ← Svelte bindings (depends on core)
@livepeer-frameworks/streamcrafter-wc ← Web Components (depends on core)

Framework packages re-export core types. You only need to install one package per product.

<Player contentId="pk_..." contentType="live" options={{ theme: "tokyo-night" }}>
<PlayButton />
<SettingsMenu />
<div className="spacer" />
<VolumeControl />
<FullscreenButton />
</Player>
<fw-streamcrafter id="studio" whip-url="..." controls="false"></fw-streamcrafter>
<aside class="control-panel">
<fw-sc-compositor for="studio"></fw-sc-compositor>
<fw-sc-layer-list for="studio"></fw-sc-layer-list>
<fw-sc-scene-switcher for="studio"></fw-sc-scene-switcher>
</aside>
<footer>
<button onclick="document.getElementById('studio').pc.startStreaming()">Go Live</button>
</footer>
function LiveDashboard() {
return (
<div className="dashboard">
<div className="broadcast">
<StreamCrafter whipUrl="..." />
</div>
<div className="preview">
<Player contentId="pk_..." contentType="live" />
</div>
</div>
);
}
<!DOCTYPE html>
<html>
<body>
<!-- Player -->
<script src="https://cdn.jsdelivr.net/npm/@livepeer-frameworks/player-wc/fw-player.js"></script>
<fw-player content-id="pk_..." content-type="live" autoplay muted></fw-player>
<!-- Studio -->
<script src="https://cdn.jsdelivr.net/npm/@livepeer-frameworks/streamcrafter-wc/fw-streamcrafter.js"></script>
<fw-streamcrafter whip-url="..." initial-profile="broadcast"></fw-streamcrafter>
</body>
</html>