Uploading and watching an asset is easy! The example below uses the Create asset API to create an upload link to upload a video.

Pro Tip: Livepeer supports resumable uploads through the TUS protocol, ensuring reliability and efficiency when transferring your asset.

For rapid processing of assets that will also be archived on IPFS or Arweave, we strongly encourage either (1) uploading to Livepeer with the IPFS storage option enabled, or (2) uploading the raw file to Livepeer via useCreateAsset or the API prior to archiving on dStorage, rather than passing the IPFS / Arweave gateway URL. The gateway URL will work, but may incur longer-than-usual processing time.

Livepeer provides versatile options for uploading and managing your assets:

  • Single Asset Upload: Upload individual assets for processing and play back.
  • Bulk Asset Upload: Explore an efficient method for uploading multiple assets simultaneously, simplifying content management.
  • Resumable Upload: Discover the power of resumable uploads, ensuring reliability and efficiency when transferring your media files.

Using Livepeer SDK

We can use the Livepeer SDK to create a Tus-compatible upload endpoint.

  • Node.js

  • Python

  • Ruby

  • PHP

  • Go

import { Livepeer } from "livepeer";

const apiKey = 'YOUR_API_KEY'; // Replace with your API key
const fileName = 'filename.mp4'; // Replace with the desired file name

const livepeer = new Livepeer(apiKey);

const assetData = {
  name: fileName

  .then((response) => {
    console.log("Asset upload request:", response);
  .catch((error) => {
    console.error("Error requesting asset upload:", error);

Once an upload endpoint is created, you can use it to upload your video file to Livepeer. The upload endpoint is tus compatible, so you can use any tus-compatible client (like tus-js-client) to upload your video file from the frontend.

Using React Hooks

We create a new React client and wrap the app with LivepeerConfig.

Now that our providers are set up, we set up file uploads with React Dropzone, a library for easily creating HTML5-compliant drag and drop zones for files (you can use another solution for file uploads):

import { useCreateAsset } from "@livepeer/react";

import { useCallback, useState } from "react";
import { useDropzone } from "react-dropzone";

export const CreateAndViewAsset = () => {
  const [video, setVideo] = useState<File | undefined>();
  const {
    mutate: createAsset,
    data: asset,
  } = useCreateAsset(
      ? {
          sources: [{ name: video.name, file: video }] as const,
      : null

  const onDrop = useCallback(async (acceptedFiles: File[]) => {
    if (acceptedFiles && acceptedFiles.length > 0 && acceptedFiles?.[0]) {
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    accept: {
      "video/*": ["*.mp4"],
    maxFiles: 1,

  const progressFormatted = useMemo(
    () =>
      progress?.[0].phase === "failed"
        ? "Failed to process video."
        : progress?.[0].phase === "waiting"
        ? "Waiting"
        : progress?.[0].phase === "uploading"
        ? `Uploading: ${Math.round(progress?.[0]?.progress * 100)}%`
        : progress?.[0].phase === "processing"
        ? `Processing: ${Math.round(progress?.[0].progress * 100)}%`
        : null,

  return (
      <div {...getRootProps()}>
        <input {...getInputProps()} />
        <p>Drag and drop or browse files</p>

      {createError?.message && <p>{createError.message}</p>}

      {video ? <p>{video.name}</p> : <p>Select a video file to upload.</p>}
      {progressFormatted && <p>{progressFormatted}</p>}

        onClick={() => {
        disabled={!createAsset || createStatus === "loading"}

Play an Asset

To learn how to play an asset, see the Play an Asset guide.