Skip to content

Commit

Permalink
feat(FEC-11540): CuePoint Manager (#488)
Browse files Browse the repository at this point in the history
* feat(FEV-1016): add cue-point manager

* feat(FEV-1016): getAllCuePoints returns array

* feat(FEV-1003): cover cue-point manager by unit tests

* feat(FEV-1016): address PR comments

* feat(FEV-1016): add context for constants

* fix(FEC-11540): add reset and destroy methods to cue-point manager

* fix(FEC-11540): add new types

* fix(FEC-11540): address PR comments

* fix(FEC-11540): address PR comments

* fix(FEC-11540): define KalturaPlayer types as a global module

* fix(FEC-11540): fix unit tests

* fix(FEC-11540): use canary playkit-js

Co-authored-by: Roy Bregman <48884909+RoyBregman@users.noreply.github.com>
  • Loading branch information
semarche-kaltura and RoyBregman committed Sep 15, 2021
1 parent d68e890 commit 025059a
Show file tree
Hide file tree
Showing 11 changed files with 916 additions and 701 deletions.
1,320 changes: 676 additions & 644 deletions docs/api.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
},
"dependencies": {
"@babel/polyfill": "^7.0.0",
"@playkit-js/playkit-js": "0.73.1",
"@playkit-js/playkit-js": "canary",
"@playkit-js/playkit-js-dash": "1.27.2",
"@playkit-js/playkit-js-hls": "1.27.1",
"@playkit-js/playkit-js-ui": "0.69.1",
Expand Down
82 changes: 82 additions & 0 deletions src/common/cuepoint/cuepoint-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//@flow
import {Cue, FakeEvent, TextTrack, EventType} from '@playkit-js/playkit-js';
import {CUE_POINTS_TEXT_TRACK, CUE_POINT_KEY} from './cuepoint-type';

interface CuePoint {
id: string;
startTime: number;
endTime: number;
}

export class CuePointManager {
_player: KalturaPlayer;
_textTrack: TextTrack | null = null;

constructor(player: KalturaPlayer) {
this._player = player;
}

_addTextTrack() {
this._textTrack = this._player.addTextTrack(TextTrack.KIND.METADATA, CUE_POINTS_TEXT_TRACK);
}

_createTextTrackCue(data: CuePoint): window.VTTCue | typeof Cue {
let cue = {};
if (window.VTTCue) {
cue = new window.VTTCue(data.startTime, data.endTime, '');
} else if (window.TextTrackCue) {
// IE11 support
cue = new Cue(data.startTime, data.endTime, '');
}
const cueValue = {key: CUE_POINT_KEY, data};
cue.id = data.id;
cue.value = cueValue;
return cue;
}

getAllCuePoints() {
return this._textTrack?.cues || [];
}

getCuePointById(id: string) {
return this._textTrack?.cues?.getCueById(id);
}

removeCuePoint(cuePoint: window.VTTCue | typeof Cue) {
this._textTrack?.removeCue(cuePoint);
}

addCuePoints(data: CuePoint[]) {
if (!this._textTrack) {
this._addTextTrack();
}
const newCuePoints: window.VTTCue | typeof Cue = [];

data.forEach((cuePoint: CuePoint) => {
const textTrackCue = this._createTextTrackCue(cuePoint);
const exisedCue = this.getCuePointById(textTrackCue.id);
if (exisedCue) {
this.removeCuePoint(exisedCue);
}
this._textTrack?.addCue(textTrackCue);
newCuePoints.push(textTrackCue);
});
this._player.dispatchEvent(new FakeEvent(EventType.TIMED_METADATA_ADDED, {cues: newCuePoints}));
}

clearAllCuePoints() {
if (this._textTrack && this._textTrack.cues.length) {
while (this._textTrack.cues.length) {
this.removeCuePoint(this._textTrack.cues[0]);
}
}
}

reset() {
this.clearAllCuePoints();
}

destroy() {
this.reset();
}
}
3 changes: 3 additions & 0 deletions src/common/cuepoint/cuepoint-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @flow
export const CUE_POINTS_TEXT_TRACK = 'CuePoints';
export const CUE_POINT_KEY = 'CuePoint';
9 changes: 9 additions & 0 deletions src/common/cuepoint/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @flow
import {CUE_POINTS_TEXT_TRACK, CUE_POINT_KEY} from './cuepoint-type';

const cuepoint = {
CUE_POINTS_TEXT_TRACK,
CUE_POINT_KEY
};

export {cuepoint};
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {getPlayers, getPlayer} from './proxy';
import {cast} from './common/cast';
// Import playlist
import {playlist} from './common/playlist';
// Import cue-points
import {cuepoint} from './common/cuepoint';

// Import plugin framework
import {Ad, AdBreak} from './common/ads';
Expand Down Expand Up @@ -48,6 +50,7 @@ export {
setup,
cast,
playlist,
cuepoint,
Ad,
AdBreak,
BasePlugin,
Expand Down
21 changes: 21 additions & 0 deletions src/kaltura-player.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
} from '@playkit-js/playkit-js';
import {PluginReadinessMiddleware} from './common/plugins/plugin-readiness-middleware';
import {ThumbnailManager} from './common/thumbnail-manager';
import {CuePointManager} from './common/cuepoint/cuepoint-manager';
import {ServiceProvider} from './common/service-provider';

class KalturaPlayer extends FakeEventTarget {
Expand All @@ -60,6 +61,7 @@ class KalturaPlayer extends FakeEventTarget {
_viewabilityManager: ViewabilityManager;
_playbackStart: boolean;
_thumbnailManager: ?ThumbnailManager = null;
_cuepointManager: CuePointManager;
_serviceProvider: ServiceProvider;

/**
Expand Down Expand Up @@ -90,6 +92,7 @@ class KalturaPlayer extends FakeEventTarget {
this._viewabilityManager = new ViewabilityManager(this.config.viewability);
this._uiWrapper = new UIWrapper(this, Utils.Object.mergeDeep(options, {ui: {logger: {getLogger, LogLevel}}}));
this._serviceProvider = new ServiceProvider(this);
this._cuepointManager = new CuePointManager(this);
this._provider = new Provider(
Utils.Object.mergeDeep(options.provider, {
logger: {
Expand Down Expand Up @@ -318,6 +321,7 @@ class KalturaPlayer extends FakeEventTarget {
this._uiWrapper.reset();
this._resetProviderPluginsConfig();
this._pluginManager.reset();
this._cuepointManager.reset();
this._localPlayer.reset();
this._thumbnailManager?.destroy();
}
Expand All @@ -330,6 +334,7 @@ class KalturaPlayer extends FakeEventTarget {
this._firstPlay = true;
this._uiWrapper.destroy();
this._pluginManager.destroy();
this._cuepointManager.destroy();
this._playlistManager.destroy();
this._localPlayer.destroy();
this._eventManager.destroy();
Expand Down Expand Up @@ -970,6 +975,22 @@ class KalturaPlayer extends FakeEventTarget {
registerService(name: string, service: Object): void {
this._serviceProvider.register(name, service);
}

get cuePointManager(): CuePointManager {
return this._cuepointManager;
}

/**
* Add text track
* @function addTextTrack
* @param {string} kind - Specifies the kind of text track.
* @param {?string} label - A string specifying the label for the text track.
* @returns {?TextTrack} - A TextTrack Object, which represents the new text track.
* @public
*/
addTextTrack(kind: string, label?: string): ?TextTrack {
return this._localPlayer.addTextTrack(kind, label);
}
}

export {KalturaPlayer};
64 changes: 64 additions & 0 deletions test/src/common/cuepoints/cuepoint-manager.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {expect} from 'chai';
import SourcesConfig from '../../configs/sources';
import {getConfigStructure} from '../../utils/test-utils';
import {KalturaPlayer as Player} from '../../../../src/kaltura-player';
import {CuePointManager} from '../../../../src/common/cuepoint/cuepoint-manager';

describe('CuePointManager', () => {
let config, player, sandbox;

before(() => {
config = getConfigStructure();
});

beforeEach(() => {
player = new Player(config);
sandbox = sinon.createSandbox();
});

afterEach(() => {
player.destroy();
sandbox.restore();
});

it('should get cue-point manager', function () {
expect(player.cuePointManager).instanceOf(CuePointManager);
});

it('should create and add text-track', function () {
player.setMedia({sources: SourcesConfig.Mp4});
expect(player.cuePointManager._textTrack).to.eql(null);
player.cuePointManager.addCuePoints([]);
expect(player.cuePointManager._textTrack).instanceOf(TextTrack);
});

it('should add/get/remove/clear-all cue points', function () {
const cuePoints = [
{
id: 'test-id-1',
startTime: 1,
endTime: 6
},
{
id: 'test-id-2',
startTime: 6,
endTime: 10
},
{
id: 'test-id-3',
startTime: 10,
endTime: 15
}
];
player.setMedia({sources: SourcesConfig.Mp4});
expect(player.cuePointManager.getAllCuePoints().length).eql(0);
player.cuePointManager.addCuePoints(cuePoints);
expect(player.cuePointManager.getAllCuePoints().length).eql(3);
const cuePoint = player.cuePointManager.getCuePointById('test-id-1');
expect(cuePoint.id).to.eql('test-id-1');
player.cuePointManager.removeCuePoint(cuePoint);
expect(player.cuePointManager.getAllCuePoints().length).eql(2);
player.cuePointManager.clearAllCuePoints();
expect(player.cuePointManager.getAllCuePoints().length).eql(0);
});
});
99 changes: 49 additions & 50 deletions ts-typed/kaltura-player.d.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,55 @@
declare global {
const KalturaPlayer: {
providers:{
RequestBuilder: any
ResponseTypes: any
};
ui: {
EventType: Record<string, string>;
redux: {
connect: (...args: any) => any;
};
reducers: Record<string, {actions: Record<string, unknown>[]}>;
createPortal: (children: any, domElement: HTMLElement) => void;
utils: {
getLogger: (name: string) => KalturaPlayerTypes.Logger;
bindActions(actions: Record<string, unknown>[]): (...args: any) => void;
};
components: {
withPlayer: any;
Tooltip: any;
Icon: any;
IconType: any;
PLAYER_SIZE: Record<string, string>;
Remove: string,
Settings: {
displayName: string
}
};
preactHooks: any;
preacti18n: any;
};
core: {
EventType: Record<string, string>;
FakeEvent: any;
Error: any;
StateType: Record<string, string>;
registerPlugin(name: string, component: any): void;
BasePlugin: {
new (...args: any[]): KalturaPlayerTypes.BasePlugin;
declare module 'global' {
declare global {
const KalturaPlayer: {
providers: {
RequestBuilder: any;
ResponseTypes: any;
};
BaseMiddleware: {
new (): KalturaPlayerTypes.BaseMiddleware;
ui: {
EventType: Record<string, string>;
redux: {
connect: (...args: any) => any;
};
reducers: Record<string, {actions: Record<string, unknown>[]}>;
createPortal: (children: any, domElement: HTMLElement) => void;
utils: {
getLogger: (name: string) => KalturaPlayerTypes.Logger;
bindActions(actions: Record<string, unknown>[]): (...args: any) => void;
};
components: {
withPlayer: any;
Tooltip: any;
Icon: any;
IconType: any;
PLAYER_SIZE: Record<string, string>;
Remove: string;
Settings: {
displayName: string;
};
};
preactHooks: any;
preacti18n: any;
};
utils: {
Object: {
mergeDeep(
target: Record<string, any>,
...sources: Record<string, any>[]
);
core: {
EventType: Record<string, string>;
FakeEvent: any;
Error: any;
StateType: Record<string, string>;
registerPlugin(name: string, component: any): void;
BasePlugin: {
new (...args: any[]): KalturaPlayerTypes.BasePlugin;
};
BaseMiddleware: {
new (): KalturaPlayerTypes.BaseMiddleware;
};
utils: {
Object: {
mergeDeep(target: Record<string, any>, ...sources: Record<string, any>[]);
};
};
};
getPlayer(targetId?: string): any;
setup(options: any): KalturaPlayer;
};
getPlayer(targetId?: string): any;
setup(options: any): KalturaPlayer;
};
}
}
6 changes: 4 additions & 2 deletions ts-typed/player.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ declare namespace KalturaPlayerTypes {
paused: boolean;
seeking: boolean;
isOnLiveEdge: () => boolean;
loadMedia: (options: {entryId: string, ks?: string}) => void;
loadMedia: (options: {entryId: string; ks?: string}) => void;
getVideoElement(): HTMLVideoElement;
addEventListener(type: string, listener: CoreEventListener): void;
removeEventListener: (type: string, listener: CoreEventListener) => void;
Event: Record<string, string>;
Event: Record<string, any>;
currentTime: number;
playbackRate: number;
duration: number;
Expand All @@ -35,6 +35,8 @@ declare namespace KalturaPlayerTypes {
configure: Function;
ui: any;
config: KalturaPlayerTypes.PlayerConfig;
cuepoint: any;
provider: any;
cuePointManager: any;
}
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1150,10 +1150,10 @@
react-redux "^7.2.0"
redux "^4.0.5"

"@playkit-js/playkit-js@0.73.1":
version "0.73.1"
resolved "https://registry.yarnpkg.com/@playkit-js/playkit-js/-/playkit-js-0.73.1.tgz#f48d1694d26b6e36f1433847639452d09c9dfedb"
integrity sha512-9u/BIj+kSr3mftS+7aAxofzXFJaLfghTSUZCNY7WS5eA322eHZtdeyafuOD0uN2opScmEZ/oha0LTvahvOOrGg==
"@playkit-js/playkit-js@canary":
version "0.74.0-canary.83c8786"
resolved "https://registry.yarnpkg.com/@playkit-js/playkit-js/-/playkit-js-0.74.0-canary.83c8786.tgz#63c3dee8b6b80bc58f1ec68cb6f73c294475632c"
integrity sha512-5eedZ/D9zSfbKmDk2h0FoN4SOHUTtSfYFlGiuMKPEXO++piklLDSwfR6x/c85F1nCLLhtvpWh5840DHXedFhtg==
dependencies:
js-logger "^1.6.0"
ua-parser-js "^0.7.21"
Expand Down

0 comments on commit 025059a

Please sign in to comment.