@mindedge/vuetify-player 0.3.1 → 0.4.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 +88 -50
- package/package.json +1 -1
- package/src/components/Media/CaptionsMenu.vue +260 -94
- package/src/components/Media/Html5Player.vue +452 -304
- package/src/components/Media/PlaylistMenu.vue +40 -42
- package/src/components/Media/SettingsMenu.vue +98 -0
- package/src/components/Media/YoutubePlayer.vue +5 -1
- package/src/components/VuetifyPlayer.vue +214 -28
- package/src/i18n/en-US.js +9 -0
- package/src/i18n/es-ES.js +12 -0
- package/src/i18n/i18n.js +6 -1
- package/src/i18n/sv-SE.js +11 -0
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-container>
|
|
3
3
|
<v-row>
|
|
4
|
-
<v-col
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
<v-col
|
|
5
|
+
ref="playerContainer"
|
|
6
|
+
:cols="!state.expandedCaptions ? 12 : 6"
|
|
7
|
+
class="pb-0 mb-0"
|
|
8
|
+
>
|
|
9
|
+
<div
|
|
10
|
+
v-if="resolvedType === 'video' && buffering"
|
|
11
|
+
class="player-overlay"
|
|
12
|
+
>
|
|
13
|
+
<div class="player-overlay--icon">
|
|
14
|
+
<v-progress-circular
|
|
15
|
+
:size="50"
|
|
16
|
+
indeterminate
|
|
17
|
+
></v-progress-circular>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
<div
|
|
21
|
+
v-if="resolvedType === 'video' && state.replay"
|
|
22
|
+
class="player-overlay"
|
|
23
|
+
>
|
|
24
|
+
<div class="player-overlay--icon">
|
|
25
|
+
<v-icon class="player-overlay--replay-icon">
|
|
26
|
+
mdi-replay
|
|
27
|
+
</v-icon>
|
|
28
|
+
</div>
|
|
10
29
|
</div>
|
|
11
30
|
<video
|
|
12
31
|
ref="player"
|
|
13
32
|
tabindex="0"
|
|
14
|
-
:class="'player-' +
|
|
33
|
+
:class="'player-' + resolvedType"
|
|
15
34
|
:height="attributes.height"
|
|
16
35
|
:width="attributes.width"
|
|
17
36
|
:autoplay="attributes.autoplay"
|
|
@@ -27,7 +46,7 @@
|
|
|
27
46
|
:playsinline="attributes.playsinline"
|
|
28
47
|
:poster="src.poster || attributes.poster"
|
|
29
48
|
:preload="attributes.preload"
|
|
30
|
-
@click="
|
|
49
|
+
@click="playToggle"
|
|
31
50
|
@seeking="onSeeking"
|
|
32
51
|
@timeupdate="onTimeupdate"
|
|
33
52
|
@progress="onMediaProgress"
|
|
@@ -44,6 +63,8 @@
|
|
|
44
63
|
@emptied="$emit('emptied', $event)"
|
|
45
64
|
@stalled="$emit('stalled', $event)"
|
|
46
65
|
@abort="$emit('abort', $event)"
|
|
66
|
+
@focusin="$emit('focusin', $event)"
|
|
67
|
+
@focusout="$emit('focusout', $event)"
|
|
47
68
|
>
|
|
48
69
|
<source
|
|
49
70
|
v-for="(source, index) of current.sources"
|
|
@@ -65,12 +86,13 @@
|
|
|
65
86
|
</video>
|
|
66
87
|
|
|
67
88
|
<div
|
|
89
|
+
ref="controlsContainer"
|
|
68
90
|
class="controls-container"
|
|
69
91
|
v-if="attributes.controls"
|
|
70
92
|
@mouseover="onControlsHover"
|
|
71
93
|
>
|
|
72
94
|
<v-slide-y-reverse-transition>
|
|
73
|
-
<div v-if="player &&
|
|
95
|
+
<div v-if="player && state.controls" class="controls">
|
|
74
96
|
<v-slider
|
|
75
97
|
dark
|
|
76
98
|
v-model="currentPercent"
|
|
@@ -89,25 +111,23 @@
|
|
|
89
111
|
>
|
|
90
112
|
<template #prepend>
|
|
91
113
|
<!-- Play button -->
|
|
92
|
-
<v-tooltip v-if="!
|
|
93
|
-
<template
|
|
94
|
-
v-slot:activator="{ on, attrs }"
|
|
95
|
-
>
|
|
114
|
+
<v-tooltip v-if="!state.replay" top>
|
|
115
|
+
<template #activator="{ on, attrs }">
|
|
96
116
|
<v-btn
|
|
97
117
|
small
|
|
98
118
|
text
|
|
99
119
|
v-bind="attrs"
|
|
100
120
|
v-on="on"
|
|
101
|
-
@click="
|
|
121
|
+
@click="playToggle"
|
|
102
122
|
>
|
|
103
123
|
<v-icon>{{
|
|
104
|
-
|
|
124
|
+
state.paused
|
|
105
125
|
? 'mdi-play'
|
|
106
126
|
: 'mdi-pause'
|
|
107
127
|
}}</v-icon>
|
|
108
128
|
<span class="d-sr-only">
|
|
109
129
|
{{
|
|
110
|
-
|
|
130
|
+
state.paused
|
|
111
131
|
? t(
|
|
112
132
|
language,
|
|
113
133
|
'player.play'
|
|
@@ -121,17 +141,15 @@
|
|
|
121
141
|
</v-btn>
|
|
122
142
|
</template>
|
|
123
143
|
<span>{{
|
|
124
|
-
|
|
144
|
+
state.paused
|
|
125
145
|
? t(language, 'player.play')
|
|
126
146
|
: t(language, 'player.pause')
|
|
127
147
|
}}</span>
|
|
128
148
|
</v-tooltip>
|
|
129
149
|
|
|
130
150
|
<!-- Replay button -->
|
|
131
|
-
<v-tooltip v-if="
|
|
132
|
-
<template
|
|
133
|
-
v-slot:activator="{ on, attrs }"
|
|
134
|
-
>
|
|
151
|
+
<v-tooltip v-if="state.replay" top>
|
|
152
|
+
<template #activator="{ on, attrs }">
|
|
135
153
|
<v-btn
|
|
136
154
|
small
|
|
137
155
|
text
|
|
@@ -160,15 +178,13 @@
|
|
|
160
178
|
v-if="attributes.rewind && !activeAd"
|
|
161
179
|
top
|
|
162
180
|
>
|
|
163
|
-
<template
|
|
164
|
-
v-slot:activator="{ on, attrs }"
|
|
165
|
-
>
|
|
181
|
+
<template #activator="{ on, attrs }">
|
|
166
182
|
<v-btn
|
|
167
183
|
small
|
|
168
184
|
text
|
|
169
185
|
v-bind="attrs"
|
|
170
186
|
v-on="on"
|
|
171
|
-
@click="
|
|
187
|
+
@click="rewind"
|
|
172
188
|
>
|
|
173
189
|
<v-icon>mdi-rewind-10</v-icon>
|
|
174
190
|
<span class="sr-only">{{
|
|
@@ -192,22 +208,21 @@
|
|
|
192
208
|
current.tracks &&
|
|
193
209
|
current.tracks.length > 0
|
|
194
210
|
"
|
|
211
|
+
:attach="$refs.controlsContainer"
|
|
195
212
|
open-on-hover
|
|
196
|
-
top
|
|
197
213
|
offset-y
|
|
214
|
+
top
|
|
198
215
|
>
|
|
199
|
-
<template
|
|
200
|
-
v-slot:activator="{ on, attrs }"
|
|
201
|
-
>
|
|
216
|
+
<template #activator="{ on, attrs }">
|
|
202
217
|
<v-btn
|
|
203
218
|
small
|
|
204
219
|
text
|
|
205
220
|
v-bind="attrs"
|
|
206
221
|
v-on="on"
|
|
207
|
-
@click="
|
|
222
|
+
@click="CCToggle"
|
|
208
223
|
>
|
|
209
224
|
<v-icon>{{
|
|
210
|
-
|
|
225
|
+
state.cc
|
|
211
226
|
? 'mdi-closed-caption'
|
|
212
227
|
: 'mdi-closed-caption-outline'
|
|
213
228
|
}}</v-icon>
|
|
@@ -240,45 +255,47 @@
|
|
|
240
255
|
</v-menu>
|
|
241
256
|
|
|
242
257
|
<!-- Volume -->
|
|
243
|
-
<v-menu
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
<v-menu
|
|
259
|
+
:attach="$refs.controlsContainer"
|
|
260
|
+
open-on-hover
|
|
261
|
+
offset-y
|
|
262
|
+
top
|
|
263
|
+
>
|
|
264
|
+
<template #activator="{ on, attrs }">
|
|
247
265
|
<v-btn
|
|
248
266
|
small
|
|
249
267
|
text
|
|
250
268
|
v-bind="attrs"
|
|
251
269
|
v-on="on"
|
|
252
|
-
@click="
|
|
270
|
+
@click="muteToggle"
|
|
253
271
|
>
|
|
254
272
|
<v-icon
|
|
255
273
|
v-if="
|
|
256
|
-
!
|
|
257
|
-
|
|
274
|
+
!state.muted &&
|
|
275
|
+
state.volume > 0.75
|
|
258
276
|
"
|
|
259
277
|
>mdi-volume-high</v-icon
|
|
260
278
|
>
|
|
261
279
|
<v-icon
|
|
262
280
|
v-if="
|
|
263
|
-
!
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
options.volume <= 0.75
|
|
281
|
+
!state.muted &&
|
|
282
|
+
state.volume >= 0.25 &&
|
|
283
|
+
state.volume <= 0.75
|
|
267
284
|
"
|
|
268
285
|
>mdi-volume-medium</v-icon
|
|
269
286
|
>
|
|
270
287
|
<v-icon
|
|
271
288
|
v-if="
|
|
272
|
-
!
|
|
273
|
-
|
|
274
|
-
|
|
289
|
+
!state.muted &&
|
|
290
|
+
state.volume > 0 &&
|
|
291
|
+
state.volume < 0.25
|
|
275
292
|
"
|
|
276
293
|
>mdi-volume-low</v-icon
|
|
277
294
|
>
|
|
278
295
|
<v-icon
|
|
279
296
|
v-if="
|
|
280
|
-
|
|
281
|
-
|
|
297
|
+
state.muted ||
|
|
298
|
+
state.volume === 0
|
|
282
299
|
"
|
|
283
300
|
>mdi-volume-off</v-icon
|
|
284
301
|
>
|
|
@@ -299,31 +316,29 @@
|
|
|
299
316
|
)
|
|
300
317
|
}}</span>
|
|
301
318
|
<v-slider
|
|
302
|
-
v-model="
|
|
319
|
+
v-model="state.volume"
|
|
303
320
|
inverse-label
|
|
304
321
|
:min="0"
|
|
305
322
|
:max="1"
|
|
306
323
|
:step="0.1"
|
|
307
324
|
vertical
|
|
308
|
-
@change="
|
|
325
|
+
@change="volumeChange"
|
|
309
326
|
></v-slider>
|
|
310
327
|
</v-sheet>
|
|
311
328
|
</v-menu>
|
|
312
329
|
|
|
313
330
|
<!-- Fullscreen -->
|
|
314
|
-
<v-tooltip v-if="
|
|
315
|
-
<template
|
|
316
|
-
v-slot:activator="{ on, attrs }"
|
|
317
|
-
>
|
|
331
|
+
<v-tooltip v-if="allowFullscreen" top>
|
|
332
|
+
<template #activator="{ on, attrs }">
|
|
318
333
|
<v-btn
|
|
319
334
|
small
|
|
320
335
|
text
|
|
321
336
|
v-bind="attrs"
|
|
322
337
|
v-on="on"
|
|
323
|
-
@click="
|
|
338
|
+
@click="fullscreenToggle"
|
|
324
339
|
>
|
|
325
340
|
<v-icon>{{
|
|
326
|
-
!
|
|
341
|
+
!state.fullscreen
|
|
327
342
|
? 'mdi-fullscreen'
|
|
328
343
|
: 'mdi-fullscreen-exit'
|
|
329
344
|
}}</v-icon>
|
|
@@ -350,9 +365,7 @@
|
|
|
350
365
|
"
|
|
351
366
|
top
|
|
352
367
|
>
|
|
353
|
-
<template
|
|
354
|
-
v-slot:activator="{ on, attrs }"
|
|
355
|
-
>
|
|
368
|
+
<template #activator="{ on, attrs }">
|
|
356
369
|
<v-btn
|
|
357
370
|
small
|
|
358
371
|
text
|
|
@@ -380,13 +393,8 @@
|
|
|
380
393
|
</v-tooltip>
|
|
381
394
|
|
|
382
395
|
<!-- Remote playback -->
|
|
383
|
-
<v-tooltip
|
|
384
|
-
|
|
385
|
-
top
|
|
386
|
-
>
|
|
387
|
-
<template
|
|
388
|
-
v-slot:activator="{ on, attrs }"
|
|
389
|
-
>
|
|
396
|
+
<v-tooltip v-if="allowRemotePlayback" top>
|
|
397
|
+
<template #activator="{ on, attrs }">
|
|
390
398
|
<v-btn
|
|
391
399
|
small
|
|
392
400
|
text
|
|
@@ -412,10 +420,8 @@
|
|
|
412
420
|
</v-tooltip>
|
|
413
421
|
|
|
414
422
|
<!-- Download -->
|
|
415
|
-
<v-tooltip v-if="
|
|
416
|
-
<template
|
|
417
|
-
v-slot:activator="{ on, attrs }"
|
|
418
|
-
>
|
|
423
|
+
<v-tooltip v-if="allowDownload" top>
|
|
424
|
+
<template #activator="{ on, attrs }">
|
|
419
425
|
<v-btn
|
|
420
426
|
small
|
|
421
427
|
text
|
|
@@ -438,117 +444,18 @@
|
|
|
438
444
|
</v-tooltip>
|
|
439
445
|
|
|
440
446
|
<!-- Settings -->
|
|
441
|
-
<
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
:
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
v-bind="attrs"
|
|
454
|
-
v-on="on"
|
|
455
|
-
>
|
|
456
|
-
<v-icon>mdi-cog</v-icon>
|
|
457
|
-
<span class="d-sr-only">{{
|
|
458
|
-
t(
|
|
459
|
-
language,
|
|
460
|
-
'player.toggle_settings'
|
|
461
|
-
)
|
|
462
|
-
}}</span>
|
|
463
|
-
</v-btn>
|
|
464
|
-
</template>
|
|
465
|
-
|
|
466
|
-
<v-list>
|
|
467
|
-
<v-list-item>
|
|
468
|
-
<v-list-item-title>
|
|
469
|
-
<v-icon
|
|
470
|
-
>mdi-play-speed</v-icon
|
|
471
|
-
>
|
|
472
|
-
{{
|
|
473
|
-
t(
|
|
474
|
-
language,
|
|
475
|
-
'player.playback_speed'
|
|
476
|
-
)
|
|
477
|
-
}}
|
|
478
|
-
</v-list-item-title>
|
|
479
|
-
</v-list-item>
|
|
480
|
-
<v-list-item>
|
|
481
|
-
<v-list-item-title
|
|
482
|
-
class="text-center"
|
|
483
|
-
>
|
|
484
|
-
<v-btn
|
|
485
|
-
small
|
|
486
|
-
:disabled="
|
|
487
|
-
options.playbackRateIndex ===
|
|
488
|
-
0
|
|
489
|
-
"
|
|
490
|
-
@click="
|
|
491
|
-
onPlaybackSpeed(
|
|
492
|
-
options.playbackRateIndex -
|
|
493
|
-
1
|
|
494
|
-
)
|
|
495
|
-
"
|
|
496
|
-
>
|
|
497
|
-
<v-icon>
|
|
498
|
-
mdi-clock-minus-outline
|
|
499
|
-
</v-icon>
|
|
500
|
-
<span
|
|
501
|
-
class="d-sr-only"
|
|
502
|
-
>{{
|
|
503
|
-
t(
|
|
504
|
-
language,
|
|
505
|
-
'player.playback_decrease'
|
|
506
|
-
)
|
|
507
|
-
}}</span
|
|
508
|
-
>
|
|
509
|
-
</v-btn>
|
|
510
|
-
<span class="pl-2 pr-2"
|
|
511
|
-
>{{
|
|
512
|
-
attributes
|
|
513
|
-
.playbackrates[
|
|
514
|
-
options
|
|
515
|
-
.playbackRateIndex
|
|
516
|
-
]
|
|
517
|
-
}}x</span
|
|
518
|
-
>
|
|
519
|
-
<v-btn
|
|
520
|
-
small
|
|
521
|
-
:disabled="
|
|
522
|
-
options.playbackRateIndex >=
|
|
523
|
-
attributes
|
|
524
|
-
.playbackrates
|
|
525
|
-
.length -
|
|
526
|
-
1
|
|
527
|
-
"
|
|
528
|
-
@click="
|
|
529
|
-
onPlaybackSpeed(
|
|
530
|
-
options.playbackRateIndex +
|
|
531
|
-
1
|
|
532
|
-
)
|
|
533
|
-
"
|
|
534
|
-
>
|
|
535
|
-
<v-icon>
|
|
536
|
-
mdi-clock-plus-outline
|
|
537
|
-
</v-icon>
|
|
538
|
-
<span
|
|
539
|
-
class="d-sr-only"
|
|
540
|
-
>{{
|
|
541
|
-
t(
|
|
542
|
-
language,
|
|
543
|
-
'player.playback_increase'
|
|
544
|
-
)
|
|
545
|
-
}}</span
|
|
546
|
-
>
|
|
547
|
-
</v-btn>
|
|
548
|
-
</v-list-item-title>
|
|
549
|
-
</v-list-item>
|
|
550
|
-
</v-list>
|
|
551
|
-
</v-menu>
|
|
447
|
+
<SettingsMenu
|
|
448
|
+
:attach="$refs.controlsContainer"
|
|
449
|
+
:state="state"
|
|
450
|
+
:attributes="attributes"
|
|
451
|
+
:language="language"
|
|
452
|
+
:captions-visible.sync="
|
|
453
|
+
captionsVisibleState
|
|
454
|
+
"
|
|
455
|
+
@change:playback-rate-index="
|
|
456
|
+
onPlaybackSpeedChange
|
|
457
|
+
"
|
|
458
|
+
></SettingsMenu>
|
|
552
459
|
</template>
|
|
553
460
|
</v-slider>
|
|
554
461
|
</div>
|
|
@@ -564,14 +471,32 @@
|
|
|
564
471
|
captions.cues &&
|
|
565
472
|
Object.keys(captions.cues).length
|
|
566
473
|
"
|
|
567
|
-
:cols="!
|
|
474
|
+
:cols="!state.expandedCaptions ? 12 : 6"
|
|
475
|
+
class="pt-0 mt-0"
|
|
568
476
|
>
|
|
569
477
|
<CaptionsMenu
|
|
570
478
|
v-model="captions"
|
|
571
479
|
:language="language"
|
|
480
|
+
:expanded.sync="captionsExpandedState"
|
|
481
|
+
:hide-expand="captionsHideExpand"
|
|
482
|
+
:paragraph-view="captionsParagraphView"
|
|
483
|
+
:hide-paragraph-view="captionsHideParagraphView"
|
|
484
|
+
:autoscroll="captionsAutoscroll"
|
|
485
|
+
:visible.sync="captionsVisibleState"
|
|
486
|
+
:hide-autoscroll="captionsHideAutoscroll"
|
|
487
|
+
:hide-close="captionsHideClose"
|
|
488
|
+
@update:paragraph-view="
|
|
489
|
+
$emit('update:captions-paragraph-view', $event)
|
|
490
|
+
"
|
|
491
|
+
@update:autoscroll="
|
|
492
|
+
$emit('update:captions-autoscroll', $event)
|
|
493
|
+
"
|
|
494
|
+
@update:close="$emit('update:captions-visible', $event)"
|
|
572
495
|
@click:cue="onCueClick"
|
|
573
496
|
@click:expand="onClickExpandCaptions"
|
|
574
|
-
@click:paragraph="onClickParagraph"
|
|
497
|
+
@click:paragraph-view="onClickParagraph"
|
|
498
|
+
@click:autoscroll="onClickAutoscroll"
|
|
499
|
+
@click:close="onClickCaptionsClose"
|
|
575
500
|
></CaptionsMenu>
|
|
576
501
|
</v-col>
|
|
577
502
|
</v-row>
|
|
@@ -580,12 +505,14 @@
|
|
|
580
505
|
|
|
581
506
|
<script>
|
|
582
507
|
import filters from '../filters'
|
|
508
|
+
import SettingsMenu from './SettingsMenu.vue'
|
|
583
509
|
import CaptionsMenu from './CaptionsMenu.vue'
|
|
584
510
|
import { t } from '../../i18n/i18n'
|
|
585
511
|
|
|
586
512
|
export default {
|
|
587
513
|
name: 'Html5Player',
|
|
588
514
|
components: {
|
|
515
|
+
SettingsMenu,
|
|
589
516
|
CaptionsMenu,
|
|
590
517
|
},
|
|
591
518
|
props: {
|
|
@@ -593,7 +520,7 @@ export default {
|
|
|
593
520
|
type: {
|
|
594
521
|
type: String,
|
|
595
522
|
required: false,
|
|
596
|
-
default: '
|
|
523
|
+
default: 'auto',
|
|
597
524
|
},
|
|
598
525
|
attributes: {
|
|
599
526
|
type: Object,
|
|
@@ -603,8 +530,84 @@ export default {
|
|
|
603
530
|
type: Object,
|
|
604
531
|
required: true,
|
|
605
532
|
},
|
|
533
|
+
captionsExpanded: {
|
|
534
|
+
type: Boolean,
|
|
535
|
+
required: false,
|
|
536
|
+
default: undefined,
|
|
537
|
+
},
|
|
538
|
+
captionsHideExpand: { type: Boolean, required: false, default: true },
|
|
539
|
+
captionsParagraphView: {
|
|
540
|
+
type: Boolean,
|
|
541
|
+
required: false,
|
|
542
|
+
default: undefined,
|
|
543
|
+
},
|
|
544
|
+
captionsHideParagraphView: {
|
|
545
|
+
type: Boolean,
|
|
546
|
+
required: false,
|
|
547
|
+
default: false,
|
|
548
|
+
},
|
|
549
|
+
captionsAutoscroll: {
|
|
550
|
+
type: Boolean,
|
|
551
|
+
required: false,
|
|
552
|
+
default: undefined,
|
|
553
|
+
},
|
|
554
|
+
captionsVisible: {
|
|
555
|
+
type: Boolean,
|
|
556
|
+
required: false,
|
|
557
|
+
default: undefined,
|
|
558
|
+
},
|
|
559
|
+
captionsHideAutoscroll: {
|
|
560
|
+
type: Boolean,
|
|
561
|
+
required: false,
|
|
562
|
+
default: false,
|
|
563
|
+
},
|
|
564
|
+
captionsHideClose: {
|
|
565
|
+
type: Boolean,
|
|
566
|
+
required: false,
|
|
567
|
+
default: false,
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
emits: [
|
|
571
|
+
'error',
|
|
572
|
+
'canplaythrough',
|
|
573
|
+
'emptied',
|
|
574
|
+
'stalled',
|
|
575
|
+
'abort',
|
|
576
|
+
'canplay',
|
|
577
|
+
'waiting',
|
|
578
|
+
'play',
|
|
579
|
+
'pause',
|
|
580
|
+
'load',
|
|
581
|
+
'mouseover',
|
|
582
|
+
'mouseout',
|
|
583
|
+
'ended',
|
|
584
|
+
'trackchange',
|
|
585
|
+
'ratechange',
|
|
586
|
+
'timeupdate',
|
|
587
|
+
'seeking',
|
|
588
|
+
'progress',
|
|
589
|
+
'volumechange',
|
|
590
|
+
'cuechange',
|
|
591
|
+
'loadeddata',
|
|
592
|
+
'loadedmetadata',
|
|
593
|
+
'click:fullscreen',
|
|
594
|
+
'click:pictureinpicture',
|
|
595
|
+
'click:remoteplayback',
|
|
596
|
+
'click:captions-expand',
|
|
597
|
+
'click:captions-paragraph-view',
|
|
598
|
+
'click:captions-autoscroll',
|
|
599
|
+
'click:captions-close',
|
|
600
|
+
'click:captions-cue',
|
|
601
|
+
'update:captions-expanded',
|
|
602
|
+
'update:captions-paragraph-view',
|
|
603
|
+
'update:captions-autoscroll',
|
|
604
|
+
'update:captions-visible',
|
|
605
|
+
],
|
|
606
|
+
watch: {
|
|
607
|
+
'state.controls': function () {
|
|
608
|
+
this.setCuePosition()
|
|
609
|
+
},
|
|
606
610
|
},
|
|
607
|
-
watch: {},
|
|
608
611
|
computed: {
|
|
609
612
|
current() {
|
|
610
613
|
// We're playing an ad currently
|
|
@@ -616,9 +619,98 @@ export default {
|
|
|
616
619
|
}
|
|
617
620
|
},
|
|
618
621
|
playerClass() {
|
|
619
|
-
let classList = 'player-' + this.
|
|
622
|
+
let classList = 'player-' + this.resolvedType
|
|
620
623
|
return classList
|
|
621
624
|
},
|
|
625
|
+
resolvedType() {
|
|
626
|
+
// Default to video if the type can't be resolved
|
|
627
|
+
let type = 'video'
|
|
628
|
+
|
|
629
|
+
// Make sure current is set and valid and has sources
|
|
630
|
+
if (
|
|
631
|
+
this.current &&
|
|
632
|
+
this.current.sources &&
|
|
633
|
+
this.current.sources.length > 0
|
|
634
|
+
) {
|
|
635
|
+
const source = this.current.sources[0]
|
|
636
|
+
|
|
637
|
+
// Determine off the type / mime field first, then check the extensions
|
|
638
|
+
if (source.type && source.type.match(/^video\//i)) {
|
|
639
|
+
type = 'video'
|
|
640
|
+
} else if (source.type && source.type.match(/^audio\//i)) {
|
|
641
|
+
type = 'audio'
|
|
642
|
+
} else if (
|
|
643
|
+
source.src &&
|
|
644
|
+
source.src.match(/(?:mp4|webm|ogg)$/)
|
|
645
|
+
) {
|
|
646
|
+
type = 'video'
|
|
647
|
+
} else if (source.src && source.src.match(/(?:mp3|wav)$/)) {
|
|
648
|
+
type = 'audio'
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
return type
|
|
653
|
+
},
|
|
654
|
+
captionsVisibleState: {
|
|
655
|
+
get() {
|
|
656
|
+
if (typeof this.captionsVisible !== 'undefined') {
|
|
657
|
+
return this.captionsVisible
|
|
658
|
+
} else {
|
|
659
|
+
return this.state.captionsVisible
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
set(v) {
|
|
663
|
+
this.$emit('update:captions-visible', v)
|
|
664
|
+
this.state.captionsVisible = v
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
captionsExpandedState: {
|
|
668
|
+
get() {
|
|
669
|
+
if (typeof this.captionsExpanded !== 'undefined') {
|
|
670
|
+
return this.captionsExpanded
|
|
671
|
+
} else {
|
|
672
|
+
return this.state.expandedCaptions
|
|
673
|
+
}
|
|
674
|
+
},
|
|
675
|
+
set(v) {
|
|
676
|
+
this.$emit('update:captions-expanded', v)
|
|
677
|
+
this.state.expandedCaptions = v
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
allowFullscreen() {
|
|
681
|
+
// Determine fullscreen settings
|
|
682
|
+
// If we explicitly disabled fullscreen in the attributes
|
|
683
|
+
// Or the browser doesn't support fullscreen
|
|
684
|
+
// Or we passed the HTML nofullscreen attribute
|
|
685
|
+
if (
|
|
686
|
+
this.attributes.playsinline ||
|
|
687
|
+
!document.fullscreenEnabled ||
|
|
688
|
+
this.state.controlslist.indexOf('nofullscreen') !== -1
|
|
689
|
+
) {
|
|
690
|
+
return false
|
|
691
|
+
} else {
|
|
692
|
+
return true
|
|
693
|
+
}
|
|
694
|
+
},
|
|
695
|
+
allowRemotePlayback() {
|
|
696
|
+
// Determine remote playback settings
|
|
697
|
+
if (
|
|
698
|
+
this.attributes.disableremoteplayback ||
|
|
699
|
+
this.state.controlslist.indexOf('noremoteplayback') !== -1
|
|
700
|
+
) {
|
|
701
|
+
return false
|
|
702
|
+
} else {
|
|
703
|
+
return true
|
|
704
|
+
}
|
|
705
|
+
},
|
|
706
|
+
allowDownload() {
|
|
707
|
+
// Determine download settings
|
|
708
|
+
if (this.state.controlslist.indexOf('nodownload') !== -1) {
|
|
709
|
+
return false
|
|
710
|
+
} else {
|
|
711
|
+
return true
|
|
712
|
+
}
|
|
713
|
+
},
|
|
622
714
|
},
|
|
623
715
|
data() {
|
|
624
716
|
return {
|
|
@@ -629,8 +721,8 @@ export default {
|
|
|
629
721
|
currentPercent: 0,
|
|
630
722
|
player: {},
|
|
631
723
|
captions: { nonce: 0 },
|
|
632
|
-
|
|
633
|
-
|
|
724
|
+
state: {
|
|
725
|
+
replay: false,
|
|
634
726
|
cc: true,
|
|
635
727
|
ccLang: this.language,
|
|
636
728
|
controls: true,
|
|
@@ -641,24 +733,22 @@ export default {
|
|
|
641
733
|
playbackRateIndex: 0,
|
|
642
734
|
fullscreen: false,
|
|
643
735
|
expandedCaptions: false,
|
|
644
|
-
|
|
645
|
-
remoteplayback: false,
|
|
736
|
+
captionsVisible: true,
|
|
646
737
|
controlslist: [],
|
|
647
738
|
},
|
|
648
739
|
watchPlayer: 0,
|
|
649
740
|
scrub: { max: 100 },
|
|
650
741
|
buffering: false,
|
|
651
|
-
showReplay: false,
|
|
652
742
|
}
|
|
653
743
|
},
|
|
654
744
|
beforeMount() {
|
|
655
|
-
// Parse the controlslist string
|
|
745
|
+
// Parse the html controlslist attribute string
|
|
656
746
|
if (
|
|
657
747
|
this.attributes.controlslist &&
|
|
658
748
|
typeof this.attributes.controlslist === 'string' &&
|
|
659
749
|
this.attributes.controlslist !== ''
|
|
660
750
|
) {
|
|
661
|
-
this.
|
|
751
|
+
this.state.controlslist = this.attributes.controlslist.split(' ')
|
|
662
752
|
}
|
|
663
753
|
|
|
664
754
|
if (
|
|
@@ -672,12 +762,12 @@ export default {
|
|
|
672
762
|
|
|
673
763
|
// Adjust the playback speed to 1 by default
|
|
674
764
|
if (this.attributes.playbackrates.indexOf(1) !== -1) {
|
|
675
|
-
this.
|
|
765
|
+
this.state.playbackRateIndex =
|
|
676
766
|
this.attributes.playbackrates.indexOf(1)
|
|
677
767
|
} else {
|
|
678
768
|
// 1 aka normal playback not enabled (What monster would do this?!)
|
|
679
769
|
// Set the playback rate to "middle of the road" for whatever is available
|
|
680
|
-
this.
|
|
770
|
+
this.state.playbackRateIndex = Math.floor(
|
|
681
771
|
this.attributes.playbackrates.length / 2
|
|
682
772
|
)
|
|
683
773
|
}
|
|
@@ -690,34 +780,6 @@ export default {
|
|
|
690
780
|
this.ads[ad.play_at_percent].complete = false
|
|
691
781
|
}
|
|
692
782
|
}
|
|
693
|
-
|
|
694
|
-
// Determine fullscreen settings
|
|
695
|
-
if (
|
|
696
|
-
this.attributes.playsinline ||
|
|
697
|
-
!document.fullscreenEnabled ||
|
|
698
|
-
this.options.controlslist.indexOf('nofullscreen') !== -1
|
|
699
|
-
) {
|
|
700
|
-
this.fullscreenEnabled = false
|
|
701
|
-
} else {
|
|
702
|
-
this.fullscreenEnabled = true
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Determine remote playback settings
|
|
706
|
-
if (
|
|
707
|
-
this.attributes.disableremoteplayback ||
|
|
708
|
-
this.options.controlslist.indexOf('noremoteplayback') !== -1
|
|
709
|
-
) {
|
|
710
|
-
this.options.remoteplayback = false
|
|
711
|
-
} else {
|
|
712
|
-
this.options.remoteplayback = true
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
// Determine download settings
|
|
716
|
-
if (this.options.controlslist.indexOf('nodownload') !== -1) {
|
|
717
|
-
this.options.download = false
|
|
718
|
-
} else {
|
|
719
|
-
this.options.download = true
|
|
720
|
-
}
|
|
721
783
|
},
|
|
722
784
|
mounted() {
|
|
723
785
|
if (
|
|
@@ -753,34 +815,45 @@ export default {
|
|
|
753
815
|
},
|
|
754
816
|
onCueClick(time) {
|
|
755
817
|
this.setTime(time)
|
|
818
|
+
this.$emit('click:captions-cue', time)
|
|
756
819
|
},
|
|
757
820
|
onClickExpandCaptions(expanded) {
|
|
758
|
-
this.options.expandedCaptions = expanded
|
|
759
821
|
this.$emit('click:captions-expand', expanded)
|
|
760
822
|
},
|
|
761
823
|
onClickParagraph(isParagraph) {
|
|
762
|
-
this.$emit('click:captions-paragraph', isParagraph)
|
|
824
|
+
this.$emit('click:captions-paragraph-view', isParagraph)
|
|
825
|
+
},
|
|
826
|
+
onClickAutoscroll(autoscroll) {
|
|
827
|
+
this.$emit('click:captions-autoscroll', autoscroll)
|
|
828
|
+
},
|
|
829
|
+
onClickCaptionsClose() {
|
|
830
|
+
this.state.captionsVisible = false
|
|
831
|
+
this.$emit('click:captions-close')
|
|
763
832
|
},
|
|
764
833
|
onDownload() {
|
|
765
834
|
window.open(this.src.sources[0].src, '_blank')
|
|
766
835
|
},
|
|
767
|
-
|
|
768
|
-
// Rewind in seconds
|
|
769
|
-
const seconds = 10
|
|
770
|
-
|
|
836
|
+
rewind(seconds = 10) {
|
|
771
837
|
if (this.player.currentTime <= seconds) {
|
|
772
838
|
this.setTime(0)
|
|
773
839
|
} else {
|
|
774
840
|
this.setTime(this.player.currentTime - seconds)
|
|
775
841
|
}
|
|
776
842
|
},
|
|
777
|
-
|
|
778
|
-
this.
|
|
843
|
+
fastForward(seconds = 10) {
|
|
844
|
+
if (this.player.currentTime + seconds >= this.player.duration) {
|
|
845
|
+
this.setTime(this.player.duration)
|
|
846
|
+
} else {
|
|
847
|
+
this.setTime(this.player.currentTime + seconds)
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
fullscreenToggle() {
|
|
851
|
+
this.state.fullscreen = !document.fullscreenElement
|
|
779
852
|
// Return the whole element to be fullscreened so the controls come with it
|
|
780
|
-
this.$emit('click:fullscreen', this.$
|
|
853
|
+
this.$emit('click:fullscreen', this.$refs.playerContainer)
|
|
781
854
|
},
|
|
782
855
|
onPictureInPicture() {
|
|
783
|
-
//this.
|
|
856
|
+
//this.state.pip = !document.fullscreenElement;
|
|
784
857
|
// Return the player aka HTMLVideoElement
|
|
785
858
|
this.$emit('click:pictureinpicture', this.$refs.player)
|
|
786
859
|
},
|
|
@@ -788,16 +861,16 @@ export default {
|
|
|
788
861
|
this.$emit('click:remoteplayback', this.$refs.player)
|
|
789
862
|
},
|
|
790
863
|
onVideoHover(e) {
|
|
791
|
-
this.
|
|
792
|
-
clearTimeout(this.
|
|
864
|
+
this.state.controls = true
|
|
865
|
+
clearTimeout(this.state.controlsDebounce)
|
|
793
866
|
this.$emit('mouseover', e)
|
|
794
867
|
},
|
|
795
868
|
onVideoLeave(e) {
|
|
796
869
|
const self = this
|
|
797
870
|
// Clear any existing timeouts before we create one
|
|
798
|
-
clearTimeout(this.
|
|
799
|
-
this.
|
|
800
|
-
self.
|
|
871
|
+
clearTimeout(this.state.controlsDebounce)
|
|
872
|
+
this.state.controlsDebounce = setTimeout(() => {
|
|
873
|
+
self.state.controls = false
|
|
801
874
|
}, 50)
|
|
802
875
|
this.$emit('mouseout', e)
|
|
803
876
|
},
|
|
@@ -828,25 +901,25 @@ export default {
|
|
|
828
901
|
this.activeAd !== null &&
|
|
829
902
|
this.activeAd.play_at_percent === 100
|
|
830
903
|
) {
|
|
831
|
-
this.
|
|
904
|
+
this.state.replay = true
|
|
832
905
|
// Ended but this ad was a postroll
|
|
833
906
|
this.$emit('ended', e)
|
|
834
907
|
} else {
|
|
835
|
-
this.
|
|
908
|
+
this.state.replay = true
|
|
836
909
|
// Ended without an ad
|
|
837
910
|
this.$emit('ended', e)
|
|
838
911
|
}
|
|
839
912
|
},
|
|
840
913
|
onControlsHover() {
|
|
841
|
-
clearTimeout(this.
|
|
842
|
-
this.
|
|
914
|
+
clearTimeout(this.state.controlsDebounce)
|
|
915
|
+
this.state.controls = true
|
|
843
916
|
},
|
|
844
917
|
onControlsLeave() {
|
|
845
918
|
const self = this
|
|
846
919
|
// Clear any existing timeouts before we create one
|
|
847
|
-
clearTimeout(this.
|
|
848
|
-
this.
|
|
849
|
-
self.
|
|
920
|
+
clearTimeout(this.state.controlsDebounce)
|
|
921
|
+
this.state.controlsDebounce = setTimeout(() => {
|
|
922
|
+
self.state.controls = false
|
|
850
923
|
}, 50)
|
|
851
924
|
},
|
|
852
925
|
/**
|
|
@@ -857,25 +930,25 @@ export default {
|
|
|
857
930
|
onSelectTrack(lang = null) {
|
|
858
931
|
if (this.player.textTracks && this.player.textTracks.length > 0) {
|
|
859
932
|
for (let i = 0; i < this.player.textTracks.length; i++) {
|
|
860
|
-
|
|
933
|
+
// Disable all tracks by default
|
|
934
|
+
// We only want to enable the correct active track otherwise track switches / replays will overlay tracks
|
|
935
|
+
this.player.textTracks[i].mode = 'disabled'
|
|
861
936
|
|
|
862
|
-
if (
|
|
863
|
-
this.
|
|
937
|
+
if (this.player.textTracks[i].language === lang) {
|
|
938
|
+
this.state.ccLang = lang
|
|
864
939
|
this.player.textTracks[i].mode = 'showing'
|
|
865
940
|
|
|
866
|
-
this.setCues(
|
|
941
|
+
this.setCues(this.player.textTracks[i])
|
|
867
942
|
|
|
868
943
|
// Emit the current track
|
|
869
|
-
this.$emit('trackchange',
|
|
870
|
-
} else {
|
|
871
|
-
this.player.textTracks[i].mode = 'disabled'
|
|
944
|
+
this.$emit('trackchange', this.player.textTracks[i])
|
|
872
945
|
}
|
|
873
946
|
}
|
|
874
947
|
}
|
|
875
948
|
},
|
|
876
|
-
|
|
949
|
+
onPlaybackSpeedChange(index) {
|
|
877
950
|
this.player.playbackRate = this.attributes.playbackrates[index]
|
|
878
|
-
this.
|
|
951
|
+
this.state.playbackRateIndex = index
|
|
879
952
|
this.$emit('ratechange', this.player.playbackRate)
|
|
880
953
|
},
|
|
881
954
|
onTimeupdate(e) {
|
|
@@ -905,31 +978,15 @@ export default {
|
|
|
905
978
|
onMediaProgress(e) {
|
|
906
979
|
this.$emit('progress', e)
|
|
907
980
|
},
|
|
908
|
-
|
|
909
|
-
this.
|
|
981
|
+
CCToggle() {
|
|
982
|
+
this.state.cc = !this.state.cc
|
|
910
983
|
|
|
911
|
-
if (this.
|
|
912
|
-
this.onSelectTrack(this.
|
|
984
|
+
if (this.state.cc) {
|
|
985
|
+
this.onSelectTrack(this.state.ccLang)
|
|
913
986
|
} else {
|
|
914
987
|
this.onSelectTrack()
|
|
915
988
|
}
|
|
916
989
|
},
|
|
917
|
-
onPlayToggle(e) {
|
|
918
|
-
const self = this
|
|
919
|
-
this.options.controls = true
|
|
920
|
-
|
|
921
|
-
// Clear any existing timeouts and close the controls in 5 seconds
|
|
922
|
-
clearTimeout(this.options.controlsDebounce)
|
|
923
|
-
this.options.controlsDebounce = setTimeout(() => {
|
|
924
|
-
self.options.controls = false
|
|
925
|
-
}, 5000)
|
|
926
|
-
|
|
927
|
-
if (this.player.paused) {
|
|
928
|
-
this.play(e)
|
|
929
|
-
} else {
|
|
930
|
-
this.pause(e)
|
|
931
|
-
}
|
|
932
|
-
},
|
|
933
990
|
onClickReplay(e) {
|
|
934
991
|
// Re-initialize the ads aka pre/post/midroll
|
|
935
992
|
if (this.src.ads && this.src.ads.length) {
|
|
@@ -955,13 +1012,13 @@ export default {
|
|
|
955
1012
|
// Restart from the beginning
|
|
956
1013
|
this.setTime(0)
|
|
957
1014
|
},
|
|
958
|
-
|
|
1015
|
+
muteToggle() {
|
|
959
1016
|
if (this.player.muted) {
|
|
960
|
-
this.
|
|
1017
|
+
this.state.muted = false
|
|
961
1018
|
this.player.muted = false
|
|
962
|
-
this.$emit('volumechange', this.
|
|
1019
|
+
this.$emit('volumechange', this.state.volume)
|
|
963
1020
|
} else {
|
|
964
|
-
this.
|
|
1021
|
+
this.state.muted = true
|
|
965
1022
|
this.player.muted = true
|
|
966
1023
|
this.$emit('volumechange', 0)
|
|
967
1024
|
}
|
|
@@ -994,6 +1051,15 @@ export default {
|
|
|
994
1051
|
if (typeof track.activeCues[0].rawText === 'undefined') {
|
|
995
1052
|
track.activeCues[0].rawText = track.activeCues[0].text
|
|
996
1053
|
}
|
|
1054
|
+
// Retain the original cue display values
|
|
1055
|
+
// This way we can swap between a modified display when the controls are visible
|
|
1056
|
+
if (typeof track.activeCues[0].defaults === 'undefined') {
|
|
1057
|
+
track.activeCues[0].defaults = {
|
|
1058
|
+
line: track.activeCues[0].line,
|
|
1059
|
+
size: track.activeCues[0].size,
|
|
1060
|
+
snapToLines: track.activeCues[0].snapToLines,
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
997
1063
|
|
|
998
1064
|
// Now remove `<c.transcript>` tags
|
|
999
1065
|
const transcriptTagRegex = /<c.transcript>.*?<\/c>/gi
|
|
@@ -1003,6 +1069,8 @@ export default {
|
|
|
1003
1069
|
transcriptTagRegex,
|
|
1004
1070
|
''
|
|
1005
1071
|
)
|
|
1072
|
+
|
|
1073
|
+
this.setCuePosition()
|
|
1006
1074
|
}
|
|
1007
1075
|
|
|
1008
1076
|
this.setCues(track)
|
|
@@ -1032,19 +1100,31 @@ export default {
|
|
|
1032
1100
|
//this.player.media = this.$refs.player;
|
|
1033
1101
|
this.$emit('loadedmetadata', e)
|
|
1034
1102
|
this.player = this.$refs.player
|
|
1035
|
-
this.player.volume = this.
|
|
1036
|
-
this.$emit('volumechange', this.
|
|
1103
|
+
this.player.volume = this.state.volume
|
|
1104
|
+
this.$emit('volumechange', this.state.volume)
|
|
1037
1105
|
},
|
|
1038
|
-
|
|
1039
|
-
|
|
1106
|
+
volumeChange(value) {
|
|
1107
|
+
// Value needs to be a decimal value between 0 and 1
|
|
1108
|
+
if (value > 1) {
|
|
1109
|
+
value = 1
|
|
1110
|
+
} else if (value < 0) {
|
|
1111
|
+
value = 0
|
|
1112
|
+
}
|
|
1113
|
+
this.state.volume = value
|
|
1040
1114
|
this.player.volume = value
|
|
1041
1115
|
this.$emit('volumechange', value)
|
|
1042
1116
|
},
|
|
1117
|
+
volumeAdjust(value) {
|
|
1118
|
+
const newVolume = this.state.volume + value
|
|
1119
|
+
this.volumeChange(newVolume)
|
|
1120
|
+
},
|
|
1043
1121
|
onDurationChange() {
|
|
1044
1122
|
// console.log('onDurationChange');
|
|
1045
1123
|
// console.log(e);
|
|
1046
1124
|
},
|
|
1047
1125
|
setTime(time) {
|
|
1126
|
+
// Scrubbing / manually setting the time should remove the replay button
|
|
1127
|
+
this.state.replay = false
|
|
1048
1128
|
this.player.currentTime = time
|
|
1049
1129
|
},
|
|
1050
1130
|
setCues(track) {
|
|
@@ -1056,19 +1136,76 @@ export default {
|
|
|
1056
1136
|
// Required so the v-model will actually update.
|
|
1057
1137
|
this.captions.nonce = Math.random()
|
|
1058
1138
|
},
|
|
1139
|
+
setCuePosition() {
|
|
1140
|
+
if (
|
|
1141
|
+
this.player &&
|
|
1142
|
+
this.player.textTracks &&
|
|
1143
|
+
this.player.textTracks.length > 0
|
|
1144
|
+
) {
|
|
1145
|
+
for (let i = 0; i < this.player.textTracks.length; i++) {
|
|
1146
|
+
// Only alter the currently showing text track
|
|
1147
|
+
if (this.player.textTracks[i].mode === 'showing') {
|
|
1148
|
+
// If the controls are showing then bump the alignment to the start
|
|
1149
|
+
if (
|
|
1150
|
+
this.state.controls &&
|
|
1151
|
+
this.player.textTracks[i].activeCues &&
|
|
1152
|
+
this.player.textTracks[i].activeCues.length > 0
|
|
1153
|
+
) {
|
|
1154
|
+
// Count the number of line breaks in the cue to figure out our offset from the bottom
|
|
1155
|
+
// VTTCue doesn't have a "margin from bottom" by default
|
|
1156
|
+
const numLines = (
|
|
1157
|
+
this.player.textTracks[
|
|
1158
|
+
i
|
|
1159
|
+
].activeCues[0].text.match(/\n/g) || []
|
|
1160
|
+
).length
|
|
1161
|
+
|
|
1162
|
+
// Limit the cues to 90% of the screen width
|
|
1163
|
+
// If this is left default / set to 100 then the above line
|
|
1164
|
+
// Also set snapToLines to true otherwise if there's a line % in the vtt file the display will be relative and make the lines not aligned properly
|
|
1165
|
+
this.player.textTracks[i].activeCues[0].line =
|
|
1166
|
+
-3 - numLines
|
|
1167
|
+
this.player.textTracks[i].activeCues[0].size = 99
|
|
1168
|
+
this.player.textTracks[
|
|
1169
|
+
i
|
|
1170
|
+
].activeCues[0].snapToLines = true
|
|
1171
|
+
} else if (
|
|
1172
|
+
this.player.textTracks[i].activeCues &&
|
|
1173
|
+
this.player.textTracks[i].activeCues.length > 0 &&
|
|
1174
|
+
typeof this.player.textTracks[i].activeCues[0]
|
|
1175
|
+
.defaults !== 'undefined'
|
|
1176
|
+
) {
|
|
1177
|
+
this.player.textTracks[i].activeCues[0].line =
|
|
1178
|
+
this.player.textTracks[
|
|
1179
|
+
i
|
|
1180
|
+
].activeCues[0].defaults.line
|
|
1181
|
+
this.player.textTracks[i].activeCues[0].size =
|
|
1182
|
+
this.player.textTracks[
|
|
1183
|
+
i
|
|
1184
|
+
].activeCues[0].defaults.size
|
|
1185
|
+
this.player.textTracks[
|
|
1186
|
+
i
|
|
1187
|
+
].activeCues[0].snapToLines =
|
|
1188
|
+
this.player.textTracks[
|
|
1189
|
+
i
|
|
1190
|
+
].activeCues[0].defaults.snapToLines
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1059
1196
|
load(e = null) {
|
|
1060
1197
|
if (this.player.load) {
|
|
1061
1198
|
// Reload the player to refresh all the sources / tracks
|
|
1062
1199
|
this.player.load()
|
|
1063
1200
|
this.$emit('load', e)
|
|
1064
1201
|
} else {
|
|
1065
|
-
console.
|
|
1202
|
+
console.error('Cannot load player')
|
|
1066
1203
|
}
|
|
1067
1204
|
},
|
|
1068
1205
|
pause(e = null) {
|
|
1069
1206
|
if (this.player.pause) {
|
|
1070
1207
|
this.player.pause()
|
|
1071
|
-
this.
|
|
1208
|
+
this.state.paused = true
|
|
1072
1209
|
this.$emit('pause', e)
|
|
1073
1210
|
} else {
|
|
1074
1211
|
console.log('Cannot pause player')
|
|
@@ -1078,12 +1215,35 @@ export default {
|
|
|
1078
1215
|
if (this.player.play) {
|
|
1079
1216
|
// Start playing the main video
|
|
1080
1217
|
this.player.play()
|
|
1081
|
-
this.
|
|
1218
|
+
this.state.paused = false
|
|
1219
|
+
this.state.replay = false
|
|
1082
1220
|
this.$emit('play', e)
|
|
1083
1221
|
} else {
|
|
1084
1222
|
console.log('Cannot play player')
|
|
1085
1223
|
}
|
|
1086
1224
|
},
|
|
1225
|
+
playToggle(e) {
|
|
1226
|
+
// If the replay button is active then we actually need to call the onClickReplay method instead
|
|
1227
|
+
// Otherwise we'd just end up replaying any postroll ad
|
|
1228
|
+
if (this.state.replay) {
|
|
1229
|
+
this.onClickReplay(e)
|
|
1230
|
+
} else {
|
|
1231
|
+
const self = this
|
|
1232
|
+
this.state.controls = true
|
|
1233
|
+
|
|
1234
|
+
// Clear any existing timeouts and close the controls in 5 seconds
|
|
1235
|
+
clearTimeout(this.state.controlsDebounce)
|
|
1236
|
+
this.state.controlsDebounce = setTimeout(() => {
|
|
1237
|
+
self.state.controls = false
|
|
1238
|
+
}, 5000)
|
|
1239
|
+
|
|
1240
|
+
if (this.player.paused) {
|
|
1241
|
+
this.play(e)
|
|
1242
|
+
} else {
|
|
1243
|
+
this.pause(e)
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
},
|
|
1087
1247
|
},
|
|
1088
1248
|
}
|
|
1089
1249
|
</script>
|
|
@@ -1094,29 +1254,11 @@ export default {
|
|
|
1094
1254
|
position: relative;
|
|
1095
1255
|
top: -50px;
|
|
1096
1256
|
margin-bottom: -40px;
|
|
1097
|
-
overflow: hidden;
|
|
1098
1257
|
}
|
|
1099
1258
|
.controls {
|
|
1100
1259
|
height: 40px;
|
|
1101
1260
|
background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.7));
|
|
1102
1261
|
}
|
|
1103
|
-
.volume-slider {
|
|
1104
|
-
position: relative;
|
|
1105
|
-
right: -50px;
|
|
1106
|
-
top: -180px;
|
|
1107
|
-
height: 180px;
|
|
1108
|
-
width: 50px;
|
|
1109
|
-
margin-left: -50px;
|
|
1110
|
-
padding-bottom: 10px;
|
|
1111
|
-
}
|
|
1112
|
-
.slider-active-area {
|
|
1113
|
-
width: 50px;
|
|
1114
|
-
height: 200px;
|
|
1115
|
-
margin-right: -50px;
|
|
1116
|
-
margin-bottom: -200px;
|
|
1117
|
-
position: relative;
|
|
1118
|
-
top: -160px; /* height of this - controls height */
|
|
1119
|
-
}
|
|
1120
1262
|
.player-audio {
|
|
1121
1263
|
height: 40px;
|
|
1122
1264
|
}
|
|
@@ -1134,12 +1276,18 @@ export default {
|
|
|
1134
1276
|
color: #fff;
|
|
1135
1277
|
left: 25%;
|
|
1136
1278
|
width: 50%;
|
|
1137
|
-
top:
|
|
1279
|
+
top: 35%;
|
|
1138
1280
|
height: 0;
|
|
1139
1281
|
text-align: center;
|
|
1140
1282
|
}
|
|
1141
|
-
.player-overlay
|
|
1283
|
+
.player-overlay--replay-icon {
|
|
1284
|
+
color: #fff;
|
|
1285
|
+
font-size: 5rem;
|
|
1286
|
+
}
|
|
1287
|
+
.player-overlay > .player-overlay--icon {
|
|
1288
|
+
display: inline-block;
|
|
1142
1289
|
background: rgba(0, 0, 0, 0.25);
|
|
1143
1290
|
border-radius: 100%;
|
|
1291
|
+
padding: 1rem;
|
|
1144
1292
|
}
|
|
1145
1293
|
</style>
|