Upload a video asset
This guide provides you the instructions to upload a video from the Livepeer Studio Dashboard or through the Livepeer API.
The Livepeer API allows you to send video files to Livepeer and get them ready for optimized playback. Videos can be provided either by you (static content) or your users, given your application offers an interface for them to do so.
You can upload video assets via a url, a direct upload or a resumable upload.
- Files are currently limited to 1GB in size. Any files greater than that will likely error out during the upload or processing steps.
- Only MP4 files encoded with H.264 and AAC are supported
Uploading via URL
When using the upload via URL method:
- Provide the name of the asset
- Provide the URL of the asset that should be imported
Step 1: Upload asset by URL
To upload the asset to the Livepeer network, you'll need to make a POST request and include the URL of the asset to be uploaded.
- Livepeer.js
- Fetch
import { useCreateAsset } from '@livepeer/react';
function App() {
const { mutate: createAsset, status } = useCreateAsset({
sources: [{ name: "test", url: "https://test.com" }] as const,
});
}
const uploadAssetURL = await fetch("https://livepeer.studio/api/asset/import", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "$EXTERNAL_URL"
name: "Example name",
}),
});
Step 2: Check the upload status
After uploading your asset, get the asset.id
from the
response object of the POST
request. The asset.id
represents the status of your upload.
When asset.status: "ready"
is returned in the response, the asset has finished
uploading and will be ready for playback. If asset.status: "waiting"
is
returned in the response, the asset is not available yet and you should make the
API call again until asset.status: "ready"
.
- Livepeer.js
- Fetch
import { useAsset } from '@livepeer/react';
function App() {
const { data: asset, status } = useAsset(asset?.id);
}
const response = await fetch("https://livepeer.studio/api/asset/{id}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
"Content-Type": "application/json",
},
});
const { status } = await response.json();
Direct Upload
A direct upload uploads the whole video asset in one HTTP request, as opposed to the resumable upload protocol, which uploads the video asset in multiple requests. Doing a direct upload reduces the number of HTTP requests but increases the chance of failures (such as connection failures) that can happen with large uploads.
Step 1: Generate upload URL
To upload the asset to the Livepeer network locally, you'll need to make a POST request to generate an upload URL.
- Fetch
const response = await fetch(
"https://livepeer.studio/api/asset/request-upload",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Example name",
}),
}
);
const { url } = await response.json();
Step 2: Upload your video to the URL
Using the URL generated in the response, upload your video with a PUT request.
- Livepeer.js
- Fetch
import { useCreateAsset } from '@livepeer/react';
function App() {
const { mutate: createAsset, status } = useCreateAsset({
sources: [{ name: "test", file: video }] as const,
});
}
const upload = await fetch(url, {
method: "PUT",
body: fs.createReadStream(path),
});
Step 3: Check the upload status
After uploading your asset, get the asset.id
from the
response object of the POST
request. The asset.id
represents the status of your upload.
When asset.status: "ready"
is returned in the response, the asset has finished
uploading and will be ready for playback. If asset.status: "waiting"
is
returned in the response, the asset is not available yet and you should make the
API call again until asset.status: "ready"
.
- Livepeer.js
- Fetch
import { useAsset } from '@livepeer/react';
function App() {
const { data: asset, status } = useAsset(asset?.id);
}
const response = await fetch("https://livepeer.studio/api/asset/{id}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
});
const { status } = await response.json();
Resumable Upload
A resumable upload allows you to resume an upload operation after a communication failure interrupts the flow of data. Because you don't have to restart large file uploads from the start, resumable uploads can also reduce your bandwidth usage if there is a network failure.
Resumable uploads are useful when your file sizes might vary greatly or when there is a fixed time limit for requests. You might also use resumable uploads for situations where you want to show an upload progress bar.
Step 1: Generate upload URL
To upload the asset to the Livepeer network locally, you'll need to make a POST request to generate an upload URL.
- JavaScript
const response = await fetch(
"https://livepeer.studio/api/asset/request-upload",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Example name",
}),
}
);
const { tusEndpoint } = await response.json();
Step 2: Upload your resumable video via Tus
Livepeer Studio supports resumable uploads via Tus. This
section provides a simple example of how to use tus-js-client
to upload a
video file.
You should use the tusEndpoint
field of the
response object to upload the
video file and track the progress.
If you are using tus
from node.js
, you need to add a custom URL
storage to enable resuming from previous uploads. On the browser, this is
enabled by default using local storage.
In node.js
, add urlStorage: new tus.FileUrlStorage("path/to/tmp/file")
, to the UploadFile
object definition.
- JavaScript
// This assumes there is an `input` element of `type="file"` with id `fileInput` in the HTML
const input = document.getElementById("fileInput");
const file = input.files[0];
const upload = new tus.Upload(file, {
endpoint: tusEndpoint, // URL from `tusEndpoint` field in the `/request-upload` response
metadata: {
filename,
filetype: "video/mp4",
},
uploadSize: file.size,
onError(err) {
console.error("Error uploading file:", err);
},
onProgress(bytesUploaded, bytesTotal) {
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
console.log("Uploaded " + percentage + "%");
},
onSuccess() {
console.log("Upload finished:", upload.url);
},
});
const previousUploads = await upload.findPreviousUploads();
if (previousUploads.length > 0) {
upload.resumeFromPreviousUpload(previousUploads[0]);
}
upload.start();