Skip to content

Commit

Permalink
fix(FEC-13766): use data aggregator only for live media without DVR (#71
Browse files Browse the repository at this point in the history
)

* Revert "Revert "fix(FEC-13766): last active slide does not appear on dual screen (#67)""

This reverts commit d7c439f.

* fix(FEC-13766): use data-aggregator only for live-without dvr cues
  • Loading branch information
semarche-kaltura authored Apr 15, 2024
1 parent d5bd3f1 commit 05c3fc2
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 8 deletions.
43 changes: 43 additions & 0 deletions src/providers/dataAggregator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
interface DataAggregatorProps {
throttleTimeout?: number;
onTimeoutFn: (data: any) => void;
}

export class DataAggregator {
private _data: any[] = [];
private _timerId: NodeJS.Timeout | null = null;
private _throttleTimeout = 250;
private _onTimeoutFn: (data: any) => void;

constructor(options: DataAggregatorProps) {
this._onTimeoutFn = options.onTimeoutFn;
}

public addData(data: any): void {
this._data.push(data);
if (!this._timerId) {
this._timerId = setTimeout(() => {
this._useData();
this._clearData();
this._timerId = null;
}, this._throttleTimeout);
}
}

private _useData(): void {
if (this._data.length > 0) {
this._onTimeoutFn(this._data);
}
}

private _clearData(): void {
this._data = [];
}

public destroy(): void {
if (this._timerId) {
clearTimeout(this._timerId);
this._clearData();
}
}
}
8 changes: 7 additions & 1 deletion src/providers/live/live-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,14 @@ export class LiveProvider extends Provider {
}

private _makeCuePointStartEndTime = (cuePointCreatedAt: number, cuePointEndTime?: number) => {
const startTime = this._player.currentTime - (this._currentTimeLive - cuePointCreatedAt);
let startTime = this._player.currentTime - (this._currentTimeLive - cuePointCreatedAt);
const endTime = cuePointEndTime ? this._player.currentTime - (this._currentTimeLive - cuePointEndTime) : Number.MAX_SAFE_INTEGER;
if (!this._player.isDvr()) {
const isCuePointBehindLiveEdge = this._currentTimeLive - cuePointCreatedAt > 0;
if (isCuePointBehindLiveEdge) {
startTime = this._player.currentTime;
}
}
return {startTime, endTime};
};

Expand Down
41 changes: 36 additions & 5 deletions src/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import EventManager = KalturaPlayerTypes.EventManager;
import {KalturaHotspotCuePoint, KalturaThumbCuePoint} from './vod/response-types';
import {HotspotLoader, ThumbLoader, ThumbUrlLoader} from './common/';
import {makeAssetUrl, generateThumb, sortArrayBy} from './utils';
import {DataAggregator} from './dataAggregator';

export interface ProviderRequest {
loader: Function;
Expand All @@ -17,16 +18,34 @@ export class Provider {
protected _eventManager: EventManager;
protected _logger: Logger;
public cuePointManager: CuePointManager | null = null;
private _dataAggregator: DataAggregator | null = null;

constructor(player: Player, eventManager: EventManager, logger: Logger, types: CuepointTypeMap) {
this._types = types;
this._logger = logger;
this._player = player;
this._eventManager = eventManager;
this._logger = logger;
if (this._useDataAggregator()) {
// for live entry without DVR use additional processing of cues (filter out cues behind Live Edge)
const onTimeoutFn = (collectedData: CuePoint[]) => {
// filter out duplicates
const collectedDataMap = new Map();
collectedData.forEach(cuePoint => {
collectedDataMap.set(cuePoint.id, cuePoint);
});
// for stream witout DVR filter out cues behind Live Edge
collectedDataMap.forEach(cue => {
if (cue.endTime === Number.MAX_SAFE_INTEGER) {
this._player.cuePointManager.addCuePoints([cue]);
}
});
};
this._dataAggregator = new DataAggregator({onTimeoutFn});
}
}

protected _addCuePointToPlayer(cuePoints: any[]) {
protected _addCuePointToPlayer(cuePoints: any[], useDataAggregator = Boolean(this._dataAggregator)) {
if (!cuePoints.length) {
return;
}
Expand All @@ -39,13 +58,17 @@ export class Provider {
this.cuePointManager = new CuePointManager(this._player, this._eventManager);
}
this.cuePointManager.addCuePoints(playerCuePoints);
} else if (useDataAggregator) {
playerCuePoints.forEach(cuePoint => {
this._dataAggregator!.addData(cuePoint);
});
} else {
this._player.cuePointManager.addCuePoints(playerCuePoints);
}
}

protected _addCuePointsData(cp: any[]): void {
this._addCuePointToPlayer(cp);
protected _addCuePointsData(cp: any[], useDataAggregator = false): void {
this._addCuePointToPlayer(cp, useDataAggregator);
}

protected _shiftCuePoints(cuePoints: any[], seekFrom: number): void {
Expand Down Expand Up @@ -120,7 +143,7 @@ export class Provider {
cuePoints = sortArrayBy(cuePoints, 'startTime');
cuePoints = this._fixCuePointsEndTime(cuePoints);
cuePoints = this._filterAndShiftCuePoints(cuePoints);
this._addCuePointsData(cuePoints);
this._addCuePointsData(cuePoints, false);
};
const thumbCuePointsLoader: ThumbLoader = data.get(ThumbLoader.id);
const thumbCuePoints: Array<KalturaThumbCuePoint> = thumbCuePointsLoader?.response.thumbCuePoints || [];
Expand Down Expand Up @@ -200,13 +223,21 @@ export class Provider {
let cuePoints = createCuePointList(hotspotCuePoints);
cuePoints = this._filterAndShiftCuePoints(cuePoints);
cuePoints = sortArrayBy(cuePoints, 'startTime', 'createdAt');
this._addCuePointsData(cuePoints);
this._addCuePointsData(cuePoints, false);
}
}

private _useDataAggregator() {
return this._player.isLive() && !this._player.isDvr();
}

public destroy() {
if (this.cuePointManager) {
this.cuePointManager.destroy();
}
if (this._dataAggregator) {
this._dataAggregator.destroy();
this._dataAggregator = null;
}
}
}
6 changes: 4 additions & 2 deletions test/src/providers/live/live-provider.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,14 @@ describe('Check Live provider', () => {
it('should test prepareThumbCuePoints method', () => {
const addCuePoints = sinon.spy();
liveProvider._player = {
isDvr: () => true,
currentTime: 5,
config: {session: {ks: 'test_ks'}},
provider: {env: {serviceUrl: 'test_url'}},
cuePointManager: {addCuePoints}
};
liveProvider._currentTimeLive = 100;
liveProvider._baseThumbAssetUrl = "http://test.te/thumbAssetId/1_initialId/test_ks"
liveProvider._baseThumbAssetUrl = 'http://test.te/thumbAssetId/1_initialId/test_ks';
liveProvider._prepareThumbCuePoints({
id: '1_test',
assetId: 'test_id',
Expand Down Expand Up @@ -166,7 +167,8 @@ describe('Check Live provider', () => {
const addCuePoints = sinon.spy();
liveProvider._player = {
currentTime: 5,
cuePointManager: {addCuePoints}
cuePointManager: {addCuePoints},
isDvr: () => true
};
liveProvider._currentTimeLive = 100;
liveProvider._prepareViewChangeCuePoints({
Expand Down

0 comments on commit 05c3fc2

Please sign in to comment.