Video Streaming

Transcode videos to HLS adaptive streaming and MP4 formats for optimal playback across all devices.

Transcode Video

Start a transcoding job to convert a video to HLS or MP4:

transcode.ts
import { Stack0 } from '@stack0/sdk'
const stack0 = new Stack0({
apiKey: process.env.STACK0_API_KEY!
})
// Start a transcoding job
const job = await stack0.cdn.transcode({
projectSlug: 'my-project',
assetId: 'video-asset-id',
outputFormat: 'hls', // 'hls' for adaptive streaming, 'mp4' for download
variants: [
{ quality: '720p', codec: 'h264' },
{ quality: '1080p', codec: 'h264' },
],
webhookUrl: 'https://your-app.com/webhook', // Optional
})
console.log(`Job ID: ${job.id}, Status: ${job.status}`)

Quality Variants

Available quality presets for video transcoding:

QualityResolutionUse Case
360p640x360Low bandwidth, mobile data
480p854x480Standard definition
720p1280x720HD, most common
1080p1920x1080Full HD
1440p2560x14402K / QHD
2160p3840x21604K Ultra HD

Check Job Status

job-status.ts
// Get job status
const job = await stack0.cdn.getJob('job_abc123')
console.log(`Status: ${job.status}`)
console.log(`Progress: ${job.progress}%`)
// Status values:
// 'pending' - Job created, waiting to be processed
// 'queued' - Job queued for processing
// 'processing' - Currently transcoding
// 'completed' - Finished successfully
// 'failed' - Transcoding failed
// 'cancelled' - Job was cancelled

List Jobs

list-jobs.ts
// List all transcoding jobs
const { jobs, total, hasMore } = await stack0.cdn.listJobs({
projectSlug: 'my-project',
assetId: 'video-asset-id', // Optional filter
status: 'processing', // Optional filter
limit: 20,
offset: 0,
})
for (const job of jobs) {
console.log(`${job.id}: ${job.status} (${job.progress}%)`)
}

Get Streaming URLs

After transcoding completes, get URLs for playback:

streaming-urls.ts
const urls = await stack0.cdn.getStreamingUrls('asset-id')
// HLS adaptive streaming (recommended for web/mobile)
console.log(`HLS: ${urls.hlsUrl}`)
// MP4 direct download by quality
for (const mp4 of urls.mp4Urls) {
console.log(`${mp4.quality}: ${mp4.url}`)
}
// Generated thumbnails
for (const thumb of urls.thumbnails) {
console.log(`Thumbnail at ${thumb.timestamp}s: ${thumb.url}`)
}

Video Player Integration

Use HLS.js for cross-browser HLS playback:

hls-player.tsx
import Hls from 'hls.js'
const urls = await stack0.cdn.getStreamingUrls('asset-id')
const video = document.getElementById('video') as HTMLVideoElement
if (Hls.isSupported() && urls.hlsUrl) {
const hls = new Hls()
hls.loadSource(urls.hlsUrl)
hls.attachMedia(video)
hls.on(Hls.Events.MANIFEST_PARSED, () => {
video.play()
})
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Safari native HLS support
video.src = urls.hlsUrl!
video.addEventListener('loadedmetadata', () => {
video.play()
})
}

Generate Thumbnails

thumbnails.ts
// Generate a thumbnail at a specific timestamp
const thumbnail = await stack0.cdn.getThumbnail({
assetId: 'video-asset-id',
timestamp: 10.5, // 10.5 seconds into the video
width: 320, // Optional: resize
format: 'webp', // 'jpg', 'png', 'webp'
})
console.log(`Thumbnail: ${thumbnail.url}`)

Extract Audio

extract-audio.ts
// Extract audio from video
const result = await stack0.cdn.extractAudio({
projectSlug: 'my-project',
assetId: 'video-asset-id',
format: 'mp3', // 'mp3', 'aac', 'wav'
bitrate: 192, // Optional: kbps
})
console.log(`Status: ${result.status}`)

Add Watermark

watermark.ts
// Transcode with image watermark
const job = await stack0.cdn.transcode({
projectSlug: 'my-project',
assetId: 'video-asset-id',
outputFormat: 'hls',
variants: [{ quality: '1080p', codec: 'h264' }],
watermark: {
type: 'image',
imageAssetId: 'logo-asset-id', // Your logo uploaded to CDN
position: 'bottom-right',
opacity: 50,
margin: 20,
},
})
// Or with text watermark
const textJob = await stack0.cdn.transcode({
projectSlug: 'my-project',
assetId: 'video-asset-id',
outputFormat: 'mp4',
variants: [{ quality: '720p', codec: 'h264' }],
watermark: {
type: 'text',
text: 'My Company',
fontFamily: 'Arial',
fontSize: 24,
fontColor: '#ffffff',
position: 'top-left',
opacity: 70,
},
})

Trim Video

trim.ts
// Transcode only a portion of the video
const job = await stack0.cdn.transcode({
projectSlug: 'my-project',
assetId: 'video-asset-id',
outputFormat: 'mp4',
variants: [{ quality: '720p', codec: 'h264' }],
trim: {
start: 30, // Start at 30 seconds
end: 120, // End at 2 minutes
},
})

Pricing

Transcoding

$0.005

per minute of output video

Streaming

$0.05

per GB bandwidth delivered

Audio

$0.002

per minute of audio processed