@npo/player 1.23.2 → 1.24.1
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.
- package/README.md +1 -1
- package/lib/js/playeractions/handlers/error.js +2 -2
- package/lib/js/playeractions/handlers/error.test.js +2 -2
- package/lib/js/playeractions/handlers/handleoffsets.d.ts +4 -6
- package/lib/js/playeractions/handlers/handleoffsets.js +16 -17
- package/lib/js/playeractions/handlers/handleoffsets.test.js +73 -29
- package/lib/js/playeractions/handlers/mediasessionactions.js +24 -12
- package/lib/js/playeractions/handlers/processsourceconfig.js +16 -3
- package/lib/js/tracking/handlers/eventbinding.d.ts +1 -1
- package/lib/js/tracking/handlers/eventbinding.js +17 -23
- package/lib/js/tracking/handlers/eventlogging.d.ts +1 -1
- package/lib/js/tracking/handlers/eventlogging.js +18 -18
- package/lib/js/tracking/handlers/eventlogging.test.js +24 -24
- package/lib/js/tracking/handlers/playertrackerstart.js +4 -2
- package/lib/lang/nl.json +3 -1
- package/lib/npoplayer.d.ts +1 -2
- package/lib/npoplayer.js +30 -44
- package/lib/package.json +5 -5
- package/lib/services/a11y/setup.js +2 -2
- package/lib/services/a11y/setup.test.js +7 -8
- package/lib/services/advertHandlers/discardAdBreak.d.ts +2 -0
- package/lib/services/advertHandlers/discardAdBreak.js +11 -0
- package/lib/services/advertHandlers/discardAdBreak.test.js +60 -0
- package/lib/services/advertHandlers/handlePreRolls.d.ts +2 -0
- package/lib/services/advertHandlers/handlePreRolls.js +132 -0
- package/lib/services/advertHandlers/handlePrerolls.test.js +52 -0
- package/lib/services/cdnProviders/cdnProviders.d.ts +4 -0
- package/lib/services/cdnProviders/cdnProviders.js +22 -0
- package/lib/services/cdnProviders/cndProviders.test.d.ts +1 -0
- package/lib/services/cdnProviders/cndProviders.test.js +22 -0
- package/lib/services/eventListenerHandlers/removeEventListeners.d.ts +1 -1
- package/lib/services/eventListenerHandlers/removeEventListeners.js +4 -4
- package/lib/services/eventListenerHandlers/removeEventListeners.test.js +28 -13
- package/lib/services/liveStreamHandlers/handleLiveStreamControls.d.ts +1 -1
- package/lib/services/liveStreamHandlers/handleLiveStreamControls.js +3 -3
- package/lib/services/liveStreamHandlers/handleLiveStreamControls.test.d.ts +2 -0
- package/lib/services/liveStreamHandlers/handleLiveStreamControls.test.js +65 -0
- package/lib/services/localStorageHandlers/localStorageHandlers.d.ts +1 -1
- package/lib/services/localStorageHandlers/localStorageHandlers.test.js +0 -1
- package/lib/services/npoPlayerAPI/contants.d.ts +5 -0
- package/lib/services/npoPlayerAPI/contants.js +5 -0
- package/lib/services/npoPlayerAPI/npoPlayerAPI.d.ts +17 -4
- package/lib/services/npoPlayerAPI/npoPlayerAPI.js +68 -3
- package/lib/services/npoPlayerAPI/npoPlayerAPI.test.js +66 -1
- package/lib/services/segmentHandlers/addSegmentEventListeners.js +3 -3
- package/lib/services/segmentHandlers/addSegmentEventListeners.test.js +10 -9
- package/lib/services/segmentHandlers/convertFragmentToSegment.d.ts +1 -1
- package/lib/services/segmentHandlers/handleSegmentSeek.d.ts +1 -1
- package/lib/services/segmentHandlers/handleSegmentSeek.test.js +4 -4
- package/lib/services/segmentHandlers/handleSegmentTimeChanged.d.ts +1 -1
- package/lib/services/segmentHandlers/handleSegmentTimeChanged.test.js +33 -24
- package/lib/services/segmentHandlers/initSegment.d.ts +1 -1
- package/lib/services/segmentHandlers/initSegment.test.js +3 -1
- package/lib/services/segmentHandlers/setSegmentMarkers.d.ts +1 -1
- package/lib/services/services.d.ts +3 -1
- package/lib/services/services.js +8 -0
- package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.d.ts +2 -0
- package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.js +8 -0
- package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.test.d.ts +1 -0
- package/lib/services/verticalVideoHandlers/handleVerticalVideoControls.test.js +36 -0
- package/lib/src/js/playeractions/handlers/handleoffsets.d.ts +4 -6
- package/lib/src/js/tracking/handlers/eventbinding.d.ts +1 -1
- package/lib/src/js/tracking/handlers/eventlogging.d.ts +1 -1
- package/lib/src/npoplayer.d.ts +1 -2
- package/lib/src/services/advertHandlers/discardAdBreak.d.ts +2 -0
- package/lib/src/services/advertHandlers/discardAdBreak.test.d.ts +1 -0
- package/lib/src/services/advertHandlers/handlePreRolls.d.ts +2 -0
- package/lib/src/services/advertHandlers/handlePrerolls.test.d.ts +1 -0
- package/lib/src/services/cdnProviders/cdnProviders.d.ts +4 -0
- package/lib/src/services/cdnProviders/cndProviders.test.d.ts +1 -0
- package/lib/src/services/eventListenerHandlers/removeEventListeners.d.ts +1 -1
- package/lib/src/services/liveStreamHandlers/handleLiveStreamControls.d.ts +1 -1
- package/lib/src/services/liveStreamHandlers/handleLiveStreamControls.test.d.ts +2 -0
- package/lib/src/services/localStorageHandlers/localStorageHandlers.d.ts +1 -1
- package/lib/src/services/npoPlayerAPI/contants.d.ts +5 -0
- package/lib/src/services/npoPlayerAPI/npoPlayerAPI.d.ts +17 -4
- package/lib/src/services/segmentHandlers/convertFragmentToSegment.d.ts +1 -1
- package/lib/src/services/segmentHandlers/handleSegmentSeek.d.ts +1 -1
- package/lib/src/services/segmentHandlers/handleSegmentTimeChanged.d.ts +1 -1
- package/lib/src/services/segmentHandlers/initSegment.d.ts +1 -1
- package/lib/src/services/segmentHandlers/setSegmentMarkers.d.ts +1 -1
- package/lib/src/services/services.d.ts +3 -1
- package/lib/src/services/verticalVideoHandlers/handleVerticalVideoControls.d.ts +2 -0
- package/lib/src/services/verticalVideoHandlers/handleVerticalVideoControls.test.d.ts +1 -0
- package/lib/src/types/events.d.ts +8 -1
- package/lib/src/types/interfaces.d.ts +8 -12
- package/lib/src/ui/components/audio/controlbar.d.ts +1 -1
- package/lib/src/ui/components/controlbar.d.ts +1 -1
- package/lib/src/ui/components/seekbar.d.ts +1 -1
- package/lib/src/ui/components/settingspanel.d.ts +1 -1
- package/lib/src/ui/components/verticalvideo/controlbar.d.ts +3 -0
- package/lib/src/ui/handlers/streamhandler.d.ts +2 -4
- package/lib/src/ui/uicontainer.d.ts +2 -2
- package/lib/tests/mocks/mockNpoplayer.js +0 -1
- package/lib/tests/mocks/playerContextMock.d.ts +67 -0
- package/lib/tests/mocks/playerContextMock.js +118 -0
- package/lib/types/events.d.ts +8 -1
- package/lib/types/events.js +184 -1
- package/lib/types/interfaces.d.ts +8 -12
- package/lib/types/interfaces.js +1 -0
- package/lib/ui/components/audio/controlbar.d.ts +1 -1
- package/lib/ui/components/audio/controlbar.js +6 -6
- package/lib/ui/components/controlbar.d.ts +1 -1
- package/lib/ui/components/controlbar.js +13 -11
- package/lib/ui/components/nativemobile/controlbar.js +0 -1
- package/lib/ui/components/seekbar.js +1 -1
- package/lib/ui/components/settingspanel.d.ts +1 -1
- package/lib/ui/components/settingspanel.js +68 -84
- package/lib/ui/components/topbar.js +6 -3
- package/lib/ui/components/verticalvideo/controlbar.d.ts +3 -0
- package/lib/ui/components/verticalvideo/controlbar.js +34 -0
- package/lib/ui/handlers/streamhandler.d.ts +2 -4
- package/lib/ui/handlers/streamhandler.js +16 -7
- package/lib/ui/nativemobileuifactory.js +2 -0
- package/lib/ui/uicontainer.d.ts +2 -2
- package/lib/ui/uicontainer.js +35 -29
- package/package.json +5 -5
- package/src/style/components/_settingspanel.scss +35 -3
- package/src/style/components/_subtitles.scss +29 -25
- package/src/style/components/_textbuttons.scss +2 -2
- package/src/style/components/_volumeslider.scss +1 -0
- package/src/style/components/vertical-video/_bottombar.scss +19 -0
- package/src/style/components/vertical-video/_buttons.scss +23 -0
- package/src/style/components/vertical-video/_hugeplaybacktogglebutton.scss +14 -0
- package/src/style/components/vertical-video/_seekbar.scss +19 -0
- package/src/style/components/vertical-video/_settingsbutton.scss +7 -0
- package/src/style/components/vertical-video/_settingspanel.scss +14 -0
- package/src/style/components/vertical-video/_shortvideo.scss +14 -0
- package/src/style/components/vertical-video/_subtitles.scss +3 -0
- package/src/style/components/vertical-video/_topbar.scss +17 -0
- package/src/style/components/vertical-video/_volumeslider.scss +9 -0
- package/src/style/npoplayer.css +74 -34
- package/src/style/npoplayer.scss +2 -1
- package/src/style/variants/_player-small.scss +18 -10
- package/src/style/variants/_player-vertical.scss +23 -0
- package/lib/js/ads/ster.d.ts +0 -4
- package/lib/js/ads/ster.js +0 -126
- package/lib/js/ads/ster.test.js +0 -63
- package/lib/js/cdnproviders.d.ts +0 -1
- package/lib/js/cdnproviders.js +0 -16
- package/lib/src/js/ads/ster.d.ts +0 -4
- package/lib/src/js/cdnproviders.d.ts +0 -1
- package/lib/tests/mocks/mockPlayerContext.d.ts +0 -2
- package/lib/tests/mocks/mockPlayerContext.js +0 -40
- /package/lib/{js/ads/ster.test.d.ts → services/advertHandlers/discardAdBreak.test.d.ts} +0 -0
- /package/lib/{src/js/ads/ster.test.d.ts → services/advertHandlers/handlePrerolls.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Extensive and up-to-date documentation is available at https://docs.npoplayer.nl
|
|
|
11
11
|
Code quality is analysed by SonarCloud. The project can be found at https://sonarcloud.io/project/overview?id=NPOstart_npo-player
|
|
12
12
|
|
|
13
13
|
# Changelog
|
|
14
|
-
Current version: v1.
|
|
14
|
+
Current version: v1.24.0
|
|
15
15
|
|
|
16
16
|
The changelog is available at https://docs.npoplayer.nl/implementation/web/changelog/
|
|
17
17
|
|
|
@@ -5,8 +5,8 @@ export function handlePlayerError(player, uiComponents, input) {
|
|
|
5
5
|
}
|
|
6
6
|
console.error('Er is iets mis met het ophalen van de stream.', input);
|
|
7
7
|
player.unload();
|
|
8
|
-
if (uiComponents.
|
|
9
|
-
uiComponents.
|
|
8
|
+
if (uiComponents.controlBar)
|
|
9
|
+
uiComponents.controlBar.hide();
|
|
10
10
|
if (uiComponents.errorMessageOverlay == undefined)
|
|
11
11
|
return;
|
|
12
12
|
uiComponents.errorMessageOverlay.show();
|
|
@@ -6,7 +6,7 @@ const show = jest.fn();
|
|
|
6
6
|
const input = 'string';
|
|
7
7
|
const player = { unload };
|
|
8
8
|
const uiComponents = {
|
|
9
|
-
|
|
9
|
+
controlBar: { hide },
|
|
10
10
|
errorMessageOverlay: {
|
|
11
11
|
errorLabel: { setText },
|
|
12
12
|
show
|
|
@@ -27,7 +27,7 @@ describe('Test DRM verification', () => {
|
|
|
27
27
|
it('should not hide the controlbar', () => {
|
|
28
28
|
const components = {
|
|
29
29
|
...uiComponents,
|
|
30
|
-
|
|
30
|
+
controlBar: undefined
|
|
31
31
|
};
|
|
32
32
|
handlePlayerError(player, components, input);
|
|
33
33
|
expect(hide).not.toHaveBeenCalled();
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function shiftToProgramStart(player: PlayerAPI | undefined, timestamp?: number): void;
|
|
6
|
-
export declare function handleLiveOffsetLogic(npoplayer: NpoPlayer, player: PlayerAPI | undefined, options: StreamOptions): void;
|
|
1
|
+
import { PlayerContext, type StreamOptions } from '../../../types/interfaces';
|
|
2
|
+
export declare function handleStartOffset(playerContext: PlayerContext, offset?: number): void;
|
|
3
|
+
export declare function shiftToProgramStart(playerContext: PlayerContext, timestamp?: number): void;
|
|
4
|
+
export declare function handleLiveOffsetLogic(playerContext: PlayerContext, options: StreamOptions): void;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export function handleStartOffset(
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { NpoPlayerEvent } from '../../../types/events';
|
|
2
|
+
export function handleStartOffset(playerContext, offset) {
|
|
3
|
+
const { player } = playerContext;
|
|
4
|
+
if (offset == undefined || playerContext.player.isLive()) {
|
|
5
|
+
if (playerContext.player.isLive()) {
|
|
5
6
|
console.warn('handleStartOffset was called but the player is playing live content.');
|
|
6
7
|
}
|
|
7
8
|
return;
|
|
8
9
|
}
|
|
9
10
|
const seek = () => {
|
|
10
|
-
player.off(
|
|
11
|
-
player.off(
|
|
12
|
-
player.off(
|
|
11
|
+
player.off(NpoPlayerEvent.SourceLoaded, seek);
|
|
12
|
+
player.off(NpoPlayerEvent.AdBreakFinished, seek);
|
|
13
|
+
player.off(NpoPlayerEvent.AdError, seek);
|
|
13
14
|
player.seek(offset);
|
|
14
15
|
};
|
|
15
|
-
player.on(
|
|
16
|
-
player.on(
|
|
17
|
-
player.on(
|
|
16
|
+
player.on(NpoPlayerEvent.SourceLoaded, seek);
|
|
17
|
+
player.on(NpoPlayerEvent.AdBreakFinished, seek);
|
|
18
|
+
player.on(NpoPlayerEvent.AdError, seek);
|
|
18
19
|
}
|
|
19
|
-
export function shiftToProgramStart(
|
|
20
|
-
|
|
21
|
-
return;
|
|
20
|
+
export function shiftToProgramStart(playerContext, timestamp) {
|
|
21
|
+
const { player } = playerContext;
|
|
22
22
|
if (timestamp == undefined || !player.isLive()) {
|
|
23
23
|
if (!player.isLive()) {
|
|
24
24
|
console.warn('shiftToProgramStart was called but the player is playing VOD content.');
|
|
@@ -27,9 +27,8 @@ export function shiftToProgramStart(player, timestamp) {
|
|
|
27
27
|
}
|
|
28
28
|
player.timeShift(timestamp);
|
|
29
29
|
}
|
|
30
|
-
export function handleLiveOffsetLogic(
|
|
31
|
-
|
|
32
|
-
return;
|
|
30
|
+
export function handleLiveOffsetLogic(playerContext, options) {
|
|
31
|
+
const { player, npoplayer } = playerContext;
|
|
33
32
|
if (npoplayer.uiComponents.watchFromStartButton == undefined)
|
|
34
33
|
return;
|
|
35
34
|
if (options?.liveProgramTime == undefined) {
|
|
@@ -45,6 +44,6 @@ export function handleLiveOffsetLogic(npoplayer, player, options) {
|
|
|
45
44
|
}
|
|
46
45
|
if (options.liveOffset !== null && options.liveOffset !== false && options.liveProgramTime > 0) {
|
|
47
46
|
npoplayer.uiComponents.watchFromStartButton.hide();
|
|
48
|
-
shiftToProgramStart(
|
|
47
|
+
shiftToProgramStart(playerContext, options.liveProgramTime);
|
|
49
48
|
}
|
|
50
49
|
}
|
|
@@ -1,49 +1,93 @@
|
|
|
1
|
+
import { PlayerEvent } from 'bitmovin-player';
|
|
2
|
+
import { createPlayerContextMock, createMockNpoPlayerAPI } from '../../../../tests/mocks/playerContextMock';
|
|
1
3
|
import { handleStartOffset, shiftToProgramStart } from './handleoffsets';
|
|
2
|
-
const isLive = () => true;
|
|
3
|
-
const onReady = jest.fn();
|
|
4
|
-
const timeShift = jest.fn();
|
|
5
|
-
const offset = 10;
|
|
6
|
-
const timestamp = 10;
|
|
7
|
-
const player = {
|
|
8
|
-
isLive,
|
|
9
|
-
on: onReady,
|
|
10
|
-
timeShift
|
|
11
|
-
};
|
|
12
4
|
describe('Test offset handling', () => {
|
|
5
|
+
const offset = 10;
|
|
13
6
|
afterEach(() => {
|
|
14
7
|
jest.resetAllMocks();
|
|
15
8
|
});
|
|
16
9
|
it('should not seek when player is live', () => {
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
const mockNpoPlayerAPI = createMockNpoPlayerAPI({
|
|
11
|
+
isLive: jest.fn().mockReturnValue(true),
|
|
12
|
+
seek: jest.fn(),
|
|
13
|
+
on: jest.fn(),
|
|
14
|
+
off: jest.fn()
|
|
15
|
+
});
|
|
16
|
+
const playerContextMock = createPlayerContextMock({
|
|
17
|
+
player: mockNpoPlayerAPI
|
|
18
|
+
});
|
|
19
|
+
handleStartOffset(playerContextMock, offset);
|
|
20
|
+
expect(mockNpoPlayerAPI.seek).not.toHaveBeenCalled();
|
|
19
21
|
});
|
|
20
22
|
it('should not seek when offset is undefined', () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
const mockNpoPlayerAPI = createMockNpoPlayerAPI({
|
|
24
|
+
isLive: jest.fn().mockReturnValue(false),
|
|
25
|
+
seek: jest.fn(),
|
|
26
|
+
on: jest.fn(),
|
|
27
|
+
off: jest.fn()
|
|
28
|
+
});
|
|
29
|
+
const playerContextMock = createPlayerContextMock({
|
|
30
|
+
player: mockNpoPlayerAPI
|
|
31
|
+
});
|
|
32
|
+
handleStartOffset(playerContextMock);
|
|
33
|
+
expect(mockNpoPlayerAPI.seek).not.toHaveBeenCalled();
|
|
23
34
|
});
|
|
24
35
|
it('should seek when player is not live and offset is defined', () => {
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
const seekMock = jest.fn();
|
|
37
|
+
const mockNpoPlayerAPI = createMockNpoPlayerAPI({
|
|
38
|
+
isLive: jest.fn().mockReturnValue(false),
|
|
39
|
+
seek: seekMock,
|
|
40
|
+
off: jest.fn(),
|
|
41
|
+
on: jest.fn((event, callback) => {
|
|
42
|
+
if (event === PlayerEvent.SourceLoaded) {
|
|
43
|
+
callback();
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
const playerContextMock = createPlayerContextMock({
|
|
48
|
+
player: mockNpoPlayerAPI
|
|
49
|
+
});
|
|
50
|
+
handleStartOffset(playerContextMock, offset);
|
|
51
|
+
expect(seekMock).toHaveBeenCalledWith(offset);
|
|
27
52
|
});
|
|
28
53
|
});
|
|
29
54
|
describe('Test programStart shift', () => {
|
|
55
|
+
const timestamp = 30;
|
|
30
56
|
afterEach(() => {
|
|
31
57
|
jest.resetAllMocks();
|
|
32
58
|
});
|
|
33
|
-
it('should not call
|
|
34
|
-
|
|
35
|
-
|
|
59
|
+
it('should not call timeShift when timestamp is undefined', () => {
|
|
60
|
+
const mockNpoPlayerAPI = createMockNpoPlayerAPI({
|
|
61
|
+
isLive: jest.fn().mockReturnValue(true),
|
|
62
|
+
timeShift: jest.fn()
|
|
63
|
+
});
|
|
64
|
+
const playerContextMock = createPlayerContextMock({
|
|
65
|
+
player: mockNpoPlayerAPI
|
|
66
|
+
});
|
|
67
|
+
shiftToProgramStart(playerContextMock);
|
|
68
|
+
expect(mockNpoPlayerAPI.timeShift).not.toHaveBeenCalled();
|
|
36
69
|
});
|
|
37
|
-
it('should not call
|
|
38
|
-
|
|
39
|
-
|
|
70
|
+
it('should not call timeShift when player is not live', () => {
|
|
71
|
+
const mockNpoPlayerAPI = createMockNpoPlayerAPI({
|
|
72
|
+
isLive: jest.fn().mockReturnValue(false),
|
|
73
|
+
timeShift: jest.fn()
|
|
74
|
+
});
|
|
75
|
+
const playerContextMock = createPlayerContextMock({
|
|
76
|
+
player: mockNpoPlayerAPI
|
|
77
|
+
});
|
|
78
|
+
shiftToProgramStart(playerContextMock, timestamp);
|
|
79
|
+
expect(mockNpoPlayerAPI.timeShift).not.toHaveBeenCalled();
|
|
40
80
|
});
|
|
41
|
-
it('should
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
81
|
+
it('should call timeShift when player is live and timestamp is set', () => {
|
|
82
|
+
const timeShiftMock = jest.fn();
|
|
83
|
+
const mockNpoPlayerAPI = createMockNpoPlayerAPI({
|
|
84
|
+
isLive: jest.fn().mockReturnValue(true),
|
|
85
|
+
timeShift: timeShiftMock
|
|
86
|
+
});
|
|
87
|
+
const playerContextMock = createPlayerContextMock({
|
|
88
|
+
player: mockNpoPlayerAPI
|
|
89
|
+
});
|
|
90
|
+
shiftToProgramStart(playerContextMock, timestamp);
|
|
91
|
+
expect(timeShiftMock).toHaveBeenCalledWith(timestamp);
|
|
48
92
|
});
|
|
49
93
|
});
|
|
@@ -1,40 +1,52 @@
|
|
|
1
1
|
import { PlayerEvent } from 'bitmovin-player';
|
|
2
2
|
export function setupMediaSessionActionHandlers(player, sourceConfig, _streamObject) {
|
|
3
|
-
|
|
3
|
+
function handlePlaying() {
|
|
4
|
+
player.off(PlayerEvent.Playing, handlePlaying);
|
|
4
5
|
if (!('mediaSession' in navigator)) {
|
|
5
6
|
return;
|
|
6
7
|
}
|
|
7
8
|
setMediaSessionMetadata();
|
|
8
9
|
setupMediaSessionActionHandlers();
|
|
9
10
|
updatePositionState();
|
|
10
|
-
}
|
|
11
|
-
|
|
11
|
+
}
|
|
12
|
+
function handlePaused() {
|
|
13
|
+
player.off(PlayerEvent.Paused, handlePaused);
|
|
12
14
|
if (!('mediaSession' in navigator)) {
|
|
13
15
|
return;
|
|
14
16
|
}
|
|
15
17
|
navigator.mediaSession.playbackState = 'paused';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
+
}
|
|
19
|
+
function handlePlay() {
|
|
20
|
+
player.off(PlayerEvent.Play, handlePlay);
|
|
18
21
|
if (!('mediaSession' in navigator)) {
|
|
19
22
|
return;
|
|
20
23
|
}
|
|
21
24
|
navigator.mediaSession.playbackState = 'playing';
|
|
22
|
-
}
|
|
23
|
-
|
|
25
|
+
}
|
|
26
|
+
function handleSourceUnloaded() {
|
|
27
|
+
player.off(PlayerEvent.SourceUnloaded, handleSourceUnloaded);
|
|
24
28
|
if (!('mediaSession' in navigator)) {
|
|
25
29
|
return;
|
|
26
30
|
}
|
|
27
31
|
navigator.mediaSession.setPositionState(undefined);
|
|
28
|
-
}
|
|
29
|
-
|
|
32
|
+
}
|
|
33
|
+
function handleDestroy() {
|
|
34
|
+
player.off(PlayerEvent.Destroy, handleDestroy);
|
|
30
35
|
if (!('mediaSession' in navigator)) {
|
|
31
36
|
return;
|
|
32
37
|
}
|
|
33
38
|
navigator.mediaSession.setPositionState(undefined);
|
|
34
|
-
}
|
|
35
|
-
|
|
39
|
+
}
|
|
40
|
+
function handlePlaybackSpeedChanged() {
|
|
41
|
+
player.off(PlayerEvent.PlaybackSpeedChanged, handlePlaybackSpeedChanged);
|
|
36
42
|
updatePositionState();
|
|
37
|
-
}
|
|
43
|
+
}
|
|
44
|
+
player.on(PlayerEvent.Playing, handlePlaying);
|
|
45
|
+
player.on(PlayerEvent.Paused, handlePaused);
|
|
46
|
+
player.on(PlayerEvent.Play, handlePlay);
|
|
47
|
+
player.on(PlayerEvent.SourceUnloaded, handleSourceUnloaded);
|
|
48
|
+
player.on(PlayerEvent.Destroy, handleDestroy);
|
|
49
|
+
player.on(PlayerEvent.PlaybackSpeedChanged, handlePlaybackSpeedChanged);
|
|
38
50
|
function setMediaSessionMetadata() {
|
|
39
51
|
const metadata = {
|
|
40
52
|
title: sourceConfig.title,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpResponseType } from 'bitmovin-player';
|
|
2
|
-
import { npoCdnProviders } from '
|
|
2
|
+
import { npoCdnProviders } from '../../../services/cdnProviders/cdnProviders';
|
|
3
3
|
import { replaceSpecialCharacters } from '../../utilities/utilities.text';
|
|
4
4
|
async function setDrm(sourceConfig, drm, _streamObject, useWidevineServerCertificate) {
|
|
5
5
|
const npoDrmGateway = 'https://npo-drm-gateway.samgcloud.nepworldwide.nl/authentication?custom_data=';
|
|
@@ -104,8 +104,12 @@ function setStreamProfile(sourceConfig, _sourceConfig, _streamObject) {
|
|
|
104
104
|
}
|
|
105
105
|
export async function processSourceConfig(NpoPlayerServices, _sourceConfig = {}, _streamObject, drm = undefined, streamOptions, version, npoTagPartyId, npoPlayerServices) {
|
|
106
106
|
let sourceConfig = {};
|
|
107
|
-
sourceConfig.title = _sourceConfig.title
|
|
108
|
-
|
|
107
|
+
sourceConfig.title = _sourceConfig.title
|
|
108
|
+
? replacePlaceholders(_sourceConfig.title, _streamObject.metadata)
|
|
109
|
+
: _streamObject.metadata.title ?? '';
|
|
110
|
+
sourceConfig.description = _sourceConfig.description
|
|
111
|
+
? replacePlaceholders(_sourceConfig.description, _streamObject.metadata)
|
|
112
|
+
: _streamObject.metadata.description ?? '';
|
|
109
113
|
sourceConfig.poster = decidePoster(_streamObject, _sourceConfig, streamOptions);
|
|
110
114
|
sourceConfig.metadata = {
|
|
111
115
|
title: sourceConfig.title,
|
|
@@ -190,3 +194,12 @@ function decidePoster(streamObject, sourceConfig, streamOptions) {
|
|
|
190
194
|
}
|
|
191
195
|
return streamObject.metadata.poster ?? '';
|
|
192
196
|
}
|
|
197
|
+
function replacePlaceholders(template, metadata) {
|
|
198
|
+
return template.replace(/{([^{}]*)}/g, (match, key) => {
|
|
199
|
+
const value = metadata[key];
|
|
200
|
+
if (Array.isArray(value)) {
|
|
201
|
+
return value.map((item) => item.trim()).join(', ');
|
|
202
|
+
}
|
|
203
|
+
return value === undefined ? '' : String(value);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type PlayerAPI } from 'bitmovin-player';
|
|
2
2
|
import type NpoPlayer from '../../../npoplayer';
|
|
3
|
-
export declare function bindPlayerEvents(
|
|
3
|
+
export declare function bindPlayerEvents(npoPlayer: NpoPlayer, player: PlayerAPI): void;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { PlayerEvent, ViewMode } from 'bitmovin-player';
|
|
2
2
|
import { logEvent } from './eventlogging';
|
|
3
3
|
const logEventHandlers = new Map();
|
|
4
|
-
export function bindPlayerEvents(
|
|
4
|
+
export function bindPlayerEvents(npoPlayer, player) {
|
|
5
5
|
if (player == undefined)
|
|
6
6
|
return;
|
|
7
|
-
|
|
8
|
-
const isLiveStream = npoplayer.streamObject.stream.isLiveStream;
|
|
7
|
+
const isLiveStream = npoPlayer.streamObject.stream.isLiveStream;
|
|
9
8
|
let currentTime = 0;
|
|
10
9
|
let isNewSource = true;
|
|
11
10
|
const timeDifference = (time) => {
|
|
@@ -17,11 +16,10 @@ export function bindPlayerEvents(npoplayer, player) {
|
|
|
17
16
|
const logEventHandler = (eventName) => {
|
|
18
17
|
return (e) => {
|
|
19
18
|
const eventTime = e.time === undefined ? undefined : timeDifference(e.time);
|
|
20
|
-
logEvent(
|
|
19
|
+
logEvent(npoPlayer, eventName, eventTime);
|
|
21
20
|
};
|
|
22
21
|
};
|
|
23
22
|
const seekHandler = (e) => {
|
|
24
|
-
isSeeking = true;
|
|
25
23
|
let data = {};
|
|
26
24
|
if (e.type === 'timeshift') {
|
|
27
25
|
const timeDifferencePosition = -1 * (Date.now() / 1000 - e.position);
|
|
@@ -37,44 +35,44 @@ export function bindPlayerEvents(npoplayer, player) {
|
|
|
37
35
|
stream_position: e.seekTarget
|
|
38
36
|
};
|
|
39
37
|
}
|
|
40
|
-
logEvent(
|
|
38
|
+
logEvent(npoPlayer, 'seek', data);
|
|
41
39
|
};
|
|
42
40
|
const handleSourceLoaded = () => {
|
|
43
41
|
isNewSource = true;
|
|
44
42
|
if (isLiveStream) {
|
|
45
|
-
logEvent(
|
|
43
|
+
logEvent(npoPlayer, 'stop');
|
|
46
44
|
}
|
|
47
45
|
};
|
|
48
46
|
const handlePlay = (e) => {
|
|
49
|
-
if (!isNewSource &&
|
|
50
|
-
logEvent(
|
|
47
|
+
if (!isNewSource && e.issuer !== 'ui-seek') {
|
|
48
|
+
logEvent(npoPlayer, 'resume', timeDifference(e.time));
|
|
51
49
|
}
|
|
52
50
|
};
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
|
|
51
|
+
const pausedHandler = (e) => {
|
|
52
|
+
if (e.issuer !== 'ui-seek') {
|
|
53
|
+
logEvent(npoPlayer, 'pause', timeDifference(e.time));
|
|
56
54
|
}
|
|
57
55
|
};
|
|
58
56
|
const handleTime = (e) => {
|
|
59
|
-
if (isNewSource && !
|
|
60
|
-
logEvent(
|
|
57
|
+
if (isNewSource && !npoPlayer.adBreakActive) {
|
|
58
|
+
logEvent(npoPlayer, 'start', timeDifference(e.time));
|
|
61
59
|
isNewSource = false;
|
|
62
60
|
}
|
|
63
61
|
else {
|
|
64
|
-
logEvent(
|
|
62
|
+
logEvent(npoPlayer, 'time', timeDifference(e.time));
|
|
65
63
|
}
|
|
66
64
|
};
|
|
67
65
|
const handleViewModeChange = () => {
|
|
68
66
|
const newViewMode = player.getViewMode();
|
|
69
67
|
if (newViewMode === ViewMode.Fullscreen) {
|
|
70
|
-
logEvent(
|
|
68
|
+
logEvent(npoPlayer, 'fullscreen', currentTime);
|
|
71
69
|
}
|
|
72
70
|
else {
|
|
73
|
-
logEvent(
|
|
71
|
+
logEvent(npoPlayer, 'windowed', currentTime);
|
|
74
72
|
}
|
|
75
73
|
};
|
|
76
74
|
const stopBeforeUnload = () => {
|
|
77
|
-
logEvent(
|
|
75
|
+
logEvent(npoPlayer, 'stop');
|
|
78
76
|
};
|
|
79
77
|
for (const [key, value] of logEventHandlers) {
|
|
80
78
|
player.off(key, value);
|
|
@@ -83,7 +81,7 @@ export function bindPlayerEvents(npoplayer, player) {
|
|
|
83
81
|
logEventHandlers.clear();
|
|
84
82
|
const playerEvents = [
|
|
85
83
|
{ event: PlayerEvent.Ready, name: 'load_complete' },
|
|
86
|
-
{ event: PlayerEvent.Paused,
|
|
84
|
+
{ event: PlayerEvent.Paused, handler: pausedHandler },
|
|
87
85
|
{ event: PlayerEvent.Play, handler: handlePlay },
|
|
88
86
|
{ event: PlayerEvent.SourceLoaded, handler: handleSourceLoaded },
|
|
89
87
|
{ event: PlayerEvent.StallStarted, name: 'buffering' },
|
|
@@ -101,10 +99,6 @@ export function bindPlayerEvents(npoplayer, player) {
|
|
|
101
99
|
logEventHandlers.set(event, eventHandler);
|
|
102
100
|
player.on(event, eventHandler);
|
|
103
101
|
}
|
|
104
|
-
if (npoplayer.streamObject.assets.preroll === null) {
|
|
105
|
-
logEventHandlers.set(PlayerEvent.Playing, handlePlaying);
|
|
106
|
-
player.on(PlayerEvent.Playing, handlePlaying);
|
|
107
|
-
}
|
|
108
102
|
logEventHandlers.set('beforeunload', stopBeforeUnload);
|
|
109
103
|
window.addEventListener('beforeunload', stopBeforeUnload);
|
|
110
104
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import NpoPlayer from '../../../npoplayer';
|
|
2
|
-
export declare function logEvent(
|
|
2
|
+
export declare function logEvent(npoPlayer: NpoPlayer, event: string, data?: any): void;
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
export function logEvent(
|
|
2
|
-
if (!
|
|
1
|
+
export function logEvent(npoPlayer, event, data) {
|
|
2
|
+
if (!npoPlayer.player || !npoPlayer.streamTracker || npoPlayer.adBreakActive || npoPlayer.player.isCasting())
|
|
3
3
|
return;
|
|
4
4
|
try {
|
|
5
|
-
|
|
5
|
+
npoPlayer.player.getCurrentTime();
|
|
6
6
|
}
|
|
7
7
|
catch (error) {
|
|
8
8
|
console.warn('Er gaat iets mis met de player API', error);
|
|
9
9
|
}
|
|
10
|
-
const streamOptions = { stream_position:
|
|
10
|
+
const streamOptions = { stream_position: npoPlayer.player.getCurrentTime() };
|
|
11
11
|
const eventHandlers = {
|
|
12
|
-
start:
|
|
13
|
-
buffering:
|
|
14
|
-
buffering_complete:
|
|
15
|
-
complete:
|
|
16
|
-
fullscreen:
|
|
17
|
-
load:
|
|
18
|
-
load_complete:
|
|
19
|
-
pause:
|
|
20
|
-
resume:
|
|
21
|
-
stop:
|
|
22
|
-
windowed:
|
|
23
|
-
time:
|
|
12
|
+
start: npoPlayer.streamTracker.start,
|
|
13
|
+
buffering: npoPlayer.streamTracker.buffering,
|
|
14
|
+
buffering_complete: npoPlayer.streamTracker.buffering_complete,
|
|
15
|
+
complete: npoPlayer.streamTracker.complete,
|
|
16
|
+
fullscreen: npoPlayer.streamTracker.fullscreen,
|
|
17
|
+
load: npoPlayer.streamTracker.load,
|
|
18
|
+
load_complete: npoPlayer.streamTracker.load_complete,
|
|
19
|
+
pause: npoPlayer.streamTracker.pause,
|
|
20
|
+
resume: npoPlayer.streamTracker.resume,
|
|
21
|
+
stop: npoPlayer.streamTracker.stop,
|
|
22
|
+
windowed: npoPlayer.streamTracker.windowed,
|
|
23
|
+
time: npoPlayer.streamTracker.time,
|
|
24
24
|
seek: () => {
|
|
25
|
-
|
|
25
|
+
npoPlayer.streamTracker?.seek(data);
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
const streamTrackerHandler = eventHandlers[event];
|
|
29
|
-
|
|
29
|
+
npoPlayer.logEmitter.emit('logEvent', event, data);
|
|
30
30
|
streamTrackerHandler(streamOptions);
|
|
31
31
|
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
import { logEvent } from './eventlogging';
|
|
2
2
|
import { mockNpoPlayer } from '../../../../tests/mocks/mockNpoplayer';
|
|
3
3
|
describe('logEvent', () => {
|
|
4
|
-
let
|
|
4
|
+
let npoPlayer;
|
|
5
5
|
beforeEach(() => {
|
|
6
|
-
|
|
6
|
+
npoPlayer = mockNpoPlayer;
|
|
7
7
|
});
|
|
8
8
|
it('should not log event if player is not available', () => {
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
logEvent(
|
|
12
|
-
expect(
|
|
13
|
-
expect(
|
|
9
|
+
npoPlayer.player = undefined;
|
|
10
|
+
if (npoPlayer.streamTracker && npoPlayer.player) {
|
|
11
|
+
logEvent(npoPlayer, 'start');
|
|
12
|
+
expect(npoPlayer.streamTracker.start).not.toHaveBeenCalled();
|
|
13
|
+
expect(npoPlayer.logEmitter.emit).not.toHaveBeenCalled();
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
16
|
it('should not log event if streamTracker is not available', () => {
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
logEvent(
|
|
20
|
-
expect(
|
|
17
|
+
npoPlayer.streamTracker = undefined;
|
|
18
|
+
if (npoPlayer.streamTracker) {
|
|
19
|
+
logEvent(npoPlayer, 'start');
|
|
20
|
+
expect(npoPlayer.logEmitter.emit).not.toHaveBeenCalled();
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
it('should not log event if adBreakActive is true', () => {
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
logEvent(
|
|
27
|
-
expect(
|
|
28
|
-
expect(
|
|
24
|
+
npoPlayer.adBreakActive = true;
|
|
25
|
+
if (npoPlayer.streamTracker) {
|
|
26
|
+
logEvent(npoPlayer, 'start');
|
|
27
|
+
expect(npoPlayer.streamTracker.start).not.toHaveBeenCalled();
|
|
28
|
+
expect(npoPlayer.logEmitter.emit).not.toHaveBeenCalled();
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
it('should log event and call the corresponding streamTracker handler', () => {
|
|
32
|
-
if (
|
|
33
|
-
logEvent(
|
|
34
|
-
expect(
|
|
35
|
-
expect(
|
|
32
|
+
if (npoPlayer.streamTracker) {
|
|
33
|
+
logEvent(npoPlayer, 'start');
|
|
34
|
+
expect(npoPlayer.streamTracker.start).toHaveBeenCalledWith({ stream_position: 10 });
|
|
35
|
+
expect(npoPlayer.logEmitter.emit).toHaveBeenCalledWith('logEvent', 'start');
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
it('should log event and call the seek streamTracker handler with data', () => {
|
|
39
39
|
const data = { position: 20 };
|
|
40
|
-
if (
|
|
41
|
-
logEvent(
|
|
42
|
-
expect(
|
|
43
|
-
expect(
|
|
40
|
+
if (npoPlayer.streamTracker) {
|
|
41
|
+
logEvent(npoPlayer, 'seek', data);
|
|
42
|
+
expect(npoPlayer.streamTracker.seek).toHaveBeenCalledWith(data);
|
|
43
|
+
expect(npoPlayer.logEmitter.emit).toHaveBeenCalledWith('logEvent', 'seek');
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
});
|
|
@@ -16,8 +16,10 @@ export function startPlayerTracker(playerInstance, duration, version, source) {
|
|
|
16
16
|
player_version: version,
|
|
17
17
|
sko_player_version: '1.0.0'
|
|
18
18
|
};
|
|
19
|
-
const
|
|
20
|
-
playerInstance.streamTracker = newStreamTracker(playerInstance.npoTag.pageTracker, streamTrackerConfig,
|
|
19
|
+
const isLiveStream = playerInstance.streamObject.stream.isLiveStream || false;
|
|
20
|
+
playerInstance.streamTracker = newStreamTracker(playerInstance.npoTag.pageTracker, streamTrackerConfig, {
|
|
21
|
+
isLive: isLiveStream
|
|
22
|
+
});
|
|
21
23
|
bindPlayerEvents(playerInstance, playerInstance.player);
|
|
22
24
|
}
|
|
23
25
|
}
|
package/lib/lang/nl.json
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"appleAirplay": "Apple AirPlay",
|
|
52
52
|
"googleCast": "Google Cast",
|
|
53
53
|
"vr": "VR",
|
|
54
|
-
"off": "
|
|
54
|
+
"off": "Uit",
|
|
55
55
|
"auto": "automatisch",
|
|
56
56
|
"back": "Terug",
|
|
57
57
|
"reset": "Herstellen",
|
|
@@ -66,6 +66,8 @@
|
|
|
66
66
|
"watermarkLink": "Link to Homepage",
|
|
67
67
|
"controlBar": "Video speler bedieningselementen",
|
|
68
68
|
"player": "Video speler",
|
|
69
|
+
"videoPlayer": "Video speler",
|
|
70
|
+
"audioPlayer": "Audio speler",
|
|
69
71
|
"seekBar": "Video tijdlijn",
|
|
70
72
|
"seekBar.value": "Waarde",
|
|
71
73
|
"seekBar.timeshift": "Timeshift",
|
package/lib/npoplayer.d.ts
CHANGED
|
@@ -32,9 +32,8 @@ export default class NpoPlayer {
|
|
|
32
32
|
mockNpoPlayer: any;
|
|
33
33
|
userPreferences: LocalStorageData;
|
|
34
34
|
constructor(_container: HTMLElement, _playerConfig: PlayerConfig, _npotag?: InitialisationProps | undefined, _npotaginstance?: NPOTag | undefined, _variant?: NpoPlayerUIVariants);
|
|
35
|
-
initPlayer(_container: HTMLElement, playerConfig: PlayerConfig
|
|
35
|
+
initPlayer(_container: HTMLElement, playerConfig: PlayerConfig): void;
|
|
36
36
|
loadStream(source: string, options?: StreamOptions): Promise<void>;
|
|
37
|
-
createUIManager(player: PlayerAPI, playerContext: PlayerContext, variant: NpoPlayerUIVariants): Promise<void>;
|
|
38
37
|
doError(input: any, status?: number): void;
|
|
39
38
|
play(): Promise<void>;
|
|
40
39
|
pause(): void;
|