@oddin-gg/havik-player 2.15.0 → 2.15.2

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
@@ -246,7 +246,7 @@ player.on('error', (e) => console.error(e.code, e.httpStatus, e.message));
246
246
  | `poster` | `string` | — | Poster image shown before playback starts. |
247
247
  | `startLevel` | `number` | `-1` | Initial rendition index (`-1` = auto). With auto, ABR starts on a conservative, sustainable rendition (~360p) and ramps up as bandwidth allows; see [Low‑latency & adaptive bitrate](#low-latency--adaptive-bitrate). |
248
248
  | `maxBitrate` | `number` | — | Cap ABR to renditions at/below this bitrate (bps). |
249
- | `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.5×, so this is the only live‑latency knob you need. Lower = closer to live but more rebuffer‑prone. Live/LL only. |
249
+ | `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. |
250
250
  | `snapToLiveOnRefocus` | `boolean` | `true` | Snap to the live edge when a backgrounded tab is refocused while far behind. Live/LL only. |
251
251
  | `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. |
252
252
  | `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. Set `false` to disable. |
@@ -265,7 +265,9 @@ don't need to set any of the live or ABR knobs:
265
265
  aren't reliably published yet; chasing that edge causes constant rebuffering.
266
266
  Set `liveLatencyTarget` lower for closer‑to‑live (more rebuffer‑prone) or
267
267
  higher for steadier playback. _Lowered from 3 s; see the migration note below._
268
- - **Drift ceiling**: after a stall, the player catches up at up to **1.5×** and,
268
+ - **Drift ceiling**: after a stall, the player catches up at up to **1.1×** (gentle
269
+ enough to be invisible; it was 1.5×, which showed as the picture speeding up
270
+ between stalls on a jittery edge) and,
269
271
  as a backstop, force‑seeks back toward the target once latency exceeds an
270
272
  internal **ceiling (~12 s, derived as `max(12, liveLatencyTarget + 9)`)**. This is what
271
273
  stops latency from snowballing to tens of seconds after buffering. The ceiling
@@ -313,6 +315,17 @@ can't crash the player: if you pass the count‑based `liveSyncDurationCount` /
313
315
  rejects mixing the two); if you set `liveSyncDuration` alone, a matching ceiling
314
316
  is derived above it.
315
317
 
318
+ - **Futile catch‑up is stopped.** hls.js speeds playback up (to 1.1×) whenever
319
+ latency sits above the target, and only lowers its ambition after a counted
320
+ rebuffer. On an edge that is itself seconds behind, a player that keeps a
321
+ deeper buffer (Safari) can chase at full rate for a whole session without ever
322
+ gaining a second, which viewers see as constant stutter. The SDK watches the
323
+ chase on its 3 s tick: a chase at the full 1.1× that gains under 0.5 s of latency
324
+ over the next three ticks (12 s in all) moves the target up to where playback
325
+ actually is (never closer than 1 s to the drift ceiling), and the rate drops
326
+ back to 1.0×. One‑way for the session; `targetLatencySeconds` reflects the
327
+ move and `liveRetargets` counts them. A rate the host sets itself is ignored.
328
+
316
329
  > **Migration note:** the default `liveLatencyTarget` **dropped from 3 s to 2 s**.
317
330
  > Nothing to change: the drift ceiling stays 12 s and the ABR reaction budgets
318
331
  > are derived from the target, so they tighten with it automatically. Expect
@@ -320,7 +333,7 @@ is derived above it.
320
333
  > `liveLatencyTarget: 3` explicitly.
321
334
 
322
335
  > **Migration note:** `liveCatchUpRate` was **removed** as a public option; the
323
- > catch‑up rate (1.5×) is now managed internally alongside the drift ceiling. If
336
+ > catch‑up rate (1.1×) is now managed internally alongside the drift ceiling. If
324
337
  > you set it before, drop it; reach for `hlsConfig.maxLiveSyncPlaybackRate` only
325
338
  > if you genuinely need to override the rate.
326
339
 
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.15.0/dist/havik-player.global.js" integrity="sha384-rjpWbfgvCFYqBjKvo1svn8xWY0IWY1Go5D76lXwkSIPGJl1mFeAr/8FAYV76b/v2" crossorigin="anonymous"></script>
31
+ <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.15.2/dist/havik-player.global.js" integrity="sha384-UOJXsjWTIgS9qCPAU4ddwav3Zexd4ElTzFYqOjlLrfn5HpQICTW9mvtdSu+5eAKr" 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.15.0/dist/havik-player.global.js" integrity="sha384-rjpWbfgvCFYqBjKvo1svn8xWY0IWY1Go5D76lXwkSIPGJl1mFeAr/8FAYV76b/v2" crossorigin="anonymous"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/@oddin-gg/havik-player@2.15.2/dist/havik-player.global.js" integrity="sha384-UOJXsjWTIgS9qCPAU4ddwav3Zexd4ElTzFYqOjlLrfn5HpQICTW9mvtdSu+5eAKr" 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.15.0",
3
+ "version": "2.15.2",
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,