Migrating from Mux
Migrating from Mux to HesedVid
This guide helps you migrate your video infrastructure from Mux to HesedVid with minimal disruption to your service.
Tip
Most migrations can be completed in phases over 2-4 weeks, allowing you to test thoroughly before switching completely.
Migration Overview
Compare APIs: Map Mux endpoints to HesedVid equivalents
Update authentication: Switch from Mux API tokens to HesedVid API keys
Modify upload flow: Adapt your upload process
Update players: Point to new playback URLs
Migrate analytics: Transition tracking and reporting
API Comparison
Core Endpoints
| Mux Endpoint | HesedVid Equivalent | Notes |
|---|---|---|
POST /video/v1/assets | Two-step process: 1. POST /{orgID}/environments/{envID}/videos/upload-url2. POST /{orgID}/environments/{envID}/videos/process | HesedVid separates upload and processing |
POST /video/v1/uploads | POST /{orgID}/environments/{envID}/videos/upload-url | Direct upload to storage |
GET /video/v1/assets/{id} | GET /{orgID}/videos/{publicID}/details | Similar response structure |
DELETE /video/v1/assets/{id} | DELETE /{orgID}/videos/{videoID} | Soft delete with cleanup |
GET /data/v1/metrics | GET /{orgID}/analytics/* | Multiple specialized endpoints |
Playback URLs
Mux:
https://stream.mux.com/{PLAYBACK_ID}.m3u8HesedVid:
https://worker.hesedvid.com/{publicID}/master.m3u8Mux:
// Generate JWT with signing keyconst token = Mux.JWT.sign(playbackId, { keyId: SIGNING_KEY_ID, keySecret: SIGNING_KEY_PRIVATE});const url = `https://stream.mux.com/${playbackId}.m3u8?token=${token}`;HesedVid:
// Request signed URL from APIconst response = await fetch( `https://api.hesedvid.com/v1/api/${orgId}/videos/${publicId}/signed-url`, { headers: { 'X-Api-Key': `${apiKey}` } });const { signed_url } = await response.json();Code Migration Examples
Upload Flow
Mux Implementation:
// Create direct uploadconst upload = await mux.video.uploads.create({ cors_origin: 'https://example.com', new_asset_settings: { playback_policy: ['public'], encoding_tier: 'baseline' }});
// Upload file using tusconst uppy = new Uppy() .use(Tus, { endpoint: upload.data.url });HesedVid Implementation:
// Get upload URLconst { body } = await fetch(`${API}/videos/upload-url`, { method: 'POST', headers: { 'X-Api-Key': `${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ filename: 'video.mp4', fileSize: file.size })}).then(r => r.json());
// Upload directlyawait fetch(body.signedURL, { method: 'PUT', body: file, headers: { 'Content-Type': 'video/mp4' }});
// Start processingconst { videoID } = await fetch(`${API}/videos/process`, { method: 'POST', headers: { 'X-Api-Key': `${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ gcsPath: body.bucketPath, videoQuality: 'high', allowPublicAccess: true })}).then(r => r.json());Mux Implementation:
const asset = await mux.video.assets.create({ input: 'https://example.com/video.mp4', playback_policy: ['public'], encoding_tier: 'baseline'});HesedVid Implementation:
// First download to our storageconst { body: downloadResult } = await fetch(`${API}/videos/download`, { method: 'POST', headers: { 'X-Api-Key': `${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceUrl: 'https://example.com/video.mp4' })}).then(r => r.json());
// Then processconst { videoID } = await fetch(`${API}/videos/process`, { method: 'POST', headers: { 'X-Api-Key': `${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ gcsPath: downloadResult.bucketPath, videoQuality: 'high', allowPublicAccess: true })}).then(r => r.json());Status Polling
Both platforms require polling for processing status:
async function waitForReady(assetId) { while (true) { const asset = await mux.video.assets.retrieve(assetId); if (asset.data.status === 'ready') { return asset.data; } if (asset.data.status === 'errored') { throw new Error('Asset failed to process'); } await new Promise(r => setTimeout(r, 5000)); }}async function waitForReady(publicId) { while (true) { const { body } = await fetch( `${API}/videos/${publicId}/details`, { headers: { 'X-Api-Key': `${apiKey}` } } ).then(r => r.json());
if (body.status.ready) { return body; } if (body.status.failed) { throw new Error('Video failed to process'); } await new Promise(r => setTimeout(r, 5000)); }}Feature Mapping
Video Processing
| Mux Feature | HesedVid Equivalent | Configuration |
|---|---|---|
| Encoding Tiers | Video Quality | standard, high, ultra |
| MP4 Support | Coming Soon | HLS-only currently |
| Thumbnails | Custom Thumbnails | Generate at any timestamp |
| Captions | Coming Soon | Q2 2024 |
| Clipping | Coming Soon | Q3 2024 |
| Live Streaming | Not Available | Focus on VOD |
Analytics
| Mux Data | HesedVid Analytics | Endpoint |
|---|---|---|
| Views | Segments Served | GET /analytics/usage |
| View Duration | Segments × 6s | Calculate from segments |
| Unique Viewers | Not Available | Privacy-focused |
| Quality Distribution | Resolution Analytics | GET /analytics/resolution |
| Errors | Not Available | Client-side only |
Migration Checklist
Set up HesedVid account
- Create organization
- Generate API keys
- Configure billing
Update backend code
- Replace Mux SDK with HesedVid API calls
- Update webhook handlers
- Modify upload flow
Update frontend
- Switch playback URLs
- Update player configuration
- Test on all platforms
Migrate content (optional)
- Export video list from Mux
- Re-upload to HesedVid
- Update video IDs in database
Monitor and optimize
- Compare analytics
- Adjust encoding settings
- Monitor costs
Cost Comparison
Tip
HesedVid typically costs 70-80% less than Mux for similar usage patterns.
Pricing Example (10,000 minutes/month)
| Service | Encoding | Storage | Delivery | Total |
|---|---|---|---|---|
| Mux | $50 | $25 | $125 | $200 |
| HesedVid | Included | Included | $0.15/min | $150 |
Savings: $50/month (25%)
Common Issues
CORS Errors
HesedVid has permissive CORS by default. No configuration needed.
Webhook Differences
Mux sends many granular events. HesedVid focuses on key events:
// Webhook handlerapp.post('/webhooks/hesedvid', (req, res) => { const { event, videoId, status } = req.body;
switch(event) { case 'video.processing.completed': // Video ready break; case 'video.processing.failed': // Handle error break; }});Player Compatibility
HesedVid uses standard HLS. Any HLS player works:
- HLS.js
- Video.js
- Native Safari
- ExoPlayer (Android)
- AVPlayer (iOS)
Support
Need help migrating?
- Documentation: docs.hesedvid.com
- Email: [email protected]
- Migration Assistance: Contact us for hands-on help
Note
Enterprise customers get free migration assistance including code review and implementation support.