Player
A professional player you embed in one line, wired to your storage and your DRM. It is free: you pay the delivery and licences playback already consumes, not the player.
What it is #
A player is a named configuration — colors, controls, restrictions — stored in your account. You embed it on any website by id, next to whichever video should play. One player serves your whole catalogue: the embed picks the content, the player brings everything else.
Underneath it is Shaka Player, the open-source player Google maintains: adaptive HLS and DASH, progressive mp4, DRM. We add the persistent configuration, URL signing, the connection to your DRM, and the one-line embed.
Why it is free
Prefer to assemble the player yourself, with your own Shaka or Video.js? The manual integration guide is still there — the player is optional by design.
Embedding it #
Two ways. The recommended one is the loader: it builds the iframe with the right permissions (autoplay, encrypted-media, fullscreen), which get forgotten when written by hand.
<div data-airi-player="PLAYER_ID" data-file="FILE_ID"></div> <script async src="https://airi.live/player.js"></script>
<iframe src="https://airi.live/embed/PLAYER_ID?file=FILE_ID" style="aspect-ratio:16/9;width:100%;border:0" allow="autoplay; encrypted-media; fullscreen; picture-in-picture" allowfullscreen></iframe>
FILE_ID is the id (or your customId) of a file in your storage: a plain mp4 or an HLS/DASH package. For an external source use data-src="https://…" instead of data-file. In a SPA that renders the div after load, call AiriPlayer.scan().
| Attribute | What it does |
|---|---|
data-airi-player | The player id. Required. |
data-file | A file from your storage (id or customId). |
data-src | An external https URL (mp4, m3u8 or mpd), unsigned. |
data-aspect | Container aspect ratio (16:9 by default). |
data-* | Any parameter from the next table, as an attribute. |
URL parameters #
Each embed can adjust the player without touching its saved configuration. Precedence is URL > configuration > defaults, and it only reaches presentation and playback — delivery (expiries, countries, speed) and allowed origins cannot be touched from a URL, by construction.
| Parameter | What it does |
|---|---|
autoplay=1 | Starts by itself, muted (browser policy). |
muted=1 | Starts silent. |
loop=1 | Repeats. |
t=90 | Starts at second 90. |
rate=1.5 | Initial speed. |
maxh=720 | Quality ceiling in lines. |
lang=en | Controls language (es, en, auto). |
captions=es | Captions in that language, visible from the start. |
audio=en | Preferred audio track. |
poster=https://… | Waiting image. |
accent=22ccaa | Accent color, hex without #. |
bigplay=0 | No big play button. |
controls=0 | No controls — for background videos. |
The configuration #
The dashboard covers the common ground with a live preview. The full surface — exact button order, menu speeds, each bar's color — lives in the API's config object, grouped in four blocks:
| Block | What it holds |
|---|---|
theme | Accent and bar colors, aspect ratio, poster, linked logo with position and opacity. |
playback | Autoplay, mute, loop, start position, rate, quality ceiling, audio and caption languages. |
ui | Which buttons appear and in what order, overflow menu, speeds, seek bar, big play button, keyboard shortcuts, mobile gestures, language, title. |
delivery | Signed URL lifetime, allowed or blocked countries, speed cap. Enforced at the CDN edge. |
Everything is optional: {} is a fully working player with Shaka's defaults. The exact schema, every field documented, is in the OpenAPI reference under PlayerConfig.
The dashboard does not stomp API configuration
config in an API PATCH is a full replacement: send the whole object you want kept.Through the API #
Players are managed with the player:read and player:write scopes. The id creation returns is the one that goes into the embed.
curl -X POST https://kms.airi.live/v1/players \ -H "Authorization: Bearer $TOKEN" \ -H 'content-type: application/json' \ -d '{ "name": "My player", "config": { "theme": { "accentColor": "#22ccaa" }, "playback": { "muted": true } }, "allowedOrigins": ["https://mysite.com"] }'
# List curl "https://kms.airi.live/v1/players" -H "Authorization: Bearer $TOKEN" # Update (config = full replacement; allowedOrigins: null removes it) curl -X PATCH "https://kms.airi.live/v1/players/$ID" \ -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' \ -d '{ "config": { "ui": { "locale": "en" } } }' # Delete — every embed with this id stops working immediately curl -X DELETE "https://kms.airi.live/v1/players/$ID" -H "Authorization: Bearer $TOKEN"
The embed calls a public resolution endpoint — GET /v1/players/{id}/resolve — that returns the configuration and, when content is named, its signed URL and licence endpoints. You can call it yourself to build your own player on top of our resolution: it needs no token.
Restricting to your domains #
A public embed works on any website — the YouTube model, and for most content the right one. If your player should only work on your sites, give it a list of origins:
curl -X PATCH "https://kms.airi.live/v1/players/$ID" \ -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' \ -d '{ "allowedOrigins": ["https://mysite.com", "https://www.mysite.com"] }'
The real wall is not a check of ours: the embed document answers with Content-Security-Policy: frame-ancestors, and it is the viewer's browser that refuses to render the iframe outside your list. The resolution also answers 403 when the origin does not match, as fast failure.
What it protects and what it does not
delivery.urlTtlSeconds. For content that needs real protection, encrypt it at encode time: the player plays it just as easily.Automatic DRM #
If a package came out of your encoding encrypted, the embed knows without any configuration: resolution detects the job's key and hands over your own DRM's licence endpoints. The embedding site sees no keys and no licence URLs — just the usual div and script.
DRM playback issues licences, and each licence bills at the usual rate ($0.009). Same cost with our player or with yours.
Safari and encrypted content
Limits of this version #
- No Chromecast. The Cast button arrives with our own receiver; we would rather show no button than a failing one.
- FairPlay pending — see the Safari note above.
- External
data-srccarries no DRM: a foreign URL cannot resolve our licences. - Plain mp4s play progressively: no adaptive ladder, no quality menu. Encode them for ABR — exactly what encoding exists for.
- No playback analytics yet: delivery data is in your daily billing.