Skip to main content

React SDK — Getting Started

Add real-time live video to a React app with @video/video-client-react — hooks, context providers, and ready-made components. This guide takes you from install to a working broadcaster and viewer in under 10 minutes.

Prerequisites

Grab these from your account before you start:

  • An authentication token (JWT) — a broadcaster token to stream, a viewer token to watch.
  • A stream key for your stream.
  • Your backend endpoint, e.g. https://your-subdomain.example.com.

React 16.8+ is required — the SDK is built on hooks.

1. Configure the registry

The SDK is published to a private registry. Add it to your project's .npmrc:

@video:registry=https://npm-packages.example.com/

2. Install

npm install @video/video-client-react

The package ships hooks, components, and TypeScript types — nothing else to add.

3. Broadcast your camera

usePreviewPlayer sets up the camera, useAuthClient handles authentication, and useCreateCall plus useBroadcast create the call and start streaming into it. Wrap your UI in the two providers and drop in the <Video /> component:

import React, { useMemo } from 'react';
import {
usePreviewPlayer,
useAuthClient,
useCreateCall,
useBroadcast
} from '@video/video-client-react/hooks';
import {
MediaStreamControllerAPIProvider,
PlayerAPIProvider
} from '@video/video-client-react/context';
import { Video } from '@video/video-client-react/components';

function Broadcaster() {
const { mediaStreamController, previewPlayer } = usePreviewPlayer();

const authClient = useAuthClient('your-broadcaster-token');

// useCreateCall and useBroadcast pin their inputs at first render, so memoize
// these — a fresh object literal every render means later changes are
// silently ignored instead of recreating the call.
const callOptions = useMemo(() => ({
streamKey: 'your-stream-key',
backendEndpoints: ['https://your-subdomain.example.com'],
auth: authClient,
user: { userId: 'user-1', displayName: 'Broadcaster' }
}), [authClient]);

const broadcastOptions = useMemo(() => ({ streamName: 'default' }), []);

const { call, status, error } = useCreateCall(authClient == null ? null : callOptions);
useBroadcast(call, mediaStreamController, broadcastOptions);

if (status === 'error') {
return <div>Could not start the call: {String(error)}</div>;
}

return (
<MediaStreamControllerAPIProvider mediaStreamController={mediaStreamController}>
<PlayerAPIProvider player={previewPlayer}>
<div>
<h1>My First Livestream</h1>
<Video /> {/* Camera preview */}
{call != null && <p>Call ID: <code>{call.id}</code></p>}
</div>
</PlayerAPIProvider>
</MediaStreamControllerAPIProvider>
);
}

export default Broadcaster;
What happened to useCallControls?

Earlier versions of this guide imported a useCallControls hook from the SDK. The SDK does not export one — it is a helper defined inside the demo app, so that import could never resolve. Start and stop are driven by useCreateCall and useBroadcast instead, as above. There are no ready-made buttons: build your own from the lifecycle functions those two hooks return — start and dispose from useCreateCall, start and stop from useBroadcast.

That's a working broadcaster — camera preview plus the call ID your viewer needs. It renders no start/stop buttons; see the note above for the functions to wire them to.

4. Watch the stream

A viewer creates a player for the broadcaster's callId and attaches it to the same <Video /> component:

import React, { useState, useEffect } from 'react';
import { useAuthClient } from '@video/video-client-react/hooks';
import { PlayerAPIProvider } from '@video/video-client-react/context';
import { Video } from '@video/video-client-react/components';
import { createPlayer } from '@video/video-client-react';

function Viewer({ callId }) {
const [player, setPlayer] = useState(null);

const authClient = useAuthClient('your-viewer-token');

useEffect(() => {
let currentPlayer;

createPlayer({
callId,
streamName: 'default',
backendEndpoints: ['https://your-subdomain.example.com'],
auth: authClient
}).then((newPlayer) => {
currentPlayer = newPlayer;
setPlayer(newPlayer);
});

return () => currentPlayer?.dispose();
}, [callId]);

if (!player) return <div>Loading stream…</div>;

return (
<PlayerAPIProvider player={player}>
<div>
<h1>Watching Livestream</h1>
<Video />
</div>
</PlayerAPIProvider>
);
}

export default Viewer;

You now have a broadcaster and a viewer watching with sub-second latency.

Next steps