@gcorevideo/player 2.10.0 → 2.12.2

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 (65) hide show
  1. package/LICENSE +13 -0
  2. package/coverage/clover.xml +6 -0
  3. package/coverage/coverage-final.json +1 -0
  4. package/coverage/lcov-report/base.css +224 -0
  5. package/coverage/lcov-report/block-navigation.js +87 -0
  6. package/coverage/lcov-report/favicon.png +0 -0
  7. package/coverage/lcov-report/index.html +101 -0
  8. package/coverage/lcov-report/prettify.css +1 -0
  9. package/coverage/lcov-report/prettify.js +2 -0
  10. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  11. package/coverage/lcov-report/sorter.js +196 -0
  12. package/coverage/lcov.info +0 -0
  13. package/dist/index.js +3115 -1209
  14. package/lib/Player.d.ts +3 -2
  15. package/lib/Player.d.ts.map +1 -1
  16. package/lib/Player.js +32 -24
  17. package/lib/index.d.ts +5 -5
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +5 -5
  20. package/lib/internal.types.d.ts +1 -10
  21. package/lib/internal.types.d.ts.map +1 -1
  22. package/lib/playback/index.d.ts +4 -0
  23. package/lib/playback/index.d.ts.map +1 -0
  24. package/lib/playback/index.js +13 -0
  25. package/lib/playback.types.d.ts +19 -0
  26. package/lib/playback.types.d.ts.map +1 -1
  27. package/lib/playback.types.js +9 -1
  28. package/lib/plugins/dash-playback/DashPlayback.d.ts +1 -1
  29. package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -1
  30. package/lib/plugins/dash-playback/DashPlayback.js +39 -100
  31. package/lib/plugins/dash-playback/types.d.ts +6 -0
  32. package/lib/plugins/dash-playback/types.d.ts.map +1 -0
  33. package/lib/plugins/dash-playback/types.js +1 -0
  34. package/lib/plugins/hls-playback/HlsPlayback.d.ts +6 -7
  35. package/lib/plugins/hls-playback/HlsPlayback.d.ts.map +1 -1
  36. package/lib/plugins/hls-playback/HlsPlayback.js +131 -80
  37. package/lib/types.d.ts +3 -3
  38. package/lib/types.d.ts.map +1 -1
  39. package/lib/utils/mediaSources.d.ts +14 -6
  40. package/lib/utils/mediaSources.d.ts.map +1 -1
  41. package/lib/utils/mediaSources.js +56 -53
  42. package/lib/utils/testUtils.d.ts +3 -0
  43. package/lib/utils/testUtils.d.ts.map +1 -0
  44. package/lib/utils/testUtils.js +12 -0
  45. package/package.json +6 -4
  46. package/src/Player.ts +40 -31
  47. package/src/__tests__/Player.test.ts +357 -0
  48. package/src/index.ts +5 -5
  49. package/src/internal.types.ts +1 -12
  50. package/src/playback/index.ts +17 -0
  51. package/src/playback.types.ts +29 -8
  52. package/src/plugins/dash-playback/DashPlayback.ts +44 -120
  53. package/src/plugins/hls-playback/HlsPlayback.ts +544 -390
  54. package/src/types.ts +5 -3
  55. package/src/typings/@clappr/core/error_mixin.d.ts +0 -2
  56. package/src/typings/@clappr/core/index.d.ts +5 -0
  57. package/src/typings/@clappr/index.d.ts +1 -0
  58. package/src/utils/__tests__/mediaSources.test.ts +230 -0
  59. package/src/utils/mediaSources.ts +78 -64
  60. package/src/utils/testUtils.ts +15 -0
  61. package/tsconfig.json +0 -9
  62. package/tsconfig.tsbuildinfo +1 -1
  63. package/vitest.config.ts +8 -0
  64. package/licenses.json +0 -782
  65. package/src/utils/queryParams.ts +0 -5
package/src/types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { ContainerPlugin, CorePlugin } from "@clappr/core"
2
+
1
3
  /**
2
4
  * Describes a media source with its MIME type and URL.
3
5
  *
@@ -44,7 +46,7 @@ export type PlaybackType = 'live' | 'vod'
44
46
  /**
45
47
  * @beta
46
48
  */
47
- export type MediaTransport = 'dash' | 'hls' | 'mpegts'
49
+ export type MediaTransport = 'dash' | 'hls'
48
50
 
49
51
  /**
50
52
  * @beta
@@ -57,7 +59,7 @@ export type TransportPreference = MediaTransport | 'auto'
57
59
  */
58
60
  export type PlayerPlugin = {
59
61
  new (...args: any[]): unknown
60
- type: 'core' | 'container'
62
+ name: string
61
63
  }
62
64
 
63
65
  /**
@@ -161,7 +163,7 @@ export interface PlayerConfig extends Record<string, unknown> {
161
163
  /**
162
164
  * Localization strings for the player UI.
163
165
  */
164
- strings: TranslationSettings
166
+ strings?: TranslationSettings
165
167
  }
166
168
 
167
169
  /**
@@ -1,7 +1,5 @@
1
1
  import '@clappr/core';
2
- // import ErrorMixin from "@clappr/core/src/base/error_mixin/error_mixin";
3
2
 
4
- // export as namespace "@clappr/core";
5
3
  declare module "@clappr/core" {
6
4
  // export ErrorMixin;
7
5
 
@@ -0,0 +1,5 @@
1
+ import '@clappr/core'
2
+
3
+ declare module '@clappr/core' {
4
+
5
+ }
@@ -0,0 +1 @@
1
+ declare module '@clappr' {}
@@ -0,0 +1,230 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ import { isDashSource, isHlsSource, buildMediaSourcesList } from '../mediaSources'
4
+ import { TransportPreference } from '../../types'
5
+ import { canPlayDash, canPlayHls } from '../../playback/index'
6
+
7
+ vi.mock('../../playback/index.js', () => ({
8
+ canPlayDash: vi.fn(),
9
+ canPlayHls: vi.fn(),
10
+ }))
11
+
12
+ beforeEach(() => {
13
+ vi.mocked(canPlayDash).mockImplementation(isDashSource)
14
+ vi.mocked(canPlayHls).mockImplementation(isHlsSource)
15
+ })
16
+
17
+ describe('mediaSources', () => {
18
+ describe('buildMediaSourcesList', () => {
19
+ describe.each([
20
+ [
21
+ 'dash',
22
+ true,
23
+ true,
24
+ [
25
+ {
26
+ source: 'http://example.com/video.m3u8',
27
+ mimeType: 'application/vnd.apple.mpegurl',
28
+ },
29
+ {
30
+ source: 'http://example.com/video.mpd',
31
+ mimeType: 'application/dash+xml',
32
+ },
33
+ {
34
+ source: 'http://example.com/video2.mpd',
35
+ mimeType: 'application/dash+xml',
36
+ },
37
+ {
38
+ source: 'http://example.com/video3.m3u8',
39
+ mimeType: 'application/vnd.apple.mpegurl',
40
+ },
41
+ ],
42
+ [
43
+ {
44
+ source: 'http://example.com/video.mpd',
45
+ mimeType: 'application/dash+xml',
46
+ },
47
+ {
48
+ source: 'http://example.com/video2.mpd',
49
+ mimeType: 'application/dash+xml',
50
+ },
51
+ {
52
+ source: 'http://example.com/video.m3u8',
53
+ mimeType: 'application/vnd.apple.mpegurl',
54
+ },
55
+ {
56
+ source: 'http://example.com/video3.m3u8',
57
+ mimeType: 'application/vnd.apple.mpegurl',
58
+ },
59
+ ],
60
+ ],
61
+ [
62
+ 'auto',
63
+ true,
64
+ true,
65
+ [
66
+ {
67
+ source: 'http://example.com/video.m3u8',
68
+ mimeType: 'application/vnd.apple.mpegurl',
69
+ },
70
+ {
71
+ source: 'http://example.com/video.mpd',
72
+ mimeType: 'application/dash+xml',
73
+ },
74
+ {
75
+ source: 'http://example.com/video2.mpd',
76
+ mimeType: 'application/dash+xml',
77
+ },
78
+ {
79
+ source: 'http://example.com/video3.m3u8',
80
+ mimeType: 'application/vnd.apple.mpegurl',
81
+ },
82
+ ],
83
+ [
84
+ {
85
+ source: 'http://example.com/video.mpd',
86
+ mimeType: 'application/dash+xml',
87
+ },
88
+ {
89
+ source: 'http://example.com/video2.mpd',
90
+ mimeType: 'application/dash+xml',
91
+ },
92
+ {
93
+ source: 'http://example.com/video.m3u8',
94
+ mimeType: 'application/vnd.apple.mpegurl',
95
+ },
96
+ {
97
+ source: 'http://example.com/video3.m3u8',
98
+ mimeType: 'application/vnd.apple.mpegurl',
99
+ },
100
+ ],
101
+ ],
102
+ [
103
+ 'hls',
104
+ true,
105
+ true,
106
+ [
107
+ {
108
+ source: 'http://example.com/video.m3u8',
109
+ mimeType: 'application/vnd.apple.mpegurl',
110
+ },
111
+ {
112
+ source: 'http://example.com/video.mpd',
113
+ mimeType: 'application/dash+xml',
114
+ },
115
+ {
116
+ source: 'http://example.com/video2.mpd',
117
+ mimeType: 'application/dash+xml',
118
+ },
119
+ {
120
+ source: 'http://example.com/video3.m3u8',
121
+ mimeType: 'application/vnd.apple.mpegurl',
122
+ },
123
+ ],
124
+ [
125
+ {
126
+ source: 'http://example.com/video.m3u8',
127
+ mimeType: 'application/vnd.apple.mpegurl',
128
+ },
129
+ {
130
+ source: 'http://example.com/video3.m3u8',
131
+ mimeType: 'application/vnd.apple.mpegurl',
132
+ },
133
+ {
134
+ source: 'http://example.com/video.mpd',
135
+ mimeType: 'application/dash+xml',
136
+ },
137
+ {
138
+ source: 'http://example.com/video2.mpd',
139
+ mimeType: 'application/dash+xml',
140
+ },
141
+ ],
142
+ ],
143
+ [
144
+ 'dash',
145
+ false,
146
+ true,
147
+ [
148
+ {
149
+ source: 'http://example.com/video.m3u8',
150
+ mimeType: 'application/vnd.apple.mpegurl',
151
+ },
152
+ {
153
+ source: 'http://example.com/video.mpd',
154
+ mimeType: 'application/dash+xml',
155
+ },
156
+ {
157
+ source: 'http://example.com/video2.mpd',
158
+ mimeType: 'application/dash+xml',
159
+ },
160
+ {
161
+ source: 'http://example.com/video3.m3u8',
162
+ mimeType: 'application/vnd.apple.mpegurl',
163
+ },
164
+ ],
165
+ [
166
+ {
167
+ source: 'http://example.com/video.m3u8',
168
+ mimeType: 'application/vnd.apple.mpegurl',
169
+ },
170
+ {
171
+ source: 'http://example.com/video3.m3u8',
172
+ mimeType: 'application/vnd.apple.mpegurl',
173
+ },
174
+ ],
175
+ ],
176
+ [
177
+ 'hls',
178
+ true,
179
+ false,
180
+ [
181
+ {
182
+ source: 'http://example.com/video.m3u8',
183
+ mimeType: 'application/vnd.apple.mpegurl',
184
+ },
185
+ {
186
+ source: 'http://example.com/video.mpd',
187
+ mimeType: 'application/dash+xml',
188
+ },
189
+ {
190
+ source: 'http://example.com/video2.mpd',
191
+ mimeType: 'application/dash+xml',
192
+ },
193
+ {
194
+ source: 'http://example.com/video3.m3u8',
195
+ mimeType: 'application/vnd.apple.mpegurl',
196
+ },
197
+ ],
198
+ [
199
+ {
200
+ source: 'http://example.com/video.mpd',
201
+ mimeType: 'application/dash+xml',
202
+ },
203
+ {
204
+ source: 'http://example.com/video2.mpd',
205
+ mimeType: 'application/dash+xml',
206
+ },
207
+ ],
208
+ ],
209
+ ])('prefer %s, dash=%s,hls=%s', (preference, dash, hls, sources, expected) => {
210
+ beforeEach(() => {
211
+ if (!dash) {
212
+ vi.mocked(canPlayDash).mockReturnValue(false)
213
+ }
214
+ if (!hls) {
215
+ vi.mocked(canPlayHls).mockReturnValue(false)
216
+ }
217
+ })
218
+ // afterEach(() => {
219
+ // vi.mocked(canPlayDash)
220
+ // })
221
+ it('should build the ordered list of available sources', () => {
222
+ const ordered = buildMediaSourcesList(
223
+ sources,
224
+ preference as TransportPreference,
225
+ )
226
+ expect(ordered).toEqual(expect.objectContaining(expected))
227
+ })
228
+ })
229
+ })
230
+ })
@@ -1,90 +1,104 @@
1
- import DashPlayback from '../plugins/dash-playback/DashPlayback'
2
- import HlsPlayback from '../plugins/hls-playback/HlsPlayback'
3
- import type { PlayerMediaSource, TransportPreference } from '../types'
1
+ import type {
2
+ PlayerMediaSource,
3
+ PlayerMediaSourceDesc,
4
+ TransportPreference,
5
+ } from '../types'
6
+ import { canPlayDash, canPlayHls } from '../playback/index.js'
4
7
 
5
8
  export type SourceVariants = {
6
- dash: string | null
7
- master: string | null
8
- hls: string | null
9
- mpegts: string | null
9
+ dash: PlayerMediaSourceDesc | null
10
+ hls: PlayerMediaSourceDesc | null
11
+ mpegts: PlayerMediaSourceDesc | null
10
12
  }
11
13
 
14
+ /**
15
+ *
16
+ * @param sources
17
+ * @deprecated
18
+ * @returns
19
+ */
12
20
  export function buildSourcesSet(sources: PlayerMediaSource[]): SourceVariants {
13
21
  const sv: SourceVariants = {
14
22
  dash: null,
15
- master: null,
16
23
  hls: null,
17
24
  mpegts: null,
18
25
  }
19
26
  sources.forEach((ps) => {
20
- const [s, t] = typeof ps === 'string' ? [ps, ''] : [ps.source, ps.mimeType]
21
- if (DashPlayback.canPlay(s, t)) {
22
- sv.dash = s
23
- } else if (HlsPlayback.canPlay(s, t)) {
24
- sv.hls = s
27
+ const ws = wrapSource(ps)
28
+ if (canPlayDash(ws.source, ws.mimeType)) {
29
+ sv.dash = ws
30
+ } else if (canPlayHls(ws.source, ws.mimeType)) {
31
+ sv.hls = ws
25
32
  } else {
26
- sv.master = s
33
+ sv.mpegts = ws
27
34
  }
28
35
  })
29
36
  return sv
30
37
  }
31
38
 
32
- export function buildSourcesPriorityList(
33
- sources: SourceVariants,
39
+ export function buildMediaSourcesList(
40
+ sources: PlayerMediaSourceDesc[],
34
41
  priorityTransport: TransportPreference = 'auto',
35
- ): PlayerMediaSource[] {
36
- const msl: string[] = []
37
- switch (priorityTransport) {
38
- case 'dash':
39
- addDash()
40
- break
41
- case 'hls':
42
- addHls()
43
- break
44
- case 'mpegts':
45
- addMpegts()
46
- break
47
- case 'auto':
48
- addDash()
49
- addHls()
50
- break
51
- }
52
- Object.values(sources).forEach((s) => {
53
- if (s) {
54
- msl.push(s)
55
- }
56
- })
57
- return msl
42
+ ): PlayerMediaSourceDesc[] {
43
+ const [preferred, rest] = sources.reduce(
44
+ priorityTransport === 'dash' || priorityTransport === 'auto'
45
+ ? (
46
+ acc: [PlayerMediaSourceDesc[], PlayerMediaSourceDesc[]],
47
+ item: PlayerMediaSourceDesc,
48
+ ) => {
49
+ if (canPlayDash(item.source, item.mimeType)) {
50
+ acc[0].push(item)
51
+ } else if (canPlayHls(item.source, item.mimeType)) {
52
+ acc[1].push(item)
53
+ }
54
+ return acc
55
+ }
56
+ : (
57
+ acc: [PlayerMediaSourceDesc[], PlayerMediaSourceDesc[]],
58
+ item: PlayerMediaSourceDesc,
59
+ ) => {
60
+ if (canPlayHls(item.source, item.mimeType)) {
61
+ acc[0].push(item)
62
+ } else if (canPlayDash(item.source, item.mimeType)) {
63
+ acc[1].push(item)
64
+ }
65
+ return acc
66
+ },
67
+ [[], []],
68
+ )
69
+ return preferred.concat(rest)
70
+ }
58
71
 
59
- function addMpegts() {
60
- if (sources.mpegts) {
61
- msl.push(sources.mpegts)
62
- sources.mpegts = null
63
- }
64
- }
72
+ export function unwrapSource(s: PlayerMediaSource): string {
73
+ return typeof s === 'string' ? s : s.source
74
+ }
65
75
 
66
- function addHls() {
67
- if (sources.hls && HlsPlayback.canPlay(sources.hls, undefined)) {
68
- msl.push(sources.hls)
69
- sources.hls = null
70
- }
71
- if (
72
- sources.master?.endsWith('.m3u8') &&
73
- HlsPlayback.canPlay(sources.master, undefined)
74
- ) {
75
- msl.push(sources.master)
76
- sources.master = null
77
- }
76
+ export function wrapSource(s: PlayerMediaSource): PlayerMediaSourceDesc {
77
+ return typeof s === 'string' ? { source: s, mimeType: guessMimeType(s) } : s
78
+ }
79
+
80
+ function guessMimeType(s: string): string {
81
+ if (s.endsWith('.mpd')) {
82
+ return 'application/dash+xml'
78
83
  }
84
+ if (s.endsWith('.m3u8')) {
85
+ return 'application/vnd.apple.mpegurl'
86
+ }
87
+ throw new Error('Unrecognized media source type')
88
+ }
79
89
 
80
- function addDash() {
81
- if (sources.dash && DashPlayback.canPlay(sources.dash, undefined)) {
82
- msl.push(sources.dash)
83
- sources.dash = null
84
- }
90
+ export function isDashSource(source: string, mimeType?: string) {
91
+ if (mimeType) {
92
+ return mimeType === 'application/dash+xml'
85
93
  }
94
+ return source.endsWith('.mpd')
86
95
  }
87
96
 
88
- export function unwrapSource(s: PlayerMediaSource): string {
89
- return typeof s === 'string' ? s : s.source
97
+ export function isHlsSource(source: string, mimeType?: string) {
98
+ if (mimeType) {
99
+ return ['application/vnd.apple.mpegurl', 'application/x-mpegURL'].includes(
100
+ mimeType,
101
+ )
102
+ }
103
+ return source.endsWith('.m3u8')
90
104
  }
@@ -0,0 +1,15 @@
1
+ export function isDashSource(source: string, mimeType?: string) {
2
+ if (mimeType) {
3
+ return mimeType === 'application/dash+xml'
4
+ }
5
+ return source.endsWith('.mpd')
6
+ }
7
+
8
+ export function isHlsSource(source: string, mimeType?: string) {
9
+ if (mimeType) {
10
+ return ['application/vnd.apple.mpegurl', 'application/x-mpegURL'].includes(
11
+ mimeType,
12
+ )
13
+ }
14
+ return source.endsWith('.m3u8')
15
+ }
package/tsconfig.json CHANGED
@@ -26,15 +26,6 @@
26
26
  "DOM.Iterable"
27
27
  ],
28
28
  "module": "ESNext",
29
- // "paths": {
30
- // // "@assets/*": ["src/assets/*"],
31
- // // "@vendor/*": ["src/vendor/*"],
32
- // },
33
- "types": [
34
- "node",
35
- // "@clappr/core",
36
- // "@clappr/plugins",
37
- ],
38
29
  "typeRoots": [
39
30
  "node_modules/@types",
40
31
  "src/typings"