Skip to content
Welcome to the new, unified Livepeer documentation! 👋
Guides
Add a Player

Add a Player

We demonstrate below how to playback live or on demand videos in your application using either Livepeer.js or Video.js.

Using the Livepeer.js Player

The example below show to use the Livepeer.js Player to view a video asset, with some custom styles to demonstrate what's possible.


Configuring Providers

First, we create a new livepeer.js client with a gateway provider and a CORS-protected API key, as well as a theme to use for all livepeer.js React components.

App.tsx
import {
  LivepeerConfig,
  ThemeConfig,
  createReactClient,
  studioProvider,
} from '@livepeer/react';
import * as React from 'react';
 
const livepeerClient = createReactClient({
  provider: studioProvider({
    apiKey: process.env.NEXT_PUBLIC_STUDIO_API_KEY,
  }),
});
 
const theme: ThemeConfig = {
  colors: {
    accent: 'rgb(0, 145, 255)',
    containerBorderColor: 'rgba(0, 145, 255, 0.9)',
  },
  fonts: {
    display: 'Inter',
  },
};
 
function App() {
  return (
    <LivepeerConfig client={livepeerClient} theme={theme}>
      <CreateAndViewAsset />
    </LivepeerConfig>
  );
}

Play Video

Now that our providers are set up, we use the Player with an IPFS CID as our playbackId, which we created previously when uploading a video asset and storing to IPFS. We use Next.js Image (opens in a new tab) as our optimized poster image, but this could also be a simple image URL.

We also override some of the custom styling to match the flow of our app!

DemoPlayer.tsx
import { Player } from '@livepeer/react';
 
import Image from 'next/image';
 
const playbackId =
  'bafybeida3w2w7fch2fy6rfvfttqamlcyxgd3ddbf4u25n7fxzvyvcaegxy';
 
import blenderPoster from '../../public/images/blender-poster.png';
 
const PosterImage = () => {
  return (
    <Image
      src={blenderPoster}
      layout="fill"
      objectFit="cover"
      priority
      placeholder="blur"
    />
  );
};
 
export const DemoPlayer = () => {
  return (
    <Player
      title="Waterfalls"
      playbackId={playbackId}
      showPipButton
      showTitle={false}
      aspectRatio="16to9"
      poster={<PosterImage />}
      controls={{
        autohide: 3000,
      }}
      theme={{
        borderStyles: { containerBorderStyle: 'hidden' },
        radii: { containerBorderRadius: '10px' },
      }}
    />
  );
};

Using your own player

Using livepeer.js is the recommended way to play back a video or a livestream - it handles different playback sources, errors from the API, and is a true web3-native media player. However, if you want to use an alternative, you can do so by following the instructions below.

Fetch playback URLs

To play back video in other players, you'll need to fetch the playback URL(s). By default, all content has an HLS endpoint. HLS is a protocol that allows you to stream video and audio content over HTTP. Also, livestreams always have a WebRTC (WHEP) playback URL, and short-form VODs (static video assets) can optionally have an MP4 playback URL.

You can get the playback URL by making a GET request to the playback endpoint and replacing the PLAYBACK_ID with your stream or asset's playbackId.

curl "https://livepeer.studio/api/playback/{PLAYBACK_ID}"
⚠️

The playback URL format is subject to change. Do not try to create the playback URLs manually, as they may change periodically.

If the playback ID corresponds to a VOD, the API will return a JSON payload which looks like:

VOD Response
{
  "type": "vod",
  "meta": {
    "playbackPolicy": null,
    "source": [
      {
        "hrn": "MP4",
        "type": "html5/video/mp4",
        "url": "https://asset-cdn.lp-playback.monster/hls/{PLAYBACK_ID}/270p0.mp4",
        "size": 1240220,
        "width": 480,
        "height": 270,
        "bitrate": 209221
      },
      {
        "hrn": "HLS (TS)",
        "type": "html5/application/vnd.apple.mpegurl",
        "url": "https://asset-cdn.lp-playback.monster/hls/{PLAYBACK_ID}/index.m3u8"
      }
    ]
  }
}

Or, if it corresponds to a livestream, it will respond with:

Livestream Response
{
  "type": "live",
  "meta": {
    "live": 0,
    "source": [
      {
        "hrn": "HLS (TS)",
        "type": "html5/application/vnd.apple.mpegurl",
        "url": "https://livepeercdn.studio/hls/{PLAYBACK_ID}/index.m3u8"
      },
      {
        "hrn": "WebRTC (H264)",
        "type": "html5/video/h264",
        "url": "https://livepeercdn.studio/webrtc/{PLAYBACK_ID}"
      }
    ]
  }
}
💡

Please note that to play back live streams inside your application you'll need to use a video player component that supports any/all of these protocols. For livestreams, we always provide both WebRTC and HLS, and for VOD, we always provide HLS, and MP4 for short-form video.

The format of this payload is defined here. The meta.source[number].url values can be used as the playback URLs.

MP4 (Short Form Videos)

🚫

To ensure consistent viewer experience, the livepeer.js Player handles choosing the correct MP4 rendition and gracefully recovers from routine RTMP reconnects through custom polling logic. In the absence of this capability, reconnects may severely degrade viewer experience and require a hard refresh to resolve, and an incorrect MP4 rendition for the screen size may be chosen.

Get the playback URL

The playback info endpoint can return multiple sources in the response, as outlined above. These may include short form MP4 playback URLs, which are URLs for your video asset that enable applications (and CDNs) to cache short videos for instant playback of subsequent videos. This means that viewers can experience near-instant time-to-first-frame (TTFF) when watching short videos.

It is important to note that short form playback URLs are only available for video assets that are less than 2 minutes in duration.

VOD Response
{
  "type": "vod",
  "meta": {
    "playbackPolicy": null,
    "source": [
      {
        "hrn": "MP4",
        "type": "html5/video/mp4",
        "url": "https://asset-cdn.lp-playback.monster/hls/{PLAYBACK_ID}/270p0.mp4",
        "size": 1240220,
        "width": 480,
        "height": 270,
        "bitrate": 209221
      },
      {
        "hrn": "HLS (TS)",
        "type": "html5/application/vnd.apple.mpegurl",
        "url": "https://asset-cdn.lp-playback.monster/hls/{PLAYBACK_ID}/index.m3u8"
      }
    ]
  }
}

There can be multiple MP4 renditions (and one HLS URL) which you can choose from, and it is up to you to decide how you want to prioritize each source for your custom player. See the Player's technical details for more information on how livepeer.js handles this.

💡

When you make a request for playback URLs, the MP4 URLs are always listed before HLS URLs. Additionally, each MP4 URL includes additional metadata about the video, such as its width, height, bitrate, and size. This metadata can be useful for mobile applications that want to optimize playback quality and size based on the viewer's device and network conditions. The Livepeer.js Player automatically handles this. See the Player docs for more information.

Use a video player

You can then use the MP4 or HLS URL with any video player. For HLS/MP4, here is a list of popular players:

Here is an example of how to use the HLS playback URL in video.js player.

<head>
  <link href="https://vjs.zencdn.net/7.20.3/video-js.css" rel="stylesheet" />
 
  <!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
  <!-- <script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script> -->
</head>
 
<body>
  <video
    id="my-video"
    class="video-js"
    controls
    preload="auto"
    width="640"
    height="264"
    poster="MY_VIDEO_POSTER.jpg"
  >
    <source
      src="https://lp-playback.com/hls/{PLAYBACK_ID}/index.m3u8"
      type="application/x-mpegURL"
    />
  </video>
 
  <script src="https://vjs.zencdn.net/7.20.3/video.min.js"></script>
</body>

WebRTC (Low Latency Livestreams)

🚫

To ensure consistent viewer experience, the livepeer.js Player handles retrying WebRTC WHEP SDP negotiation and any HTTP status codes from the SDP endpoint - the endpoint will 404 if the stream not currently online, and this must be handled with retry.

The playback URLs may also include WebRTC URLs for low latency livestream playback. These must be played back with our ICE servers, which are used to route traffic in restricted networking environments. This is similar to the Stream via Browser docs for the steps to get the ICE config which should be used with playback, with a few minor differences.

Get the SDP Host

You will need to make a request to get the proper egress URL for the region which your end user is in. We have a global presence, and we handle redirects based on GeoDNS to allow users to get the lowest latency server.

To get the URL for this server, make a GET request to the WebRTC URL which was returned from the playback info endpoint:

curl -L 'https://livepeercdn.studio/webrtc/{PLAYBACK_ID}'
...
> Location: https://lax-prod-catalyst-2.lp-playback.studio/webrtc/{PLAYBACK_ID}

You may safely ignore any errors returned from the GET request - we are only interested in getting the redirect location URL from the final response, so that we can set up the correct ICE servers.

⚠️

The process will change in the future to remove the need for this extraneous GET request - please check back later.

Play the Livestream

Now that we have the endpoint for the ICE servers, we can start SDP negotiation following the WHIP spec (opens in a new tab) and kick off a livestream. First, form an SDP offer with your WebRTC library of choice. Make sure you specify the ICE servers, so that connectivity issues are not an issue.

const host = new URL(redirectUrl).host;
 
const iceServers = [
  {
    urls: `stun:${host}`,
  },
  {
    urls: `turn:${host}`,
    username: 'livepeer',
    credential: 'livepeer',
  },
];
 
const peerConnection = new RTCPeerConnection({ iceServers });
 
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
 
// send offer.sdp with a POST request

Then send offer.sdp to the host you received in the previous step (adding the path shown below).

curl -X POST \
  -H 'Content-Type: application/sdp' \
  --data-binary @offer.sdp \
  'https://lax-prod-catalyst-2.lp-playback.studio/webrtc/{PLAYBACK_ID}'

The server will respond, according to the WHEP spec, with an SDP response that you can then use to set up low latency WebRTC playback!

Embeddable Player

⚠️

The embeddable player is currently in beta and some elements may change as we mature the product. For a production-grade application consider using Livepeer.js instead.

This is one of the easiest way to playback a video on your website/applications. You can embed the player on your website/applications by using the below code snippet.

You can replace the PLAYBACK_ID with your video's playback id.

<iframe
  src="https://lvpr.tv?v={PLAYBACK_ID}"
  allowfullscreen
  allow="autoplay; encrypted-media; picture-in-picture"
  sandbox="allow-same-origin allow-scripts"
>
</iframe>

If the embeddable player does not succeed in playing back or errors (due to a slow network or connectivity issues), it will automatically fall back to HLS playback. Also, if the stream contains B-frames, or bidirectional frames, (which are common for users streaming with OBS or other streaming apps), the Player will automatically fall back, so that out-of-order frames are not displayed. This only applies to users who are playing back livestreams.

You may also specify lowLatency=force or lowLatency=false in the query string - force will disable HLS fallback and only attempt playback from WebRTC, and false will completely disable WebRTC playback with livestreams.

⚠️

OBS users should be instructed to use the Livepeer stream profile, or to manually turn off B-frames in their stream. See our Stream from OBS docs for more information.