@gumlet/insights-js-core 1.1.62 → 2.0.1

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/README.md CHANGED
@@ -1,30 +1,332 @@
1
- # Gumlet Analytics Collector
1
+ # @gumlet/insights-js-core
2
2
 
3
- ## Prerequisites
3
+ Browser-side video analytics SDK for [Gumlet Insights](https://docs.gumlet.com/docs/insights-getting-started). Collects playback lifecycle events — startup, play, pause, seek, rebuffering, quality change, error, end — and sends them to the Gumlet ingest API.
4
4
 
5
- * Node >= 8.x
6
- * Yarn package manager: https://yarnpkg.com
5
+ Supports **HTML5**, **HLS.js**, and **Shaka Player**.
7
6
 
8
- NOTE: `npm` will also work with the same scripts added the `run ...` command.
7
+ ---
9
8
 
10
- ## Setup
9
+ ## Requirements
11
10
 
11
+ - Node.js ≥ 20.x
12
+ - One of the three supported players loaded in the page before this SDK
13
+
14
+ ---
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @gumlet/insights-js-core
20
+ ```
21
+
22
+ Or load the pre-built IIFE bundle directly in a `<script>` tag (sets `window.gumlet.GumletInsights`):
23
+
24
+ ```html
25
+ <script src="dist/main.iife.js"></script>
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Quick start
31
+
32
+ ### ESM / npm
33
+
34
+ ```js
35
+ import { GumletInsights } from '@gumlet/insights-js-core';
36
+
37
+ const insights = new GumletInsights({ property_id: 'YOUR_PROPERTY_ID' });
38
+
39
+ // HTML5 native video element — pass the element directly
40
+ await insights.attach(document.querySelector('video'));
41
+
42
+ // HLS.js — pass the Hls instance (media element auto-detected from hls.media)
43
+ await insights.attach(hls);
44
+
45
+ // Shaka Player — mediaElement is required
46
+ await insights.attach(player, { mediaElement: videoEl });
47
+ ```
48
+
49
+ ### CDN / IIFE
50
+
51
+ ```html
52
+ <script src="dist/main.iife.js"></script>
53
+ <script type="module">
54
+ const insights = new gumlet.GumletInsights({ property_id: 'YOUR_PROPERTY_ID' });
55
+ await insights.attach(player, { mediaElement: videoEl });
56
+ </script>
57
+ ```
58
+
59
+ ---
60
+
61
+ ## API reference
62
+
63
+ ### `new GumletInsights(config)`
64
+
65
+ Creates the analytics instance. If `property_id` is missing or empty, a `console.error` is logged and the SDK is disabled — all subsequent calls become no-ops.
66
+
67
+ ### `insights.attach(player?, opts?)`
68
+
69
+ Connects the SDK to a player. Runs all [validation checks](#validation) before attaching.
70
+
71
+ | `player` value | Behaviour |
72
+ |---|---|
73
+ | `Hls` instance | HLS.js adapter |
74
+ | `shaka.Player` instance | Shaka adapter — `opts.mediaElement` required |
75
+ | `HTMLVideoElement` | HTML5 adapter |
76
+ | `null` / `undefined` | HTML5 adapter — `opts.mediaElement` required |
77
+
78
+ **`opts`:**
79
+
80
+ | Option | Type | Description |
81
+ |--------|------|-------------|
82
+ | `mediaElement` | `HTMLVideoElement` | The `<video>` element. Required for Shaka; recommended for HLS.js. |
83
+ | `starttime` | `number` | Unix epoch ms marking the session start. Defaults to `Date.now()`. |
84
+
85
+ Calling `attach()` while already attached logs a warning and detaches the previous player first.
86
+
87
+ ### `insights.detach()`
88
+
89
+ Removes all event listeners and disconnects from the player. Safe to call when nothing is attached.
90
+
91
+ ### `insights.isAttached`
92
+
93
+ `boolean` — `true` after a successful `attach()`, `false` after `detach()` or a failed attach.
94
+
95
+ ### `insights.getImpressionId()`
96
+
97
+ Returns the current impression ID string, or `undefined` if the SDK failed to initialize.
98
+
99
+ ### `insights.updateConfig(partial)`
100
+
101
+ Merges a partial config into the running session — updates custom data slots, video metadata, user metadata, and player metadata simultaneously.
102
+
103
+ ```js
104
+ insights.updateConfig({
105
+ custom_data_1: 'experiment-a',
106
+ customVideoTitle: 'Episode 3',
107
+ });
108
+ ```
109
+
110
+ ### Individual update helpers
111
+
112
+ ```js
113
+ insights.updateCustomData({ custom_data_1: 'value' });
114
+ insights.updateCustomVideoData({ customVideoTitle: 'Episode 2' });
115
+ insights.updateCustomUserData({ userName: 'alice' });
116
+ insights.updateCustomPlayerData({ customPlayerName: 'shaka-v4' });
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Validation
122
+
123
+ `attach()` checks the player and options before connecting. On failure it logs a `[GumletInsights]`-prefixed `console.error` and returns without sending any events.
124
+
125
+ | Scenario | Error message |
126
+ |---|---|
127
+ | SDK not initialized (`property_id` empty/missing) | `attach() called but the SDK is not initialized. Check that you passed a valid property_id` |
128
+ | `null` / `undefined` with no `mediaElement` | `HTML5 mode requires opts.mediaElement (an HTMLVideoElement)` |
129
+ | `opts.mediaElement` is not an `HTMLVideoElement` | `opts.mediaElement must be an HTMLVideoElement, got: [object …]` |
130
+ | Unrecognized player type | `Unrecognized player type (…). Supported: HLS.js, Shaka Player, HTMLVideoElement…` |
131
+ | HLS.js player missing core API (likely destroyed) | `HLS.js player is not in a valid state. The player may have been destroyed.` |
132
+ | Shaka without resolvable video element | `Shaka Player requires opts.mediaElement — the HTMLVideoElement Shaka is playing into` |
133
+ | Shaka player with `isDestroyed() === true` | `Shaka Player is not in a valid state. The player may have been destroyed.` |
134
+ | Already attached (not an error — just a warning) | `attach() called while a player is already attached. Detaching previous player first.` |
135
+
136
+ ---
137
+
138
+ ## Configuration
139
+
140
+ All options are passed to the `GumletInsights` constructor:
141
+
142
+ | Key | Type | Required | Description |
143
+ |-----|------|----------|-------------|
144
+ | `property_id` | `string` | **Yes** | Gumlet Insights property ID |
145
+ | `debug` | `boolean` | No | Enable verbose console logging |
146
+ | `test` | `boolean` | No | Use a test user/session ID (events flagged, not counted in production) |
147
+ | `page_url` | `string` | No | Override the detected page URL (useful in iframes / SSR) |
148
+ | `sessionID` | `string` | No | Override the auto-generated session ID |
149
+ | `userID` | `string` | No | Override the auto-generated user ID |
150
+ | `sendSessionRequest` | `boolean` | No | Set to `false` to skip the session-init HTTP call (default `true`) |
151
+ | `getUUID` | `() => string` | No | Custom UUID generator for event and playback IDs |
152
+ | `customData1` … `customData10` | `string` | No | Arbitrary metadata attached to every event |
153
+ | `customVideoId` | `string` | No | Override video ID (auto-detected from `video.gumlet.io` URLs) |
154
+ | `customVideoTitle` | `string` | No | Video title |
155
+ | `customVideoDurationMillis` | `string` | No | Override video duration |
156
+ | `customVideoSeries` | `string` | No | Series/playlist name |
157
+ | `customVideoProducer` | `string` | No | Producer / uploader name |
158
+ | `customVideoLanguage` | `string` | No | Video language |
159
+ | `customVideoVariantName` | `string` | No | A/B variant label |
160
+ | `customVideoVariant` | `string` | No | A/B variant value |
161
+ | `customContentType` | `string` | No | Content category (e.g. `"live"`, `"vod"`) |
162
+ | `customEncodingVariant` | `string` | No | Encoding profile label |
163
+ | `userName` / `userEMail` / `userCity` / … | `string` | No | User identity metadata |
164
+ | `customPlayerName` / `customPageType` / `experimentName` | `string` | No | Player / experiment metadata |
165
+
166
+ ---
167
+
168
+ ## Analytics events emitted
169
+
170
+ | Wire event | Trigger |
171
+ |------------|---------|
172
+ | `event_setup` | SDK initialised |
173
+ | `event_player_ready` | Player reported ready |
174
+ | `event_playback_ready` | Source loaded |
175
+ | `event_play` | User pressed play (first play or resume) |
176
+ | `event_playing` | First frame rendered / resumed after pause or seek |
177
+ | `event_playback_started` | Startup latency measurement point |
178
+ | `event_pause` | Playback paused |
179
+ | `event_rebuffer_start` | Stall / buffering begun |
180
+ | `event_rebuffer_end` | Buffering recovered |
181
+ | `event_seeked` | Seek completed |
182
+ | `event_playback_update` | Heartbeat every ~10 seconds of watch time |
183
+ | `event_error` | Fatal **or** non-fatal player error (always sent) |
184
+ | `event_error_recovered` | Player resumed after a **fatal** error only |
185
+ | `event_ended` | Video played to completion |
186
+ | `event_mute` / `event_unmute` | Mute state changed |
187
+
188
+ ### Error severity (Shaka Player)
189
+
190
+ `event_error` fires for all Shaka errors regardless of severity. The state machine handles them differently:
191
+
192
+ | Severity | Value | State machine effect |
193
+ |----------|-------|----------------------|
194
+ | `RECOVERABLE` | 1 | Self-transition — state unchanged, `event_error_recovered` **never** fires |
195
+ | `CRITICAL` | 2 | Transitions to `ERROR` state; `event_error_recovered` fires if playback resumes |
196
+
197
+ ---
198
+
199
+ ## Development
200
+
201
+ ### Install dependencies
202
+
203
+ ```bash
204
+ npm install
12
205
  ```
13
- yarn install
206
+
207
+ ### Start dev server
208
+
209
+ ```bash
210
+ npm start
211
+ ```
212
+
213
+ Runs the TypeScript build in watch mode and serves the demo pages at <http://localhost:8080>. Opens `html/hlsjs.html` automatically. Navigate between players using the header on any demo page:
214
+
215
+ | URL | Player |
216
+ |-----|--------|
217
+ | `/html/html5.html` | Native `<video>` element |
218
+ | `/html/hlsjs.html` | HLS.js |
219
+ | `/html/shaka.html` | Shaka Player — includes fatal and non-fatal error triggers |
220
+
221
+ Each page includes a live event log (clock timestamp · event family · event name · previous event · playback time). Click any row to inspect the full payload.
222
+
223
+ ### Build
224
+
225
+ ```bash
226
+ npm run build:release # production bundle → dist/
227
+ npm run build:debug # watch mode
14
228
  ```
15
229
 
16
- ## Build scripts
230
+ Output files:
231
+
232
+ | File | Format | Use |
233
+ |------|--------|-----|
234
+ | `dist/main.mjs` | ESM | npm / bundlers |
235
+ | `dist/main.iife.js` | IIFE | CDN `<script>` tag |
236
+ | `dist/main.cjs` | CJS | CommonJS |
17
237
 
238
+ ### Test
239
+
240
+ ```bash
241
+ npm test
18
242
  ```
19
- yarn build:debug
243
+
244
+ 149 tests across 12 test files:
245
+
246
+ | Suite | Coverage |
247
+ |-------|----------|
248
+ | `SessionManager` | Identity, custom data, session expiry |
249
+ | `SampleBuilder` | Payload assembly, `playback_time_instant_millis` |
250
+ | `EventPublisher` | Duration guard, 24-hour live-stream guard |
251
+ | `GumletStateMachine` | Full lifecycle, rebuffering, error recovery, non-fatal errors, seek-while-paused, quality-change self-transitions |
252
+ | `HTML5Adapter` | DOM event → analytics event mapping, `destroy()` |
253
+ | `HlsjsAdapter` | Quality level extraction, error forwarding |
254
+ | `ShakaAdapter` | MIME type detection, variant track parsing, error pipeline |
255
+ | `GumletInsights` | All `attach()` validation paths, double-attach, detach, impression ID |
256
+ | Heartbeat timer | Regression tests for quality-change and mute resetting the window |
257
+
258
+ ### Lint
259
+
260
+ ```bash
261
+ npm run lint # check
262
+ npm run lint:fix # auto-fix
20
263
  ```
21
264
 
265
+ ---
266
+
267
+ ## Architecture
268
+
22
269
  ```
23
- yarn build:release
270
+ GumletInsights (public API — attach/detach/validate)
271
+ └── Analytics (orchestrator)
272
+ ├── SessionManager — identity (userId, sessionId, playbackId), custom metadata
273
+ ├── SampleBuilder — playback-state fields, payload assembly (getSample)
274
+ ├── EventPublisher — HTTP dispatch (EventsCall), send-and-clear, unload
275
+ └── GumletStateMachine — jsm v3 FSM: SETUP → READY → STARTUP → PLAYING → … → END/ERROR
276
+ ├── HTML5Adapter — native HTMLVideoElement events (abstract base)
277
+ ├── HlsjsAdapter — extends HTML5Adapter; hooks Hls.js engine events
278
+ └── ShakaAdapter — extends HTML5Adapter; hooks Shaka 'error' event
24
279
  ```
25
280
 
26
- ## Dev mode
281
+ ### Key design decisions
282
+
283
+ - **`GumletInsights` wraps `Analytics`** — Validation, lifecycle management (`attach`/`detach`), and the public API surface live in `GumletInsights`. `Analytics` and its adapters are internal implementation detail.
284
+ - **Single state machine for all players** — `GumletStateMachine` (jsm v3) is shared across all three adapters. Player-specific behaviour lives entirely in the adapter layer.
285
+ - **`lastKnownCurrentTime_`** — `video.currentTime` resets to `0` when a player replaces its `MediaSource` — before error and pause events fire. Adapters cache the last non-zero value from `timeupdate` events and use that for error timestamps instead.
286
+ - **`sourceSwitching_` flag** — A `MediaSource` replacement causes the browser to fire `emptied → pause → playing` — none of which are user actions. The flag (set on `emptied`, cleared only when `timeupdate` fires with `currentTime > 0`) suppresses spurious pause and playing analytics events during the switch.
287
+ - **Heartbeat isolation** — `heartbeatTimestamp` is independent of `onEnterStateTimestamp`. Quality-change and mute self-transitions reset `onEnterStateTimestamp` (for state-duration maths) but must never reset the 10-second heartbeat window.
288
+ - **Non-fatal vs fatal errors** — Shaka `RECOVERABLE` (severity 1) errors use a `playerNonFatalError` self-transition: `event_error` is still sent, but the state machine stays in its current state so `event_error_recovered` can never fire spuriously.
289
+
290
+ ---
291
+
292
+ ## Project structure
27
293
 
28
294
  ```
29
- yarn start // run webpack-dev-server
295
+ src/
296
+ core/ — GumletInsights (public API), Analytics, SessionManager,
297
+ SampleBuilder, EventPublisher, GumletInsightsExport (CDN entry)
298
+ adapters/ — HTML5Adapter (base), HlsjsAdapter, ShakaAdapter
299
+ stateMachine/ — GumletStateMachine (jsm v3)
300
+ cast/ — CastClient, CastReceiver (implemented; wiring pending — see TODO.md)
301
+ enums/ — Events, GumletEnum (wire names), MIMETypes, Players, StreamTypes
302
+ types/ — AnalyticsConfig, SamplePayload, IAdapter, IStateMachine, ambient .d.ts
303
+ utils/ — Logger, Utils, Settings, PlayerDetector, DetectDevice, …
304
+ html/ — manual test pages (html5, hlsjs, shaka) + event-logger.js
305
+ tests/ — unit tests (phase1 … phase5 + stage1 regression)
306
+ dist/ — built output (main.mjs, main.iife.js, main.cjs)
307
+ CHANGELOG.md — full technical history for agents and developers
308
+ TODO.md — known issues and pending work
309
+ V2_REVAMP_PLAN.md — 8-phase revamp plan (read-only reference)
30
310
  ```
311
+
312
+ ---
313
+
314
+ ## Legacy API
315
+
316
+ The pre-v2 `gumlet.insights(config).registerXxxPlayer(...)` API is still available for CDN users and will not be removed:
317
+
318
+ ```js
319
+ // Still works — backward compatible
320
+ const analytics = gumlet.insights({ property_id: 'YOUR_ID' });
321
+ analytics.registerShakaPlayer(player, { mediaElement: video });
322
+ analytics.registerHLSJSPlayer(hls);
323
+ analytics.registerHTML5Player(video);
324
+ ```
325
+
326
+ New integrations should use `GumletInsights` instead.
327
+
328
+ ---
329
+
330
+ ## License
331
+
332
+ MIT © Gumlet Pte. Ltd.
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ const e={READY:`ready`,STARTUP:`startup`,SOURCE_LOADED:`sourceLoaded`,PLAY:`play`,PAUSE:`pause`,TIMECHANGED:`timechanged`,SEEK:`seek`,SEEKED:`seeked`,START_CAST:`startCasting`,END_CAST:`endCasting`,START_BUFFERING:`startBuffering`,END_BUFFERING:`endBuffering`,AUDIO_CHANGE:`audioChange`,VIDEO_CHANGE:`videoChange`,START_FULLSCREEN:`startFullscreen`,END_FULLSCREEN:`endFullscreen`,START_AD:`adStart`,END_AD:`adEnd`,MUTE:`mute`,UN_MUTE:`unMute`,ERROR:`playerError`,NON_FATAL_ERROR:`playerNonFatalError`,PLAYBACK_FINISHED:`end`,SCREEN_RESIZE:`resize`,UNLOAD:`unload`,END:`end`,METADATA_LOADED:`metadataLoaded`,SOURCE_UNLOADED:`sourceUnloaded`,PLAYBACK_PLAYING:`playback_playing`};export{e as t};
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ import{t as e}from"./Logger-C-OVMkpG.mjs";import{t}from"./Events-DB36UnQj.mjs";var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),l=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e},u=((e,t,i)=>(i=e==null?{}:n(o(e)),l(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e)))(c(((e,t)=>{(function(n,r){typeof e==`object`&&typeof t==`object`?t.exports=r():typeof define==`function`&&define.amd?define(`StateMachine`,[],r):typeof e==`object`?e.StateMachine=r():n.StateMachine=r()})(e,function(){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=5)})([(function(e,t,n){e.exports=function(e,t){var n,r,i;for(n=1;n<arguments.length;n++)for(i in r=arguments[n],r)r.hasOwnProperty(i)&&(e[i]=r[i]);return e}}),(function(e,t,n){var r=n(0);e.exports={build:function(e,t){var n,i,a,o=t.plugins;for(n=0,i=o.length;n<i;n++)a=o[n],a.methods&&r(e,a.methods),a.properties&&Object.defineProperties(e,a.properties)},hook:function(e,t,n){var r,i,a,o,s=e.config.plugins,c=[e.context];for(n&&(c=c.concat(n)),r=0,i=s.length;r<i;r++)o=s[r],a=s[r][t],a&&a.apply(o,c)}}}),(function(e,t,n){function r(e){if(e.length===0)return e;var t,n,r=e.split(/[_-]/);if(r.length===1&&r[0][0].toLowerCase()===r[0][0])return e;for(n=r[0].toLowerCase(),t=1;t<r.length;t++)n=n+r[t].charAt(0).toUpperCase()+r[t].substring(1).toLowerCase();return n}r.prepended=function(e,t){return t=r(t),e+t[0].toUpperCase()+t.substring(1)},e.exports=r}),(function(e,t,n){var r=n(0),i=n(2);function a(e,t){e||={},this.options=e,this.defaults=t.defaults,this.states=[],this.transitions=[],this.map={},this.lifecycle=this.configureLifecycle(),this.init=this.configureInitTransition(e.init),this.data=this.configureData(e.data),this.methods=this.configureMethods(e.methods),this.map[this.defaults.wildcard]={},this.configureTransitions(e.transitions||[]),this.plugins=this.configurePlugins(e.plugins,t.plugin)}r(a.prototype,{addState:function(e){this.map[e]||(this.states.push(e),this.addStateLifecycleNames(e),this.map[e]={})},addStateLifecycleNames:function(e){this.lifecycle.onEnter[e]=i.prepended(`onEnter`,e),this.lifecycle.onLeave[e]=i.prepended(`onLeave`,e),this.lifecycle.on[e]=i.prepended(`on`,e)},addTransition:function(e){this.transitions.indexOf(e)<0&&(this.transitions.push(e),this.addTransitionLifecycleNames(e))},addTransitionLifecycleNames:function(e){this.lifecycle.onBefore[e]=i.prepended(`onBefore`,e),this.lifecycle.onAfter[e]=i.prepended(`onAfter`,e),this.lifecycle.on[e]=i.prepended(`on`,e)},mapTransition:function(e){var t=e.name,n=e.from,r=e.to;return this.addState(n),typeof r!=`function`&&this.addState(r),this.addTransition(t),this.map[n][t]=e,e},configureLifecycle:function(){return{onBefore:{transition:`onBeforeTransition`},onAfter:{transition:`onAfterTransition`},onEnter:{state:`onEnterState`},onLeave:{state:`onLeaveState`},on:{transition:`onTransition`}}},configureInitTransition:function(e){return typeof e==`string`?this.mapTransition(r({},this.defaults.init,{to:e,active:!0})):typeof e==`object`?this.mapTransition(r({},this.defaults.init,e,{active:!0})):(this.addState(this.defaults.init.from),this.defaults.init)},configureData:function(e){return typeof e==`function`?e:typeof e==`object`?function(){return e}:function(){return{}}},configureMethods:function(e){return e||{}},configurePlugins:function(e,t){e||=[];var n,r,i;for(n=0,r=e.length;n<r;n++)i=e[n],typeof i==`function`&&(e[n]=i=i()),i.configure&&i.configure(this);return e},configureTransitions:function(e){var t,n,r,i,a,o=this.defaults.wildcard;for(n=0;n<e.length;n++)for(r=e[n],i=Array.isArray(r.from)?r.from:[r.from||o],a=r.to||o,t=0;t<i.length;t++)this.mapTransition({name:r.name,from:i[t],to:a})},transitionFor:function(e,t){var n=this.defaults.wildcard;return this.map[e][t]||this.map[n][t]},transitionsFor:function(e){var t=this.defaults.wildcard;return Object.keys(this.map[e]).concat(Object.keys(this.map[t]))},allStates:function(){return this.states},allTransitions:function(){return this.transitions}}),e.exports=a}),(function(e,t,n){var r=n(0),i=n(6),a=n(1),o=[null,[]];function s(e,t){this.context=e,this.config=t,this.state=t.init.from,this.observers=[e]}r(s.prototype,{init:function(e){if(r(this.context,this.config.data.apply(this.context,e)),a.hook(this,`init`),this.config.init.active)return this.fire(this.config.init.name,[])},is:function(e){return Array.isArray(e)?e.indexOf(this.state)>=0:this.state===e},isPending:function(){return this.pending},can:function(e){return!this.isPending()&&!!this.seek(e)},cannot:function(e){return!this.can(e)},allStates:function(){return this.config.allStates()},allTransitions:function(){return this.config.allTransitions()},transitions:function(){return this.config.transitionsFor(this.state)},seek:function(e,t){var n=this.config.defaults.wildcard,r=this.config.transitionFor(this.state,e),i=r&&r.to;return typeof i==`function`?i.apply(this.context,t):i===n?this.state:i},fire:function(e,t){return this.transit(e,this.state,this.seek(e,t),t)},transit:function(e,t,n,r){var i=this.config.lifecycle,a=this.config.options.observeUnchangedState||t!==n;return n?this.isPending()?this.context.onPendingTransition(e,t,n):(this.config.addState(n),this.beginTransit(),r.unshift({transition:e,from:t,to:n,fsm:this.context}),this.observeEvents([this.observersForEvent(i.onBefore.transition),this.observersForEvent(i.onBefore[e]),a?this.observersForEvent(i.onLeave.state):o,a?this.observersForEvent(i.onLeave[t]):o,this.observersForEvent(i.on.transition),a?[`doTransit`,[this]]:o,a?this.observersForEvent(i.onEnter.state):o,a?this.observersForEvent(i.onEnter[n]):o,a?this.observersForEvent(i.on[n]):o,this.observersForEvent(i.onAfter.transition),this.observersForEvent(i.onAfter[e]),this.observersForEvent(i.on[e])],r)):this.context.onInvalidTransition(e,t,n)},beginTransit:function(){this.pending=!0},endTransit:function(e){return this.pending=!1,e},failTransit:function(e){throw this.pending=!1,e},doTransit:function(e){this.state=e.to},observe:function(e){if(e.length===2){var t={};t[e[0]]=e[1],this.observers.push(t)}else this.observers.push(e[0])},observersForEvent:function(e){for(var t=0,n=this.observers.length,r,i=[];t<n;t++)r=this.observers[t],r[e]&&i.push(r);return[e,i,!0]},observeEvents:function(e,t,n,r){if(e.length===0)return this.endTransit(r===void 0?!0:r);var i=e[0][0],o=e[0][1],s=e[0][2];if(t[0].event=i,i&&s&&i!==n&&a.hook(this,`lifecycle`,t),o.length===0)return e.shift(),this.observeEvents(e,t,i,r);var c=o.shift(),l=c[i].apply(c,t);return l&&typeof l.then==`function`?l.then(this.observeEvents.bind(this,e,t,i)).catch(this.failTransit.bind(this)):l===!1?this.endTransit(!1):this.observeEvents(e,t,i,l)},onInvalidTransition:function(e,t,n){throw new i(`transition is invalid in current state`,e,t,n,this.state)},onPendingTransition:function(e,t,n){throw new i(`transition is invalid while previous transition is still in progress`,e,t,n,this.state)}}),e.exports=s}),(function(e,t,n){var r=n(0),i=n(2),a=n(1),o=n(3),s=n(4),c={is:function(e){return this._fsm.is(e)},can:function(e){return this._fsm.can(e)},cannot:function(e){return this._fsm.cannot(e)},observe:function(){return this._fsm.observe(arguments)},transitions:function(){return this._fsm.transitions()},allTransitions:function(){return this._fsm.allTransitions()},allStates:function(){return this._fsm.allStates()},onInvalidTransition:function(e,t,n){return this._fsm.onInvalidTransition(e,t,n)},onPendingTransition:function(e,t,n){return this._fsm.onPendingTransition(e,t,n)}},l={state:{configurable:!1,enumerable:!0,get:function(){return this._fsm.state},set:function(e){throw Error(`use transitions to change state`)}}};function u(e){return f(this||{},e)}function d(){var e,t;typeof arguments[0]==`function`?(e=arguments[0],t=arguments[1]||{}):(e=function(){this._fsm.apply(this,arguments)},t=arguments[0]||{});var n=new o(t,u);return p(e.prototype,n),e.prototype._fsm.config=n,e}function f(e,t){return p(e,new o(t,u)),e._fsm(),e}function p(e,t){if(typeof e!=`object`||Array.isArray(e))throw Error(`StateMachine can only be applied to objects`);a.build(e,t),Object.defineProperties(e,l),r(e,c),r(e,t.methods),t.allTransitions().forEach(function(t){e[i(t)]=function(){return this._fsm.fire(t,[].slice.call(arguments))}}),e._fsm=function(){this._fsm=new s(this,t),this._fsm.init(arguments)}}u.version=`3.0.1`,u.factory=d,u.apply=f,u.defaults={wildcard:`*`,init:{name:`init`,from:`none`}},e.exports=u}),(function(e,t,n){e.exports=function(e,t,n,r,i){this.message=e,this.transition=t,this.from=n,this.to=r,this.current=i}})])})}))(),1),d=class{constructor(e,t={}){this.previousRecordTime=0,this.playbackWatchTime=0,this.lastPlayHeadDuration=0,this.onEnterStateTimestamp=0,this.heartbeatTimestamp=0,this.seekStartedAt=null,this.seekedFrom=0,this.seekedTimestamp=0,this.playTimeStamp=null,this.startupBufferingPending=!1,this.pendingErrorRecovery_=!1,this.States={SETUP:`SETUP`,STARTUP:`STARTUP`,READY:`READY`,PLAYING:`PLAYING`,REBUFFERING:`REBUFFERING`,PAUSE:`PAUSE`,PAUSED_SEEKING:`PAUSED_SEEKING`,END:`END`,ERROR:`ERROR`,CASTING:`CASTING`},this.callbacks=e,this.opts=t,this.createStateMachine()}callEvent(t,n,r){this.fsm.can(t)?this.fsm[t](r,n):e.log(`Ignored Event: ${t}`)}updateMetadata(e){this.callbacks.updateSample(e)}allStates(){return Object.values(this.States)}createStateMachine(){let n=this,r=this.States,i=this.opts,a=[t.PLAY,t.PAUSE,t.SEEK,t.SEEKED,t.PLAYBACK_PLAYING,t.PLAYBACK_FINISHED,t.READY,t.SCREEN_RESIZE,t.END,t.ERROR,t.NON_FATAL_ERROR,t.UN_MUTE,t.MUTE];this.fsm=new u.default({init:r.SETUP,transitions:[{name:t.TIMECHANGED,from:r.SETUP,to:r.SETUP},{name:t.READY,from:[r.SETUP,r.ERROR],to:r.READY},{name:t.SOURCE_LOADED,from:r.SETUP,to:r.SETUP},{name:t.PLAY,from:r.READY,to:r.STARTUP},{name:t.SOURCE_LOADED,from:r.READY,to:r.READY},{name:t.SEEK,from:r.READY,to:r.READY},{name:t.SEEKED,from:r.READY,to:r.READY},{name:t.MUTE,from:r.READY,to:r.READY},{name:t.UN_MUTE,from:r.READY,to:r.READY},{name:t.VIDEO_CHANGE,from:r.READY,to:r.READY},{name:t.AUDIO_CHANGE,from:r.READY,to:r.READY},{name:t.TIMECHANGED,from:r.STARTUP,to:r.PLAYING},{name:t.START_BUFFERING,from:r.STARTUP,to:r.STARTUP},{name:t.END_BUFFERING,from:r.STARTUP,to:r.STARTUP},{name:t.VIDEO_CHANGE,from:r.STARTUP,to:r.STARTUP},{name:t.AUDIO_CHANGE,from:r.STARTUP,to:r.STARTUP},{name:t.SEEK,from:r.STARTUP,to:r.STARTUP},{name:t.SEEKED,from:r.STARTUP,to:r.STARTUP},{name:t.SOURCE_LOADED,from:r.STARTUP,to:r.STARTUP},{name:t.END,from:r.STARTUP,to:r.END},{name:t.TIMECHANGED,from:r.PLAYING,to:r.PLAYING},{name:t.END_BUFFERING,from:r.PLAYING,to:r.PLAYING},{name:t.SEEKED,from:r.PLAYING,to:r.PLAYING},{name:t.SOURCE_LOADED,from:r.PLAYING,to:r.PLAYING},{name:t.VIDEO_CHANGE,from:r.PLAYING,to:r.PLAYING},{name:t.AUDIO_CHANGE,from:r.PLAYING,to:r.PLAYING},{name:t.MUTE,from:r.PLAYING,to:r.PLAYING},{name:t.UN_MUTE,from:r.PLAYING,to:r.PLAYING},{name:t.PAUSE,from:r.PLAYING,to:r.PAUSE},{name:t.START_BUFFERING,from:r.PLAYING,to:r.REBUFFERING},{name:t.END,from:r.PLAYING,to:r.END},{name:t.START_BUFFERING,from:r.REBUFFERING,to:r.REBUFFERING},{name:t.VIDEO_CHANGE,from:r.REBUFFERING,to:r.REBUFFERING},{name:t.AUDIO_CHANGE,from:r.REBUFFERING,to:r.REBUFFERING},{name:t.PLAY,from:r.REBUFFERING,to:r.PLAYING},{name:t.TIMECHANGED,from:r.REBUFFERING,to:r.PLAYING},{name:t.PAUSE,from:r.REBUFFERING,to:r.PAUSE},{name:t.END,from:r.REBUFFERING,to:r.END},{name:t.TIMECHANGED,from:r.PAUSE,to:r.PAUSE},{name:t.SEEKED,from:r.PAUSE,to:r.PAUSE},{name:t.VIDEO_CHANGE,from:r.PAUSE,to:r.PAUSE},{name:t.AUDIO_CHANGE,from:r.PAUSE,to:r.PAUSE},{name:t.MUTE,from:r.PAUSE,to:r.PAUSE},{name:t.UN_MUTE,from:r.PAUSE,to:r.PAUSE},{name:t.PLAY,from:r.PAUSE,to:r.PLAYING},{name:t.SEEK,from:r.PAUSE,to:r.PAUSED_SEEKING},{name:t.END,from:r.PAUSE,to:r.END},{name:t.SEEK,from:r.PAUSED_SEEKING,to:r.PAUSED_SEEKING},{name:t.AUDIO_CHANGE,from:r.PAUSED_SEEKING,to:r.PAUSED_SEEKING},{name:t.VIDEO_CHANGE,from:r.PAUSED_SEEKING,to:r.PAUSED_SEEKING},{name:t.START_BUFFERING,from:r.PAUSED_SEEKING,to:r.PAUSED_SEEKING},{name:t.END_BUFFERING,from:r.PAUSED_SEEKING,to:r.PAUSED_SEEKING},{name:t.PLAY,from:r.PAUSED_SEEKING,to:r.PAUSED_SEEKING},{name:t.SEEKED,from:r.PAUSED_SEEKING,to:r.PAUSE},{name:t.TIMECHANGED,from:r.PAUSED_SEEKING,to:r.PLAYING},{name:t.PAUSE,from:r.PAUSED_SEEKING,to:r.PAUSE},{name:t.END,from:r.PAUSED_SEEKING,to:r.END},{name:t.SEEK,from:r.END,to:r.END},{name:t.SEEKED,from:r.END,to:r.END},{name:t.TIMECHANGED,from:r.END,to:r.END},{name:t.END_BUFFERING,from:r.END,to:r.END},{name:t.START_BUFFERING,from:r.END,to:r.END},{name:t.END,from:r.END,to:r.END},{name:t.PLAY,from:r.END,to:r.PLAYING},{name:t.ERROR,from:this.allStates(),to:r.ERROR},{name:t.PAUSE,from:r.ERROR,to:r.ERROR},{name:t.PLAY,from:r.ERROR,to:r.PLAYING},{name:t.TIMECHANGED,from:r.ERROR,to:r.PLAYING},{name:t.SOURCE_LOADED,from:r.ERROR,to:r.ERROR},{name:t.METADATA_LOADED,from:r.ERROR,to:r.ERROR},{name:t.START_BUFFERING,from:r.ERROR,to:r.REBUFFERING},{name:t.SEEK,from:r.ERROR,to:r.ERROR},{name:t.SEEKED,from:r.ERROR,to:r.ERROR},{name:t.MUTE,from:r.ERROR,to:r.ERROR},{name:t.UN_MUTE,from:r.ERROR,to:r.ERROR},{name:t.VIDEO_CHANGE,from:r.ERROR,to:r.ERROR},{name:t.AUDIO_CHANGE,from:r.ERROR,to:r.ERROR},{name:t.END_BUFFERING,from:r.ERROR,to:r.ERROR},{name:t.END,from:r.ERROR,to:r.END},...this.allStates().map(e=>({name:t.NON_FATAL_ERROR,from:e,to:e})),{name:t.UNLOAD,from:this.allStates(),to:r.END},{name:t.START_CAST,from:[r.READY,r.PAUSE],to:r.CASTING},{name:t.PAUSE,from:r.CASTING,to:r.CASTING},{name:t.PLAY,from:r.CASTING,to:r.CASTING},{name:t.TIMECHANGED,from:r.CASTING,to:r.CASTING},{name:t.MUTE,from:r.CASTING,to:r.CASTING},{name:t.SEEK,from:r.CASTING,to:r.CASTING},{name:t.SEEKED,from:r.CASTING,to:r.CASTING},{name:t.END_CAST,from:r.CASTING,to:r.READY}],methods:{onBeforeTransition(e,i,o){n.callbacks.playbackWatchTime(n.playbackWatchTime),a.includes(e.transition)&&(e.transition===t.PLAYBACK_FINISHED&&(n.previousRecordTime=0),o&&(n.previousRecordTime=o.currentTime)),e.transition===t.SEEK&&e.from===r.PAUSE&&(n.seekedFrom=n.lastPlayHeadDuration),o&&e.transition!==t.SOURCE_LOADED&&(n.lastPlayHeadDuration=o.currentTime*1e3)},onLeaveState(i,a,o){if(!a)return;let s=a-n.onEnterStateTimestamp;o&&i.to!==r.PAUSED_SEEKING&&(e.log(`Setting video time end to ${o.currentTime}, going to ${i.to}`),n.callbacks.setVideoTimeEndFromEvent(o));let c=i.from.toLowerCase();if(i.from===r.PAUSED_SEEKING){let t=a-(n.seekStartedAt??a);n.seekStartedAt=null,n.callbacks.playback_seeked(n.seekedFrom,o.currentTime*1e3,t,i.to),n.callbacks.heartbeat(a,r.PAUSE.toLowerCase(),o),e.log(`Seek was ${t}ms`)}else i.transition===t.UNLOAD&&i.from===r.PLAYING?n.callbacks.playingAndBye(s,c,o):i.from===r.PAUSE&&i.to!==r.PAUSED_SEEKING&&i.to!==r.PLAYING&&(n.callbacks.setVideoTimeStartFromEvent(i.transition),n.callbacks.pause(s,c,o),n.callbacks.heartbeat(a,c,o))},onAfterTransition(r,i,a){n.callbacks.resetSessionExpiry(),r.transition===t.VIDEO_CHANGE?n.callbacks.videoChange(a):r.transition===t.AUDIO_CHANGE?n.callbacks.audioChange(a):r.transition===t.MUTE?(e.log(`Setting sample to muted`),n.callbacks.mute(i,a)):r.transition===t.UN_MUTE&&(e.log(`Setting sample to unmuted`),n.callbacks.unMute(i,a))},onEnterState(e,o,s){e.to===r.ERROR&&(n.pendingErrorRecovery_=!1),n.callbacks.playbackWatchTime(n.playbackWatchTime),a.includes(e.transition)&&s&&(n.previousRecordTime=s.currentTime),e.transition!==t.NON_FATAL_ERROR&&(e.from===`none`&&i.starttime?n.onEnterStateTimestamp=i.starttime:n.onEnterStateTimestamp=o||Date.now()),(e.to===r.PLAYING&&(e.from===r.STARTUP||e.from===r.PAUSE||e.from===r.REBUFFERING||e.from===r.PAUSED_SEEKING||e.from===r.ERROR)||e.from===`none`&&e.to===r.SETUP)&&(n.heartbeatTimestamp=e.from===`none`&&i.starttime?i.starttime:o||Date.now()),s&&e.to!==r.PAUSED_SEEKING&&n.callbacks.setVideoTimeStartFromEvent(s)},onEnterSetup(e,t,a){e.from===`none`&&n.callbacks.setup(t,r.SETUP,a,i)},onEnterReady(e,t,i){e.from===r.SETUP&&n.callbacks.ready(t,r.READY,i)},onEnterStartup(e,i,a){e.transition===t.PLAY&&(n.playTimeStamp=new Date,n.callbacks.first_play(i,r.STARTUP,a))},onEnterPlaying(e,i,a){e.transition===t.PLAY&&e.from===r.PAUSE?(n.callbacks.play(i,r.PLAYING,a),n.callbacks.playing(i,r.PLAYING,a),n.callbacks.heartbeat(i,r.PLAYING,a)):e.from===r.STARTUP?(n.startupBufferingPending&&(n.startupBufferingPending=!1,n.callbacks.start_rebuffer(i,r.REBUFFERING,a),n.callbacks.end_rebuffer(i,r.REBUFFERING,a)),n.callbacks.playing(i,r.PLAYING,a),n.callbacks.playback_started(a)):e.from===r.REBUFFERING?(n.callbacks.end_rebuffer(i,r.REBUFFERING,a),n.pendingErrorRecovery_&&(n.pendingErrorRecovery_=!1,n.callbacks.error_recovered(i,r.ERROR,a))):e.from===r.ERROR&&n.callbacks.error_recovered(i,r.ERROR,a)},onEnterPause(e,t,i){e.from===r.PLAYING&&(n.callbacks.pause(t,r.PAUSE,i),n.callbacks.heartbeat(t,r.PAUSE,i))},onEnterRebuffering(e,i,a){e.transition===t.START_BUFFERING&&(n.callbacks.start_rebuffer(i,r.REBUFFERING,a),e.from===r.ERROR&&(n.pendingErrorRecovery_=!0))},onBeforeStartBuffering(e,t,i){e.from===r.STARTUP&&(n.startupBufferingPending=!0)},onEnterEnd(e,t,i){n.callbacks.end(t,r.END,i),n.callbacks.heartbeat(t,r.END,i)},onBeforeSourceLoaded(e,t,i){let a=e.from===r.PLAYING&&n.playTimeStamp?Date.now()-n.playTimeStamp.getTime():null;n.callbacks.loaded(t,r.READY,i,a)},onSeek(e,t,r){r&&(n.previousRecordTime=r.currentTime),n.callbacks.playbackWatchTime(n.playbackWatchTime),n.seekStartedAt=n.seekStartedAt??t},onSeeked(e,t,r){r&&(n.previousRecordTime=r.currentTime),n.callbacks.playbackWatchTime(n.playbackWatchTime),n.seekedTimestamp=t},onTimechanged(t,r,i){n.callbacks.playbackWatchTime(n.playbackWatchTime);let a=i.currentTime-n.previousRecordTime;a>0&&a<5&&(n.playbackWatchTime+=Math.round(a*1e3),n.previousRecordTime=i.currentTime);let o=r-n.heartbeatTimestamp;o>1e4&&(n.callbacks.setVideoTimeEndFromEvent(i),e.log(`Sending heartbeat`),n.callbacks.heartbeat(o,t.from.toLowerCase(),i),n.heartbeatTimestamp=r,n.callbacks.setVideoTimeStartFromEvent(i),n.callbacks.resetSessionExpiry())},onPlayerError(e,t,r){n.callbacks.error(r)},onPlayerNonFatalError(e,t,r){n.callbacks.error(r)}}})}static pad(e,t){return(e+Array(t).join(` `)).slice(0,t)}};export{d as GumletStateMachine};
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ import{t as e}from"./Players-bc-BW3HQ.mjs";import{t}from"./Events-DB36UnQj.mjs";const n=`video/mp4`,r=`video/webm`,i=`application/x-mpegURL`,a=`application/dash+xml`,o={MP4:n,WEBM:r,HLS:i,DASH:a};function s(e){return e=e.toLowerCase(),e.endsWith(`.m3u8`)?i:e.endsWith(`.mp4`)||e.endsWith(`.m4v`)||e.endsWith(`.m4a`)?n:e.endsWith(`.webm`)?r:e.endsWith(`.mpd`)?a:null}const{MP4:c,WEBM:l,HLS:u,DASH:d}=o,f={[c]:`mp4`,[l]:`webm`,[u]:`hls`,[d]:`dash`};function p(e){return f[e]}const m=1e3;var h=class{constructor(t,n,r,i=null){this.lastKnownCurrentTime_=0,this.sourceSwitching_=!1,this.eventCallback=n,this.playerSoftwareName=i??e.HTML,this.stateMachine=r,this.mediaEl=t,this.mediaElEventHandlers=[],this.analyticsBitrate_=-1,this.audioCodec_=``,this.videoCodec_=``,this.bufferingTimeout_=null,this.isBuffering_=!1,this.isLive_=!1,this.isPaused_=!1,this.previousMediaTime_=null,this.needsReadyEvent_=!0,this.needsFirstPlayIntent_=!0,this.mediaElementSet_=!1,this.playbackReadySet_=!1,t&&this.setMediaElement()}getCurrentQualityLevelInfo(){return null}isLive(){return!1}getMIMEType(){let e=this.mediaEl;if(!e)return null;let t=e.src||e.querySelector(`source`)?.src||null;return t?s(t):null}getStreamType(){return p(this.getMIMEType()??``)}getPlayerVersion(){return null}getStreamURL(){let e=this.mediaEl;return e&&(e.src||e.querySelector(`source`)?.src)||null}destroy(){this.mediaEl&&this.unregisterMediaElement()}setMediaElement(e=null){if(e&&this.mediaEl&&(this.unregisterMediaElement(),this.mediaElementSet_=!1),e&&(this.mediaEl=e),!this.mediaEl)throw Error(`No media element owned`);if(this.mediaElementSet_)throw Error(`Media element already set (only call this once)`);this.mediaElementSet_=!0,this.registerMediaElement(),this.onMaybeReady()}resetMedia(){this.mediaEl=null,this.mediaElEventHandlers=[]}registerMediaElement(){let e=this.mediaEl;e&&(this.listenToMediaElementEvent(`loadedmetadata`,()=>{if(e.readyState!==1)return;this.checkQualityLevelAttributes(!0);let{duration:n,autoplay:r,videoWidth:i,videoHeight:a,muted:o}=e,s={type:`html5`,isLive:this.isLive(),version:this.getPlayerVersion()??`html5`,streamType:this.getStreamType(),streamUrl:this.getStreamURL(),duration:n,autoplay:r,currentVideoData:{height:a,width:i,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},videoWindowWidth:e.clientWidth,videoWindowHeight:e.clientHeight,muted:o};this.needsFirstPlayIntent_||this.eventCallback(t.METADATA_LOADED,s)}),this.listenToMediaElementEvent(`canplay`,()=>{if(this.playbackReadySet_)return;this.playbackReadySet_=!0;let{duration:n,autoplay:r,videoWidth:i,videoHeight:a,muted:o}=e,s={type:`html5`,isLive:this.isLive(),version:this.getPlayerVersion()??`html5`,streamType:this.getStreamType(),streamUrl:this.getStreamURL(),duration:n,autoplay:r,playerSoftware:this.playerSoftwareName,videoWindowWidth:e.clientWidth,videoWindowHeight:e.clientHeight,currentVideoData:{height:a,width:i,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},muted:o};this.eventCallback(t.SOURCE_LOADED,s)}),this.listenToMediaElementEvent(`emptied`,()=>{this.sourceSwitching_=!0}),this.listenToMediaElementEvent(`play`,()=>{let{currentTime:n,videoWidth:r,videoHeight:i}=e;this.needsFirstPlayIntent_=!1,this.eventCallback(t.PLAY,{currentVideoData:{height:i,width:r,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:n})}),this.listenToMediaElementEvent(`pause`,()=>{this.onPaused()}),this.listenToMediaElementEvent(`playing`,()=>{let{currentTime:n,videoWidth:r,videoHeight:i}=e;this.isPaused_=!1,!this.needsFirstPlayIntent_&&(this.sourceSwitching_||this.eventCallback(t.TIMECHANGED,{currentVideoData:{height:i,width:r,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:n}))}),this.listenToMediaElementEvent(`error`,()=>{let{error:n}=e;this.eventCallback(t.ERROR,{currentTime:this.lastKnownCurrentTime_,code:n?.code,message:n?.message})}),this.listenToMediaElementEvent(`volumechange`,()=>{let{muted:n,currentTime:r}=e;n?this.eventCallback(t.MUTE,{currentTime:r}):this.eventCallback(t.UN_MUTE,{currentTime:r})}),this.listenToMediaElementEvent(`seeking`,()=>{let{currentTime:n,videoWidth:r,videoHeight:i}=e;this.eventCallback(t.SEEK,{currentVideoData:{height:i,width:r,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:n,droppedFrames:0})}),this.listenToMediaElementEvent(`seeked`,()=>{let{currentTime:n,videoWidth:r,videoHeight:i}=e;this.bufferingTimeout_&&clearTimeout(this.bufferingTimeout_),this.eventCallback(t.SEEKED,{currentVideoData:{height:i,width:r,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:n,droppedFrames:0})}),this.listenToMediaElementEvent(`ended`,()=>{let{currentTime:n,videoWidth:r,videoHeight:i}=e;this.eventCallback(t.END,{currentVideoData:{height:i,width:r,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:n})}),this.listenToMediaElementEvent(`timeupdate`,()=>{let{currentTime:n,videoHeight:r,videoWidth:i}=e;this.isBuffering_=!1,n>0&&(this.lastKnownCurrentTime_=n,this.sourceSwitching_=!1),!this.needsFirstPlayIntent_&&(!this.isPaused_&&!this.sourceSwitching_&&this.eventCallback(t.TIMECHANGED,{currentVideoData:{height:r,width:i,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:n}),this.checkQualityLevelAttributes(),this.checkPlayheadProgress(),this.previousMediaTime_=n)}),this.listenToMediaElementEvent(`stalled`,()=>{}),this.listenToMediaElementEvent(`waiting`,()=>{this.onBuffering()}))}listenToMediaElementEvent(e,t){if(!this.mediaEl)throw Error(`No media attached`);let n=t.bind(this);this.mediaElEventHandlers.push({event:e,handler:n}),this.mediaEl.addEventListener(e,n,!1)}unregisterMediaElement(){if(!this.mediaEl)throw Error(`No media attached`);for(let{event:e,handler:t}of this.mediaElEventHandlers)this.mediaEl.removeEventListener(e,t,!1);this.resetMedia()}onMaybeReady(){if(!this.needsReadyEvent_||!this.mediaEl)return;this.needsReadyEvent_=!1;let{duration:e,autoplay:n,videoWidth:r,videoHeight:i,muted:a,preload:o}=this.mediaEl,s=this.getStreamURL(),c=o!==`none`,l={type:`html5`,isLive:this.isLive(),version:this.getPlayerVersion()??`html5`,streamType:this.getStreamType(),streamUrl:s,duration:e,autoplay:n,preload:c,playerSoftware:this.playerSoftwareName,currentVideoData:{height:i,width:r,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},videoWindowWidth:this.mediaEl.clientWidth,videoWindowHeight:this.mediaEl.clientHeight,muted:a};this.stateMachine.updateMetadata(l),this.eventCallback(t.READY,l)}onBuffering(){let{currentTime:e}=this.mediaEl;this.isBuffering_||this.isPaused_||(this.eventCallback(t.START_BUFFERING,{currentTime:e}),this.isBuffering_=!0)}onPaused(){if(this.isPaused_)return;if(this.sourceSwitching_){this.isPaused_=!0;return}let{videoHeight:e,videoWidth:n}=this.mediaEl,r=this.lastKnownCurrentTime_>0?this.lastKnownCurrentTime_:this.mediaEl.currentTime??0;this.eventCallback(t.PAUSE,{currentVideoData:{height:e,width:n,bitrate:this.analyticsBitrate_,audioCodec:this.audioCodec_,videoCodec:this.videoCodec_},currentTime:r}),this.isPaused_=!0}checkPlayheadProgress(){let e=this.mediaEl;e.paused&&this.onPaused(),this.bufferingTimeout_&&clearTimeout(this.bufferingTimeout_),this.bufferingTimeout_=setTimeout(()=>{(e.paused||e.ended)&&!this.isBuffering_||e.currentTime-(this.previousMediaTime_??e.currentTime)<m&&this.onBuffering()},m)}checkQualityLevelAttributes(e=!1){let n=this.mediaEl,r=this.getCurrentQualityLevelInfo();if(!r)return;let{bitrate:i,width:a,height:o,videoCodec:s,audioCodec:c}=r,l=this.isLive();if(l!==this.isLive_&&(this.isLive_=l,e||this.stateMachine.updateMetadata({isLive:l})),this.audioCodec_=c??``,this.videoCodec_=s??``,this.analyticsBitrate_!==i){let r={width:a,height:o,bitrate:i,videoCodec:s,audioCodec:c,currentTime:n.currentTime};e||this.eventCallback(t.VIDEO_CHANGE,r),this.analyticsBitrate_=i??-1}}};export{h as HTML5Adapter,o as t};
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ import{t as e}from"./Players-bc-BW3HQ.mjs";import{t}from"./Events-DB36UnQj.mjs";import{HTML5Adapter as n,t as r}from"./HTML5Adapter-CofiXxOr.mjs";var i=class extends n{constructor(t,n,r){super(null,n,r,e.HLSJS),this.hls=t,this.playerSoftwareName=e.HLSJS,this.boundOnMediaAttaching=this.onMediaAttaching.bind(this),this.boundOnMediaDetaching=this.onMediaDetaching.bind(this),this.boundOnManifestLoading=this.onManifestLoading.bind(this),this.hlsErrorHandler=(e,t)=>this.onError(t),this.resetMedia(),this.registerHlsEvents()}getCurrentQualityLevelInfo(){let e=this.hls,t=e.levels?.[e.currentLevel];if(!t)return null;let n=t.attrs,r=n.BANDWIDTH?parseInt(n.BANDWIDTH,10):0,i=n.RESOLUTION?.width?parseInt(n.RESOLUTION.width,10):0,a=n.RESOLUTION?.height?parseInt(n.RESOLUTION.height,10):0,o=null,s=null;if(n.CODECS){let e=n.CODECS.split(`,`);s=e[0]??null,o=e.length>1?e[1]:null}return{bitrate:r,width:i,height:a,audioCodec:o,videoCodec:s}}isLive(){let e=this.hls;return e.currentLevel<0?!1:!!(e.levels?.[e.currentLevel])?.details?.live}getPlayerVersion(){return Hls.version}getMIMEType(){return r.HLS}getStreamURL(){return this.hls.url??null}destroy(){let e=this.hls;e.off(Hls.Events.MEDIA_ATTACHING,this.boundOnMediaAttaching),e.off(Hls.Events.MEDIA_DETACHING,this.boundOnMediaDetaching),e.off(Hls.Events.MANIFEST_LOADING,this.boundOnManifestLoading),e.off(Hls.Events.ERROR,this.hlsErrorHandler),super.destroy()}registerHlsEvents(){let e=this.hls;if(!Hls)throw Error(`Hls.js is not installed (must be loaded before analytics module)`);e.on(Hls.Events.MEDIA_ATTACHING,this.boundOnMediaAttaching),e.on(Hls.Events.MEDIA_DETACHING,this.boundOnMediaDetaching),e.on(Hls.Events.MANIFEST_LOADING,this.boundOnManifestLoading),e.on(Hls.Events.ERROR,this.hlsErrorHandler),e.media&&this.onMediaAttaching(),e.url&&this.onManifestLoading()}onMediaAttaching(){this.mediaEl||(this.mediaEl=this.hls.media,this.registerMediaElement(),this.onMaybeReady())}onMediaDetaching(){this.unregisterMediaElement()}onManifestLoading(){this.onMaybeReady()}onError(e){let n=e,r=this.lastKnownCurrentTime_>0?this.lastKnownCurrentTime_:this.mediaEl?.currentTime??0;n?.fatal===!0&&n?.details===`internalException`&&console.error(e),this.eventCallback(t.ERROR,{currentTime:r,code:n?.type,message:JSON.stringify({details:n?.details,fatal:n?.fatal,type:n?.type,fragment_url:n?.url,error:{message:n?.error?.message,stack:n?.error?.stack},extra:{networkDetails:{status:n?.networkDetails?.status,statusText:n?.networkDetails?.statusText,url:n?.networkDetails?.url,responseHeaders:n?.networkDetails?.responseHeaders,responseText:n?.networkDetails?.responseText,responseURL:n?.networkDetails?.responseURL,data:n?.networkDetails?.data}}})})}};export{i as HlsjsAdapter};
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ const e=`urn:x-cast:com.gumlet.ingest.cast`,t=`https://ingest.gumlytics.com`,n=1e4,r=new class{constructor(e=!1){this.log=e=>{this.showLogs&&console.log(e)},this.error=e=>{this.showLogs&&console.error(e)},this.warning=e=>{this.showLogs&&console.warn(e)},this.showLogs=e}setLogging(e){this.showLogs=e}isLogging(){return this.showLogs}};export{e as i,t as n,n as r,r as t};
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ const e={JW:`jw`,RADIANT:`radiant`,HLSJS:`hlsjs`,SHAKA:`shaka`,HTML:`html5`,REACTNATIVEVIDEO:`react-native-video`};export{e as t};
@@ -0,0 +1,9 @@
1
+
2
+ // Copyright (C) 2026, Gumlet Pte Ltd., All Rights Reserved
3
+
4
+ // This source code and its use and distribution, is subject to the terms
5
+ // and conditions of the applicable license agreement.
6
+
7
+ // @gumlet/insights-js-core version 2.0.1
8
+
9
+ import{t as e}from"./Players-bc-BW3HQ.mjs";import{t}from"./Events-DB36UnQj.mjs";import{HTML5Adapter as n,t as r}from"./HTML5Adapter-CofiXxOr.mjs";var i=class extends n{constructor(n,r,i,a){if(super(a,r,i,e.SHAKA),typeof shaka>`u`)throw Error("`shaka` lib is not installed (must be loaded before analytics module)");this.shakaPlayer=n,this.playerSoftwareName=e.SHAKA,this.shakaErrorHandler=e=>{this.onGumletShakaError(e,this.eventCallback,this.mediaEl).catch(()=>{let e=this.lastKnownCurrentTime_>0?this.lastKnownCurrentTime_:this.mediaEl?.currentTime??0;this.eventCallback(t.ERROR,{currentTime:e,code:`error_handler_exception`,message:`Shaka error handler threw before firing callback`})})},this.registerShakaEvents()}getPlayerVersion(){return shaka.Player.version}isLive(){return this.shakaPlayer?.isLive()??!1}getMIMEType(){return this.shakaPlayer?.getManifestType?.()===`HLS`?r.HLS:r.DASH}getStreamURL(){return this.shakaPlayer?.getAssetUri()??null}getCurrentQualityLevelInfo(){let e=this.shakaPlayer.getVariantTracks().filter(e=>e.active).find(e=>e.videoCodec!==null||e.videoId!==null);return e?{bitrate:e.videoBandwidth??e.bandwidth??null,width:e.width??null,height:e.height??null,videoCodec:e.videoCodec??null,audioCodec:e.audioCodec??null}:null}destroy(){this.shakaPlayer.removeEventListener(`error`,this.shakaErrorHandler),super.destroy()}registerShakaEvents(){if(!this.shakaPlayer)throw Error(`Shaka player object is not defined`);this.shakaPlayer.addEventListener(`error`,this.shakaErrorHandler)}async onGumletShakaError(e,n,r){let i=this.lastKnownCurrentTime_>0?this.lastKnownCurrentTime_:r?.currentTime??0,a=e;if(!a.detail){n(t.ERROR,{currentTime:i,code:`not_set_by_shaka`,message:`{}`});return}let o=a.detail,s=[];if(o.data)for(let e of o.data)s.push(e);let c=[],l=null;try{let e=[];if(this.shakaPlayer.getVariantTracks().forEach(t=>{e.push({width:t.width,height:t.height,bitrate:t.videoBandwidth??t.bandwidth,framerate:t.frameRate,contentType:`${t.mimeType}; codecs="${t.videoCodec}"`})}),navigator?.mediaCapabilities?.decodingInfo)for(let t of e)try{let e={type:`media-source`,video:{contentType:t.contentType,width:t.width??0,height:t.height??0,bitrate:t.bitrate??0,framerate:t.framerate??0},keySystemConfiguration:{keySystem:`com.widevine.alpha`,video:{contentType:t.contentType}}},n=await navigator.mediaCapabilities.decodingInfo(e);c.push({...n,keySystemAccess:n.keySystemAccess?.getConfiguration()})}catch{}l=this.getCurrentQualityLevelInfo()}catch{}n(!o.severity||o.severity===2?t.ERROR:t.NON_FATAL_ERROR,{currentTime:i,code:o.code,message:JSON.stringify({category:o.v,code:o.code,severity:o.severity,handled:o.handled,timestamp:a.timestamp,extra_data:s,media_capabilities:c,selected_quality_info:l})})}};export{i as ShakaAdapter};