@oddin-gg/havik-player 2.17.0 → 2.18.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/docs/API.md CHANGED
@@ -249,6 +249,7 @@ player.on('error', (e) => console.error(e.code, e.httpStatus, e.message));
249
249
  | `maxBitrate` | `number` | — | Cap ABR to renditions at/below this bitrate (bps). |
250
250
  | `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. |
251
251
  | `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. |
252
+ | `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). |
252
253
  | `mediaDuringKey` | `boolean` | `true` | DRM cold start: download the first init segment and parts while the first key is still being acquired, instead of after it. Bytes reach hls.js only when it asks for them; only the network time moves off the critical path (~0.5 s on Widevine LL-HLS). Ignored on clear streams and when `hlsConfig.fLoader` is set. Pass `false` to opt out. |
253
254
  | `liveStateEvents` | `boolean` | `true` | Use the push-based **live-state SSE** channel for go-live and end-of-stream (see [Live state](#live-state-sse)). Graceful: falls back to polling if the endpoint is unreachable. On a return from the background (5 s or more away, or a back/forward-cache restore) the subscription is reopened so the server replays the current state: a page suspended through the end of a match does not sit buffering on a socket that will never deliver it. Set `false` to disable. |
254
255
  | `rejoinOnLive` | `boolean` | `true` | Rejoin automatically when a stream that ended comes back live. An ingest outage longer than the bridge's reconnect grace recreates the session under a **new manifest URL** (the old playlist freezes at HTTP 200), so the player keeps the live-state subscription open after `ended` (until `gone`) and re-arms on a pushed `live`. Set `false` to keep `ended` terminal. Needs `liveStateEvents`. |
@@ -305,7 +306,14 @@ don't need to set any of the live or ABR knobs:
305
306
  rendition is one a modest link can sustain (**~360p**) and then **ramps up**
306
307
  within a few seconds as measured bandwidth allows, rather than grabbing a high
307
308
  rung and rebuffering on a constrained link. This trades a slightly softer first
308
- ~2 s for a **stall‑free start** (the first‑seconds buffering fix). In addition,
309
+ ~2 s for a **stall‑free start** (the first‑seconds buffering fix). A device
310
+ that has **measured a fast line in the last 3 days** starts from that
311
+ measurement instead (`rememberBandwidth`, on by default: the estimate after
312
+ ~10 s of playback, stored per connection type and reused at 80%), so a
313
+ returning viewer on a fast line starts near full quality without a 360p jump,
314
+ and a device that measured a slow line starts from that lower figure (also at
315
+ 80%, never below 0.3 Mbps). A first visit or a device with no usable record
316
+ keeps the ~1 Mbps start. In addition,
309
317
  the session is bounded to the player's pixel box, so a small/embedded player
310
318
  won't fetch 1080p, but by an SDK‑managed, **debounced** size cap rather than
311
319
  hls.js's own `capLevelToPlayerSize` poller: a size change only reaches ABR
@@ -769,6 +777,18 @@ function clearDeviceId(): void;
769
777
  > under GDPR/ePrivacy). Disclose it in your privacy policy and offer a reset:
770
778
  > `clearDeviceId()` removes the stored id so the next call generates a fresh one.
771
779
 
780
+ ### `clearRememberedBandwidth`
781
+
782
+ ```ts
783
+ function clearRememberedBandwidth(): void;
784
+ ```
785
+
786
+ Forgets the bandwidth the player remembered for this device (the
787
+ `rememberBandwidth` option, `localStorage` key `havik.player.bandwidth`). The next
788
+ session starts from the conservative ~1 Mbps estimate again. The record holds
789
+ only an estimated speed and a timestamp per connection type; offer it beside
790
+ `clearDeviceId()` in a "reset player data" control.
791
+
772
792
  ### `fetchCatalog`
773
793
 
774
794
  ```ts
package/docs/STABILITY.md CHANGED
@@ -13,7 +13,7 @@ breaking change → major. **Pin a version in production** (npm and the CDN URL)
13
13
 
14
14
  - `createPlayer` + the `Player` interface (Mode A)
15
15
  - `resolveStream`, `fetchCatalog`, `flattenMatches`, `watchStatus`,
16
- `licenseRequestHeaders`, `getDeviceId`, `clearDeviceId`, `isLowLatencyManifest` (Mode B)
16
+ `licenseRequestHeaders`, `getDeviceId`, `clearDeviceId`, `clearRememberedBandwidth`, `isLowLatencyManifest` (Mode B)
17
17
  - `mountEmbed` / `bootEmbed` + `EmbedHandle` / the `oddin:*` postMessage protocol (Mode C)
18
18
  - `PlaybackError` and all exported `type` definitions
19
19
 
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.17.0/dist/havik-player.global.js" integrity="sha384-iRLq+VhRDTaRt6z5NvY8V9X979b3eHBEZCYTwi4+6ycDHiaZvYLH0B02LhDJ7DoL" crossorigin="anonymous"></script>
31
+ <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.18.0/dist/havik-player.global.js" integrity="sha384-bna/v7G8EjUwpvfY3vAwrzvlkh2RO3sMM8ccsC/A0LO1gYZyIluCR/6t5Mj8Qmmj" crossorigin="anonymous"></script>
32
32
  <script>
33
33
  HavikPlayer.bootEmbed();
34
34
  </script>
@@ -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.17.0/dist/havik-player.global.js" integrity="sha384-iRLq+VhRDTaRt6z5NvY8V9X979b3eHBEZCYTwi4+6ycDHiaZvYLH0B02LhDJ7DoL" crossorigin="anonymous"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.18.0/dist/havik-player.global.js" integrity="sha384-bna/v7G8EjUwpvfY3vAwrzvlkh2RO3sMM8ccsC/A0LO1gYZyIluCR/6t5Mj8Qmmj" 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.17.0",
3
+ "version": "2.18.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,