@gcorevideo/player 2.20.21 → 2.21.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/assets/audio-selector/style.scss +48 -82
- package/assets/audio-selector/track-selector.ejs +3 -3
- package/assets/bottom-gear/bottomgear.ejs +10 -12
- package/assets/bottom-gear/gear-sub-menu.scss +0 -15
- package/assets/bottom-gear/gear.scss +3 -32
- package/assets/media-control/media-control.ejs +5 -20
- package/assets/media-control/media-control.scss +124 -34
- package/assets/media-control/width370.scss +32 -104
- package/assets/picture-in-picture/button.ejs +1 -1
- package/assets/picture-in-picture/button.scss +5 -4
- package/dist/core.js +151 -24
- package/dist/index.css +1063 -1149
- package/dist/index.js +287 -283
- package/dist/player.d.ts +19 -16
- package/dist/plugins/index.css +953 -1039
- package/dist/plugins/index.js +709 -23402
- package/docs/api/player.audioselector.md +4 -59
- package/docs/api/player.md +1 -1
- package/docs/api/player.mediacontrol.getelement.md +5 -0
- package/docs/api/player.mediacontrol.md +14 -0
- package/docs/api/{player.audioselector.updatecurrenttrack.md → player.mediacontrol.putelement.md} +7 -7
- package/docs/api/player.mediacontrolelement.md +1 -1
- package/docs/api/{player.audioselector.starttrackswitch.md → player.pictureinpicture.attributes.md} +5 -7
- package/docs/api/player.pictureinpicture.md +45 -0
- package/lib/playback/BasePlayback.d.ts +0 -1
- package/lib/playback/BasePlayback.d.ts.map +1 -1
- package/lib/playback/BasePlayback.js +0 -1
- package/lib/playback/HTML5Video.d.ts +4 -0
- package/lib/playback/HTML5Video.d.ts.map +1 -1
- package/lib/playback/HTML5Video.js +57 -6
- package/lib/playback/dash-playback/DashPlayback.d.ts +5 -0
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +48 -4
- package/lib/playback/hls-playback/HlsPlayback.d.ts +31 -25
- package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/playback/hls-playback/HlsPlayback.js +47 -14
- package/lib/plugins/audio-selector/AudioSelector.d.ts +12 -11
- package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
- package/lib/plugins/audio-selector/AudioSelector.js +65 -185
- package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
- package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
- package/lib/plugins/bottom-gear/BottomGear.js +10 -9
- package/lib/plugins/level-selector/LevelSelector.js +1 -1
- package/lib/plugins/media-control/MediaControl.d.ts +3 -3
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +17 -9
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +3 -0
- package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
- package/lib/plugins/picture-in-picture/PictureInPicture.js +6 -1
- package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
- package/lib/plugins/source-controller/SourceController.js +0 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +0 -2
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
- package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +1 -18
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +2 -0
- package/package.json +1 -1
- package/src/playback/BasePlayback.ts +0 -1
- package/src/playback/HTML5Video.ts +61 -6
- package/src/playback/dash-playback/DashPlayback.ts +64 -6
- package/src/playback/hls-playback/HlsPlayback.ts +82 -40
- package/src/plugins/audio-selector/AudioSelector.ts +84 -278
- package/src/plugins/bottom-gear/BottomGear.ts +11 -10
- package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -3
- package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +14 -37
- package/src/plugins/level-selector/LevelSelector.ts +1 -1
- package/src/plugins/media-control/MediaControl.ts +18 -13
- package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -1
- package/src/plugins/source-controller/SourceController.ts +0 -1
- package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +1 -20
- package/src/testUtils.ts +2 -0
- package/src/typings/globals.d.ts +19 -0
- package/temp/player.api.json +102 -143
- package/tsconfig.tsbuildinfo +1 -1
- package/assets/media-control/plugins.scss +0 -94
- package/docs/api/player.audioselector.highlightcurrenttrack.md +0 -18
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
|
|
8
8
|
>
|
|
9
9
|
|
|
10
|
-
`PLUGIN` that
|
|
10
|
+
`PLUGIN` that makes possible to switch audio tracks via the media control UI.
|
|
11
11
|
|
|
12
12
|
**Signature:**
|
|
13
13
|
|
|
@@ -16,64 +16,9 @@ export declare class AudioSelector extends UICorePlugin
|
|
|
16
16
|
```
|
|
17
17
|
**Extends:** UICorePlugin
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Remarks
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
The plugin is activated when there are multiple audio tracks available. The plugin adds a button showing the current audio track and a dropdown to switch to another audio track. Depends on:
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
- [MediaControl](./player.mediacontrol.md)
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
</th><th>
|
|
27
|
-
|
|
28
|
-
Modifiers
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</th><th>
|
|
32
|
-
|
|
33
|
-
Description
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</th></tr></thead>
|
|
37
|
-
<tbody><tr><td>
|
|
38
|
-
|
|
39
|
-
[highlightCurrentTrack()](./player.audioselector.highlightcurrenttrack.md)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
</td><td>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</td><td>
|
|
46
|
-
|
|
47
|
-
**_(BETA)_**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
</td></tr>
|
|
51
|
-
<tr><td>
|
|
52
|
-
|
|
53
|
-
[startTrackSwitch()](./player.audioselector.starttrackswitch.md)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
</td><td>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</td><td>
|
|
60
|
-
|
|
61
|
-
**_(BETA)_**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
</td></tr>
|
|
65
|
-
<tr><td>
|
|
66
|
-
|
|
67
|
-
[updateCurrentTrack(e, info)](./player.audioselector.updatecurrenttrack.md)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
</td><td>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
</td><td>
|
|
74
|
-
|
|
75
|
-
**_(BETA)_**
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
</td></tr>
|
|
79
|
-
</tbody></table>
|
package/docs/api/player.md
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
|
|
8
8
|
>
|
|
9
9
|
|
|
10
|
+
> Warning: This API is now obsolete.
|
|
11
|
+
>
|
|
12
|
+
> Use [MediaControl.putElement()](./player.mediacontrol.putelement.md) instead
|
|
13
|
+
>
|
|
14
|
+
|
|
10
15
|
Get a media control element DOM node
|
|
11
16
|
|
|
12
17
|
**Signature:**
|
|
@@ -271,6 +271,20 @@ Description
|
|
|
271
271
|
**_(BETA)_** Get the right panel area to append custom elements to
|
|
272
272
|
|
|
273
273
|
|
|
274
|
+
</td></tr>
|
|
275
|
+
<tr><td>
|
|
276
|
+
|
|
277
|
+
[putElement(name, element)](./player.mediacontrol.putelement.md)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
</td><td>
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
</td><td>
|
|
284
|
+
|
|
285
|
+
**_(BETA)_**
|
|
286
|
+
|
|
287
|
+
|
|
274
288
|
</td></tr>
|
|
275
289
|
<tr><td>
|
|
276
290
|
|
package/docs/api/{player.audioselector.updatecurrenttrack.md → player.mediacontrol.putelement.md}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
2
2
|
|
|
3
|
-
[Home](./index.md) > [@gcorevideo/player](./player.md) > [
|
|
3
|
+
[Home](./index.md) > [@gcorevideo/player](./player.md) > [MediaControl](./player.mediacontrol.md) > [putElement](./player.mediacontrol.putelement.md)
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## MediaControl.putElement() method
|
|
6
6
|
|
|
7
7
|
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
|
|
8
8
|
>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
**Signature:**
|
|
11
11
|
|
|
12
12
|
```typescript
|
|
13
|
-
|
|
13
|
+
putElement(name: MediaControlElement, element: ZeptoResult): void;
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Parameters
|
|
@@ -33,12 +33,12 @@ Description
|
|
|
33
33
|
</th></tr></thead>
|
|
34
34
|
<tbody><tr><td>
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
name
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
</td><td>
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
[MediaControlElement](./player.mediacontrolelement.md)
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
</td><td>
|
|
@@ -47,12 +47,12 @@ HlsEvents.AUDIO\_TRACK\_SWITCHED
|
|
|
47
47
|
</td></tr>
|
|
48
48
|
<tr><td>
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
element
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
</td><td>
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
[ZeptoResult](./player.zeptoresult.md)
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
</td><td>
|
|
@@ -12,5 +12,5 @@ Media control elements, mount points for additional plugins
|
|
|
12
12
|
**Signature:**
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
|
-
export type MediaControlElement = 'audioTracksSelector' | '
|
|
15
|
+
export type MediaControlElement = 'audioTracksSelector' | 'clipText' | 'gear' | 'pip' | 'playbackRate' | 'seekBarContainer' | 'subtitlesSelector';
|
|
16
16
|
```
|
package/docs/api/{player.audioselector.starttrackswitch.md → player.pictureinpicture.attributes.md}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
2
2
|
|
|
3
|
-
[Home](./index.md) > [@gcorevideo/player](./player.md) > [
|
|
3
|
+
[Home](./index.md) > [@gcorevideo/player](./player.md) > [PictureInPicture](./player.pictureinpicture.md) > [attributes](./player.pictureinpicture.attributes.md)
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## PictureInPicture.attributes property
|
|
6
6
|
|
|
7
7
|
> This API is provided as a beta preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
|
|
8
8
|
>
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
**Signature:**
|
|
11
11
|
|
|
12
12
|
```typescript
|
|
13
|
-
|
|
13
|
+
get attributes(): {
|
|
14
|
+
class: string;
|
|
15
|
+
};
|
|
14
16
|
```
|
|
15
|
-
**Returns:**
|
|
16
|
-
|
|
17
|
-
void
|
|
18
|
-
|
|
@@ -24,3 +24,48 @@ Depends on:
|
|
|
24
24
|
|
|
25
25
|
It renders a button to toggle picture in picture mode in the media control UI.
|
|
26
26
|
|
|
27
|
+
## Properties
|
|
28
|
+
|
|
29
|
+
<table><thead><tr><th>
|
|
30
|
+
|
|
31
|
+
Property
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
</th><th>
|
|
35
|
+
|
|
36
|
+
Modifiers
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
</th><th>
|
|
40
|
+
|
|
41
|
+
Type
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
</th><th>
|
|
45
|
+
|
|
46
|
+
Description
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
</th></tr></thead>
|
|
50
|
+
<tbody><tr><td>
|
|
51
|
+
|
|
52
|
+
[attributes](./player.pictureinpicture.attributes.md)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
</td><td>
|
|
56
|
+
|
|
57
|
+
`readonly`
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
</td><td>
|
|
61
|
+
|
|
62
|
+
{ class: string; }
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
</td><td>
|
|
66
|
+
|
|
67
|
+
**_(BETA)_**
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
</td></tr>
|
|
71
|
+
</tbody></table>
|
|
@@ -2,7 +2,6 @@ import { ErrorOptions, HTML5Video } from '@clappr/core';
|
|
|
2
2
|
/**
|
|
3
3
|
* This class adds common behaviors to all playback modules.
|
|
4
4
|
* @internal
|
|
5
|
-
* TODO use custom HTML5Video playback with this layer applied
|
|
6
5
|
*/
|
|
7
6
|
export declare class BasePlayback extends HTML5Video {
|
|
8
7
|
createError(errorData: any, options?: ErrorOptions): Error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BasePlayback.d.ts","sourceRoot":"","sources":["../../src/playback/BasePlayback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAU,UAAU,EAAe,MAAM,cAAc,CAAA;AAI5E
|
|
1
|
+
{"version":3,"file":"BasePlayback.d.ts","sourceRoot":"","sources":["../../src/playback/BasePlayback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAU,UAAU,EAAe,MAAM,cAAc,CAAA;AAI5E;;;GAGG;AACH,qBAAa,YAAa,SAAQ,UAAU;IAC1C,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY;IA0BlD;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM;IAInB,UAAU;CAIpB"}
|
|
@@ -3,7 +3,6 @@ import { PlaybackErrorCode } from '../playback.types.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* This class adds common behaviors to all playback modules.
|
|
5
5
|
* @internal
|
|
6
|
-
* TODO use custom HTML5Video playback with this layer applied
|
|
7
6
|
*/
|
|
8
7
|
export class BasePlayback extends HTML5Video {
|
|
9
8
|
createError(errorData, options) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ErrorOptions } from '@clappr/core';
|
|
2
2
|
import { BasePlayback } from './BasePlayback.js';
|
|
3
|
+
import { AudioTrack } from '@clappr/core/types/base/playback/playback.js';
|
|
3
4
|
export default class HTML5Video extends BasePlayback {
|
|
4
5
|
private stallTimerId;
|
|
5
6
|
/**
|
|
@@ -11,5 +12,8 @@ export default class HTML5Video extends BasePlayback {
|
|
|
11
12
|
_handleBufferingEvents(): void;
|
|
12
13
|
_onPlaying(): void;
|
|
13
14
|
_onPause(): void;
|
|
15
|
+
get audioTracks(): AudioTrack[];
|
|
16
|
+
get currentAudioTrack(): AudioTrack | null;
|
|
17
|
+
switchAudioTrack(id: string): void;
|
|
14
18
|
}
|
|
15
19
|
//# sourceMappingURL=HTML5Video.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HTML5Video.d.ts","sourceRoot":"","sources":["../../src/playback/HTML5Video.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAG3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"HTML5Video.d.ts","sourceRoot":"","sources":["../../src/playback/HTML5Video.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAG3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAA;AAMzE,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,YAAY;IAClD,OAAO,CAAC,YAAY,CAAuB;IAE3C;;OAEG;IACM,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY;IAqBlD,UAAU;IAKV,QAAQ;IASR,sBAAsB;IAwBtB,UAAU;IASV,QAAQ;IASjB,IAAI,WAAW,IAAI,UAAU,EAAE,CAiB9B;IAGD,IAAI,iBAAiB,sBAoBpB;IAED,gBAAgB,CAAC,EAAE,EAAE,MAAM;CAa5B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PlayerError } from '@clappr/core';
|
|
1
|
+
import { PlayerError, Events as ClapprEvents } from '@clappr/core';
|
|
2
2
|
import { PlaybackErrorCode } from '../playback.types.js';
|
|
3
3
|
import { BasePlayback } from './BasePlayback.js';
|
|
4
4
|
import { trace } from '@gcorevideo/utils';
|
|
@@ -21,10 +21,6 @@ export default class HTML5Video extends BasePlayback {
|
|
|
21
21
|
if (i18n &&
|
|
22
22
|
!errorData.UI &&
|
|
23
23
|
errorData.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {
|
|
24
|
-
// errorData.UI = {
|
|
25
|
-
// title: i18n.t('no_broadcast'),
|
|
26
|
-
// message: errorData.message,
|
|
27
|
-
// }
|
|
28
24
|
errorData.code = PlaybackErrorCode.MediaSourceUnavailable;
|
|
29
25
|
}
|
|
30
26
|
return super.createError(errorData, { ...options, useCodePrefix: false });
|
|
@@ -52,12 +48,14 @@ export default class HTML5Video extends BasePlayback {
|
|
|
52
48
|
ended: this.ended,
|
|
53
49
|
});
|
|
54
50
|
this.stallTimerId = null;
|
|
55
|
-
this.createError({
|
|
51
|
+
const error = this.createError({
|
|
56
52
|
code: PlaybackErrorCode.MediaSourceUnavailable,
|
|
57
53
|
level: PlayerError.Levels.FATAL,
|
|
58
54
|
message: 'Stall timeout',
|
|
59
55
|
description: 'Playback stalled for too long',
|
|
60
56
|
});
|
|
57
|
+
this.trigger(ClapprEvents.PLAYBACK_ERROR, error);
|
|
58
|
+
setTimeout(() => this.stop(), 0);
|
|
61
59
|
}, STALL_TIMEOUT);
|
|
62
60
|
}
|
|
63
61
|
super._handleBufferingEvents();
|
|
@@ -78,4 +76,57 @@ export default class HTML5Video extends BasePlayback {
|
|
|
78
76
|
this.stallTimerId = null;
|
|
79
77
|
}
|
|
80
78
|
}
|
|
79
|
+
get audioTracks() {
|
|
80
|
+
const tracks = this.el.audioTracks;
|
|
81
|
+
const supported = !!tracks;
|
|
82
|
+
trace(`${T} get audioTracks`, { supported });
|
|
83
|
+
const retval = [];
|
|
84
|
+
if (supported) {
|
|
85
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
86
|
+
const track = tracks[i];
|
|
87
|
+
retval.push({
|
|
88
|
+
id: track.id,
|
|
89
|
+
label: track.label,
|
|
90
|
+
language: track.language,
|
|
91
|
+
kind: track.kind, // TODO check
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return retval;
|
|
96
|
+
}
|
|
97
|
+
// @ts-expect-error
|
|
98
|
+
get currentAudioTrack() {
|
|
99
|
+
const tracks = this.el.audioTracks;
|
|
100
|
+
const supported = !!tracks;
|
|
101
|
+
trace(`${T} get currentAudioTrack`, {
|
|
102
|
+
supported,
|
|
103
|
+
});
|
|
104
|
+
if (supported) {
|
|
105
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
106
|
+
const track = tracks[i];
|
|
107
|
+
if (track.enabled) {
|
|
108
|
+
return {
|
|
109
|
+
id: track.id,
|
|
110
|
+
label: track.label,
|
|
111
|
+
language: track.language,
|
|
112
|
+
kind: track.kind,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
switchAudioTrack(id) {
|
|
120
|
+
const tracks = this.el.audioTracks;
|
|
121
|
+
const supported = !!tracks;
|
|
122
|
+
trace(`${T} switchAudioTrack`, {
|
|
123
|
+
supported,
|
|
124
|
+
});
|
|
125
|
+
if (supported) {
|
|
126
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
127
|
+
const track = tracks[i];
|
|
128
|
+
track.enabled = track.id === id;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
81
132
|
}
|
|
@@ -2,6 +2,7 @@ import { Playback } from '@clappr/core';
|
|
|
2
2
|
import DASHJS, { type BitrateInfo as DashBitrateInfo, IManifestInfo } from 'dashjs';
|
|
3
3
|
import { QualityLevel, TimePosition, TimeValue } from '../../playback.types.js';
|
|
4
4
|
import { BasePlayback } from '../BasePlayback.js';
|
|
5
|
+
import { AudioTrack } from '@clappr/core/types/base/playback/playback.js';
|
|
5
6
|
type PlaybackType = typeof Playback.VOD | typeof Playback.LIVE | typeof Playback.AOD | typeof Playback.NO_OP;
|
|
6
7
|
type PlaylistType = string;
|
|
7
8
|
type LocalTimeCorrelation = {
|
|
@@ -72,6 +73,10 @@ export default class DashPlayback extends BasePlayback {
|
|
|
72
73
|
isSeekEnabled(): boolean;
|
|
73
74
|
private getLevel;
|
|
74
75
|
setPlaybackRate(rate: number): void;
|
|
76
|
+
get audioTracks(): AudioTrack[];
|
|
77
|
+
get currentAudioTrack(): AudioTrack | null;
|
|
78
|
+
switchAudioTrack(id: string): void;
|
|
79
|
+
private checkAudioTracks;
|
|
75
80
|
}
|
|
76
81
|
export {};
|
|
77
82
|
//# sourceMappingURL=DashPlayback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashPlayback.d.ts","sourceRoot":"","sources":["../../../src/playback/dash-playback/DashPlayback.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DashPlayback.d.ts","sourceRoot":"","sources":["../../../src/playback/dash-playback/DashPlayback.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// license
|
|
1
|
+
// This code is derived on works by Globo.com.
|
|
2
|
+
// This code is distributed under the terms of the Apache License 2.0.
|
|
3
|
+
// Original code's license can be found on
|
|
4
|
+
// https://github.com/clappr/clappr/blob/8752995ea439321ac7ca3cd35e8c64de7a3c3d17/LICENSE
|
|
4
5
|
import { Events, Log, Playback, PlayerError, Utils, $ } from '@clappr/core';
|
|
5
6
|
import { trace } from '@gcorevideo/utils';
|
|
6
7
|
import assert from 'assert';
|
|
@@ -12,7 +13,6 @@ import { PlaybackEvents } from '../types.js';
|
|
|
12
13
|
const AUTO = -1;
|
|
13
14
|
const { now } = Utils;
|
|
14
15
|
const T = 'playback.dash';
|
|
15
|
-
// @ts-expect-error
|
|
16
16
|
export default class DashPlayback extends BasePlayback {
|
|
17
17
|
_levels = null;
|
|
18
18
|
_currentLevel = null;
|
|
@@ -172,6 +172,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
172
172
|
const newLevel = this.getLevel(evt.newQuality);
|
|
173
173
|
this.onLevelSwitch(newLevel);
|
|
174
174
|
});
|
|
175
|
+
this.checkAudioTracks();
|
|
175
176
|
});
|
|
176
177
|
this._dash.on(DASHJS.MediaPlayer.events.QUALITY_CHANGE_RENDERED, (evt) => {
|
|
177
178
|
const currentLevel = this.getLevel(evt.newQuality);
|
|
@@ -192,6 +193,11 @@ export default class DashPlayback extends BasePlayback {
|
|
|
192
193
|
this._dash.on(DASHJS.MediaPlayer.events.PLAYBACK_RATE_CHANGED, (e) => {
|
|
193
194
|
this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate);
|
|
194
195
|
});
|
|
196
|
+
this._dash.on(DASHJS.MediaPlayer.events.TRACK_CHANGE_RENDERED, (e) => {
|
|
197
|
+
if (e.mediaType === 'audio') {
|
|
198
|
+
this.trigger(Events.PLAYBACK_AUDIO_CHANGED, toClapprTrack(e.newMediaInfo));
|
|
199
|
+
}
|
|
200
|
+
});
|
|
195
201
|
}
|
|
196
202
|
render() {
|
|
197
203
|
this._ready();
|
|
@@ -459,6 +465,36 @@ export default class DashPlayback extends BasePlayback {
|
|
|
459
465
|
setPlaybackRate(rate) {
|
|
460
466
|
this._dash?.setPlaybackRate(rate);
|
|
461
467
|
}
|
|
468
|
+
get audioTracks() {
|
|
469
|
+
assert.ok(this._dash, 'DASH.js MediaPlayer is not initialized');
|
|
470
|
+
const tracks = this._dash.getTracksFor('audio');
|
|
471
|
+
trace(`${T} get audioTracks`, { tracks });
|
|
472
|
+
return tracks.map(toClapprTrack);
|
|
473
|
+
}
|
|
474
|
+
// @ts-expect-error
|
|
475
|
+
get currentAudioTrack() {
|
|
476
|
+
trace(`${T} get currentAudioTrack`);
|
|
477
|
+
assert.ok(this._dash, 'DASH.js MediaPlayer is not initialized');
|
|
478
|
+
const t = this._dash.getCurrentTrackFor('audio');
|
|
479
|
+
if (!t) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
return toClapprTrack(t);
|
|
483
|
+
}
|
|
484
|
+
switchAudioTrack(id) {
|
|
485
|
+
assert.ok(this._dash, 'DASH.js MediaPlayer is not initialized');
|
|
486
|
+
const tracks = this._dash.getTracksFor('audio');
|
|
487
|
+
const track = tracks.find((t) => t.id === id);
|
|
488
|
+
assert.ok(track, 'Invalid audio track ID');
|
|
489
|
+
this._dash.setCurrentTrack(track);
|
|
490
|
+
}
|
|
491
|
+
checkAudioTracks() {
|
|
492
|
+
// @ts-ignore
|
|
493
|
+
const tracks = this._dash.getTracksFor('audio');
|
|
494
|
+
if (tracks.length) {
|
|
495
|
+
this.trigger(Events.PLAYBACK_AUDIO_AVAILABLE, tracks.map(toClapprTrack));
|
|
496
|
+
}
|
|
497
|
+
}
|
|
462
498
|
}
|
|
463
499
|
DashPlayback.canPlay = function (resource, mimeType) {
|
|
464
500
|
if (!isDashSource(resource, mimeType)) {
|
|
@@ -470,3 +506,11 @@ DashPlayback.canPlay = function (resource, mimeType) {
|
|
|
470
506
|
const ctor = ms || mms || wms;
|
|
471
507
|
return typeof ctor === 'function';
|
|
472
508
|
};
|
|
509
|
+
function toClapprTrack(t) {
|
|
510
|
+
return {
|
|
511
|
+
id: t.id,
|
|
512
|
+
kind: t.roles && t.roles?.length > 0 ? t.roles[0] : 'main', // TODO
|
|
513
|
+
label: t.labels.map((l) => l.text).join(' '), // TODO
|
|
514
|
+
language: t.lang,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import HLSJS, { Events as HlsEvents, type
|
|
1
|
+
import HLSJS, { Events as HlsEvents, type FragChangedData, type FragLoadedData, type LevelSwitchingData } from 'hls.js';
|
|
2
2
|
import { QualityLevel } from '../../playback.types.js';
|
|
3
3
|
import { PlaybackType } from '../../types.js';
|
|
4
4
|
import { BasePlayback } from '../BasePlayback.js';
|
|
5
|
+
import { AudioTrack } from '@clappr/core/types/base/playback/playback.js';
|
|
5
6
|
export default class HlsPlayback extends BasePlayback {
|
|
6
7
|
private _ccIsSetup;
|
|
7
8
|
private _ccTracksUpdated;
|
|
@@ -38,12 +39,12 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
38
39
|
set currentLevel(id: number);
|
|
39
40
|
get latency(): number;
|
|
40
41
|
get currentProgramDateTime(): Date;
|
|
41
|
-
get _startTime()
|
|
42
|
-
get _now()
|
|
43
|
-
get _extrapolatedStartTime()
|
|
42
|
+
private get _startTime();
|
|
43
|
+
private get _now();
|
|
44
|
+
private get _extrapolatedStartTime();
|
|
44
45
|
get _extrapolatedEndTime(): number;
|
|
45
|
-
get _duration()
|
|
46
|
-
get _extrapolatedWindowDuration()
|
|
46
|
+
private get _duration();
|
|
47
|
+
private get _extrapolatedWindowDuration();
|
|
47
48
|
get bandwidthEstimate(): number | null;
|
|
48
49
|
get defaultOptions(): {
|
|
49
50
|
preload: boolean;
|
|
@@ -53,33 +54,33 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
53
54
|
get currentTimestamp(): number | null;
|
|
54
55
|
static get HLSJS(): typeof HLSJS;
|
|
55
56
|
constructor(...args: any[]);
|
|
56
|
-
_setInitialState
|
|
57
|
-
_setup
|
|
58
|
-
_destroyHLSInstance
|
|
59
|
-
_createHLSInstance
|
|
60
|
-
_attachHLSMedia
|
|
61
|
-
_listenHLSEvents
|
|
62
|
-
bindCustomListeners
|
|
63
|
-
unbindCustomListeners
|
|
64
|
-
_onFragmentParsingMetadata
|
|
65
|
-
render(): this;
|
|
66
|
-
_ready(): void;
|
|
57
|
+
private _setInitialState;
|
|
58
|
+
private _setup;
|
|
59
|
+
private _destroyHLSInstance;
|
|
60
|
+
private _createHLSInstance;
|
|
61
|
+
private _attachHLSMedia;
|
|
62
|
+
private _listenHLSEvents;
|
|
63
|
+
private bindCustomListeners;
|
|
64
|
+
private unbindCustomListeners;
|
|
65
|
+
private _onFragmentParsingMetadata;
|
|
66
|
+
protected render(): this;
|
|
67
|
+
protected _ready(): void;
|
|
67
68
|
private _recover;
|
|
68
69
|
protected _setupSrc(srcUrl: string): void;
|
|
69
|
-
_startTimeUpdateTimer
|
|
70
|
-
_stopTimeUpdateTimer
|
|
71
|
-
getProgramDateTime
|
|
70
|
+
private _startTimeUpdateTimer;
|
|
71
|
+
private _stopTimeUpdateTimer;
|
|
72
|
+
private getProgramDateTime;
|
|
72
73
|
getDuration(): number;
|
|
73
74
|
getCurrentTime(): number;
|
|
74
75
|
getStartTimeOffset(): number;
|
|
75
76
|
seekPercentage(percentage: number): void;
|
|
76
77
|
seek(time: number): void;
|
|
77
78
|
seekToLivePoint(): void;
|
|
78
|
-
_updateDvr
|
|
79
|
-
_updateSettings
|
|
80
|
-
_onHLSJSError
|
|
81
|
-
_keyIsDenied
|
|
82
|
-
_onTimeUpdate
|
|
79
|
+
private _updateDvr;
|
|
80
|
+
private _updateSettings;
|
|
81
|
+
private _onHLSJSError;
|
|
82
|
+
private _keyIsDenied;
|
|
83
|
+
private _onTimeUpdate;
|
|
83
84
|
_onDurationChange(): void;
|
|
84
85
|
_onProgress(): void;
|
|
85
86
|
load(url: string): void;
|
|
@@ -101,5 +102,10 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
101
102
|
getPlaybackType(): PlaybackType;
|
|
102
103
|
isSeekEnabled(): boolean;
|
|
103
104
|
private triggerError;
|
|
105
|
+
get audioTracks(): AudioTrack[];
|
|
106
|
+
get currentAudioTrack(): AudioTrack | null;
|
|
107
|
+
switchAudioTrack(id: string): void;
|
|
108
|
+
private _onAudioTracksUpdated;
|
|
109
|
+
private _onAudioTrackSwitched;
|
|
104
110
|
}
|
|
105
111
|
//# sourceMappingURL=HlsPlayback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HlsPlayback.d.ts","sourceRoot":"","sources":["../../../src/playback/hls-playback/HlsPlayback.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,EACZ,MAAM,IAAI,SAAS,
|
|
1
|
+
{"version":3,"file":"HlsPlayback.d.ts","sourceRoot":"","sources":["../../../src/playback/hls-playback/HlsPlayback.ts"],"names":[],"mappings":"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"}
|