VOD library
Two ways a VOD lands in your library:
- Upload — user uploads an mp4/mov/mkv/webm, Hakari transcodes into an adaptive HLS/DASH ladder and serves it from the global edge.
- Live recording — a stream with recording enabled finalizes on stop; the resulting playlist is playable at the stream's
vodPlaybackUrl.
This page covers the upload path. For live recording, see Live streams — Recording.
Upload flow
client ──PUT presigned URL──▶ cloud storage
│ ▲
├──POST /vod──▶ Hakari ──── dispatches transcode
│ │
└── polls GET /vod/:id for progress
│
transcode pipeline ──┘
│
└──▶ webhook → status: complete, playbackUrl ready
Status progression: pending_upload → uploaded → queued → processing → complete (or failed / cancelled).
Creating a VOD via the dashboard
Dashboard → VOD Library → + Upload video:
- Title
- Source file — mp4/mov/mkv/webm. Upload is direct-to-storage via a presigned URL, so even multi-GB files don't hit our API.
- Output format — HLS or MPEG-DASH. HLS for widest compatibility; DASH if you prefer MPD manifests.
- Video codec —
h264(widest),h265(better compression),vp9,av1(best compression, slow). Plan-gated. - Aspect ratio —
preserve(no padding), or a fixed16:9,9:16,4:3,1:1. Fixed ratios pad with black bars. - Rendition ladder — pick rungs (
1080p,720p,480p,360p). Each is a separate playable quality. - Bitrate per rung — override defaults if you want a higher-quality 720p or a cheaper 1080p.
Hit Upload & transcode. The upload manager runs in the browser — you can navigate away, it keeps going. Watch progress on the VOD detail page.
Playback
A completed VOD has playbackUrl set — paste it into any HLS/DASH player. The edge serves these with:
- Long-lived per-object cache — once a segment is cached at an edge, subsequent viewers in the same region get it without a round-trip to storage.
- Long
Cache-Control: max-age=31536000, immutableon segments, shortmax-age=60on.m3u8manifests. - CORS
*so browser players work out of the box. - HTTP/2 + TLS 1.3.
Thumbnail is auto-extracted from the source and served at …/vod/<id>/thumb.jpg.
Signed playback
Per-VOD toggle on the detail page. When on, the edge enforces ?policy=&signature= on every /vod/<id>/* request. See signed playback for the algorithm and client examples.
Programmatic upload
# 1. Create the VOD record + get a presigned PUT URL.
curl -X POST https://api.hakari.cloud/v1/projects/my-project/vod \
-H "Authorization: Bearer hkr_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Launch recording",
"filename": "launch.mp4",
"outputFormat": "hls",
"videoCodec": "h264",
"ladder": [
{"name":"720p","width":1280,"height":720,"videoBitrate":"3M"},
{"name":"480p","width":854,"height":480,"videoBitrate":"1500k"}
]
}'
# → { vod: {...}, upload: { url, method: "PUT", ... } }
# 2. PUT the file to the presigned URL.
curl -X PUT --data-binary @launch.mp4 "<upload.url>"
# 3. Mark upload complete → dispatches the transcode job.
curl -X POST https://api.hakari.cloud/v1/projects/my-project/vod/<vodId>/uploaded \
-H "Authorization: Bearer hkr_xxx"
# 4. Poll until status === "complete"
curl https://api.hakari.cloud/v1/projects/my-project/vod/<vodId> \
-H "Authorization: Bearer hkr_xxx"
For vod.complete notifications instead of polling, subscribe to the webhook.
Plan limits
Your plan gates:
- Max source size (hard ceiling on each upload).
- Concurrent transcode jobs per project (excess jobs queue).
- Allowed video codecs (
h265/av1often require higher tiers). - Allowed output formats.
Limits return as 403 from the create endpoint when exceeded.