Skip to content

Getting started

Havik Player plays Oddin's live esports streams (low-latency HLS with DRM) in any modern browser. There are three ways to integrate it:

ModeBest forYou provideThe SDK owns
Iframe embedFastest drop-in, CMS pages, no build stepan iframe sloteverything, behind a postMessage API
Managed playerFull control of look & behavior in your appa <video> elementhls.js, LL-HLS tuning, DRM/EME, retries, controls
Bring your own playerExisting player stacks (hls.js, Shaka, wrapper)the player + <video>auth → catalog → playback resolution + DRM helpers

All three modes need the same two things:

  • a match URN, which identifies the stream, e.g. od:match:1234
  • a publishable api-key (pk_live_… / pk_test_…), safe to ship in browser JavaScript because it only works from allow-listed origins

1. Get a key and a match

Onboarding is handled by Oddin: email havik-support@oddin.gg to get an api-key scoped to the tournaments you serve. Match URNs come from your odds-feed integration or from the SDK's catalog helpers.

2. Get your origins allow-listed

The api-key is publishable, and its only guardrail is a server-side origin allow-list. Until your origins are onboarded, every request fails its CORS preflight and nothing plays. Send havik-support the exact origins you serve from, for both of:

  1. the key's AllowedOrigins: every origin the player runs on (and AllowedIframeParents for iframe embeds: the parent page's origin)
  2. the DRM service's CORS allow-list, the same origins again. Miss this one and the license request dies in preflight, which looks like black video with no error at all

Never ship a wildcard

A ["*"] allow-list disables the only guardrail on a publishable key. Don't ask for one in production.

Allow a few minutes for propagation. Include http://localhost:5173 (or your dev port) if you want local development to work, and https://player-dev.oddin-video.gg if you want to exercise your key in the playground. Once the catalog loads there, your key and your allow-listing are known-good.

3. Point at the right environment

baseUrl selects the Havik environment. Don't hard-code it deeper than a config value. Serve it from your backend, and keep the backend current from the endpoint directory of the environment you target. This site's directory is status-dev.oddin-video.gg/v1/endpoints.json; the URL for the other environment is provided at onboarding.

Every sample on this site targets https://feed-dev.oddin-video.gg.

EnvironmentAPI baseUrlHosted embed page
Integrationhttps://feed-dev.oddin-video.gghttps://player-dev.oddin-video.gg/embed/
Productionhttps://feed.oddin-video.gghttps://player.oddin-video.gg/embed/

Test keys (pk_test_…) work against integration; production keys (pk_live_…) against production. A key on the wrong environment fails with UNAUTHORIZED.

Live service health for every Havik component is published at status-dev.oddin-video.gg, the status page for this site's environment. The other one is provided at onboarding.

4. Install

For the iframe embed there is nothing to install. For the SDK modes:

bash
npm install @oddin-gg/havik-player
html
<!-- Exposes window.HavikPlayer. Pin an exact version in production. -->
<script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@1/dist/havik-player.global.js"></script>

TypeScript definitions ship with the package, and the types are the source of truth for the API surface.

5. First playback

ts
import { createPlayer } from '@oddin-gg/havik-player';

const player = await createPlayer({
  video: document.querySelector('video')!,
  baseUrl: 'https://feed-dev.oddin-video.gg',
  matchUrn: 'od:match:1234',
  credential: { apiKey: 'pk_test_…' },
  autoplay: true,
  muted: true, // required for reliable autoplay under browser sound policies
  waitForLive: true, // arm on an upcoming match, auto-play at go-live
});

player.on('statechange', (s) => console.log('state:', s));
player.on('error', (e) => console.error(e.code, e.httpStatus, e.message));

If the match hasn't started, waitForLive arms the player and it attaches the moment the stream goes live. See the managed player guide.

Browser support

Chrome, Firefox, and Edge play via hls.js + Widevine. Safari and iOS play via hls.js (ManagedMediaSource) or native HLS with FairPlay. Use detectDrmSupport() to check a browser before rendering the player. See the DRM guide.

Building a native app instead of a web page? See the iOS SDK (preview) and Android SDK (in development).

Next steps

ISC licensed. Bundles hls.js (Apache-2.0).