Skip to content

Commit 1eee561

Browse files
Merge pull request #38 from apivideo/v1.2.15
v1.2.15
2 parents b464177 + 2ebde1d commit 1eee561

File tree

7 files changed

+155
-26
lines changed

7 files changed

+155
-26
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Changelog
22
All changes to this project will be documented in this file.
33

4+
## [1.2.15] - 2022-04-20
5+
- Add event callback types
6+
- Delay some methods execution after ready event is received
7+
- Add playbackRate option
8+
- Add hideTitle() and showTitle() methods
9+
- Add setAutoplay() method
10+
411
## [1.2.14] - 2022-04-11
512
- Add `chromeless` mode
613
- Add `hidePoster` option

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
- [`setChromeless(chromeless: boolean)`](#setchromelesschromeless-boolean)
2828
- [`hideSubtitles()`](#hidesubtitles)
2929
- [`showSubtitles()`](#showsubtitles)
30+
- [`hideTitles()`](#hidetitles)
31+
- [`showTitles()`](#showtitles)
3032
- [`setLoop(loop: boolean)`](#setlooploop-boolean)
33+
- [`setAutoplay(autoplay: boolean)`](#setautoplayautoplay-boolean)
3134
- [`seek(time: number)`](#seektime-number)
3235
- [`setPlaybackRate(rate: number)`](#setplaybackraterate-number)
3336
- [`setCurrentTime(time: number)`](#setcurrenttimetime-number)
@@ -139,6 +142,7 @@ The PlayerSdk constructor takes 2 parameters:
139142
| hidePoster | no (default: false) | boolean | the poster image isn't displayed |
140143
| showSubtitles | no (default: false) | boolean | the video subtitles are shown by default |
141144
| loop | no (default: false) | boolean | once the video is finished it automatically starts again |
145+
| playbackRate | no (default: 1) | number | the playback rate of the video: 1 for normal, 2 for x2, etc. |
142146

143147

144148
The sdk instance can be used to control the video playback, and to listen to player events.
@@ -226,8 +230,14 @@ The sdk instance has the following methods:
226230
> Hide the player subtitles.
227231
#### `showSubtitles()`
228232
> Show the player subtitles.
233+
#### `hideTitles()`
234+
> Hide the video title at the top of the video.
235+
#### `showTitles()`
236+
> Show the video title at the top of the video.
229237
#### `setLoop(loop: boolean)`
230238
> Define if the video should be played in loop.
239+
#### `setAutoplay(autoplay: boolean)`
240+
> Define if the video should start playing as soon as it is loaded |
231241
#### `seek(time: number)`
232242
> Add/substract the given number of seconds to/from the playback time.
233243
#### `setPlaybackRate(rate: number)`

dist/index.d.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,47 @@ declare type SdkOptions = {
2626
iframeUrl?: string;
2727
token?: string;
2828
showSubtitles?: boolean;
29+
playbackRate?: number;
2930
};
30-
declare type ControlName = "play" | "seekBack" | "seekForward" | "playbackRate" | "volume" | "fullscreen" | "subtitles" | "chapters" | "pictureInPicture" | "progressBar" | "chromecast" | "download" | "more";
31+
declare type PlayerSdkEvent = {
32+
controlsdisabled: () => void;
33+
controlsenabled: () => void;
34+
ended: () => void;
35+
error: () => void;
36+
firstplay: () => void;
37+
fullscreenchange: () => void;
38+
mouseenter: () => void;
39+
mouseleave: () => void;
40+
pause: () => void;
41+
play: () => void;
42+
playerresize: () => void;
43+
qualitychange: (value: {
44+
resolution: {
45+
height: number;
46+
width: number;
47+
};
48+
}) => void;
49+
ratechange: () => void;
50+
ready: () => void;
51+
resize: () => void;
52+
seeking: () => void;
53+
timeupdate: (value: {
54+
currentTime: number;
55+
}) => void;
56+
useractive: () => void;
57+
userinactive: () => void;
58+
volumechange: (value: {
59+
volume: number;
60+
}) => void;
61+
};
62+
export declare type ControlName = "play" | "seekBackward" | "seekForward" | "playbackRate" | "volume" | "fullscreen" | "subtitles" | "chapters" | "pictureInPicture" | "progressBar" | "chromecast" | "download" | "more";
3163
export declare class PlayerSdk {
3264
private static DEFAULT_IFRAME_URL;
3365
private iframe;
34-
private playerReady;
35-
private onceReadyCallbacks;
66+
private sdkInSync;
67+
private currentVideoReady;
68+
private onceSdkInSyncCallbacks;
69+
private onceVideoReadyCallbacks;
3670
private userEventListeners;
3771
private sdkPlayerId;
3872
private sdkOrigin;
@@ -47,12 +81,15 @@ export declare class PlayerSdk {
4781
showControls(controls?: ControlName[]): void;
4882
hideSubtitles(): void;
4983
showSubtitles(): void;
84+
hideTitle(): void;
85+
showTitle(): void;
5086
pause(): void;
5187
mute(): void;
5288
unmute(): void;
5389
seek(time: number): void;
5490
setCurrentTime(time: number): void;
5591
setVolume(volume: number): void;
92+
setAutoplay(autoplay: boolean): void;
5693
setLoop(loop: boolean): void;
5794
setChromeless(chromeless: boolean): void;
5895
setPlaybackRate(rate: number): void;
@@ -64,15 +101,23 @@ export declare class PlayerSdk {
64101
getPlaybackRate(callback?: (rate: number) => void): Promise<number>;
65102
getVolume(callback?: (volume: number) => void): Promise<number>;
66103
getLoop(callback?: (loop: boolean) => void): Promise<boolean>;
67-
addEventListener(event: string, callback: () => void): void;
104+
getVideoSize(callback?: (size: {
105+
width: number;
106+
height: number;
107+
}) => void): Promise<{
108+
width: number;
109+
height: number;
110+
}>;
111+
addEventListener<K extends keyof PlayerSdkEvent>(event: K, callback: PlayerSdkEvent[K]): void;
68112
destroy(): void;
69113
private createNewPlayer;
70114
private buildPlayerUrl;
71115
private bindExistingPlayer;
72116
private addParametersInIframeHash;
73117
private urlParametersFromOptions;
74118
private onEvent;
75-
private onReady;
119+
private onSdkInSync;
120+
private onVideoReady;
76121
private postMessage;
77122
private makeId;
78123
private createIframe;

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.ts

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,33 @@ type SdkOptions = {
3737
iframeUrl?: string;
3838
token?: string;
3939
showSubtitles?: boolean;
40+
playbackRate?: number;
4041
}
4142

42-
type ControlName = "play" | "seekBack" | "seekForward" | "playbackRate"
43+
type PlayerSdkEvent = {
44+
controlsdisabled: () => void;
45+
controlsenabled: () => void;
46+
ended: () => void;
47+
error: () => void;
48+
firstplay: () => void;
49+
fullscreenchange: () => void;
50+
mouseenter: () => void;
51+
mouseleave: () => void;
52+
pause: () => void;
53+
play: () => void;
54+
playerresize: () => void;
55+
qualitychange: (value: { resolution: { height: number, width: number }}) => void;
56+
ratechange: () => void;
57+
ready: () => void;
58+
resize: () => void;
59+
seeking: () => void;
60+
timeupdate: (value: { currentTime: number}) => void;
61+
useractive: () => void;
62+
userinactive: () => void;
63+
volumechange: (value: { volume: number}) => void;
64+
}
65+
66+
export type ControlName = "play" | "seekBackward" | "seekForward" | "playbackRate"
4367
| "volume" | "fullscreen" | "subtitles" | "chapters"
4468
| "pictureInPicture" | "progressBar" | "chromecast" | "download" | "more";
4569

@@ -48,8 +72,10 @@ export class PlayerSdk {
4872
private static DEFAULT_IFRAME_URL = "https://embed.api.video/${type}/${id}";
4973

5074
private iframe: HTMLIFrameElement | null = null;
51-
private playerReady: boolean = false;
52-
private onceReadyCallbacks: (() => void)[] = [];
75+
private sdkInSync: boolean = false;
76+
private currentVideoReady: boolean = false;
77+
private onceSdkInSyncCallbacks: (() => void)[] = [];
78+
private onceVideoReadyCallbacks: (() => void)[] = [];
5379
private userEventListeners: UserEventListener[] = [];
5480
private sdkPlayerId: number;
5581
private sdkOrigin: string;
@@ -85,9 +111,10 @@ export class PlayerSdk {
85111
this.bindExistingPlayer(this.iframe);
86112
}
87113

88-
this.onceReadyCallbacks = [];
114+
this.onceSdkInSyncCallbacks = [];
89115
this.userEventListeners = [];
90-
this.playerReady = false;
116+
this.sdkInSync = false;
117+
this.currentVideoReady = false;
91118
this.playerOrigin = new URL(this.iframeUrl).origin;
92119

93120
window.addEventListener("message", (message) => {
@@ -99,9 +126,14 @@ export class PlayerSdk {
99126
}
100127
}
101128
}, false);
129+
130+
if(options.playbackRate) {
131+
this.setPlaybackRate(options.playbackRate);
132+
}
102133
}
103134

104135
loadConfig(options: SdkOptions) {
136+
this.currentVideoReady = false;
105137
this.postMessage({
106138
message: 'loadConfig',
107139
url: this.buildPlayerUrl(options)
@@ -123,6 +155,12 @@ export class PlayerSdk {
123155
showSubtitles() {
124156
this.postMessage({ message: 'showSubtitles' });
125157
}
158+
hideTitle() {
159+
this.postMessage({ message: 'hideTitle' });
160+
}
161+
showTitle() {
162+
this.postMessage({ message: 'showTitle' });
163+
}
126164
pause() {
127165
this.postMessage({ message: 'pause' });
128166
}
@@ -141,14 +179,17 @@ export class PlayerSdk {
141179
setVolume(volume: number) {
142180
this.postMessage({ message: 'setVolume', volume });
143181
}
182+
setAutoplay(autoplay: boolean) {
183+
this.postMessage({ message: 'setAutoplay', autoplay });
184+
}
144185
setLoop(loop: boolean) {
145186
this.postMessage({ message: 'setLoop', loop });
146187
}
147188
setChromeless(chromeless: boolean) {
148189
this.postMessage({ message: 'setChromeless', chromeless });
149190
}
150191
setPlaybackRate(rate: number) {
151-
this.postMessage({ message: 'setPlaybackRate', rate });
192+
this.postMessage({ message: 'setPlaybackRate', rate }, undefined, true);
152193
}
153194
setTheme(theme: PlayerTheme) {
154195
this.postMessage({ message: 'setTheme', theme });
@@ -160,7 +201,7 @@ export class PlayerSdk {
160201
return this.postMessage({ message: 'getMuted' }, callback);
161202
}
162203
getDuration(callback?: (duration: number) => void): Promise<number> {
163-
return this.postMessage({ message: 'getDuration' }, callback);
204+
return this.postMessage({ message: 'getDuration' }, callback, true);
164205
}
165206
getCurrentTime(callback?: (currentTime: number) => void): Promise<number> {
166207
return this.postMessage({ message: 'getCurrentTime' }, callback);
@@ -174,8 +215,11 @@ export class PlayerSdk {
174215
getLoop(callback?: (loop: boolean) => void): Promise<boolean> {
175216
return this.postMessage({ message: 'getLoop' }, callback);
176217
}
218+
getVideoSize(callback?: (size: {width: number, height: number}) => void): Promise<{width: number, height: number}> {
219+
return this.postMessage({ message: 'getVideoSize' }, callback, true);
220+
}
177221

178-
addEventListener(event: string, callback: () => void) {
222+
addEventListener<K extends keyof PlayerSdkEvent>(event: K, callback: PlayerSdkEvent[K]) {
179223
this.userEventListeners.push({ event, callback });
180224
}
181225

@@ -252,9 +296,15 @@ export class PlayerSdk {
252296
}
253297

254298
private urlParametersFromOptions(options: SdkOptions) {
299+
const allowedKeys = ["id", "live", "autoplay", "muted", "metadata", "hideControls", "hidePoster",
300+
"chromeless", "loop", "hideTitle", "iframeUrl", "token", "showSubtitles", "ts"];
301+
255302
const optionsAsAny = options as any;
256303
optionsAsAny.ts = new Date().getTime();
257304
return Object.keys(options).map((key: string) => {
305+
if(allowedKeys.indexOf(key) === -1) {
306+
return;
307+
}
258308
if (key === "metadata" && typeof optionsAsAny[key] === "object") {
259309
const metadata = optionsAsAny[key];
260310
return Object.keys(metadata).map((metadataName: string) => {
@@ -275,22 +325,34 @@ export class PlayerSdk {
275325
.forEach(uel => uel.callback(userData));
276326

277327
switch (data.type) {
328+
case 'ready':
329+
this.onVideoReady();
330+
break;
278331
case 'sdkSync':
279-
this.onReady();
332+
this.onSdkInSync();
280333
break;
281334
}
282335
}
283336

284-
private onReady() {
285-
if (!this.playerReady) {
286-
this.playerReady = true;
287-
this.onceReadyCallbacks.forEach(cb => {
337+
private onSdkInSync() {
338+
if (!this.sdkInSync) {
339+
this.sdkInSync = true;
340+
this.onceSdkInSyncCallbacks.forEach(cb => {
341+
cb();
342+
});
343+
}
344+
}
345+
346+
private onVideoReady() {
347+
if(!this.currentVideoReady) {
348+
this.currentVideoReady = true;
349+
this.onceVideoReadyCallbacks.forEach(cb => {
288350
cb();
289351
});
290352
}
291353
}
292354

293-
private postMessage<T>(message: any, callback?: (arg: T) => void): Promise<T> {
355+
private postMessage<T>(message: any, callback?: (arg: T) => void, requireVideoReady: boolean = false): Promise<T> {
294356

295357
return new Promise((resolve, reject): void => {
296358

@@ -313,12 +375,17 @@ export class PlayerSdk {
313375
};
314376
messageWithPlayerId.callbackId = callbackId;
315377

378+
if(!this.currentVideoReady && requireVideoReady) {
379+
this.onceVideoReadyCallbacks.push(() => this.playerOrigin && this.iframe?.contentWindow?.postMessage(messageWithPlayerId, this.playerOrigin));
380+
return;
381+
}
316382

317-
if (this.playerReady && !!this.playerOrigin) {
383+
if (this.sdkInSync && !!this.playerOrigin) {
318384
this.iframe.contentWindow.postMessage(messageWithPlayerId, this.playerOrigin);
319-
} else {
320-
this.onceReadyCallbacks.push(() => this.playerOrigin && this.iframe?.contentWindow?.postMessage(messageWithPlayerId, this.playerOrigin));
385+
return;
321386
}
387+
388+
this.onceSdkInSyncCallbacks.push(() => this.playerOrigin && this.iframe?.contentWindow?.postMessage(messageWithPlayerId, this.playerOrigin));
322389
});
323390
}
324391

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@api.video/player-sdk",
3-
"version": "1.2.14",
3+
"version": "1.2.15",
44
"description": "api.video player SDK",
55
"repository": {
66
"type": "git",

0 commit comments

Comments
 (0)