One video player API across Android, iOS and the web. This package is the web implementation: the same model types, listener callbacks, error codes and UI behavior as the Android SDK (the reference platform), built on web standards.
OGPlayer is a product of Inverse DOO.
<video> element plays the media. HLS streams
are fed to it through hls.js using
Media Source Extensions; Safari plays HLS natively so hls.js steps aside
there. Progressive MP4 plays directly.<og-player> that works identically in plain
HTML, React, Vue and Angular, with all styles isolated in a shadow DOM so
host-page CSS can't break the player (and vice versa).OGP1.… offline keys as Android/iOS, verified with
the browser's built-in WebCrypto — one license unlocks all three
platforms. On the web, apps patterns bind to the page hostname.<script type="module">
import { OGPlayer } from "ogplayer";
const player = new OGPlayer({ licenseKey: "OGP1...." });
document.querySelector("og-player").player = player;
player.addListener({
onStateChanged: (s) => console.log(s),
onProgress: (positionMs, bufferedMs, durationMs) => {},
});
player.load({
url: "https://example.com/stream.m3u8",
title: "My movie",
contentRatings: [{ age: "SIXTEEN" }, { descriptor: "FEAR" }],
sideloadedSubtitles: [{ url: "/subs/en.vtt", language: "en", label: "English", isDefault: true }],
});
</script>
<og-player style="width:100%;aspect-ratio:16/9"></og-player>
Overlays (watermarks, logos) use the nine named slots, mirroring
Android/iOS OverlaySlot — including the clearance choreography around the
controls and rating icons:
<og-player>
<img slot="top-end" src="/logo.png" width="90">
</og-player>
Custom action icons (max 8, inline in the top-end control row, hide with the controls — same contract as Android/iOS):
el.config = {
customActions: [
{ svg: shareIconSvg, accessibilityLabel: "Share", onClick: () => share() },
],
};
npm install ogplayer — ESM module
with TypeScript types, hls.js pulled in as a dependency. Publishing is one
npm publish from CI; scoped to the @ogplayer org.dist/ogplayer.global.js is a
single self-contained file (hls.js included) exposing window.OGPlayerSDK.
Hosted on our own domain (e.g. cdn.ogplayer.tv) or jsDelivr once public.<script src="https://cdn.ogplayer.tv/0.1.0/ogplayer.global.js"></script>
<script>
const player = new OGPlayerSDK.OGPlayer();
document.querySelector("og-player").player = player;
player.load({ url: "…" });
</script>
Evergreen Chrome / Edge / Firefox / Safari 16+ (desktop & mobile). Every API used (MSE, custom elements, shadow DOM, WebCrypto, Fullscreen) has been baseline for years; no polyfills.
| Feature | Android | iOS | Web |
|---|---|---|---|
| Transport / state / listeners | ✅ | ✅ | ✅ same names |
| Analytics events | ✅ | ✅ | ✅ same shapes |
| Error taxonomy | ✅ | ✅ | ✅ same codes |
| HLS + ABR qualities | ✅ | ✅ | ✅ (hls.js/native) |
| DASH | ✅ | — | ⏳ later (dash.js/Shaka) |
| Live & DVR | ✅ | ✅ | ✅ |
| Embedded + sideloaded subtitles | ✅ | ✅ | ✅ (native cue rendering) |
| Audio tracks | ✅ | ✅ | ✅ |
| Offline license (shared keypair) | ✅ | ✅ | ✅ WebCrypto |
| Controls chrome (tokens) | ✅ | ✅ | ✅ same tokens/icons |
| Title / NICAM ratings / watermark slots | ✅ | ✅ | ✅ incl. reflow choreography |
| Custom action icons (≤8) | ✅ | ✅ | ✅ |
| Ads (IMA / FreeWheel) | ✅ | ✅ | ⏳ SPI defined, provider later |
| DRM | Widevine/PlayReady | FairPlay | ⏳ EME later |
| Casting | Chromecast module | AirPlay | ⏳ Remote Playback API later |
| Trick-play thumbnails | ✅ | ✅ | ⏳ |