Hakari

Live streams

A stream is the unit of live broadcast. Each stream runs on a dedicated live pipeline at a Hakari origin, exposes a unique ingest port, and serves playback through the global edge fleet.

Lifecycle

CREATE ──▶ IDLE ──(push starts)──▶ LIVE ──(push stops or idle timeout)──▶ DISABLED
                                     │                                        │
                                     └── playback served ◀──────────── activate to reuse

The status flips via Hakari's admission webhook the moment your encoder connects / disconnects. An idle-timeout watchdog tears the pipeline down after N seconds of no input (configurable per plan) so you're not paying for empty capacity.

Ingest

You push with RTMP or SRT. The dashboard shows both URLs on the stream detail page.

| Protocol | Use when | | --- | --- | | RTMP | OBS, Wirecast, vMix, FFmpeg. Universally supported. TCP-based; retransmits everything. | | SRT | Long-haul contribution over the public internet. UDP-based with ARQ — handles packet loss gracefully without the full head-of-line blocking penalty TCP pays. |

OBS

Settings → Stream → Service: Custom. The Ingest URL on your stream detail page already includes your credentials (rtmp://user:pass@host:port/app). Paste it straight into Server and paste the stream key into Stream Key. Leave "Use authentication" unchecked — that checkbox triggers a different RTMP auth mode we don't validate against.

FFmpeg

ffmpeg -re -i source.mp4 \
  -c:v libx264 -preset veryfast -tune zerolatency \
  -c:a aac -ar 44100 -b:a 128k \
  -f flv "rtmp://USER:PASS@ingest-in-mum-1.hakari.cloud:11935/app/hkr_abc123"

For SRT, swap the URL scheme: srt://ingest-in-mum-1.hakari.cloud:9000?streamid=hkr_abc123&passphrase=....

Push authentication

Every stream has a per-stream username + password. Hakari rejects pushes that don't match. Rotate from the stream detail page — pre-rotate sessions keep their RTMP socket, post-rotate connects require the new creds.

Wrong-port safety: the admission check also verifies the port the encoder hit matches the stream's provisioned rtmpPort. If you mistype the port and land on another stream's endpoint, the push is rejected instead of silently going to the wrong stream.

Playback protocols

Pick protocols at create time. You can enable more than one; each adds a playback URL.

| Protocol | Latency | Browser support | Use when | | --- | --- | --- | --- | | LLHLS | 2–4 s | Universal (hls.js, OvenPlayer, Safari native) | Default. Best latency-compatibility trade-off. | | HLS | 6–10 s | Universal | Legacy Safari, downstream CDN compatibility. | | WebRTC | < 1 s | Modern browsers via WebRTC, OvenPlayer | Interactive use — auctions, trading floors. |

Every stream exposes:

  • LLHLS (resilient)…/app/<key>/index.m3u8 — goes through Hakari's resilience layer, which keeps the player's clock advancing when your broadcaster's upload hiccups. No client stall, no restart. This is the default.
  • LLHLS (direct)…/app/<key>/d/llhls.m3u8 — unbuffered live path, slightly lower latency, no cushion if the upstream stalls.
  • HLS…/app/<key>/ts:hls.m3u8 — MPEG-TS legacy.
  • WebRTC…/app/<key> — signalling endpoint (dashboard embed handles this).

Recording (VOD)

Tick Recording at create time. While the stream is live, the recorder uploads segments to cloud storage at vod/<streamKey>/. On stream end, the recorder finalizes the master + chunklist playlists (including #EXT-X-DISCONTINUITY markers for each publisher session) and fires a completion webhook so the dashboard can show the duration.

Playback URL is available on the stream detail page as soon as segments start uploading. Your viewers can keep playing the same live URL after the stream ends — the edge falls back to the recorded copy with long cache headers.

DVR

Lets viewers scrub backwards into the live window. Enabled per-stream with a configurable window (e.g. 1 hour, 6 hours). The LLHLS playlist stays PLAYLIST-TYPE:EVENT so DVR-aware players (OvenPlayer, hls.js with liveDurationInfinity: false) expose the full scrub range.

Max DVR window is plan-limited. Higher DVR windows cost more RAM per stream (all DVR segments are kept hot per rendition), so large DVR + many renditions scales up your plan tier.

Signed playback

Toggle Signed playback on the stream detail page to require ?policy=&signature= on every playback request. The edge enforces this against a per-stream HMAC secret; expired or tampered signatures get 401 at the auth_request layer before any bytes are served.

See the signed playback guide for how to mint ticket URLs server-side (or client-side using the signing secret).

Programmatic access

All dashboard actions have REST counterparts. Full list at API reference, but the essentials:

# Create a stream
curl -X POST https://api.hakari.cloud/v1/projects/my-project/streams \
  -H "Authorization: Bearer hkr_xxx" \
  -H "Content-Type: application/json" \
  -d '{"name":"Launch","qualities":["720p","480p"],"protocols":["llhls"],"vodEnabled":true}'

# List streams
curl https://api.hakari.cloud/v1/projects/my-project/streams \
  -H "Authorization: Bearer hkr_xxx"

# Rotate push credentials
curl -X POST https://api.hakari.cloud/v1/projects/my-project/streams/<id>/rotate-push \
  -H "Authorization: Bearer hkr_xxx"

# Disable (destroys the container, marks stream disabled)
curl -X DELETE https://api.hakari.cloud/v1/projects/my-project/streams/<id> \
  -H "Authorization: Bearer hkr_xxx"

Create an API key to use these.