Uploading an asset transcodes the file to adaptive bitrate HLS and makes it available for VOD playback. The API supports direct upload, URL-based import, and resumable upload via the tus protocol.
Step 1 — Create an asset and get upload URL
import { Livepeer } from 'livepeer' ;
const client = new Livepeer ({ apiKey: process . env . LIVEPEER_API_KEY });
const response = await client . asset . create ({
name: 'product-demo.mp4' ,
});
const asset = response . asset ;
console . log ( 'Asset ID:' , asset . id );
console . log ( 'Upload URL (tus):' , response . tusEndpoint );
Step 2 — Upload the file
Direct upload (small files < 200 MB):
const fs = require ( 'fs' );
await fetch ( response . uploadUrl , {
method: 'PUT' ,
headers: { 'Content-Type' : 'video/mp4' },
body: fs . readFileSync ( './product-demo.mp4' ),
});
Resumable upload with tus (recommended for large files):
npm install tus-js-client
import * as tus from 'tus-js-client' ;
const upload = new tus . Upload ( file , {
endpoint: response . tusEndpoint ,
uploadSize: file . size ,
onError : ( error ) => console . error ( 'Upload failed:' , error ),
onProgress : ( bytesUploaded , bytesTotal ) => {
console . log ( ` ${ (( bytesUploaded / bytesTotal ) * 100 ). toFixed ( 1 ) } % uploaded` );
},
onSuccess : () => console . log ( 'Upload complete' ),
});
upload . start ();
URL-based import:
const response = await client . asset . create ({
name: 'imported-video.mp4' ,
url: 'https://your-storage.com/video.mp4' ,
});
Step 3 — Wait for transcoding
Poll for status or use the asset.ready webhook:
// Poll approach
let asset ;
do {
await new Promise ( r => setTimeout ( r , 5000 )); // wait 5 seconds
const response = await client . asset . get ( assetId );
asset = response . asset ;
} while ( asset . status . phase === 'processing' || asset . status . phase === 'waiting' );
if ( asset . status . phase === 'ready' ) {
const playbackUrl = `https://livepeercdn.studio/asset/hls/ ${ asset . playbackId } /index.m3u8` ;
console . log ( 'Ready:' , playbackUrl );
} else {
console . error ( 'Failed:' , asset . status . error );
}
Transcoding time varies by file size: a 10-minute HD file typically takes 2-3 minutes.
Related pages
Playback Embed the playback URL after transcoding is complete.
Webhooks Subscribe to asset.ready and asset.failed to avoid polling.
Last modified on April 7, 2026