@oddin-gg/havik-player 2.26.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +205 -161
- package/dist/index.js.map +1 -1
- package/docs/API.md +11 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/docs/API.md
CHANGED
|
@@ -251,6 +251,7 @@ player.on('error', (e) => console.error(e.code, e.httpStatus, e.message));
|
|
|
251
251
|
| `liveLatencyTarget` | `number` | `2` | Target live‑edge latency in seconds (hls.js `liveSyncDuration`). The player derives a matching latency **ceiling** internally and catches up at 1.1×, so this is the only live‑latency knob you need. Lower = closer to live but more rebuffer‑prone. Live/LL only. |
|
|
252
252
|
| `adaptiveHoldBack` | `boolean` | `true` | hls.js engine: raise the live‑sync target for a session whose part fetches are slow, instead of letting it stall. A viewer far from the origin plays from a local edge whose every cache miss on a 0.5 s part is a cross‑continent fetch (250–310 ms per part from South America, Canada/Mexico and APAC on the global slot, against 44 ms in Europe), so the fetch cycle outruns the part cadence and the 2 s buffer drains. The session's own part fetches are timed (first byte, as a share of the part's duration, over a 10 s window): a window whose p95 is at or above 60% **and** whose median is at or above 40%, two 3 s ticks running, steps the target up 0.5 s, to `adaptiveHoldBackCeiling` at most; a p95 under 40% for 60 s steps it back down. A session whose fetches are fast never moves. Each move fires [`latencytargetchange`](#player-events), counts in `holdBackSteps`, and shows in `targetLatencySeconds`. Live/LL only. |
|
|
253
253
|
| `adaptiveHoldBackCeiling` | `number` | `3.5` | Highest live‑sync target the adaptive hold‑back may step to, in seconds. Kept a second under the drift ceiling; at or below `liveLatencyTarget` it disables the stepping. |
|
|
254
|
+
| `stallCap` | `boolean` | `true` | hls.js engine: after a playback stall (not in the first 10 s after playback starts or resumes, not while seeking, not with media still buffered ahead, not a wait at the live edge for a part not yet published), cap quality one rendition below the one that stalled, and give one rendition back per 3 minutes of playback without another stall (paused time does not count); a stall while capped steps down again or restarts the 3 minutes. Without it, ABR climbs straight back onto a rendition the connection just failed to carry: on measured production sessions, 55–65 % of rebuffer time was such a repeat within 3 minutes. Counted in `stallDownCaps`; `capReason` is `'stall'` while it is the binding ceiling. Never applies to a quality the viewer pinned; off when `hlsConfig.capLevelToPlayerSize` or `capLevelOnFPSDrop: true` hands capping to hls.js. |
|
|
254
255
|
| `snapToLiveOnRefocus` | `boolean` | `true` | Snap to the live edge when a backgrounded tab is refocused: on hls.js while far behind; on the native player (iPhone, iPad, FairPlay) on every return after 2 s or more away and on every back/forward‑cache restore, 3 s behind the edge once the first playlist refresh after the return moves it (up to 6 s wait; the edge on return is still the one from before leaving), which also redraws a picture iOS left black. Live/LL only. |
|
|
255
256
|
| `rememberBandwidth` | `boolean` | `true` | hls.js engine: start from the bandwidth this device measured in a recent session (`localStorage` key `havik.player.bandwidth`, per connection type, up to 3 days old, reused at 80%) instead of the conservative ~1 Mbps start; a slow record starts from that lower figure (0.3 Mbps floor). A first visit, a stale record or blocked storage keeps the conservative start; an explicit `hlsConfig.abrEwmaDefaultEstimate` or `startLevel` wins. Reset with [`clearRememberedBandwidth()`](#clearrememberedbandwidth). |
|
|
256
257
|
| `sizeCapHeadroom` | `number` | unset | hls.js engine: rendition rungs ABR may pick above the one that merely covers the player's pixel box. Unset: `1` on displays below 2× `devicePixelRatio`, **earned per session on LL-HLS** (its parts download within half a part duration even at that rung's bitrate, the bandwidth estimate is twice the rung and stays above 1.5×, and no stall in the last 2 minutes; a stall after the first 10 s of playback drops the rung at once; streams without parts get the rung as before), `0` at 2× and above. A 960 px box at 1x covers with 960×540; one rung of headroom plays 720p downscaled instead, which looks sharper for the same box; phones and 2× screens keep the cover-only cap (their covering rung already matches their device pixels; a rung above it mostly costs data). An explicit value applies on every display: `0` = strict cover-only cap, `Infinity` = no size cap. Never past the top rung; `maxBitrate` and the frame-drop cap still apply. `hlsConfig.capLevelToPlayerSize: true` caps to the covering rung with no headroom. |
|
|
@@ -348,6 +349,14 @@ can't crash the player: if you pass the count‑based `liveSyncDurationCount` /
|
|
|
348
349
|
rejects mixing the two); if you set `liveSyncDuration` alone, a matching ceiling
|
|
349
350
|
is derived above it.
|
|
350
351
|
|
|
352
|
+
- **Quality steps down after a stall, and comes back slowly.** A playback
|
|
353
|
+
stall (not in the first 10 s after playback starts or resumes, not during a
|
|
354
|
+
seek, not with media still buffered ahead, not a wait at the live edge for a
|
|
355
|
+
part not yet published) caps ABR one rendition below the
|
|
356
|
+
one that stalled; each further 3 minutes of playback without a stall gives
|
|
357
|
+
one rendition back. ABR otherwise climbs straight back to the
|
|
358
|
+
rendition that just failed, which on slow connections is most of the
|
|
359
|
+
rebuffering. Counted in `stallDownCaps`; `stallCap: false` turns it off.
|
|
351
360
|
- **Quality steps down when the device can't decode it.** If the browser keeps
|
|
352
361
|
dropping more than 20% of frames for two 3 s checks in a row, the SDK caps
|
|
353
362
|
ABR one rendition below the one playing (counted in `fpsDownCaps`). The two
|
|
@@ -1454,7 +1463,8 @@ interface PlaybackStats {
|
|
|
1454
1463
|
holdBackSteps?: number; // times the adaptive hold-back moved the live target, up or down (hls.js engine)
|
|
1455
1464
|
fpsDownCaps?: number; // times quality was capped because the device dropped frames (hls.js engine)
|
|
1456
1465
|
maxLevelHeight?: number; // highest rendition ABR may pick right now; absent when uncapped (hls.js engine)
|
|
1457
|
-
|
|
1466
|
+
stallDownCaps?: number; // times a playback stall stepped the quality ceiling down (hls.js engine)
|
|
1467
|
+
capReason?: 'size' | 'bitrate' | 'fps' | 'stall'; // which SDK cap set maxLevelHeight: player pixel box, maxBitrate, frame drops, recent stall
|
|
1458
1468
|
}
|
|
1459
1469
|
```
|
|
1460
1470
|
|
package/embed/index.html
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
beacons endpoint can be derived and QoE analytics is silently off.
|
|
29
29
|
`analytics` is honoured from the injected config only, never the query.
|
|
30
30
|
-->
|
|
31
|
-
<script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.
|
|
31
|
+
<script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.27.0/dist/havik-player.global.js" integrity="sha384-aQyHrT52eFKTpv4ZcXX72CQTB7Fi5vVjMlJnVQI32AazRYtxQBSySuBgn26bQ0+M" crossorigin="anonymous"></script>
|
|
32
32
|
<script>
|
|
33
33
|
HavikPlayer.bootEmbed();
|
|
34
34
|
</script>
|
package/examples/vanilla.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
shipped in each npm release is pinned to that release with Subresource
|
|
13
13
|
Integrity, injected at publish time (scripts/inject-sri.mjs). In
|
|
14
14
|
production, always use a pinned + SRI'd tag like the released copy. -->
|
|
15
|
-
<script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.
|
|
15
|
+
<script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.27.0/dist/havik-player.global.js" integrity="sha384-aQyHrT52eFKTpv4ZcXX72CQTB7Fi5vVjMlJnVQI32AazRYtxQBSySuBgn26bQ0+M" crossorigin="anonymous"></script>
|
|
16
16
|
<script>
|
|
17
17
|
(async () => {
|
|
18
18
|
const player = await HavikPlayer.createPlayer({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oddin-gg/havik-player",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.27.0",
|
|
4
4
|
"description": "Havik HTML5 player SDK — LL-HLS + DRM playback for Oddin live streams (managed, bring-your-own-player, and iframe-embed modes).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|