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 jobconst job = await stack0.cdn.transcode({projectSlug: 'my-project',assetId: 'video-asset-id',outputFormat: 'hls', // 'hls' for adaptive streaming, 'mp4' for downloadvariants: [{ 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:
| Quality | Resolution | Use Case |
|---|---|---|
| 360p | 640x360 | Low bandwidth, mobile data |
| 480p | 854x480 | Standard definition |
| 720p | 1280x720 | HD, most common |
| 1080p | 1920x1080 | Full HD |
| 1440p | 2560x1440 | 2K / QHD |
| 2160p | 3840x2160 | 4K Ultra HD |
Check Job Status
job-status.ts
// Get job statusconst 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 jobsconst { jobs, total, hasMore } = await stack0.cdn.listJobs({projectSlug: 'my-project',assetId: 'video-asset-id', // Optional filterstatus: 'processing', // Optional filterlimit: 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 qualityfor (const mp4 of urls.mp4Urls) {console.log(`${mp4.quality}: ${mp4.url}`)}// Generated thumbnailsfor (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 HTMLVideoElementif (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 supportvideo.src = urls.hlsUrl!video.addEventListener('loadedmetadata', () => {video.play()})}
Generate Thumbnails
thumbnails.ts
// Generate a thumbnail at a specific timestampconst thumbnail = await stack0.cdn.getThumbnail({assetId: 'video-asset-id',timestamp: 10.5, // 10.5 seconds into the videowidth: 320, // Optional: resizeformat: 'webp', // 'jpg', 'png', 'webp'})console.log(`Thumbnail: ${thumbnail.url}`)
Extract Audio
extract-audio.ts
// Extract audio from videoconst 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 watermarkconst 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 CDNposition: 'bottom-right',opacity: 50,margin: 20,},})// Or with text watermarkconst 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 videoconst 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 secondsend: 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