Livestreaming with Fishjam
This section explains how to set up livestreaming using Fishjam. We show how to quickly prototype a livestreaming scenario in Quickstart with Sandbox API and how to get ready for production in Production Livestreaming with Server SDKs.
Fishjam implements two real-time streaming standards: WHIP (for publishing) and WHEP (for receiving).
In this tutorial we explain how to publish and view streams with the client SDKs, which wrap these standards. If you prefer to use WHIP or WHEP directly, then you should read WHIP/WHEP with Fishjam.
Quickstart with Sandbox API
If you don't have a backend server setup, you can still prototype a livestreaming use-case with the Sandbox API. If you want to start by setting up your backend, then you can start by reading Production Livestreaming with Server SDKs.
Streamer setup
To start streaming with Fishjam, we need two things: a streamer token and video/audio sources.
Obtaining a token
The easiest way to obtain a sandbox streamer token is by using the Sandbox API in the client SDKs:
- React
- React Native
import {
useSandbox } from '@fishjam-cloud/react-client'; const {getSandboxLivestream } =useSandbox (); const {streamerToken ,room : {id :roomId }, } = awaitgetSandboxLivestream ('example-room');
import {
useSandbox } from '@fishjam-cloud/react-native-client'; const {getSandboxLivestream } =useSandbox ({fishjamId :FISHJAM_ID }); const {streamerToken } = awaitgetSandboxLivestream ('example-room');
Starting the stream
We can now start sending media, which we can obtain from the user's camera, screen share or microphone:
- React
- React Native
- Camera + Mic
- Screen Share
import {
useCamera ,useLivestreamStreamer ,useMicrophone , } from '@fishjam-cloud/react-client'; const {cameraStream ,toggleCamera } =useCamera (); const {microphoneStream ,toggleMicrophone } =useMicrophone (); const {connect } =useLivestreamStreamer (); // ...toggleCamera ();toggleMicrophone (); // ... if (cameraStream &µphoneStream ) { awaitconnect ({token :streamerToken ,inputs : {video :cameraStream ,audio :microphoneStream } }); }
import {
useLivestreamStreamer ,useScreenShare , } from '@fishjam-cloud/react-client'; const {stream :screenShareStream ,startStreaming } =useScreenShare (); const {connect } =useLivestreamStreamer (); // ...startStreaming (); // ... if (screenShareStream ) { awaitconnect ({token :streamerToken ,inputs : {video :screenShareStream ,audio :screenShareStream } }); }
- Camera + Mic
import {
LivestreamStreamer ,useLivestreamStreamer ,cameras , } from '@fishjam-cloud/react-native-client'; const {connect } =useLivestreamStreamer ({camera :cameras [0] }); // ... awaitconnect (streamerToken ); // Render the livestream <LivestreamStreamer />
Et voilà, we've published a livestream!
Viewer setup
To receive the published livestream, we need one thing: a viewer token.
In this guide, we've created a private livestream, where viewers need a token to join. A livestream may also be public, where anyone can join if they know the livestream's room id.
You can learn more about public livestreams in Private vs Public Livestreams.
Obtaining a token
We obtain a sandbox viewer token using the Sandbox API in the client SDKs:
- React
- React Native
import {
useSandbox } from '@fishjam-cloud/react-client'; const {getSandboxViewerToken } =useSandbox (); constviewerToken = awaitgetSandboxViewerToken ('example-room');
import {
useSandbox } from '@fishjam-cloud/react-native-client'; const {getSandboxViewerToken } =useSandbox ({fishjamId :FISHJAM_ID }); constviewerToken = awaitgetSandboxViewerToken ('example-room');
Receiving the stream
We can now begin receiving the stream
- React
- React Native
import {
useLivestreamViewer } from '@fishjam-cloud/react-client'; const {connect ,stream } =useLivestreamViewer (); awaitconnect ({token :viewerToken }); // You can now use `stream` with a <video> element or your player of choice
import {
LivestreamViewer ,useLivestreamViewer , } from '@fishjam-cloud/react-native-client'; const {connect } =useLivestreamViewer (); awaitconnect ({token :viewerToken }); // Render the livestream <LivestreamViewer />
That's it! Now you can focus on your business logic and replace the Sandbox API usage in the future, when your backend is ready, or continue on to see how to set up your backend for livestreaming.
Production Livestreaming with Server SDKs
The Quickstart with Sandbox API shows how to get livestreaming up and running quickly. However, in a production scenario, we need a backend application with proper authentication and authorization. In this section, we explain what such a backend application should do.
Our backend needs to do three things to be ready for streaming:
- It needs to create a room of
livestream
type. - It needs to create a streamer token for that room.
- It needs to create a viewer token for that room.
- Typescript
- Python
import {
FishjamClient } from '@fishjam-cloud/js-server-sdk'; constfishjamClient = newFishjamClient ({fishjamId ,managementToken , }); // 1. constroom = awaitfishjamClient .createRoom ({roomType : 'livestream' }); // 2. const {token :streamerToken } = awaitfishjamClient .createLivestreamStreamerToken (room .id ); // 3. const {token :viewerToken } = awaitfishjamClient .createLivestreamViewerToken (room .id );
from fishjam import FishjamClient fishjam_client = FishjamClient( fishjam_id=fishjam_id, management_token=management_token, ); # 1. room = await fishjam_client.create_room(room_type="livestream") # 2. streamer_token = await fishjam_client.create_livestream_streamer_token(room.id) # 3. viewer_token = await fishjam_client.create_livestream_viewer_token(room.id)
Now, you need to supply these generated tokens to your frontend applications (e.g. by exposing a REST endpoint). You most likely will want to only supply these tokens to properly authenticate and authorize streamers and viewers before giving them tokens.
Then, you can start streaming as described in Starting the stream and start receiving as describe in Receiving the stream.
See also
Learn how to use WHIP/WHEP with Fishjam:
If you want to get a better understanding of livestreaming with Fishjam, make sure to check out:
If you have a different use case, then you should see