@amplitude/analytics-core 2.44.0 → 2.44.2-SR-3115.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/lib/cjs/observers/video.d.ts +25 -0
- package/lib/cjs/observers/video.d.ts.map +1 -0
- package/lib/cjs/observers/video.js +55 -0
- package/lib/cjs/observers/video.js.map +1 -0
- package/lib/cjs/video-analytics/track-video.d.ts +21 -0
- package/lib/cjs/video-analytics/track-video.d.ts.map +1 -0
- package/lib/cjs/video-analytics/track-video.js +165 -0
- package/lib/cjs/video-analytics/track-video.js.map +1 -0
- package/lib/cjs/video-analytics/types.d.ts +36 -0
- package/lib/cjs/video-analytics/types.d.ts.map +1 -0
- package/lib/cjs/video-analytics/types.js +3 -0
- package/lib/cjs/video-analytics/types.js.map +1 -0
- package/lib/esm/observers/video.d.ts +25 -0
- package/lib/esm/observers/video.d.ts.map +1 -0
- package/lib/esm/observers/video.js +52 -0
- package/lib/esm/observers/video.js.map +1 -0
- package/lib/esm/video-analytics/track-video.d.ts +21 -0
- package/lib/esm/video-analytics/track-video.d.ts.map +1 -0
- package/lib/esm/video-analytics/track-video.js +157 -0
- package/lib/esm/video-analytics/track-video.js.map +1 -0
- package/lib/esm/video-analytics/types.d.ts +36 -0
- package/lib/esm/video-analytics/types.d.ts.map +1 -0
- package/lib/esm/video-analytics/types.js +2 -0
- package/lib/esm/video-analytics/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { VideoEvent, MuxEmbeddedPlayer, MuxElement } from '../video-analytics/types';
|
|
2
|
+
type PlaybackState = 'playing' | 'paused' | 'ended' | 'error';
|
|
3
|
+
type Vendor = 'mux';
|
|
4
|
+
type State = {
|
|
5
|
+
playbackState: PlaybackState;
|
|
6
|
+
errorMessage?: string;
|
|
7
|
+
lastEvent?: VideoEvent;
|
|
8
|
+
};
|
|
9
|
+
type VideoObserverParams = {
|
|
10
|
+
videoEl: HTMLVideoElement | MuxEmbeddedPlayer | MuxElement;
|
|
11
|
+
onStateChange: (previousState: State, nextState: State) => void;
|
|
12
|
+
vendor?: Vendor;
|
|
13
|
+
isEmbedded?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare class VideoObserver {
|
|
16
|
+
private state;
|
|
17
|
+
private untrack;
|
|
18
|
+
private onStateChange;
|
|
19
|
+
private handler;
|
|
20
|
+
constructor({ videoEl, onStateChange, vendor, isEmbedded }: VideoObserverParams);
|
|
21
|
+
private updateState;
|
|
22
|
+
destroy(): void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/observers/video.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAExG,KAAK,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE9D,KAAK,MAAM,GAAG,KAAK,CAAC;AAEpB,KAAK,KAAK,GAAG;IACX,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,UAAU,CAAC;IAC3D,aAAa,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,KAAK,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAEX;IAEF,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,OAAO,CAab;gBAEU,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,mBAAmB;IAU/E,OAAO,CAAC,WAAW;IAcnB,OAAO;CAGR"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VideoObserver = void 0;
|
|
4
|
+
var track_video_1 = require("../video-analytics/track-video");
|
|
5
|
+
var VideoObserver = /** @class */ (function () {
|
|
6
|
+
function VideoObserver(_a) {
|
|
7
|
+
var videoEl = _a.videoEl, onStateChange = _a.onStateChange, vendor = _a.vendor, isEmbedded = _a.isEmbedded;
|
|
8
|
+
var _this = this;
|
|
9
|
+
this.state = {
|
|
10
|
+
playbackState: 'paused',
|
|
11
|
+
};
|
|
12
|
+
this.handler = {
|
|
13
|
+
onPlay: function (evt) {
|
|
14
|
+
_this.updateState('playing', evt);
|
|
15
|
+
},
|
|
16
|
+
onPause: function (evt) {
|
|
17
|
+
_this.updateState('paused', evt);
|
|
18
|
+
},
|
|
19
|
+
onEnded: function (evt) {
|
|
20
|
+
_this.updateState('ended', evt);
|
|
21
|
+
},
|
|
22
|
+
onError: function () {
|
|
23
|
+
_this.updateState('error');
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
this.onStateChange = onStateChange;
|
|
27
|
+
if (isEmbedded) {
|
|
28
|
+
// TODO: support embedded iFrame video with no Vendor
|
|
29
|
+
this.untrack = (0, track_video_1.trackMuxEmbeddedVideo)(videoEl, this.handler);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.untrack = (0, track_video_1.trackHtmlVideo)(videoEl, this.handler, vendor);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
VideoObserver.prototype.updateState = function (playbackState, event) {
|
|
36
|
+
var previousState = this.state;
|
|
37
|
+
var nextState = {
|
|
38
|
+
playbackState: playbackState,
|
|
39
|
+
lastEvent: event,
|
|
40
|
+
};
|
|
41
|
+
this.state = nextState;
|
|
42
|
+
try {
|
|
43
|
+
this.onStateChange(previousState, nextState);
|
|
44
|
+
}
|
|
45
|
+
catch (_error) {
|
|
46
|
+
// Swallow callback errors to keep observer state consistent.
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
VideoObserver.prototype.destroy = function () {
|
|
50
|
+
this.untrack();
|
|
51
|
+
};
|
|
52
|
+
return VideoObserver;
|
|
53
|
+
}());
|
|
54
|
+
exports.VideoObserver = VideoObserver;
|
|
55
|
+
//# sourceMappingURL=video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video.js","sourceRoot":"","sources":["../../../src/observers/video.ts"],"names":[],"mappings":";;;AAAA,8DAAuF;AAoBvF;IAsBE,uBAAY,EAAmE;YAAjE,OAAO,aAAA,EAAE,aAAa,mBAAA,EAAE,MAAM,YAAA,EAAE,UAAU,gBAAA;QAAxD,iBAQC;QA7BO,UAAK,GAAU;YACrB,aAAa,EAAE,QAAQ;SACxB,CAAC;QAIM,YAAO,GAAiB;YAC9B,MAAM,EAAE,UAAC,GAAe;gBACtB,KAAI,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,EAAE,UAAC,GAAe;gBACvB,KAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAClC,CAAC;YACD,OAAO,EAAE,UAAC,GAAe;gBACvB,KAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,EAAE;gBACP,KAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;SACF,CAAC;QAGA,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,UAAU,EAAE;YACd,qDAAqD;YACrD,IAAI,CAAC,OAAO,GAAG,IAAA,mCAAqB,EAAC,OAA4B,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;SAClF;aAAM;YACL,IAAI,CAAC,OAAO,GAAG,IAAA,4BAAc,EAAC,OAA2B,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;SAClF;IACH,CAAC;IAEO,mCAAW,GAAnB,UAAoB,aAA4B,EAAE,KAAkB;QAClE,IAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,IAAM,SAAS,GAAU;YACvB,aAAa,eAAA;YACb,SAAS,EAAE,KAAK;SACjB,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI;YACF,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;SAC9C;QAAC,OAAO,MAAM,EAAE;YACf,6DAA6D;SAC9D;IACH,CAAC;IAED,+BAAO,GAAP;QACE,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IACH,oBAAC;AAAD,CAAC,AAjDD,IAiDC;AAjDY,sCAAa","sourcesContent":["import { trackHtmlVideo, trackMuxEmbeddedVideo } from '../video-analytics/track-video';\nimport type { VideoHandler, VideoEvent, MuxEmbeddedPlayer, MuxElement } from '../video-analytics/types';\n\ntype PlaybackState = 'playing' | 'paused' | 'ended' | 'error';\n\ntype Vendor = 'mux'; // | 'vimeo' | 'youtube' | 'other'\n\ntype State = {\n playbackState: PlaybackState;\n errorMessage?: string;\n lastEvent?: VideoEvent;\n};\n\ntype VideoObserverParams = {\n videoEl: HTMLVideoElement | MuxEmbeddedPlayer | MuxElement;\n onStateChange: (previousState: State, nextState: State) => void;\n vendor?: Vendor;\n isEmbedded?: boolean;\n};\n\nexport class VideoObserver {\n private state: State = {\n playbackState: 'paused',\n };\n\n private untrack: () => void;\n private onStateChange: (previousState: State, nextState: State) => void;\n private handler: VideoHandler = {\n onPlay: (evt: VideoEvent) => {\n this.updateState('playing', evt);\n },\n onPause: (evt: VideoEvent) => {\n this.updateState('paused', evt);\n },\n onEnded: (evt: VideoEvent) => {\n this.updateState('ended', evt);\n },\n onError: () => {\n this.updateState('error');\n },\n };\n\n constructor({ videoEl, onStateChange, vendor, isEmbedded }: VideoObserverParams) {\n this.onStateChange = onStateChange;\n if (isEmbedded) {\n // TODO: support embedded iFrame video with no Vendor\n this.untrack = trackMuxEmbeddedVideo(videoEl as MuxEmbeddedPlayer, this.handler);\n } else {\n this.untrack = trackHtmlVideo(videoEl as HTMLVideoElement, this.handler, vendor);\n }\n }\n\n private updateState(playbackState: PlaybackState, event?: VideoEvent) {\n const previousState = this.state;\n const nextState: State = {\n playbackState,\n lastEvent: event,\n };\n this.state = nextState;\n try {\n this.onStateChange(previousState, nextState);\n } catch (_error) {\n // Swallow callback errors to keep observer state consistent.\n }\n }\n\n destroy() {\n this.untrack();\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { VideoHandler, MuxEmbeddedPlayer, MuxElement } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Track a standard HTML video element.
|
|
4
|
+
*
|
|
5
|
+
* @param videoEl - The HTML video element to track.
|
|
6
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
7
|
+
* @returns A function to untrack the video.
|
|
8
|
+
*/
|
|
9
|
+
export declare function trackHtmlVideo(videoEl: HTMLVideoElement | MuxElement, handlers: VideoHandler, vendor?: 'mux'): () => void;
|
|
10
|
+
/**
|
|
11
|
+
* Track a Mux HTML video element.
|
|
12
|
+
*
|
|
13
|
+
* @param videoEl - The HTML Mux video element to track.
|
|
14
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
15
|
+
* @returns A function to untrack the video.
|
|
16
|
+
*/
|
|
17
|
+
export declare function trackMuxHtmlVideo(videoEl: MuxElement, handlers: VideoHandler): () => void;
|
|
18
|
+
export declare function trackMuxEmbeddedVideo(player: MuxEmbeddedPlayer, handlers: VideoHandler): () => void;
|
|
19
|
+
export declare function trackYoutubeEmbeddedVideo(): void;
|
|
20
|
+
export declare function trackVimeoEmbeddedVideo(): void;
|
|
21
|
+
//# sourceMappingURL=track-video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-video.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA4ClF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,gBAAgB,GAAG,UAAU,EACtC,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,KAAK,cAkCf;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,cAE5E;AA8BD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,cAuDtF;AAED,wBAAgB,yBAAyB,SAExC;AAED,wBAAgB,uBAAuB,SAEtC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trackVimeoEmbeddedVideo = exports.trackYoutubeEmbeddedVideo = exports.trackMuxEmbeddedVideo = exports.trackMuxHtmlVideo = exports.trackHtmlVideo = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
function getPlayData(videoEl) {
|
|
6
|
+
return {
|
|
7
|
+
program_duration: videoEl.duration,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function calculatePercentCompleted(currentTime, duration) {
|
|
11
|
+
var percentCompleted = 0;
|
|
12
|
+
if (Number.isFinite(currentTime) && Number.isFinite(duration) && duration > 0) {
|
|
13
|
+
var rawPercent = (currentTime / duration) * 100;
|
|
14
|
+
// Clamp to [0, 100] to avoid invalid analytics values.
|
|
15
|
+
percentCompleted = Math.min(100, Math.max(0, rawPercent));
|
|
16
|
+
}
|
|
17
|
+
return percentCompleted;
|
|
18
|
+
}
|
|
19
|
+
function getPauseData(videoEl) {
|
|
20
|
+
var currentTime = videoEl.currentTime;
|
|
21
|
+
var duration = videoEl.duration;
|
|
22
|
+
return tslib_1.__assign(tslib_1.__assign({}, getPlayData(videoEl)), { last_position: currentTime, percent_completed: calculatePercentCompleted(currentTime, duration) });
|
|
23
|
+
}
|
|
24
|
+
function getEndData(videoEl) {
|
|
25
|
+
return tslib_1.__assign({}, getPauseData(videoEl));
|
|
26
|
+
}
|
|
27
|
+
function getMuxMetadata(videoEl) {
|
|
28
|
+
return {
|
|
29
|
+
mux_playback_id: videoEl.getAttribute('playback-id'),
|
|
30
|
+
mux_video_id: videoEl.getAttribute('metadata-video-id'),
|
|
31
|
+
mux_video_title: videoEl.getAttribute('metadata-video-title'),
|
|
32
|
+
mux_session_id: videoEl.getAttribute('session-id'),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Track a standard HTML video element.
|
|
37
|
+
*
|
|
38
|
+
* @param videoEl - The HTML video element to track.
|
|
39
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
40
|
+
* @returns A function to untrack the video.
|
|
41
|
+
*/
|
|
42
|
+
function trackHtmlVideo(videoEl, handlers, vendor) {
|
|
43
|
+
var playHandler = function () {
|
|
44
|
+
var startEvent = tslib_1.__assign(tslib_1.__assign({}, getPlayData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
45
|
+
handlers.onPlay(startEvent);
|
|
46
|
+
};
|
|
47
|
+
videoEl.addEventListener('play', playHandler);
|
|
48
|
+
var pauseHandler = function () {
|
|
49
|
+
var pauseEvent = tslib_1.__assign(tslib_1.__assign({}, getPauseData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
50
|
+
handlers.onPause(pauseEvent);
|
|
51
|
+
};
|
|
52
|
+
videoEl.addEventListener('pause', pauseHandler);
|
|
53
|
+
var endedHandler = function () {
|
|
54
|
+
var endedEvent = tslib_1.__assign(tslib_1.__assign({}, getEndData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
55
|
+
handlers.onEnded(endedEvent);
|
|
56
|
+
};
|
|
57
|
+
videoEl.addEventListener('ended', endedHandler);
|
|
58
|
+
return function () {
|
|
59
|
+
videoEl.removeEventListener('play', playHandler);
|
|
60
|
+
videoEl.removeEventListener('pause', pauseHandler);
|
|
61
|
+
videoEl.removeEventListener('ended', endedHandler);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
exports.trackHtmlVideo = trackHtmlVideo;
|
|
65
|
+
/**
|
|
66
|
+
* Track a Mux HTML video element.
|
|
67
|
+
*
|
|
68
|
+
* @param videoEl - The HTML Mux video element to track.
|
|
69
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
70
|
+
* @returns A function to untrack the video.
|
|
71
|
+
*/
|
|
72
|
+
function trackMuxHtmlVideo(videoEl, handlers) {
|
|
73
|
+
return trackHtmlVideo(videoEl, handlers, 'mux');
|
|
74
|
+
}
|
|
75
|
+
exports.trackMuxHtmlVideo = trackMuxHtmlVideo;
|
|
76
|
+
function getMuxIframeMetadata(player, elem) {
|
|
77
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
78
|
+
var _a, duration, currentTime, url, metadataVideoTitle, metadataVideoId, playerId;
|
|
79
|
+
return tslib_1.__generator(this, function (_b) {
|
|
80
|
+
switch (_b.label) {
|
|
81
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
82
|
+
new Promise(function (resolve) { return player.getDuration(resolve); }),
|
|
83
|
+
new Promise(function (resolve) { return player.getCurrentTime(resolve); }),
|
|
84
|
+
])];
|
|
85
|
+
case 1:
|
|
86
|
+
_a = tslib_1.__read.apply(void 0, [_b.sent(), 2]), duration = _a[0], currentTime = _a[1];
|
|
87
|
+
metadataVideoTitle = null, metadataVideoId = null, playerId = null;
|
|
88
|
+
try {
|
|
89
|
+
url = new URL(elem.getAttribute('src'));
|
|
90
|
+
metadataVideoTitle = url.searchParams.get('metadata-video-title');
|
|
91
|
+
metadataVideoId = url.searchParams.get('metadata-video-id');
|
|
92
|
+
playerId = url.pathname.split('/').pop();
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// invalid or no src url, skip the header metadata
|
|
96
|
+
}
|
|
97
|
+
return [2 /*return*/, {
|
|
98
|
+
percent_completed: calculatePercentCompleted(currentTime, duration),
|
|
99
|
+
program_duration: duration,
|
|
100
|
+
last_position: currentTime,
|
|
101
|
+
mux_video_title: metadataVideoTitle,
|
|
102
|
+
mux_video_id: metadataVideoId,
|
|
103
|
+
mux_playback_id: playerId,
|
|
104
|
+
}];
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function trackMuxEmbeddedVideo(player, handlers) {
|
|
110
|
+
var onUnsubscribe = [];
|
|
111
|
+
var readyHandler = function () {
|
|
112
|
+
var elem = player.elem;
|
|
113
|
+
var playHandler = function () {
|
|
114
|
+
getMuxIframeMetadata(player, elem)
|
|
115
|
+
.then(function (playerState) {
|
|
116
|
+
var startEvent = tslib_1.__assign({}, playerState);
|
|
117
|
+
handlers.onPlay(startEvent);
|
|
118
|
+
})
|
|
119
|
+
.catch(function (error) {
|
|
120
|
+
handlers.onError("Error getting Mux iframe metadata from 'play' handler: ".concat(error));
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
player.on('play', playHandler);
|
|
124
|
+
onUnsubscribe.push(function () { return player.off('play', playHandler); });
|
|
125
|
+
var pauseHandler = function () {
|
|
126
|
+
getMuxIframeMetadata(player, elem)
|
|
127
|
+
.then(function (playerState) {
|
|
128
|
+
var pauseEvent = tslib_1.__assign({}, playerState);
|
|
129
|
+
handlers.onPause(pauseEvent);
|
|
130
|
+
})
|
|
131
|
+
.catch(function (error) {
|
|
132
|
+
handlers.onError("Error getting Mux iframe metadata from 'pause' handler: ".concat(error));
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
player.on('pause', pauseHandler);
|
|
136
|
+
onUnsubscribe.push(function () { return player.off('pause', pauseHandler); });
|
|
137
|
+
var endedHandler = function () {
|
|
138
|
+
getMuxIframeMetadata(player, elem)
|
|
139
|
+
.then(function (playerState) {
|
|
140
|
+
var endedEvent = tslib_1.__assign({}, playerState);
|
|
141
|
+
handlers.onEnded(endedEvent);
|
|
142
|
+
})
|
|
143
|
+
.catch(function (error) {
|
|
144
|
+
handlers.onError("Error getting Mux iframe metadata from 'ended' handler: ".concat(error));
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
player.on('ended', endedHandler);
|
|
148
|
+
onUnsubscribe.push(function () { return player.off('ended', endedHandler); });
|
|
149
|
+
};
|
|
150
|
+
player.on('ready', readyHandler);
|
|
151
|
+
return function () {
|
|
152
|
+
player.off('ready', readyHandler);
|
|
153
|
+
onUnsubscribe.forEach(function (unsubscribe) { return unsubscribe(); });
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
exports.trackMuxEmbeddedVideo = trackMuxEmbeddedVideo;
|
|
157
|
+
function trackYoutubeEmbeddedVideo() {
|
|
158
|
+
throw new Error('Not implemented');
|
|
159
|
+
}
|
|
160
|
+
exports.trackYoutubeEmbeddedVideo = trackYoutubeEmbeddedVideo;
|
|
161
|
+
function trackVimeoEmbeddedVideo() {
|
|
162
|
+
throw new Error('Not implemented');
|
|
163
|
+
}
|
|
164
|
+
exports.trackVimeoEmbeddedVideo = trackVimeoEmbeddedVideo;
|
|
165
|
+
//# sourceMappingURL=track-video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-video.js","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"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","sourcesContent":["import { VideoHandler, VideoEvent, MuxEmbeddedPlayer, MuxElement } from './types';\n\nfunction getPlayData(videoEl: HTMLVideoElement | MuxElement) {\n return {\n program_duration: videoEl.duration,\n };\n}\n\nfunction calculatePercentCompleted(currentTime: number, duration: number) {\n let percentCompleted = 0;\n if (Number.isFinite(currentTime) && Number.isFinite(duration) && duration > 0) {\n const rawPercent = (currentTime / duration) * 100;\n // Clamp to [0, 100] to avoid invalid analytics values.\n percentCompleted = Math.min(100, Math.max(0, rawPercent));\n }\n return percentCompleted;\n}\n\nfunction getPauseData(videoEl: HTMLVideoElement | MuxElement) {\n const currentTime = videoEl.currentTime;\n const duration = videoEl.duration;\n\n return {\n ...getPlayData(videoEl),\n last_position: currentTime,\n percent_completed: calculatePercentCompleted(currentTime, duration),\n };\n}\n\nfunction getEndData(videoEl: HTMLVideoElement | MuxElement) {\n return {\n ...getPauseData(videoEl),\n };\n}\n\nfunction getMuxMetadata(videoEl: MuxElement) {\n return {\n mux_playback_id: videoEl.getAttribute('playback-id'),\n mux_video_id: videoEl.getAttribute('metadata-video-id'),\n mux_video_title: videoEl.getAttribute('metadata-video-title'),\n mux_session_id: videoEl.getAttribute('session-id'),\n };\n}\n\n/**\n * Track a standard HTML video element.\n *\n * @param videoEl - The HTML video element to track.\n * @param handlers - The video handlers to call when on video lifecycle events.\n * @returns A function to untrack the video.\n */\nexport function trackHtmlVideo(\n videoEl: HTMLVideoElement | MuxElement,\n handlers: VideoHandler,\n vendor?: 'mux', // if new vendors add them to this as enum\n) {\n const playHandler = () => {\n const startEvent: VideoEvent = {\n ...getPlayData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPlay(startEvent);\n };\n videoEl.addEventListener('play', playHandler);\n\n const pauseHandler = () => {\n const pauseEvent: VideoEvent = {\n ...getPauseData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPause(pauseEvent);\n };\n videoEl.addEventListener('pause', pauseHandler);\n\n const endedHandler = () => {\n const endedEvent: VideoEvent = {\n ...getEndData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onEnded(endedEvent);\n };\n videoEl.addEventListener('ended', endedHandler);\n\n return () => {\n videoEl.removeEventListener('play', playHandler);\n videoEl.removeEventListener('pause', pauseHandler);\n videoEl.removeEventListener('ended', endedHandler);\n };\n}\n\n/**\n * Track a Mux HTML video element.\n *\n * @param videoEl - The HTML Mux video element to track.\n * @param handlers - The video handlers to call when on video lifecycle events.\n * @returns A function to untrack the video.\n */\nexport function trackMuxHtmlVideo(videoEl: MuxElement, handlers: VideoHandler) {\n return trackHtmlVideo(videoEl, handlers, 'mux');\n}\n\nasync function getMuxIframeMetadata(player: MuxEmbeddedPlayer, elem: HTMLIFrameElement) {\n const [duration, currentTime] = await Promise.all([\n new Promise<number>((resolve) => player.getDuration(resolve)),\n new Promise<number>((resolve) => player.getCurrentTime(resolve)),\n ]);\n\n let url,\n metadataVideoTitle = null,\n metadataVideoId = null,\n playerId = null;\n try {\n url = new URL(elem.getAttribute('src') as string);\n metadataVideoTitle = url.searchParams.get('metadata-video-title');\n metadataVideoId = url.searchParams.get('metadata-video-id');\n playerId = url.pathname.split('/').pop();\n } catch (error) {\n // invalid or no src url, skip the header metadata\n }\n return {\n percent_completed: calculatePercentCompleted(currentTime, duration),\n program_duration: duration,\n last_position: currentTime,\n mux_video_title: metadataVideoTitle,\n mux_video_id: metadataVideoId,\n mux_playback_id: playerId,\n };\n}\n\nexport function trackMuxEmbeddedVideo(player: MuxEmbeddedPlayer, handlers: VideoHandler) {\n const onUnsubscribe: (() => void)[] = [];\n const readyHandler = () => {\n const { elem } = player;\n const playHandler = () => {\n getMuxIframeMetadata(player, elem)\n .then((playerState) => {\n const startEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onPlay(startEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting Mux iframe metadata from 'play' handler: ${error as string}`);\n });\n };\n player.on('play', playHandler);\n onUnsubscribe.push(() => player.off('play', playHandler));\n\n const pauseHandler = () => {\n getMuxIframeMetadata(player, elem)\n .then((playerState) => {\n const pauseEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onPause(pauseEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting Mux iframe metadata from 'pause' handler: ${error as string}`);\n });\n };\n player.on('pause', pauseHandler);\n onUnsubscribe.push(() => player.off('pause', pauseHandler));\n\n const endedHandler = () => {\n getMuxIframeMetadata(player, elem)\n .then((playerState) => {\n const endedEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onEnded(endedEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting Mux iframe metadata from 'ended' handler: ${error as string}`);\n });\n };\n player.on('ended', endedHandler);\n onUnsubscribe.push(() => player.off('ended', endedHandler));\n };\n player.on('ready', readyHandler);\n\n return () => {\n player.off('ready', readyHandler);\n onUnsubscribe.forEach((unsubscribe) => unsubscribe());\n };\n}\n\nexport function trackYoutubeEmbeddedVideo() {\n throw new Error('Not implemented');\n}\n\nexport function trackVimeoEmbeddedVideo() {\n throw new Error('Not implemented');\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type VideoHandler = {
|
|
2
|
+
onPlay: (startEvent: VideoEvent) => void;
|
|
3
|
+
onPause: (pauseEvent: VideoEvent) => void;
|
|
4
|
+
onEnded: (endedEvent: VideoEvent) => void;
|
|
5
|
+
onError: (error: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export type VideoEvent = {
|
|
8
|
+
program_duration: number;
|
|
9
|
+
playback_id?: string | undefined;
|
|
10
|
+
video_id?: string | undefined;
|
|
11
|
+
video_title?: string | undefined;
|
|
12
|
+
content_id?: string | undefined;
|
|
13
|
+
content_type?: string | undefined;
|
|
14
|
+
session_id?: string | undefined;
|
|
15
|
+
mux_playback_id?: string | undefined | null;
|
|
16
|
+
mux_video_id?: string | undefined | null;
|
|
17
|
+
mux_video_title?: string | undefined | null;
|
|
18
|
+
mux_session_id?: string | undefined | null;
|
|
19
|
+
last_position?: number | undefined | null;
|
|
20
|
+
percent_completed?: number;
|
|
21
|
+
};
|
|
22
|
+
type MuxEmbeddedPlayer = {
|
|
23
|
+
getCurrentTime: (cb: (time: number) => void) => void;
|
|
24
|
+
getDuration: (cb: (duration: number) => void) => void;
|
|
25
|
+
on: (event: string, callback: () => void) => void;
|
|
26
|
+
off: (event: string, callback: () => void) => void;
|
|
27
|
+
elem: HTMLIFrameElement;
|
|
28
|
+
};
|
|
29
|
+
type MuxElement = EventTarget & Element & {
|
|
30
|
+
duration: number;
|
|
31
|
+
currentTime: number;
|
|
32
|
+
play?: () => Promise<unknown>;
|
|
33
|
+
pause?: () => void;
|
|
34
|
+
};
|
|
35
|
+
export { MuxElement, MuxEmbeddedPlayer };
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;IACtD,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAClD,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACnD,IAAI,EAAE,iBAAiB,CAAC;CACzB,CAAC;AAEF,KAAK,UAAU,GAAG,WAAW,GAC3B,OAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAEzG,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"","sourcesContent":["export type VideoHandler = {\n onPlay: (startEvent: VideoEvent) => void;\n onPause: (pauseEvent: VideoEvent) => void;\n onEnded: (endedEvent: VideoEvent) => void;\n onError: (error: string) => void;\n};\n\nexport type VideoEvent = {\n program_duration: number;\n playback_id?: string | undefined;\n video_id?: string | undefined;\n video_title?: string | undefined;\n content_id?: string | undefined;\n content_type?: string | undefined;\n session_id?: string | undefined;\n mux_playback_id?: string | undefined | null;\n mux_video_id?: string | undefined | null;\n mux_video_title?: string | undefined | null;\n mux_session_id?: string | undefined | null;\n last_position?: number | undefined | null;\n percent_completed?: number;\n};\n\ntype MuxEmbeddedPlayer = {\n getCurrentTime: (cb: (time: number) => void) => void;\n getDuration: (cb: (duration: number) => void) => void;\n on: (event: string, callback: () => void) => void;\n off: (event: string, callback: () => void) => void;\n elem: HTMLIFrameElement;\n};\n\ntype MuxElement = EventTarget &\n Element & { duration: number; currentTime: number; play?: () => Promise<unknown>; pause?: () => void };\n\nexport { MuxElement, MuxEmbeddedPlayer };\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { VideoEvent, MuxEmbeddedPlayer, MuxElement } from '../video-analytics/types';
|
|
2
|
+
type PlaybackState = 'playing' | 'paused' | 'ended' | 'error';
|
|
3
|
+
type Vendor = 'mux';
|
|
4
|
+
type State = {
|
|
5
|
+
playbackState: PlaybackState;
|
|
6
|
+
errorMessage?: string;
|
|
7
|
+
lastEvent?: VideoEvent;
|
|
8
|
+
};
|
|
9
|
+
type VideoObserverParams = {
|
|
10
|
+
videoEl: HTMLVideoElement | MuxEmbeddedPlayer | MuxElement;
|
|
11
|
+
onStateChange: (previousState: State, nextState: State) => void;
|
|
12
|
+
vendor?: Vendor;
|
|
13
|
+
isEmbedded?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare class VideoObserver {
|
|
16
|
+
private state;
|
|
17
|
+
private untrack;
|
|
18
|
+
private onStateChange;
|
|
19
|
+
private handler;
|
|
20
|
+
constructor({ videoEl, onStateChange, vendor, isEmbedded }: VideoObserverParams);
|
|
21
|
+
private updateState;
|
|
22
|
+
destroy(): void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../src/observers/video.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAExG,KAAK,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE9D,KAAK,MAAM,GAAG,KAAK,CAAC;AAEpB,KAAK,KAAK,GAAG;IACX,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,UAAU,CAAC;IAC3D,aAAa,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,KAAK,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAEX;IAEF,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,OAAO,CAab;gBAEU,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,mBAAmB;IAU/E,OAAO,CAAC,WAAW;IAcnB,OAAO;CAGR"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { trackHtmlVideo, trackMuxEmbeddedVideo } from '../video-analytics/track-video';
|
|
2
|
+
var VideoObserver = /** @class */ (function () {
|
|
3
|
+
function VideoObserver(_a) {
|
|
4
|
+
var videoEl = _a.videoEl, onStateChange = _a.onStateChange, vendor = _a.vendor, isEmbedded = _a.isEmbedded;
|
|
5
|
+
var _this = this;
|
|
6
|
+
this.state = {
|
|
7
|
+
playbackState: 'paused',
|
|
8
|
+
};
|
|
9
|
+
this.handler = {
|
|
10
|
+
onPlay: function (evt) {
|
|
11
|
+
_this.updateState('playing', evt);
|
|
12
|
+
},
|
|
13
|
+
onPause: function (evt) {
|
|
14
|
+
_this.updateState('paused', evt);
|
|
15
|
+
},
|
|
16
|
+
onEnded: function (evt) {
|
|
17
|
+
_this.updateState('ended', evt);
|
|
18
|
+
},
|
|
19
|
+
onError: function () {
|
|
20
|
+
_this.updateState('error');
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
this.onStateChange = onStateChange;
|
|
24
|
+
if (isEmbedded) {
|
|
25
|
+
// TODO: support embedded iFrame video with no Vendor
|
|
26
|
+
this.untrack = trackMuxEmbeddedVideo(videoEl, this.handler);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.untrack = trackHtmlVideo(videoEl, this.handler, vendor);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
VideoObserver.prototype.updateState = function (playbackState, event) {
|
|
33
|
+
var previousState = this.state;
|
|
34
|
+
var nextState = {
|
|
35
|
+
playbackState: playbackState,
|
|
36
|
+
lastEvent: event,
|
|
37
|
+
};
|
|
38
|
+
this.state = nextState;
|
|
39
|
+
try {
|
|
40
|
+
this.onStateChange(previousState, nextState);
|
|
41
|
+
}
|
|
42
|
+
catch (_error) {
|
|
43
|
+
// Swallow callback errors to keep observer state consistent.
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
VideoObserver.prototype.destroy = function () {
|
|
47
|
+
this.untrack();
|
|
48
|
+
};
|
|
49
|
+
return VideoObserver;
|
|
50
|
+
}());
|
|
51
|
+
export { VideoObserver };
|
|
52
|
+
//# sourceMappingURL=video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"video.js","sourceRoot":"","sources":["../../../src/observers/video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAoBvF;IAsBE,uBAAY,EAAmE;YAAjE,OAAO,aAAA,EAAE,aAAa,mBAAA,EAAE,MAAM,YAAA,EAAE,UAAU,gBAAA;QAAxD,iBAQC;QA7BO,UAAK,GAAU;YACrB,aAAa,EAAE,QAAQ;SACxB,CAAC;QAIM,YAAO,GAAiB;YAC9B,MAAM,EAAE,UAAC,GAAe;gBACtB,KAAI,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,EAAE,UAAC,GAAe;gBACvB,KAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAClC,CAAC;YACD,OAAO,EAAE,UAAC,GAAe;gBACvB,KAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,EAAE;gBACP,KAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;SACF,CAAC;QAGA,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,UAAU,EAAE;YACd,qDAAqD;YACrD,IAAI,CAAC,OAAO,GAAG,qBAAqB,CAAC,OAA4B,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;SAClF;aAAM;YACL,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,OAA2B,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;SAClF;IACH,CAAC;IAEO,mCAAW,GAAnB,UAAoB,aAA4B,EAAE,KAAkB;QAClE,IAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,IAAM,SAAS,GAAU;YACvB,aAAa,eAAA;YACb,SAAS,EAAE,KAAK;SACjB,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI;YACF,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;SAC9C;QAAC,OAAO,MAAM,EAAE;YACf,6DAA6D;SAC9D;IACH,CAAC;IAED,+BAAO,GAAP;QACE,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IACH,oBAAC;AAAD,CAAC,AAjDD,IAiDC","sourcesContent":["import { trackHtmlVideo, trackMuxEmbeddedVideo } from '../video-analytics/track-video';\nimport type { VideoHandler, VideoEvent, MuxEmbeddedPlayer, MuxElement } from '../video-analytics/types';\n\ntype PlaybackState = 'playing' | 'paused' | 'ended' | 'error';\n\ntype Vendor = 'mux'; // | 'vimeo' | 'youtube' | 'other'\n\ntype State = {\n playbackState: PlaybackState;\n errorMessage?: string;\n lastEvent?: VideoEvent;\n};\n\ntype VideoObserverParams = {\n videoEl: HTMLVideoElement | MuxEmbeddedPlayer | MuxElement;\n onStateChange: (previousState: State, nextState: State) => void;\n vendor?: Vendor;\n isEmbedded?: boolean;\n};\n\nexport class VideoObserver {\n private state: State = {\n playbackState: 'paused',\n };\n\n private untrack: () => void;\n private onStateChange: (previousState: State, nextState: State) => void;\n private handler: VideoHandler = {\n onPlay: (evt: VideoEvent) => {\n this.updateState('playing', evt);\n },\n onPause: (evt: VideoEvent) => {\n this.updateState('paused', evt);\n },\n onEnded: (evt: VideoEvent) => {\n this.updateState('ended', evt);\n },\n onError: () => {\n this.updateState('error');\n },\n };\n\n constructor({ videoEl, onStateChange, vendor, isEmbedded }: VideoObserverParams) {\n this.onStateChange = onStateChange;\n if (isEmbedded) {\n // TODO: support embedded iFrame video with no Vendor\n this.untrack = trackMuxEmbeddedVideo(videoEl as MuxEmbeddedPlayer, this.handler);\n } else {\n this.untrack = trackHtmlVideo(videoEl as HTMLVideoElement, this.handler, vendor);\n }\n }\n\n private updateState(playbackState: PlaybackState, event?: VideoEvent) {\n const previousState = this.state;\n const nextState: State = {\n playbackState,\n lastEvent: event,\n };\n this.state = nextState;\n try {\n this.onStateChange(previousState, nextState);\n } catch (_error) {\n // Swallow callback errors to keep observer state consistent.\n }\n }\n\n destroy() {\n this.untrack();\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { VideoHandler, MuxEmbeddedPlayer, MuxElement } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Track a standard HTML video element.
|
|
4
|
+
*
|
|
5
|
+
* @param videoEl - The HTML video element to track.
|
|
6
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
7
|
+
* @returns A function to untrack the video.
|
|
8
|
+
*/
|
|
9
|
+
export declare function trackHtmlVideo(videoEl: HTMLVideoElement | MuxElement, handlers: VideoHandler, vendor?: 'mux'): () => void;
|
|
10
|
+
/**
|
|
11
|
+
* Track a Mux HTML video element.
|
|
12
|
+
*
|
|
13
|
+
* @param videoEl - The HTML Mux video element to track.
|
|
14
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
15
|
+
* @returns A function to untrack the video.
|
|
16
|
+
*/
|
|
17
|
+
export declare function trackMuxHtmlVideo(videoEl: MuxElement, handlers: VideoHandler): () => void;
|
|
18
|
+
export declare function trackMuxEmbeddedVideo(player: MuxEmbeddedPlayer, handlers: VideoHandler): () => void;
|
|
19
|
+
export declare function trackYoutubeEmbeddedVideo(): void;
|
|
20
|
+
export declare function trackVimeoEmbeddedVideo(): void;
|
|
21
|
+
//# sourceMappingURL=track-video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-video.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA4ClF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,gBAAgB,GAAG,UAAU,EACtC,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,KAAK,cAkCf;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,cAE5E;AA8BD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,cAuDtF;AAED,wBAAgB,yBAAyB,SAExC;AAED,wBAAgB,uBAAuB,SAEtC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { __assign, __awaiter, __generator, __read } from "tslib";
|
|
2
|
+
function getPlayData(videoEl) {
|
|
3
|
+
return {
|
|
4
|
+
program_duration: videoEl.duration,
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
function calculatePercentCompleted(currentTime, duration) {
|
|
8
|
+
var percentCompleted = 0;
|
|
9
|
+
if (Number.isFinite(currentTime) && Number.isFinite(duration) && duration > 0) {
|
|
10
|
+
var rawPercent = (currentTime / duration) * 100;
|
|
11
|
+
// Clamp to [0, 100] to avoid invalid analytics values.
|
|
12
|
+
percentCompleted = Math.min(100, Math.max(0, rawPercent));
|
|
13
|
+
}
|
|
14
|
+
return percentCompleted;
|
|
15
|
+
}
|
|
16
|
+
function getPauseData(videoEl) {
|
|
17
|
+
var currentTime = videoEl.currentTime;
|
|
18
|
+
var duration = videoEl.duration;
|
|
19
|
+
return __assign(__assign({}, getPlayData(videoEl)), { last_position: currentTime, percent_completed: calculatePercentCompleted(currentTime, duration) });
|
|
20
|
+
}
|
|
21
|
+
function getEndData(videoEl) {
|
|
22
|
+
return __assign({}, getPauseData(videoEl));
|
|
23
|
+
}
|
|
24
|
+
function getMuxMetadata(videoEl) {
|
|
25
|
+
return {
|
|
26
|
+
mux_playback_id: videoEl.getAttribute('playback-id'),
|
|
27
|
+
mux_video_id: videoEl.getAttribute('metadata-video-id'),
|
|
28
|
+
mux_video_title: videoEl.getAttribute('metadata-video-title'),
|
|
29
|
+
mux_session_id: videoEl.getAttribute('session-id'),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Track a standard HTML video element.
|
|
34
|
+
*
|
|
35
|
+
* @param videoEl - The HTML video element to track.
|
|
36
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
37
|
+
* @returns A function to untrack the video.
|
|
38
|
+
*/
|
|
39
|
+
export function trackHtmlVideo(videoEl, handlers, vendor) {
|
|
40
|
+
var playHandler = function () {
|
|
41
|
+
var startEvent = __assign(__assign({}, getPlayData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
42
|
+
handlers.onPlay(startEvent);
|
|
43
|
+
};
|
|
44
|
+
videoEl.addEventListener('play', playHandler);
|
|
45
|
+
var pauseHandler = function () {
|
|
46
|
+
var pauseEvent = __assign(__assign({}, getPauseData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
47
|
+
handlers.onPause(pauseEvent);
|
|
48
|
+
};
|
|
49
|
+
videoEl.addEventListener('pause', pauseHandler);
|
|
50
|
+
var endedHandler = function () {
|
|
51
|
+
var endedEvent = __assign(__assign({}, getEndData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
52
|
+
handlers.onEnded(endedEvent);
|
|
53
|
+
};
|
|
54
|
+
videoEl.addEventListener('ended', endedHandler);
|
|
55
|
+
return function () {
|
|
56
|
+
videoEl.removeEventListener('play', playHandler);
|
|
57
|
+
videoEl.removeEventListener('pause', pauseHandler);
|
|
58
|
+
videoEl.removeEventListener('ended', endedHandler);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Track a Mux HTML video element.
|
|
63
|
+
*
|
|
64
|
+
* @param videoEl - The HTML Mux video element to track.
|
|
65
|
+
* @param handlers - The video handlers to call when on video lifecycle events.
|
|
66
|
+
* @returns A function to untrack the video.
|
|
67
|
+
*/
|
|
68
|
+
export function trackMuxHtmlVideo(videoEl, handlers) {
|
|
69
|
+
return trackHtmlVideo(videoEl, handlers, 'mux');
|
|
70
|
+
}
|
|
71
|
+
function getMuxIframeMetadata(player, elem) {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
73
|
+
var _a, duration, currentTime, url, metadataVideoTitle, metadataVideoId, playerId;
|
|
74
|
+
return __generator(this, function (_b) {
|
|
75
|
+
switch (_b.label) {
|
|
76
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
77
|
+
new Promise(function (resolve) { return player.getDuration(resolve); }),
|
|
78
|
+
new Promise(function (resolve) { return player.getCurrentTime(resolve); }),
|
|
79
|
+
])];
|
|
80
|
+
case 1:
|
|
81
|
+
_a = __read.apply(void 0, [_b.sent(), 2]), duration = _a[0], currentTime = _a[1];
|
|
82
|
+
metadataVideoTitle = null, metadataVideoId = null, playerId = null;
|
|
83
|
+
try {
|
|
84
|
+
url = new URL(elem.getAttribute('src'));
|
|
85
|
+
metadataVideoTitle = url.searchParams.get('metadata-video-title');
|
|
86
|
+
metadataVideoId = url.searchParams.get('metadata-video-id');
|
|
87
|
+
playerId = url.pathname.split('/').pop();
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
// invalid or no src url, skip the header metadata
|
|
91
|
+
}
|
|
92
|
+
return [2 /*return*/, {
|
|
93
|
+
percent_completed: calculatePercentCompleted(currentTime, duration),
|
|
94
|
+
program_duration: duration,
|
|
95
|
+
last_position: currentTime,
|
|
96
|
+
mux_video_title: metadataVideoTitle,
|
|
97
|
+
mux_video_id: metadataVideoId,
|
|
98
|
+
mux_playback_id: playerId,
|
|
99
|
+
}];
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
export function trackMuxEmbeddedVideo(player, handlers) {
|
|
105
|
+
var onUnsubscribe = [];
|
|
106
|
+
var readyHandler = function () {
|
|
107
|
+
var elem = player.elem;
|
|
108
|
+
var playHandler = function () {
|
|
109
|
+
getMuxIframeMetadata(player, elem)
|
|
110
|
+
.then(function (playerState) {
|
|
111
|
+
var startEvent = __assign({}, playerState);
|
|
112
|
+
handlers.onPlay(startEvent);
|
|
113
|
+
})
|
|
114
|
+
.catch(function (error) {
|
|
115
|
+
handlers.onError("Error getting Mux iframe metadata from 'play' handler: ".concat(error));
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
player.on('play', playHandler);
|
|
119
|
+
onUnsubscribe.push(function () { return player.off('play', playHandler); });
|
|
120
|
+
var pauseHandler = function () {
|
|
121
|
+
getMuxIframeMetadata(player, elem)
|
|
122
|
+
.then(function (playerState) {
|
|
123
|
+
var pauseEvent = __assign({}, playerState);
|
|
124
|
+
handlers.onPause(pauseEvent);
|
|
125
|
+
})
|
|
126
|
+
.catch(function (error) {
|
|
127
|
+
handlers.onError("Error getting Mux iframe metadata from 'pause' handler: ".concat(error));
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
player.on('pause', pauseHandler);
|
|
131
|
+
onUnsubscribe.push(function () { return player.off('pause', pauseHandler); });
|
|
132
|
+
var endedHandler = function () {
|
|
133
|
+
getMuxIframeMetadata(player, elem)
|
|
134
|
+
.then(function (playerState) {
|
|
135
|
+
var endedEvent = __assign({}, playerState);
|
|
136
|
+
handlers.onEnded(endedEvent);
|
|
137
|
+
})
|
|
138
|
+
.catch(function (error) {
|
|
139
|
+
handlers.onError("Error getting Mux iframe metadata from 'ended' handler: ".concat(error));
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
player.on('ended', endedHandler);
|
|
143
|
+
onUnsubscribe.push(function () { return player.off('ended', endedHandler); });
|
|
144
|
+
};
|
|
145
|
+
player.on('ready', readyHandler);
|
|
146
|
+
return function () {
|
|
147
|
+
player.off('ready', readyHandler);
|
|
148
|
+
onUnsubscribe.forEach(function (unsubscribe) { return unsubscribe(); });
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export function trackYoutubeEmbeddedVideo() {
|
|
152
|
+
throw new Error('Not implemented');
|
|
153
|
+
}
|
|
154
|
+
export function trackVimeoEmbeddedVideo() {
|
|
155
|
+
throw new Error('Not implemented');
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=track-video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-video.js","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"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","sourcesContent":["import { VideoHandler, VideoEvent, MuxEmbeddedPlayer, MuxElement } from './types';\n\nfunction getPlayData(videoEl: HTMLVideoElement | MuxElement) {\n return {\n program_duration: videoEl.duration,\n };\n}\n\nfunction calculatePercentCompleted(currentTime: number, duration: number) {\n let percentCompleted = 0;\n if (Number.isFinite(currentTime) && Number.isFinite(duration) && duration > 0) {\n const rawPercent = (currentTime / duration) * 100;\n // Clamp to [0, 100] to avoid invalid analytics values.\n percentCompleted = Math.min(100, Math.max(0, rawPercent));\n }\n return percentCompleted;\n}\n\nfunction getPauseData(videoEl: HTMLVideoElement | MuxElement) {\n const currentTime = videoEl.currentTime;\n const duration = videoEl.duration;\n\n return {\n ...getPlayData(videoEl),\n last_position: currentTime,\n percent_completed: calculatePercentCompleted(currentTime, duration),\n };\n}\n\nfunction getEndData(videoEl: HTMLVideoElement | MuxElement) {\n return {\n ...getPauseData(videoEl),\n };\n}\n\nfunction getMuxMetadata(videoEl: MuxElement) {\n return {\n mux_playback_id: videoEl.getAttribute('playback-id'),\n mux_video_id: videoEl.getAttribute('metadata-video-id'),\n mux_video_title: videoEl.getAttribute('metadata-video-title'),\n mux_session_id: videoEl.getAttribute('session-id'),\n };\n}\n\n/**\n * Track a standard HTML video element.\n *\n * @param videoEl - The HTML video element to track.\n * @param handlers - The video handlers to call when on video lifecycle events.\n * @returns A function to untrack the video.\n */\nexport function trackHtmlVideo(\n videoEl: HTMLVideoElement | MuxElement,\n handlers: VideoHandler,\n vendor?: 'mux', // if new vendors add them to this as enum\n) {\n const playHandler = () => {\n const startEvent: VideoEvent = {\n ...getPlayData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPlay(startEvent);\n };\n videoEl.addEventListener('play', playHandler);\n\n const pauseHandler = () => {\n const pauseEvent: VideoEvent = {\n ...getPauseData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPause(pauseEvent);\n };\n videoEl.addEventListener('pause', pauseHandler);\n\n const endedHandler = () => {\n const endedEvent: VideoEvent = {\n ...getEndData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onEnded(endedEvent);\n };\n videoEl.addEventListener('ended', endedHandler);\n\n return () => {\n videoEl.removeEventListener('play', playHandler);\n videoEl.removeEventListener('pause', pauseHandler);\n videoEl.removeEventListener('ended', endedHandler);\n };\n}\n\n/**\n * Track a Mux HTML video element.\n *\n * @param videoEl - The HTML Mux video element to track.\n * @param handlers - The video handlers to call when on video lifecycle events.\n * @returns A function to untrack the video.\n */\nexport function trackMuxHtmlVideo(videoEl: MuxElement, handlers: VideoHandler) {\n return trackHtmlVideo(videoEl, handlers, 'mux');\n}\n\nasync function getMuxIframeMetadata(player: MuxEmbeddedPlayer, elem: HTMLIFrameElement) {\n const [duration, currentTime] = await Promise.all([\n new Promise<number>((resolve) => player.getDuration(resolve)),\n new Promise<number>((resolve) => player.getCurrentTime(resolve)),\n ]);\n\n let url,\n metadataVideoTitle = null,\n metadataVideoId = null,\n playerId = null;\n try {\n url = new URL(elem.getAttribute('src') as string);\n metadataVideoTitle = url.searchParams.get('metadata-video-title');\n metadataVideoId = url.searchParams.get('metadata-video-id');\n playerId = url.pathname.split('/').pop();\n } catch (error) {\n // invalid or no src url, skip the header metadata\n }\n return {\n percent_completed: calculatePercentCompleted(currentTime, duration),\n program_duration: duration,\n last_position: currentTime,\n mux_video_title: metadataVideoTitle,\n mux_video_id: metadataVideoId,\n mux_playback_id: playerId,\n };\n}\n\nexport function trackMuxEmbeddedVideo(player: MuxEmbeddedPlayer, handlers: VideoHandler) {\n const onUnsubscribe: (() => void)[] = [];\n const readyHandler = () => {\n const { elem } = player;\n const playHandler = () => {\n getMuxIframeMetadata(player, elem)\n .then((playerState) => {\n const startEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onPlay(startEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting Mux iframe metadata from 'play' handler: ${error as string}`);\n });\n };\n player.on('play', playHandler);\n onUnsubscribe.push(() => player.off('play', playHandler));\n\n const pauseHandler = () => {\n getMuxIframeMetadata(player, elem)\n .then((playerState) => {\n const pauseEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onPause(pauseEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting Mux iframe metadata from 'pause' handler: ${error as string}`);\n });\n };\n player.on('pause', pauseHandler);\n onUnsubscribe.push(() => player.off('pause', pauseHandler));\n\n const endedHandler = () => {\n getMuxIframeMetadata(player, elem)\n .then((playerState) => {\n const endedEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onEnded(endedEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting Mux iframe metadata from 'ended' handler: ${error as string}`);\n });\n };\n player.on('ended', endedHandler);\n onUnsubscribe.push(() => player.off('ended', endedHandler));\n };\n player.on('ready', readyHandler);\n\n return () => {\n player.off('ready', readyHandler);\n onUnsubscribe.forEach((unsubscribe) => unsubscribe());\n };\n}\n\nexport function trackYoutubeEmbeddedVideo() {\n throw new Error('Not implemented');\n}\n\nexport function trackVimeoEmbeddedVideo() {\n throw new Error('Not implemented');\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type VideoHandler = {
|
|
2
|
+
onPlay: (startEvent: VideoEvent) => void;
|
|
3
|
+
onPause: (pauseEvent: VideoEvent) => void;
|
|
4
|
+
onEnded: (endedEvent: VideoEvent) => void;
|
|
5
|
+
onError: (error: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export type VideoEvent = {
|
|
8
|
+
program_duration: number;
|
|
9
|
+
playback_id?: string | undefined;
|
|
10
|
+
video_id?: string | undefined;
|
|
11
|
+
video_title?: string | undefined;
|
|
12
|
+
content_id?: string | undefined;
|
|
13
|
+
content_type?: string | undefined;
|
|
14
|
+
session_id?: string | undefined;
|
|
15
|
+
mux_playback_id?: string | undefined | null;
|
|
16
|
+
mux_video_id?: string | undefined | null;
|
|
17
|
+
mux_video_title?: string | undefined | null;
|
|
18
|
+
mux_session_id?: string | undefined | null;
|
|
19
|
+
last_position?: number | undefined | null;
|
|
20
|
+
percent_completed?: number;
|
|
21
|
+
};
|
|
22
|
+
type MuxEmbeddedPlayer = {
|
|
23
|
+
getCurrentTime: (cb: (time: number) => void) => void;
|
|
24
|
+
getDuration: (cb: (duration: number) => void) => void;
|
|
25
|
+
on: (event: string, callback: () => void) => void;
|
|
26
|
+
off: (event: string, callback: () => void) => void;
|
|
27
|
+
elem: HTMLIFrameElement;
|
|
28
|
+
};
|
|
29
|
+
type MuxElement = EventTarget & Element & {
|
|
30
|
+
duration: number;
|
|
31
|
+
currentTime: number;
|
|
32
|
+
play?: () => Promise<unknown>;
|
|
33
|
+
pause?: () => void;
|
|
34
|
+
};
|
|
35
|
+
export { MuxElement, MuxEmbeddedPlayer };
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;IACtD,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAClD,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACnD,IAAI,EAAE,iBAAiB,CAAC;CACzB,CAAC;AAEF,KAAK,UAAU,GAAG,WAAW,GAC3B,OAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAEzG,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"","sourcesContent":["export type VideoHandler = {\n onPlay: (startEvent: VideoEvent) => void;\n onPause: (pauseEvent: VideoEvent) => void;\n onEnded: (endedEvent: VideoEvent) => void;\n onError: (error: string) => void;\n};\n\nexport type VideoEvent = {\n program_duration: number;\n playback_id?: string | undefined;\n video_id?: string | undefined;\n video_title?: string | undefined;\n content_id?: string | undefined;\n content_type?: string | undefined;\n session_id?: string | undefined;\n mux_playback_id?: string | undefined | null;\n mux_video_id?: string | undefined | null;\n mux_video_title?: string | undefined | null;\n mux_session_id?: string | undefined | null;\n last_position?: number | undefined | null;\n percent_completed?: number;\n};\n\ntype MuxEmbeddedPlayer = {\n getCurrentTime: (cb: (time: number) => void) => void;\n getDuration: (cb: (duration: number) => void) => void;\n on: (event: string, callback: () => void) => void;\n off: (event: string, callback: () => void) => void;\n elem: HTMLIFrameElement;\n};\n\ntype MuxElement = EventTarget &\n Element & { duration: number; currentTime: number; play?: () => Promise<unknown>; pause?: () => void };\n\nexport { MuxElement, MuxEmbeddedPlayer };\n"]}
|