@xnstream/player-sdk
Version:
XStream Player SDK - A powerful video player SDK for streaming content
80 lines • 3.19 kB
JavaScript
import { WatchtimeCollector } from './WatchtimeCollector';
import { DeliveryCollector } from './DeliveryCollector';
import { generateSignature, base64Encode, generateRandomSalt } from '../utils/crypto';
import { canonicalJSONStringify } from '../utils/utils';
export class AnalyticsCollector {
constructor(options) {
this.flushTimeout = null;
this.collectors = [];
this.flushInterval = options.flushIntervalMs || 5000;
this.context = options;
this.context.ref = this.getDocumentReferer();
// Create collectors
this.collectors.push(new DeliveryCollector(this.context.stream_code, this.context.hlsPlayer, this.context.resource, this.context.edge_id, options.userContext));
this.collectors.push(new WatchtimeCollector(this.context.video, this.context.stream_code, this.context.resource, this.context.edge_id, options.userContext));
// Auto-flush events at regular intervals
this.flushTimeout = setInterval(() => {
this.flush();
}, this.flushInterval);
}
async flush() {
// First flush all collectors
const events = this.collectors.flatMap(collector => collector.flush());
if (!events.length)
return;
const nce = generateRandomSalt();
const at = Math.floor(Date.now() / 1000);
const message = [
canonicalJSONStringify(events),
nce,
at,
this.context.appId,
this.context.sid,
this.context.resource.resource.id,
this.context.ref,
this.context.resource.resource.organization_id,
].join('|');
const sig = base64Encode(generateSignature(message, this.context.appId));
try {
await fetch(`${this.context.host}/player/stats/report`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
app_id: this.context.appId,
sid: this.context.sid,
nce: nce,
at: at,
sig: sig,
rs: this.context.resource.resource.id,
data: {
events,
device: this.context.device,
version: this.context.appVersion,
pb_id: this.context.pb_id,
ref: this.context.ref,
ow: this.context.resource.resource.organization_id,
},
}),
});
}
catch (error) {
console.error('Failed to send analytics:', error);
}
}
destroy() {
this.flush();
if (this.flushTimeout) {
clearInterval(this.flushTimeout);
this.collectors.forEach(collector => collector.destroy());
}
}
getDocumentReferer() {
let referer = document.referrer;
if (referer === '' || !referer)
referer = document.location.href;
return referer;
}
}
//# sourceMappingURL=AnalyticsCollector.js.map