@gcorevideo/player 2.28.35 → 2.29.0
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 +22 -1
- package/assets/{subtitles → cc}/style.scss +5 -0
- package/assets/media-control/media-control.scss +8 -6
- package/assets/multi-camera/multicamera.ejs +27 -23
- package/assets/multi-camera/style.scss +7 -34
- package/assets/style/main.scss +2 -2
- package/dist/core.js +24 -28
- package/dist/index.css +384 -402
- package/dist/index.embed.js +54 -84
- package/dist/index.js +122 -219
- package/docs/api/player.md +22 -9
- package/docs/api/player.mediacontrol.setkeepvisible.md +56 -0
- package/docs/api/player.multicamera.md +0 -28
- package/docs/api/player.multiccamerasourceinfo.md +27 -0
- package/docs/api/{player.multicamera.unbindevents.md → player.multisourcesmode.md} +4 -7
- package/docs/api/player.sourcecontroller.md +0 -37
- package/lib/playback/BasePlayback.d.ts +1 -0
- package/lib/playback/BasePlayback.d.ts.map +1 -1
- package/lib/playback/BasePlayback.js +3 -0
- package/lib/playback/dash-playback/DashPlayback.d.ts +3 -1
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +9 -22
- package/lib/playback/hls-playback/HlsPlayback.d.ts +2 -1
- package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/playback/hls-playback/HlsPlayback.js +4 -0
- package/lib/playback/types.d.ts +9 -0
- package/lib/playback/types.d.ts.map +1 -1
- package/lib/playback.types.d.ts +0 -6
- package/lib/playback.types.d.ts.map +1 -1
- package/lib/plugins/multi-camera/MultiCamera.d.ts +21 -4
- package/lib/plugins/multi-camera/MultiCamera.d.ts.map +1 -1
- package/lib/plugins/multi-camera/MultiCamera.js +70 -134
- package/lib/plugins/source-controller/SourceController.d.ts +0 -39
- package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
- package/lib/plugins/source-controller/SourceController.js +0 -39
- package/lib/plugins/subtitles/ClosedCaptions.d.ts +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
- package/lib/plugins/subtitles/ClosedCaptions.js +32 -22
- package/lib/testUtils.d.ts +1 -0
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +3 -0
- package/lib/utils/mediaSources.d.ts +4 -0
- package/lib/utils/mediaSources.d.ts.map +1 -1
- package/lib/utils/mediaSources.js +8 -6
- package/package.json +1 -1
- package/src/playback/BasePlayback.ts +4 -0
- package/src/playback/dash-playback/DashPlayback.ts +11 -29
- package/src/playback/hls-playback/HlsPlayback.ts +5 -1
- package/src/playback/types.ts +10 -0
- package/src/playback.types.ts +0 -6
- package/src/plugins/multi-camera/MultiCamera.ts +103 -166
- package/src/plugins/source-controller/SourceController.ts +0 -39
- package/src/plugins/subtitles/ClosedCaptions.ts +35 -21
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +73 -112
- package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +3 -3
- package/src/testUtils.ts +3 -0
- package/src/utils/mediaSources.ts +10 -6
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/api/player.multicamera.activebyid.md +0 -67
- /package/assets/{subtitles → cc}/combobox.ejs +0 -0
- /package/assets/{subtitles → cc}/string.ejs +0 -0
|
@@ -30,11 +30,10 @@ import {
|
|
|
30
30
|
QualityLevel,
|
|
31
31
|
TimePosition,
|
|
32
32
|
TimeValue,
|
|
33
|
-
VTTCueInfo,
|
|
34
33
|
} from '../../playback.types.js'
|
|
35
34
|
import { isDashSource } from '../../utils/mediaSources.js'
|
|
36
35
|
import { BasePlayback } from '../BasePlayback.js'
|
|
37
|
-
import { PlaybackEvents } from '../types.js'
|
|
36
|
+
import { PlaybackEvents, VTTCueInfo } from '../types.js'
|
|
38
37
|
import { AudioTrack } from '@clappr/core/types/base/playback/playback.js'
|
|
39
38
|
|
|
40
39
|
const AUTO = -1
|
|
@@ -61,6 +60,8 @@ export default class DashPlayback extends BasePlayback {
|
|
|
61
60
|
|
|
62
61
|
_currentLevel: number = AUTO
|
|
63
62
|
|
|
63
|
+
_currentTextTrackId: number = -1
|
|
64
|
+
|
|
64
65
|
// true when the actual duration is longer than hlsjs's live sync point
|
|
65
66
|
// when this is false playableRegionDuration will be the actual duration
|
|
66
67
|
// when this is true playableRegionDuration will exclude the time after the sync point
|
|
@@ -248,7 +249,11 @@ export default class DashPlayback extends BasePlayback {
|
|
|
248
249
|
streaming: {
|
|
249
250
|
text: {
|
|
250
251
|
defaultEnabled: false,
|
|
251
|
-
|
|
252
|
+
// NOTE: dispatchForManualRendering is not correctly implemented in DASH.js;
|
|
253
|
+
// it does not work when there are multiple text tracks.
|
|
254
|
+
// CUE_ENTER and CUE_EXIT events might be dispatched additionally
|
|
255
|
+
// for a track, other than the currently active one.
|
|
256
|
+
// dispatchForManualRendering: true, // TODO only when useNativeSubtitles is not true?
|
|
252
257
|
},
|
|
253
258
|
},
|
|
254
259
|
},
|
|
@@ -319,29 +324,6 @@ export default class DashPlayback extends BasePlayback {
|
|
|
319
324
|
this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate)
|
|
320
325
|
},
|
|
321
326
|
)
|
|
322
|
-
|
|
323
|
-
this._dash.on(MediaPlayer.events.TRACK_CHANGE_RENDERED, (e: any) => {
|
|
324
|
-
if ((e as TrackChangeRenderedEvent).mediaType === 'audio') {
|
|
325
|
-
this.trigger(
|
|
326
|
-
Events.PLAYBACK_AUDIO_CHANGED,
|
|
327
|
-
toClapprTrack(e.newMediaInfo),
|
|
328
|
-
)
|
|
329
|
-
}
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
this._dash.on(MediaPlayer.events.CUE_ENTER, (e: CueEnterEvent) => {
|
|
333
|
-
this.oncueenter?.({
|
|
334
|
-
end: e.end,
|
|
335
|
-
id: e.id,
|
|
336
|
-
start: e.start,
|
|
337
|
-
text: e.text,
|
|
338
|
-
})
|
|
339
|
-
})
|
|
340
|
-
this._dash.on(MediaPlayer.events.CUE_EXIT, (e: CueExitEvent) => {
|
|
341
|
-
this.oncueexit?.({
|
|
342
|
-
id: e.id,
|
|
343
|
-
})
|
|
344
|
-
})
|
|
345
327
|
}
|
|
346
328
|
|
|
347
329
|
render() {
|
|
@@ -725,6 +707,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
725
707
|
}
|
|
726
708
|
|
|
727
709
|
setTextTrack(id: number) {
|
|
710
|
+
this._currentTextTrackId = id
|
|
728
711
|
this._dash?.setTextTrack(id)
|
|
729
712
|
}
|
|
730
713
|
|
|
@@ -732,8 +715,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
732
715
|
* @override
|
|
733
716
|
*/
|
|
734
717
|
get closedCaptionsTracks() {
|
|
735
|
-
|
|
736
|
-
return tt;
|
|
718
|
+
return this.getTextTracks()
|
|
737
719
|
}
|
|
738
720
|
|
|
739
721
|
private getTextTracks() {
|
|
@@ -744,7 +726,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
744
726
|
id: index,
|
|
745
727
|
label: getTextTrackLabel(t) || "",
|
|
746
728
|
language: t.lang,
|
|
747
|
-
mode: "hidden",
|
|
729
|
+
mode: this._currentTextTrackId === index ? "showing" : "hidden",
|
|
748
730
|
},
|
|
749
731
|
})) || []
|
|
750
732
|
}
|
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
PlayerComponentType,
|
|
27
27
|
QualityLevel,
|
|
28
28
|
TimePosition,
|
|
29
|
-
VTTCueInfo,
|
|
30
29
|
} from '../../playback.types.js'
|
|
31
30
|
import { PlaybackType } from '../../types.js'
|
|
32
31
|
import { isHlsSource } from '../../utils/mediaSources.js'
|
|
@@ -35,6 +34,7 @@ import { BasePlayback } from '../BasePlayback.js'
|
|
|
35
34
|
|
|
36
35
|
import { CLAPPR_VERSION } from '../../build.js'
|
|
37
36
|
import { AudioTrack } from '@clappr/core/types/base/playback/playback.js'
|
|
37
|
+
import { VTTCueInfo } from '../types.js'
|
|
38
38
|
|
|
39
39
|
const { now } = Utils
|
|
40
40
|
|
|
@@ -1135,7 +1135,11 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
1135
1135
|
}
|
|
1136
1136
|
|
|
1137
1137
|
setTextTrack(id: number) {
|
|
1138
|
+
if (id === this._hls!.subtitleTrack) {
|
|
1139
|
+
return
|
|
1140
|
+
}
|
|
1138
1141
|
this._hls!.subtitleTrack = id
|
|
1142
|
+
this.cues = []
|
|
1139
1143
|
}
|
|
1140
1144
|
|
|
1141
1145
|
/**
|
package/src/playback/types.ts
CHANGED
package/src/playback.types.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
UICorePlugin,
|
|
8
8
|
} from '@clappr/core'
|
|
9
9
|
import { reportError, trace } from '@gcorevideo/utils'
|
|
10
|
+
import { guessMimeType, MIME_TYPE_DASH } from '../../utils/mediaSources.js'
|
|
10
11
|
|
|
11
12
|
import { CLAPPR_VERSION } from '../../build.js'
|
|
12
13
|
|
|
@@ -14,18 +15,28 @@ import pluginHtml from '../../../assets/multi-camera/multicamera.ejs'
|
|
|
14
15
|
import '../../../assets/multi-camera/style.scss'
|
|
15
16
|
|
|
16
17
|
import streamsIcon from '../../../assets/icons/old/streams.svg'
|
|
17
|
-
import
|
|
18
|
-
import streamsWhiteNightsIcon from '../../../assets/icons/old/wn.svg'
|
|
19
|
-
import { ZeptoResult } from '../../types.js'
|
|
18
|
+
import { PlayerMediaSource, TransportPreference, ZeptoResult } from '../../types.js'
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
/**
|
|
21
|
+
* @beta
|
|
22
|
+
*/
|
|
23
|
+
export type MultisourcesMode = 'one_first' | 'only_live' | 'show_all'
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Extended media source description
|
|
27
|
+
* @beta
|
|
28
|
+
*/
|
|
29
|
+
export type MulticCameraSourceInfo = {
|
|
30
|
+
description: string
|
|
27
31
|
dvr: boolean
|
|
32
|
+
hls_mpegts_url: string | null
|
|
33
|
+
id: number
|
|
34
|
+
live: boolean
|
|
28
35
|
projection: string | null
|
|
36
|
+
screenshot: string | null
|
|
37
|
+
source: string
|
|
38
|
+
source_dash: string | null
|
|
39
|
+
title: string
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
const VERSION = '0.0.1'
|
|
@@ -37,13 +48,13 @@ const T = 'plugins.multicamera'
|
|
|
37
48
|
* @beta
|
|
38
49
|
*/
|
|
39
50
|
export class MultiCamera extends UICorePlugin {
|
|
40
|
-
private currentCamera:
|
|
51
|
+
private currentCamera: MulticCameraSourceInfo | null = null
|
|
41
52
|
|
|
42
53
|
private currentTime: number = 0
|
|
43
54
|
|
|
44
55
|
private playing = false
|
|
45
56
|
|
|
46
|
-
private multicamera:
|
|
57
|
+
private multicamera: MulticCameraSourceInfo[] = []
|
|
47
58
|
|
|
48
59
|
private noActiveStreams = false
|
|
49
60
|
|
|
@@ -89,9 +100,11 @@ export class MultiCamera extends UICorePlugin {
|
|
|
89
100
|
this.playing = this.options.multicameraPlay
|
|
90
101
|
// Don't mutate the options, TODO check if some plugin observes the options.multicamera
|
|
91
102
|
this.multicamera = this.options.multisources.map(
|
|
92
|
-
(item:
|
|
103
|
+
(item: MulticCameraSourceInfo) => ({ ...item }),
|
|
93
104
|
)
|
|
94
105
|
this.noActiveStreams = this.multicamera.every((item) => !item.live)
|
|
106
|
+
// TODO filter out non-live
|
|
107
|
+
this.core.options.sources = expandMediaSource(this.multicamera[0])
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
override bindEvents() {
|
|
@@ -113,19 +126,15 @@ export class MultiCamera extends UICorePlugin {
|
|
|
113
126
|
)
|
|
114
127
|
}
|
|
115
128
|
|
|
116
|
-
unBindEvents() {
|
|
117
|
-
|
|
118
|
-
this.stopListening(this.core, Events.CORE_READY)
|
|
119
|
-
// @ts-ignore
|
|
129
|
+
private unBindEvents() {
|
|
130
|
+
this.stopListening(this.core, Events.CORE_READY, this.bindPlaybackEvents)
|
|
120
131
|
this.stopListening(
|
|
121
132
|
this.core.mediaControl,
|
|
122
133
|
Events.MEDIACONTROL_CONTAINERCHANGED,
|
|
134
|
+
this.reload,
|
|
123
135
|
)
|
|
124
|
-
|
|
125
|
-
this.stopListening(this.core.mediaControl, Events.
|
|
126
|
-
// @ts-ignore
|
|
127
|
-
this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_HIDE)
|
|
128
|
-
// @ts-ignore
|
|
136
|
+
this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_RENDERED, this.render)
|
|
137
|
+
this.stopListening(this.core.mediaControl, Events.MEDIACONTROL_HIDE, this.hideSelectLevelMenu)
|
|
129
138
|
this.stopListening(
|
|
130
139
|
this.core.activePlayback,
|
|
131
140
|
Events.PLAYBACK_PLAY,
|
|
@@ -150,11 +159,7 @@ export class MultiCamera extends UICorePlugin {
|
|
|
150
159
|
}
|
|
151
160
|
|
|
152
161
|
private shouldRender() {
|
|
153
|
-
if (
|
|
154
|
-
return false
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (!this.core.activePlayback) {
|
|
162
|
+
if (this.noActiveStreams) {
|
|
158
163
|
return false
|
|
159
164
|
}
|
|
160
165
|
|
|
@@ -162,90 +167,61 @@ export class MultiCamera extends UICorePlugin {
|
|
|
162
167
|
}
|
|
163
168
|
|
|
164
169
|
override render() {
|
|
165
|
-
if (this.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
if (!this.core.activeContainer || !this.core.activePlayback) {
|
|
171
|
+
return this
|
|
172
|
+
}
|
|
173
|
+
if (!this.shouldRender()) {
|
|
174
|
+
return this
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let numActiveSources = 0
|
|
178
|
+
const currentSource = this.core.activePlayback?.sourceMedia
|
|
179
|
+
|
|
180
|
+
for (const item of this.multicamera) {
|
|
181
|
+
if (item.live) {
|
|
182
|
+
numActiveSources++
|
|
183
|
+
}
|
|
184
|
+
if (!this.currentCamera && item.source === currentSource) {
|
|
185
|
+
this.currentCamera = item
|
|
177
186
|
}
|
|
187
|
+
}
|
|
178
188
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.core.
|
|
185
|
-
) {
|
|
186
|
-
if (this.currentTime < this.core.activePlayback.getDuration()) {
|
|
187
|
-
this.core.activePlayback.seek(this.currentTime)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
this.currentTime = 0
|
|
191
|
-
|
|
192
|
-
// if (mediaControl.$el.hasClass('dvr')) {
|
|
193
|
-
// this.core.activeContainer.dvrInUse = true;
|
|
194
|
-
// }
|
|
189
|
+
if (
|
|
190
|
+
this.currentTime &&
|
|
191
|
+
this.core.getPlaybackType() !== Playback.LIVE
|
|
192
|
+
) {
|
|
193
|
+
if (this.currentTime < this.core.activePlayback.getDuration()) {
|
|
194
|
+
this.core.activePlayback.seek(this.currentTime)
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
this.template({
|
|
200
|
-
streams: this.multicamera,
|
|
201
|
-
multisources_mode: this.options.multisourcesMode,
|
|
202
|
-
}),
|
|
203
|
-
)
|
|
197
|
+
this.currentTime = 0
|
|
198
|
+
}
|
|
204
199
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
this.options.multisourcesMode
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
} else {
|
|
212
|
-
this.$el.show()
|
|
213
|
-
}
|
|
200
|
+
this.$el.html(
|
|
201
|
+
this.template({
|
|
202
|
+
streams: this.multicamera,
|
|
203
|
+
multisources_mode: this.options.multisourcesMode,
|
|
204
|
+
}),
|
|
205
|
+
)
|
|
214
206
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (
|
|
224
|
-
Object.prototype.hasOwnProperty.call(
|
|
225
|
-
this.core.mediaControl,
|
|
226
|
-
'$multiCameraSelector',
|
|
227
|
-
) &&
|
|
228
|
-
this.core.mediaControl.$multiCameraSelector.find(
|
|
229
|
-
'span.multicamera-icon',
|
|
230
|
-
).length > 0
|
|
231
|
-
) {
|
|
232
|
-
if (~window.location.href.indexOf('whitenights.gcdn.co')) {
|
|
233
|
-
this.core.mediaControl.$multiCameraSelector
|
|
234
|
-
.find('span.multicamera-icon')
|
|
235
|
-
.append(streamsWhiteNightsIcon)
|
|
236
|
-
} else if (~window.location.href.indexOf('momentosolutions.gcdn.co')) {
|
|
237
|
-
this.core.mediaControl.$multiCameraSelector
|
|
238
|
-
.find('span.multicamera-icon')
|
|
239
|
-
.append(streamsMomentoIcon)
|
|
240
|
-
} else {
|
|
241
|
-
this.core.mediaControl.$multiCameraSelector
|
|
242
|
-
.find('span.multicamera-icon')
|
|
243
|
-
.append(streamsIcon)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
this.highlightCurrentLevel()
|
|
207
|
+
if (
|
|
208
|
+
(numActiveSources < 2 &&
|
|
209
|
+
this.options.multisourcesMode !== 'show_all') ||
|
|
210
|
+
this.options.multisourcesMode === 'one_first'
|
|
211
|
+
) {
|
|
212
|
+
this.$el.hide()
|
|
213
|
+
} else {
|
|
214
|
+
this.$el.show()
|
|
247
215
|
}
|
|
248
216
|
|
|
217
|
+
const mediaControl = this.core.getPlugin('media_control')
|
|
218
|
+
|
|
219
|
+
mediaControl.slot('multicamera', this.$el)
|
|
220
|
+
this.$el
|
|
221
|
+
.find('span.multicamera-icon')
|
|
222
|
+
.html(streamsIcon)
|
|
223
|
+
this.highlightCurrentLevel()
|
|
224
|
+
|
|
249
225
|
return this
|
|
250
226
|
}
|
|
251
227
|
|
|
@@ -260,36 +236,6 @@ export class MultiCamera extends UICorePlugin {
|
|
|
260
236
|
return false
|
|
261
237
|
}
|
|
262
238
|
|
|
263
|
-
activeById(id: number, active: boolean) {
|
|
264
|
-
this.setLiveStatus(id, active)
|
|
265
|
-
|
|
266
|
-
if (!this.currentCamera && !this.noActiveStreams) {
|
|
267
|
-
return
|
|
268
|
-
}
|
|
269
|
-
if (this.noActiveStreams && !active) {
|
|
270
|
-
return
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (this.currentCamera) {
|
|
274
|
-
if (this.options.multisourcesMode === 'only_live') {
|
|
275
|
-
this.behaviorLive(id, active)
|
|
276
|
-
}
|
|
277
|
-
if (this.options.multisourcesMode === 'one_first') {
|
|
278
|
-
this.behaviorOne(id, active)
|
|
279
|
-
}
|
|
280
|
-
if (this.options.multisourcesMode === 'show_all') {
|
|
281
|
-
this.behaviorAll(id, active)
|
|
282
|
-
}
|
|
283
|
-
} else {
|
|
284
|
-
if (this.noActiveStreams && active) {
|
|
285
|
-
this.changeById(id)
|
|
286
|
-
this.noActiveStreams = false
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
this.render()
|
|
291
|
-
}
|
|
292
|
-
|
|
293
239
|
private setLiveStatus(id: number, active: boolean) {
|
|
294
240
|
try {
|
|
295
241
|
const index = this.findIndexById(id)
|
|
@@ -355,7 +301,6 @@ export class MultiCamera extends UICorePlugin {
|
|
|
355
301
|
this.currentCamera = null
|
|
356
302
|
this.noActiveStreams = true
|
|
357
303
|
this.core.trigger('core:multicamera:no_active_translation')
|
|
358
|
-
// this.changeById(this.multicamera[nextIndex].id);
|
|
359
304
|
}
|
|
360
305
|
|
|
361
306
|
private showError() {
|
|
@@ -379,7 +324,7 @@ export class MultiCamera extends UICorePlugin {
|
|
|
379
324
|
|
|
380
325
|
private hideError() {
|
|
381
326
|
try {
|
|
382
|
-
this.core.
|
|
327
|
+
this.core.getPlugin('media_control')?.enableControlButton()
|
|
383
328
|
} catch (error) {
|
|
384
329
|
reportError(error)
|
|
385
330
|
}
|
|
@@ -390,14 +335,9 @@ export class MultiCamera extends UICorePlugin {
|
|
|
390
335
|
queueMicrotask(() => {
|
|
391
336
|
const playbackOptions = this.core.options.playback || {}
|
|
392
337
|
|
|
393
|
-
// TODO figure out
|
|
338
|
+
// TODO figure out if it's needed
|
|
394
339
|
playbackOptions.recycleVideo = Browser.isMobile
|
|
395
|
-
this.currentCamera = this.findElementById(id)
|
|
396
|
-
trace(`${T} changeById`, {
|
|
397
|
-
id,
|
|
398
|
-
currentCamera: this.currentCamera,
|
|
399
|
-
multicamera: this.multicamera,
|
|
400
|
-
})
|
|
340
|
+
this.currentCamera = this.findElementById(id)
|
|
401
341
|
|
|
402
342
|
if (!this.currentCamera) {
|
|
403
343
|
return
|
|
@@ -423,29 +363,17 @@ export class MultiCamera extends UICorePlugin {
|
|
|
423
363
|
this.core.configure({
|
|
424
364
|
playback: playbackOptions,
|
|
425
365
|
source: this.currentCamera.source, // TODO ensure that the preferred transport is used
|
|
426
|
-
video360: {
|
|
427
|
-
// TODO
|
|
428
|
-
projection: this.currentCamera.projection,
|
|
429
|
-
},
|
|
430
366
|
fullscreenDisable,
|
|
431
367
|
autoPlay: this.playing,
|
|
432
368
|
disableCanAutoPlay: true,
|
|
433
369
|
})
|
|
434
|
-
this.core.activeContainer
|
|
370
|
+
this.core.activeContainer?.enableMediaControl()
|
|
435
371
|
})
|
|
436
372
|
this.toggleContextMenu()
|
|
437
373
|
}
|
|
438
374
|
|
|
439
|
-
private
|
|
440
|
-
return this.multicamera
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
private getCurrentCamera() {
|
|
444
|
-
return this.currentCamera
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
private findElementById(id: number): MediaSourceInfo | undefined {
|
|
448
|
-
return this.multicamera.find((element) => element.id === id)
|
|
375
|
+
private findElementById(id: number): MulticCameraSourceInfo | null {
|
|
376
|
+
return this.multicamera.find((element) => element.id === id) ?? null
|
|
449
377
|
}
|
|
450
378
|
|
|
451
379
|
private findIndexById(id: number): number {
|
|
@@ -457,24 +385,16 @@ export class MultiCamera extends UICorePlugin {
|
|
|
457
385
|
}
|
|
458
386
|
|
|
459
387
|
private hideSelectLevelMenu() {
|
|
460
|
-
; (this.$('
|
|
388
|
+
; (this.$('ul') as ZeptoResult).hide()
|
|
461
389
|
}
|
|
462
390
|
|
|
463
391
|
private toggleContextMenu() {
|
|
464
|
-
; (this.$('
|
|
392
|
+
; (this.$('ul') as ZeptoResult).toggle()
|
|
465
393
|
}
|
|
466
394
|
|
|
467
|
-
// private buttonElement(): ZeptoResult {
|
|
468
|
-
// return this.$('.multicamera button');
|
|
469
|
-
// }
|
|
470
|
-
|
|
471
|
-
// private buttonElementText(): ZeptoResult {
|
|
472
|
-
// return this.$('.multicamera button .quality-text');
|
|
473
|
-
// }
|
|
474
|
-
|
|
475
395
|
private levelElement(id?: number): ZeptoResult {
|
|
476
396
|
return this.$(
|
|
477
|
-
'.multicamera
|
|
397
|
+
'ul .multicamera-item' +
|
|
478
398
|
(id !== undefined
|
|
479
399
|
? '[data-multicamera-selector-select="' + id + '"]'
|
|
480
400
|
: ''),
|
|
@@ -488,3 +408,20 @@ export class MultiCamera extends UICorePlugin {
|
|
|
488
408
|
this.levelElement(this.currentCamera.id).addClass('multicamera-active')
|
|
489
409
|
}
|
|
490
410
|
}
|
|
411
|
+
|
|
412
|
+
function expandMediaSource(source: MulticCameraSourceInfo): PlayerMediaSource[] {
|
|
413
|
+
const result: PlayerMediaSource[] = [{
|
|
414
|
+
source: source.source,
|
|
415
|
+
mimeType: guessMimeType(source.source),
|
|
416
|
+
}]
|
|
417
|
+
if (source.source_dash) {
|
|
418
|
+
result.push({
|
|
419
|
+
source: source.source_dash,
|
|
420
|
+
mimeType: MIME_TYPE_DASH,
|
|
421
|
+
})
|
|
422
|
+
}
|
|
423
|
+
if (source.hls_mpegts_url) {
|
|
424
|
+
result.push(source.hls_mpegts_url)
|
|
425
|
+
}
|
|
426
|
+
return result
|
|
427
|
+
}
|
|
@@ -30,45 +30,6 @@ function noSync(cb: () => void) {
|
|
|
30
30
|
* `PLUGIN` that is managing the automatic failover between media sources.
|
|
31
31
|
* @public
|
|
32
32
|
* @remarks
|
|
33
|
-
* Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
|
|
34
|
-
* on how sources ordering and selection works. Below is a simplified diagram:
|
|
35
|
-
*
|
|
36
|
-
* ```markdown
|
|
37
|
-
* sources_list:
|
|
38
|
-
* - a.mpd | +--------------------+
|
|
39
|
-
* - b.m3u8 |--->| init |
|
|
40
|
-
* - ... | |--------------------|
|
|
41
|
-
* | current_source = 0 |
|
|
42
|
-
* +--------------------+
|
|
43
|
-
* |
|
|
44
|
-
* | source = a.mpd
|
|
45
|
-
* | playback = dash.js
|
|
46
|
-
* v
|
|
47
|
-
* +------------------+
|
|
48
|
-
* +-->| load source |
|
|
49
|
-
* | +---------|--------+
|
|
50
|
-
* | v
|
|
51
|
-
* | +------------------+
|
|
52
|
-
* | | play |
|
|
53
|
-
* | +---------|--------+
|
|
54
|
-
* | |
|
|
55
|
-
* | v
|
|
56
|
-
* | +-----------------------+
|
|
57
|
-
* | | on playback_error |
|
|
58
|
-
* | |-----------------------|
|
|
59
|
-
* | | current_source = |
|
|
60
|
-
* | | (current_source + 1) |
|
|
61
|
-
* | | % len sources_list |
|
|
62
|
-
* | | |
|
|
63
|
-
* | | delay 1..3s |
|
|
64
|
-
* | +---------------|-------+
|
|
65
|
-
* | |
|
|
66
|
-
* | source=b.m3u8 |
|
|
67
|
-
* | playback=hls.js |
|
|
68
|
-
* +-------------------+
|
|
69
|
-
*
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
33
|
* @example
|
|
73
34
|
* ```ts
|
|
74
35
|
* import { SourceController } from '@gcorevideo/player'
|