@mediakind/mkplayer 1.0.7

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.
Files changed (45) hide show
  1. package/README.md +125 -0
  2. package/azure-pipelines.yml +34 -0
  3. package/dist/BufferLevel.d.ts +4 -0
  4. package/dist/Logger.d.ts +9 -0
  5. package/dist/MKPlayer.d.ts +26 -0
  6. package/dist/MKPlayerConfiguration.d.ts +6 -0
  7. package/dist/MKStream.d.ts +16 -0
  8. package/dist/SubtitleTrack.d.ts +4 -0
  9. package/dist/events/MKEvent.d.ts +13 -0
  10. package/dist/events/MKPlayerEventCallback.d.ts +4 -0
  11. package/dist/index.d.ts +4 -0
  12. package/dist/mkplayer.js +1 -0
  13. package/doc/assets/css/main.css +1 -0
  14. package/doc/assets/images/icons.png +0 -0
  15. package/doc/assets/images/icons@2x.png +0 -0
  16. package/doc/assets/images/widgets.png +0 -0
  17. package/doc/assets/images/widgets@2x.png +0 -0
  18. package/doc/assets/js/main.js +51 -0
  19. package/doc/assets/js/search.json +1 -0
  20. package/doc/classes/mkplayer.html +588 -0
  21. package/doc/enums/mkevent.html +303 -0
  22. package/doc/globals.html +146 -0
  23. package/doc/index.html +309 -0
  24. package/doc/interfaces/bufferlevel.html +140 -0
  25. package/doc/interfaces/mkplayerconfiguration.html +233 -0
  26. package/doc/interfaces/mkplayereventcallback.html +167 -0
  27. package/doc/interfaces/subtitletrack.html +195 -0
  28. package/favicon.ico +0 -0
  29. package/index.html +430 -0
  30. package/mk_logo.png +0 -0
  31. package/mkplayer-ui.min.css +2 -0
  32. package/mkplayer.zip +0 -0
  33. package/package.json +51 -0
  34. package/src/BufferLevel.ts +7 -0
  35. package/src/Logger.ts +51 -0
  36. package/src/MKPlayer.ts +289 -0
  37. package/src/MKPlayerConfiguration.ts +24 -0
  38. package/src/MKStream.ts +74 -0
  39. package/src/SubtitleTrack.ts +14 -0
  40. package/src/events/MKEvent.ts +16 -0
  41. package/src/events/MKPlayerEventCallback.ts +8 -0
  42. package/src/index.ts +4 -0
  43. package/tsconfig.json +20 -0
  44. package/tslint.json +72 -0
  45. package/typedoc.json +11 -0
@@ -0,0 +1,289 @@
1
+ import {
2
+ BufferType, HttpRequestType, LogLevel, MediaType, Player, PlayerAPI, PlayerConfig, PlayerEvent, SourceConfig,
3
+ SubtitleTrack,
4
+ } from 'bitmovin-player';
5
+ import { UIFactory } from 'bitmovin-player-ui';
6
+ import { MKPlayerConfiguration } from './MKPlayerConfiguration';
7
+ import { MKStream } from './MKStream';
8
+ import { MKEvent } from './events/MKEvent';
9
+ import { BufferLevel } from './BufferLevel';
10
+ import { MKPlayerEventCallback } from './events/MKPlayerEventCallback';
11
+ import { Logger } from './Logger';
12
+
13
+ /**
14
+ * MKPlayer is an HTML5 video player used for playback of HLS and DASH adaptive bitrate streams
15
+ */
16
+ export class MKPlayer {
17
+ private player: PlayerAPI;
18
+
19
+ /**
20
+ * constructor used to create a new MKPlayer instance
21
+ *
22
+ * @param containerElement - container that the video player will be rendered in
23
+ * @param mkPlayerConfiguration - configuration for this MKPlayer instance
24
+ */
25
+ constructor(containerElement: HTMLElement, mkPlayerConfiguration: MKPlayerConfiguration) {
26
+ let playerConfig: PlayerConfig = {
27
+ key: '84dc4716-55f9-43fa-ae8e-6fa334c5189b',
28
+ playback: {
29
+ autoplay: mkPlayerConfiguration.autoplay,
30
+ muted: mkPlayerConfiguration.muted,
31
+ },
32
+ analytics: {
33
+ key: '1c45ae9c-345e-4462-95e2-3e8faccd64f1',
34
+ },
35
+ location: {
36
+ ui: '//cdn.bitmovin.com/player/web/8.46.0/bitmovinplayer-ui.js',
37
+ ui_css: 'mkplayer-ui.min.css',
38
+ },
39
+ logs: {
40
+ level: LogLevel.OFF,
41
+ bitmovin: false,
42
+ },
43
+ network: {
44
+ preprocessHttpResponse: function(type, response) {
45
+ if (type === HttpRequestType.MANIFEST_HLS_VARIANT) {
46
+ // @ts-ignore
47
+ response.body = (response.body as string).replace('TIME-OFFSET=0',
48
+ 'TIME-OFFSET=0,PRECISE="YES"');
49
+ } else if (type === HttpRequestType.MANIFEST_HLS_MASTER) {
50
+ // @ts-ignore
51
+ response.body = (response.body as string).replace(',wvtt"',
52
+ '"');
53
+ }
54
+ return Promise.resolve(response);
55
+ },
56
+ },
57
+ };
58
+
59
+ let player = new Player(document.getElementById('player'), playerConfig);
60
+
61
+ if (mkPlayerConfiguration.smallScreen) {
62
+ UIFactory.buildDefaultSmallScreenUI(player);
63
+ } else {
64
+ UIFactory.buildDefaultUI(player);
65
+ }
66
+
67
+ if (mkPlayerConfiguration.debug) {
68
+ Logger.enable();
69
+ }
70
+
71
+ this.player = player;
72
+
73
+ console.log('%c MKPlayer ' + this.version() + ' www.mediakind.com', 'color: blue');
74
+ }
75
+
76
+ /**
77
+ * start playback or resumes playback after the player has been paused
78
+ */
79
+ play(): Promise<void> {
80
+ return this.player.play();
81
+ }
82
+
83
+ /**
84
+ * pauses playback on the player
85
+ */
86
+ pause(): void {
87
+ this.player.pause();
88
+ }
89
+
90
+ /**
91
+ * destroys the video player. You must create a new MKPlayer if this method is called
92
+ */
93
+ destroy(): Promise<void> {
94
+ return this.player.destroy();
95
+ }
96
+
97
+ /**
98
+ * Loads a new stream for playback
99
+ *
100
+ * @param stream - the stream the player will load
101
+ */
102
+ load(stream: MKStream): Promise<void> {
103
+ let playerSource: SourceConfig;
104
+ let url: string = MKPlayer.selectUrl(stream);
105
+
106
+ if (url.includes('.m3u8')) {
107
+ playerSource = {
108
+ hls: url,
109
+ };
110
+ } else if (url.includes('.mp4')) {
111
+ playerSource = {
112
+ progressive: url,
113
+ };
114
+ } else {
115
+ playerSource = {
116
+ dash: url,
117
+ };
118
+ }
119
+
120
+ if (stream.poster) {
121
+ playerSource.poster = stream.poster;
122
+ }
123
+
124
+ if (stream.assetIdentifier) {
125
+ playerSource.analytics = {
126
+ videoId: stream.assetIdentifier,
127
+ };
128
+ }
129
+
130
+ if (stream.subtitleTracks) {
131
+ playerSource.subtitleTracks = stream.subtitleTracks.map((track) => <SubtitleTrack>{
132
+ lang: track.language,
133
+ url: track.url,
134
+ id: MKPlayer.makeId(4),
135
+ });
136
+ }
137
+
138
+ Logger.log('[MKPlayer] loading source - ' + JSON.stringify(playerSource));
139
+
140
+ return this.player.load(playerSource);
141
+ }
142
+
143
+ /**
144
+ * Removes a handler for a MKEvent
145
+ *
146
+ * @param eventType
147
+ * @param callback
148
+ */
149
+ off(eventType: MKEvent, callback: MKPlayerEventCallback): void {
150
+ let playerEventType = MKPlayer.mapEvent(eventType);
151
+
152
+ return this.player.off(playerEventType, callback);
153
+ }
154
+
155
+ /**
156
+ * Subscribes and event handler to a MKEvent
157
+ *
158
+ * @param eventType
159
+ * @param callback
160
+ */
161
+ on(eventType: MKEvent, callback: MKPlayerEventCallback): void {
162
+ let playerEventType = MKPlayer.mapEvent(eventType);
163
+
164
+ return this.player.on(playerEventType, callback);
165
+ }
166
+
167
+ /**
168
+ * unloads the current playing stream
169
+ */
170
+ unload(): Promise<void> {
171
+ return this.player.unload();
172
+ }
173
+
174
+ /**
175
+ * gets the player's current time
176
+ */
177
+ getCurrentTime(): number {
178
+ return this.player.getCurrentTime();
179
+ }
180
+
181
+ /**
182
+ * gets the current audio and video buffer levels
183
+ *
184
+ * @returns
185
+ */
186
+ getBufferLevels(): BufferLevel {
187
+ return {
188
+ audio: this.player.buffer.getLevel(BufferType.ForwardDuration, MediaType.Audio).level,
189
+ video: this.player.buffer.getLevel(BufferType.ForwardDuration, MediaType.Video).level,
190
+ };
191
+ }
192
+
193
+ /**
194
+ * mutes the player
195
+ */
196
+ mute(): void {
197
+ this.player.mute();
198
+ }
199
+
200
+ /**
201
+ * unmute the player
202
+ */
203
+ unmute(): void {
204
+ this.player.unmute();
205
+ }
206
+
207
+ /**
208
+ * sets the player's volume in the range of 0 (silent) to 100 (max volume)
209
+ *
210
+ * @param volume The volume to set between 0 and 100
211
+
212
+ */
213
+ setVolume(volume: number): void {
214
+ this.player.setVolume(volume);
215
+ }
216
+
217
+ /**
218
+ * returns the current player version
219
+ */
220
+ version(): string {
221
+ return '1.0.7';
222
+ }
223
+
224
+ private static selectUrl(source: MKStream): string {
225
+ let rand = MKPlayer.getRandomInt(99);
226
+ if (source.cdnFailoverPercent && source.secondaryUrl && rand < source.cdnFailoverPercent) {
227
+ Logger.log('[MKPlayer] selecting secondary source url - ' + source.secondaryUrl);
228
+ return source.secondaryUrl;
229
+ } else {
230
+ Logger.log('[MKPlayer] selecting primary source url - ' + source.primaryUrl);
231
+ return source.primaryUrl;
232
+ }
233
+ }
234
+
235
+ private static getRandomInt(max: number) {
236
+ return Math.floor(Math.random() * Math.floor(max));
237
+ }
238
+
239
+ private static makeId(length) {
240
+ let result = '';
241
+ let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
242
+ let charactersLength = characters.length;
243
+ for (let i = 0; i < length; i++) {
244
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
245
+ }
246
+ return result;
247
+ }
248
+
249
+ private static mapEvent(event: MKEvent): PlayerEvent {
250
+ let playerEventType: PlayerEvent;
251
+ switch (event) {
252
+ case MKEvent.BufferingStarted:
253
+ playerEventType = PlayerEvent.StallStarted;
254
+ break;
255
+ case MKEvent.BufferingEnded:
256
+ playerEventType = PlayerEvent.StallEnded;
257
+ break;
258
+ case MKEvent.Playing:
259
+ playerEventType = PlayerEvent.Playing;
260
+ break;
261
+ case MKEvent.TimeChanged:
262
+ playerEventType = PlayerEvent.TimeChanged;
263
+ break;
264
+ case MKEvent.Ready:
265
+ playerEventType = PlayerEvent.Ready;
266
+ break;
267
+ case MKEvent.Error:
268
+ playerEventType = PlayerEvent.Error;
269
+ break;
270
+ case MKEvent.StreamFinished:
271
+ playerEventType = PlayerEvent.PlaybackFinished;
272
+ break;
273
+ case MKEvent.Warning:
274
+ playerEventType = PlayerEvent.Warning;
275
+ break;
276
+ case MKEvent.QualityChanged:
277
+ playerEventType = PlayerEvent.VideoPlaybackQualityChanged;
278
+ break;
279
+ case MKEvent.SegmentPlayback:
280
+ playerEventType = PlayerEvent.SegmentPlayback;
281
+ break;
282
+ case MKEvent.Unloaded:
283
+ playerEventType = PlayerEvent.SourceUnloaded;
284
+ break;
285
+ }
286
+
287
+ return playerEventType;
288
+ }
289
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * MKPlayer's configuration interface
3
+ */
4
+ export interface MKPlayerConfiguration {
5
+ /**
6
+ * Toggles debug output logging
7
+ */
8
+ debug: boolean;
9
+
10
+ /**
11
+ * Option to enable the player to start playback after successfully loading a source
12
+ */
13
+ autoplay: boolean;
14
+
15
+ /**
16
+ * Option to enable the player to start in a muted state. The user is able to unmute via the UI or an API call through
17
+ */
18
+ muted: boolean;
19
+
20
+ /**
21
+ * Boolean indicating if the player should load the small screen ui
22
+ */
23
+ smallScreen: boolean;
24
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Configuration object used when loading a new stream
3
+ */
4
+ import { SubtitleTrack } from './SubtitleTrack';
5
+
6
+ export class MKStream {
7
+ private readonly _assetIdentifier: string;
8
+ private readonly _primaryUrl?: string;
9
+ private readonly _secondaryUrl?: string;
10
+ private readonly _subtitleTracks: SubtitleTrack[];
11
+ private readonly _cdnFailoverPercent: number = 0;
12
+ private readonly _poster: string;
13
+
14
+ /**
15
+ *
16
+ * @param primaryUrl - primary stream url
17
+ * @param secondaryUrl - secondary backup stream url
18
+ * @param subtitleTracks - a list of external subtitle tracks that should be loaded with the player
19
+ * @param poster - url to a poster image to render on the player
20
+ * @param cdnFailoverPercent - percent value from 0-100 describing what percentage of users should initially playback
21
+ * the secondary url
22
+ * @param assetIdentifier - identifier for the current stream
23
+ */
24
+ constructor(primaryUrl: string, assetIdentifier: string, subtitleTracks?: SubtitleTrack[], poster?: string, secondaryUrl?: string, cdnFailoverPercent?: number) {
25
+ this._cdnFailoverPercent = cdnFailoverPercent;
26
+ this._secondaryUrl = secondaryUrl;
27
+ this._primaryUrl = primaryUrl;
28
+ this._assetIdentifier = assetIdentifier;
29
+ this._subtitleTracks = subtitleTracks;
30
+ this._poster = poster;
31
+ }
32
+
33
+ /**
34
+ * percent value from 0-100 describing what percentage of users should playback the secondary url
35
+ */
36
+ public get cdnFailoverPercent(): number {
37
+ return this._cdnFailoverPercent;
38
+ }
39
+
40
+ /**
41
+ * primary stream url used during playback
42
+ */
43
+ public get primaryUrl(): string {
44
+ return this._primaryUrl;
45
+ }
46
+
47
+ /**
48
+ * secondary stream url used during playback
49
+ */
50
+ public get secondaryUrl(): string {
51
+ return this._secondaryUrl;
52
+ }
53
+
54
+ /**
55
+ * percent value from 0-100 describing what percentage of users should playback the secondary url
56
+ */
57
+ public get subtitleTracks(): SubtitleTrack[] {
58
+ return this._subtitleTracks;
59
+ }
60
+
61
+ /**
62
+ * identifier for the current stream
63
+ */
64
+ public get assetIdentifier(): string {
65
+ return this._assetIdentifier;
66
+ }
67
+
68
+ /**
69
+ * poster art for the current stream
70
+ */
71
+ public get poster(): string {
72
+ return this._poster;
73
+ }
74
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Used to describe an external subtitle track (WebVtt or srt) outside of the MKStream manifest url
3
+ */
4
+ export interface SubtitleTrack {
5
+ /**
6
+ * url to the external subtitle track
7
+ */
8
+ url: string;
9
+
10
+ /**
11
+ * language of the subtitle track. This string will be displayed in the UI
12
+ */
13
+ language: string;
14
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Events that are fired during playback
3
+ */
4
+ export enum MKEvent {
5
+ Playing = 'playing',
6
+ Ready = 'ready',
7
+ TimeChanged = 'timechanged',
8
+ Error = 'error',
9
+ BufferingStarted = 'bufferingstarted',
10
+ BufferingEnded = 'bufferingended',
11
+ StreamFinished = 'streamfinished',
12
+ Warning = 'warning',
13
+ QualityChanged = 'qualitychanged',
14
+ SegmentPlayback = 'segmentplayback',
15
+ Unloaded = 'unloaded',
16
+ }
@@ -0,0 +1,8 @@
1
+ import { PlayerEventBase } from 'bitmovin-player';
2
+
3
+ /**
4
+ * Interface describing the data returned in the MKPlayer event callback
5
+ */
6
+ export interface MKPlayerEventCallback {
7
+ (event: PlayerEventBase): void;
8
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { MKPlayer } from './MKPlayer';
2
+ export { MKPlayerConfiguration } from './MKPlayerConfiguration';
3
+ export { MKStream } from './MKStream';
4
+ export { MKEvent } from './events/MKEvent';
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "files": [
3
+ "src/index.ts"
4
+ ],
5
+ "compilerOptions": {
6
+ "outDir": "./dist",
7
+ "target": "es5",
8
+ "module": "commonjs",
9
+ "moduleResolution": "node",
10
+ "declaration": true,
11
+ "lib": ["es2016", "es2015.promise", "dom"],
12
+ "sourceMap": true,
13
+ "noImplicitAny": false,
14
+ "removeComments": true,
15
+ "skipLibCheck": true
16
+ },
17
+ "include": [
18
+ "./src"
19
+ ]
20
+ }
package/tslint.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "rules": {
3
+ "class-name": true,
4
+ "comment-format": [
5
+ true,
6
+ "check-space"
7
+ ],
8
+ "indent": [
9
+ true,
10
+ "spaces"
11
+ ],
12
+ "no-duplicate-variable": true,
13
+ "no-eval": true,
14
+ "no-internal-module": true,
15
+ "no-trailing-whitespace": true,
16
+ "no-var-keyword": false,
17
+ "one-line": [
18
+ true,
19
+ "check-open-brace",
20
+ "check-whitespace"
21
+ ],
22
+ "quotemark": [
23
+ true,
24
+ "single"
25
+ ],
26
+ "semicolon": [
27
+ true,
28
+ "always",
29
+ "ignore-bound-class-methods"
30
+ ],
31
+ "triple-equals": [
32
+ true,
33
+ "allow-null-check"
34
+ ],
35
+ "typedef-whitespace": [
36
+ true,
37
+ {
38
+ "call-signature": "nospace",
39
+ "index-signature": "nospace",
40
+ "parameter": "nospace",
41
+ "property-declaration": "nospace",
42
+ "variable-declaration": "nospace"
43
+ }
44
+ ],
45
+ "variable-name": [
46
+ true,
47
+ "ban-keywords"
48
+ ],
49
+ "whitespace": [
50
+ true,
51
+ "check-branch",
52
+ "check-decl",
53
+ "check-operator",
54
+ "check-separator",
55
+ "check-type"
56
+ ],
57
+ "trailing-comma": [
58
+ true,
59
+ {
60
+ "multiline": {
61
+ "arrays": "always",
62
+ "exports": "always",
63
+ "functions": "never",
64
+ "imports": "always",
65
+ "objects": "always",
66
+ "typeLiterals": "always"
67
+ },
68
+ "singleline": "never"
69
+ }
70
+ ]
71
+ }
72
+ }
package/typedoc.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "stripInternal": "true",
3
+ "out": "doc",
4
+ "excludeNotExported": "true",
5
+ "name": "MKPlayer",
6
+ "exclude": "src/index.ts",
7
+ "mode": "file",
8
+ "excludePrivate": "true",
9
+ "excludeProtected": true,
10
+ "excludeNotDocumented": true
11
+ }