@mindedge/vuetify-player 0.4.0 → 0.4.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.
package/README.md CHANGED
@@ -192,39 +192,43 @@ See [Full media `src` structure for where the ads array is placed](#full-media-s
192
192
 
193
193
  ## Supported `<VuetifyPlayer>` Attributes
194
194
 
195
- | Attribute Name | Datatype | Allowed Values | Default | Description |
196
- | ------------------------------ | --------- | -------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
- | `language` | `String` | en-US \| See BCP 47 Spec | "en-US" | Defines which locale the video player controls will load in |
198
- | `src` | `Object` | See [src attribute](#the-src-attribute) | {} | A single media source |
199
- | `playlist` | `Array ` | See [playlist attribute](#the-playlist-attribute) | [] | A collection of media source(s) |
200
- | `type` | `String` | auto \| video \| audio \| image | "auto" | In audio mode the player has a max-height of 40px |
201
- | `autoplay` | `Boolean` | true \| false | false | Autoplay on load. It's in the spec but DON'T USE THIS |
202
- | `autopictureinpicture` | `Boolean` | true \| false | false | Start with picture in picture mode |
203
- | `controls` | `Boolean` | true \| false | true | Show video controls. When false only play/pause allowed but clicking on the video itself |
204
- | `controlslist` | `String` | nodownload nofullscreen noremoteplayback | "nodownload noremoteplayback" | Space separated string per <video>. Allowed 'nodownload nofullscreen noremoteplayback' |
205
- | `crossorigin` | `String` | anonymous \| use-credentials | "anonymous" | Indicates whether to use CORS to fetch the related video |
206
- | `disablepictureinpicture` | `Boolean` | true \| false | true | Shows the picture in picture button |
207
- | `disableremoteplayback` | `Boolean` | true \| false | true | Shows the remote playback button but functionality does not exist when clicked |
208
- | `height` | `String` | `css pixel value` | "auto" | The players height |
209
- | `width` | `String` | `css pixel value` | "100%" | The players width |
210
- | `rewind` | `Boolean` | true \| false | true | Enabled the rewind 10s button |
211
- | `loop` | `Boolean` | true \| false | false | Loop the video on completion |
212
- | `muted` | `Boolean` | true \| false | false | Start the video muted |
213
- | `playsinline` | `Boolean` | true \| false | false | Force inline & disable fullscreen |
214
- | `poster` | `String` | `image url` | "" | Overridden with the playlist.poster if one is set there |
215
- | `preload` | `String` | "none" \| "metadata" \| "auto" \| `_empty string_` | "" | Empty string = `auto` Provide a hint to the browser about what the author thinks will lead to the best user experience with regards to what content is loaded before the video is played. |
216
- | `captionsmenu` | `Boolean` | true \| false | true | Allow the captions below the video |
217
- | `playlistmenu` | `Boolean` | true \| false | true | Show the playlist menu if there's multiple videos |
218
- | `playlistautoadvance` | `Boolean` | true \| false | true | Play the next source group |
219
- | `playbackrates` | `Array` | [`array of numbers`] | [0.5, 1, 1.5, 2] | Default playback speeds. Anything below 0.25 and above 4 will make cause audio distortion |
220
- | `captions-expanded` | `Boolean` | true \| false | undefined | Supports `.sync`. The initial state of the captions transcript being expanded. |
221
- | `captions-hide-expand` | `Boolean` | true \| false | true | Show / allow the captions transcript expand button for users |
222
- | `captions-paragraph-view` | `Boolean` | true \| false | undefined | Supports `.sync`. The initial state of the captions transcript paragraph view |
223
- | `captions-hide-paragraph-view` | `Boolean` | true \| false | false | Allow the captions transcript paragraph view for users |
224
- | `captions-autoscroll` | `Boolean` | true \| false | false | Supports `.sync`. The initial state for the captions transcript autoscroll state |
225
- | `captions-hide-autoscroll` | `Boolean` | true \| false | undefined | Allow users to enable / disable captions transcript autoscrolling |
226
- | `captions-hide-close` | `Boolean` | true \| false | false | Allow users to show / hide the captions transcript box |
227
- | `captions-visible` | `Boolean` | true \| false | false | Supports `.sync`. The initial state for the captions transcript visibility |
195
+ | Attribute Name | Datatype | Allowed Values | Default | Description |
196
+ | ------------------------------ | ------------------ | -------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
+ | `language` | `String` | en-US \| See BCP 47 Spec | "en-US" | Defines which locale the video player controls will load in |
198
+ | `src` | `Object` | See [src attribute](#the-src-attribute) | {} | A single media source |
199
+ | `playlist` | `Array ` | See [playlist attribute](#the-playlist-attribute) | [] | A collection of media source(s) |
200
+ | `type` | `String` | auto \| video \| audio \| image | "auto" | In audio mode the player has a max-height of 40px |
201
+ | `autoplay` | `Boolean` | true \| false | false | Autoplay on load. It's in the spec but DON'T USE THIS |
202
+ | `autopictureinpicture` | `Boolean` | true \| false | false | Start with picture in picture mode |
203
+ | `controls` | `Boolean` | true \| false | true | Show video controls. When false only play/pause allowed but clicking on the video itself |
204
+ | `controlslist` | `String` | nodownload nofullscreen noremoteplayback | "nodownload noremoteplayback" | Space separated string per <video>. Allowed 'nodownload nofullscreen noremoteplayback' |
205
+ | `crossorigin` | `String` | anonymous \| use-credentials | "anonymous" | Indicates whether to use CORS to fetch the related video |
206
+ | `disablepictureinpicture` | `Boolean` | true \| false | true | Shows the picture in picture button |
207
+ | `disableremoteplayback` | `Boolean` | true \| false | true | Shows the remote playback button but functionality does not exist when clicked |
208
+ | `height` | `String` | `css pixel value` | "auto" | The players height |
209
+ | `width` | `String` | `css pixel value` | "100%" | The players width |
210
+ | `rewind` | `Boolean` | true \| false | true | Enabled the rewind 10s button |
211
+ | `loop` | `Boolean` | true \| false | false | Loop the video on completion |
212
+ | `muted` | `Boolean` | true \| false | false | Start the video muted |
213
+ | `playsinline` | `Boolean` | true \| false | false | Force inline & disable fullscreen |
214
+ | `poster` | `String` | `image url` | "" | Overridden with the playlist.poster if one is set there |
215
+ | `preload` | `String` | "none" \| "metadata" \| "auto" \| `_empty string_` | "" | Empty string = `auto` Provide a hint to the browser about what the author thinks will lead to the best user experience with regards to what content is loaded before the video is played. |
216
+ | `captionsmenu` | `Boolean` | true \| false | true | Allow the captions below the video |
217
+ | `playlistmenu` | `Boolean` | true \| false | true | Show the playlist menu if there's multiple videos |
218
+ | `playlistautoadvance` | `Boolean` | true \| false | true | Play the next source group |
219
+ | `playbackrates` | `Array` | [`array of numbers`] | [0.5, 1, 1.5, 2] | Default playback speeds. Anything below 0.25 and above 4 will make cause audio distortion |
220
+ | `volume` | `Number` | 0-1 | 0.5 | Supports `.sync`. The initial volume of the player. |
221
+ | `cc` | `Boolean` | true \| false | false | Supports `.sync`. The initial state of the player embedded closed captions. |
222
+ | `captions-expanded` | `Boolean` | true \| false | undefined | Supports `.sync`. The initial state of the captions transcript being expanded. |
223
+ | `captions-hide-expand` | `Boolean` | true \| false | true | Show / allow the captions transcript expand button for users |
224
+ | `captions-paragraph-view` | `Boolean` | true \| false | undefined | Supports `.sync`. The initial state of the captions transcript paragraph view |
225
+ | `captions-hide-paragraph-view` | `Boolean` | true \| false | false | Allow the captions transcript paragraph view for users |
226
+ | `captions-autoscroll` | `Boolean` | true \| false | false | Supports `.sync`. The initial state for the captions transcript autoscroll state |
227
+ | `captions-hide-autoscroll` | `Boolean` | true \| false | undefined | Allow users to enable / disable captions transcript autoscrolling |
228
+ | `captions-hide-close` | `Boolean` | true \| false | false | Allow users to show / hide the captions transcript box |
229
+ | `captions-visible` | `Boolean` | true \| false | false | Supports `.sync`. The initial state for the captions transcript visibility |
230
+ | `elevation` | `Number`\|`String` | 0-24 | 2 | Designates an elevation applied to the component between 0 and 24 |
231
+ | `flat` | `Boolean` | true \| false | false | Removes the elevation |
228
232
 
229
233
  ## Supported `<VuetifyPlayer>` Events
230
234
 
@@ -256,6 +260,8 @@ See [Full media `src` structure for where the ads array is placed](#full-media-s
256
260
  | `click:captions-paragraph-view` | `true` \| `false` | When the view as paragraph button is clicked. true when viewing as a paragraph, false when viewing as timed captions |
257
261
  | `click:captions-autoscroll` | `true` \| `false` | When the autoscroll captions button is clicked. true on autoscrolling otherwise false |
258
262
  | `click:captions-close` | `true` \| `false` | When the c;pse captions button is clicked. true on closed, false on visible |
263
+ | `update:volume` | `Number` | When the volume is updated. This is the same as `volumechange` |
264
+ | `update:cc` | `true` \| `false` | When the players closed captions state is updated |
259
265
  | `update:captions-expanded` | `true` \| `false` | When the captions expand state is updated |
260
266
  | `update:captions-paragraph-view` | `true` \| `false` | When the captions paragraph-view state is updated |
261
267
  | `update:captions-autoscroll` | `true` \| `false` | When the captions autoscroll state is updated |
@@ -263,9 +269,10 @@ See [Full media `src` structure for where the ads array is placed](#full-media-s
263
269
 
264
270
  ## Supported `<VuetifyPlayer>` Slots
265
271
 
266
- | Slot name | Attributes | Description |
267
- | ----------- | ---------- | --------------------------------------------------------------------------- |
268
- | `no-source` | `none` | Displayed over the media skeleton loader when no media source is configured |
272
+ | Slot name | Attributes | Description |
273
+ | ----------- | ---------- | ------------------------------------------------------------------------------------ |
274
+ | `no-source` | `none` | Displayed over the media skeleton loader when no media source is configured |
275
+ | `loading` | `none` | Displayed over the media skeleton loader when the playlist has changed via its props |
269
276
 
270
277
  ## Captions
271
278
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindedge/vuetify-player",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "private": false,
5
5
  "description": "Accessible, localized, full featured media player with Vuetifyjs",
6
6
  "author": "Jacob Rogaishio",
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <v-card v-if="visibleState">
2
+ <v-card v-if="visibleState" :elevation="elevation">
3
3
  <v-card-actions class="d-flex flex-wrap flex-row-reverse mb-0 pb-0">
4
4
  <div class="d-flex ml-auto">
5
5
  <v-tooltip v-if="!hideAutoscroll" top>
@@ -147,15 +147,6 @@
147
147
  @click="onCueClick(cue.startTime)"
148
148
  >
149
149
  <template v-if="!expandedState">
150
- <v-list-item-icon v-if="!paragraphViewState">
151
- <v-icon
152
- >{{
153
- index === captionIndex
154
- ? 'mdi-arrow-right-drop-circle-outline'
155
- : 'mdi-checkbox-blank-circle-outline'
156
- }}
157
- </v-icon>
158
- </v-list-item-icon>
159
150
  <v-list-item-content>
160
151
  <v-list-item-title
161
152
  v-html="cue.rawText || cue.text"
@@ -231,6 +222,7 @@ export default {
231
222
  hideAutoscroll: { type: Boolean, required: false, default: false },
232
223
  visible: { type: Boolean, required: false, default: undefined },
233
224
  hideClose: { type: Boolean, required: false, default: false },
225
+ elevation: { type: [Number, String], required: false, default: 2 },
234
226
  },
235
227
  emits: [
236
228
  'click:cue',
@@ -298,20 +290,23 @@ export default {
298
290
  }
299
291
 
300
292
  // Create a new paragraph every 3 sentences
301
- if (puncuationCount > 3) {
302
- // Find the first puncuation and include it in the slice
293
+ if (
294
+ puncuationCount > 3 &&
295
+ typeof cues[i + 1] !== 'undefined'
296
+ ) {
297
+ // Find the first puncuation and include it in the slice so the NEXT paragraph doesn't start mid sentence
303
298
  const breakIndex = cues[i].text.search(/[.?!]/) + 1
304
299
 
305
300
  // Append the first part to the previous paragraph so it ends on a period
306
301
  paragraphs[paragraphs.length - 1].text +=
307
- ' ' + cues[i].text.slice(0, breakIndex)
302
+ ' ' + cues[i].text.slice(0, breakIndex).trim()
308
303
 
309
304
  // Use `new VTTCue` to break the reference. Otherwise the below appends will duplicate text
310
305
  // Also grab from the breakIndex afterwards to get the potential next sentence
311
306
  paragraphs.push(
312
307
  new VTTCue(
313
- cues[i].startTime,
314
- cues[i].endTime,
308
+ cues[i + 1].startTime,
309
+ cues[i + 1].endTime,
315
310
  cues[i].text.slice(breakIndex).trim()
316
311
  )
317
312
  )
@@ -184,7 +184,7 @@
184
184
  text
185
185
  v-bind="attrs"
186
186
  v-on="on"
187
- @click="rewind"
187
+ @click="rewind(10)"
188
188
  >
189
189
  <v-icon>mdi-rewind-10</v-icon>
190
190
  <span class="sr-only">{{
@@ -219,10 +219,10 @@
219
219
  text
220
220
  v-bind="attrs"
221
221
  v-on="on"
222
- @click="CCToggle"
222
+ @click="onClickCCToggle"
223
223
  >
224
224
  <v-icon>{{
225
- state.cc
225
+ ccState
226
226
  ? 'mdi-closed-caption'
227
227
  : 'mdi-closed-caption-outline'
228
228
  }}</v-icon>
@@ -485,6 +485,7 @@
485
485
  :visible.sync="captionsVisibleState"
486
486
  :hide-autoscroll="captionsHideAutoscroll"
487
487
  :hide-close="captionsHideClose"
488
+ :elevation="elevation"
488
489
  @update:paragraph-view="
489
490
  $emit('update:captions-paragraph-view', $event)
490
491
  "
@@ -530,6 +531,16 @@ export default {
530
531
  type: Object,
531
532
  required: true,
532
533
  },
534
+ volume: {
535
+ type: Number,
536
+ required: false,
537
+ default: undefined,
538
+ },
539
+ cc: {
540
+ type: Boolean,
541
+ required: false,
542
+ default: undefined,
543
+ },
533
544
  captionsExpanded: {
534
545
  type: Boolean,
535
546
  required: false,
@@ -566,6 +577,7 @@ export default {
566
577
  required: false,
567
578
  default: false,
568
579
  },
580
+ elevation: { type: [Number, String], required: false, default: 2 },
569
581
  },
570
582
  emits: [
571
583
  'error',
@@ -598,6 +610,7 @@ export default {
598
610
  'click:captions-autoscroll',
599
611
  'click:captions-close',
600
612
  'click:captions-cue',
613
+ 'update:cc',
601
614
  'update:captions-expanded',
602
615
  'update:captions-paragraph-view',
603
616
  'update:captions-autoscroll',
@@ -651,6 +664,19 @@ export default {
651
664
 
652
665
  return type
653
666
  },
667
+ ccState: {
668
+ get() {
669
+ if (typeof this.cc !== 'undefined') {
670
+ return this.cc
671
+ } else {
672
+ return this.state.cc
673
+ }
674
+ },
675
+ set(v) {
676
+ this.$emit('update:cc', v)
677
+ this.state.cc = v
678
+ },
679
+ },
654
680
  captionsVisibleState: {
655
681
  get() {
656
682
  if (typeof this.captionsVisible !== 'undefined') {
@@ -729,6 +755,7 @@ export default {
729
755
  controlsDebounce: null,
730
756
  volume: 0.5, // default 50%
731
757
  muted: false,
758
+ unmuteVolume: 0, // The stored volume to return to the initial volume when unmuting
732
759
  paused: true,
733
760
  playbackRateIndex: 0,
734
761
  fullscreen: false,
@@ -780,6 +807,11 @@ export default {
780
807
  this.ads[ad.play_at_percent].complete = false
781
808
  }
782
809
  }
810
+
811
+ // Set the initial volume
812
+ if (typeof this.volume !== 'undefined') {
813
+ this.state.volume = this.volume
814
+ }
783
815
  },
784
816
  mounted() {
785
817
  if (
@@ -927,7 +959,7 @@ export default {
927
959
  *
928
960
  * @param String|null lang The lang to load. Eg en-US, sv-SE, etc. Pass nothing / null to turn off captions
929
961
  */
930
- onSelectTrack(lang = null) {
962
+ onSelectTrack(lang = null, mode = 'showing') {
931
963
  if (this.player.textTracks && this.player.textTracks.length > 0) {
932
964
  for (let i = 0; i < this.player.textTracks.length; i++) {
933
965
  // Disable all tracks by default
@@ -936,7 +968,7 @@ export default {
936
968
 
937
969
  if (this.player.textTracks[i].language === lang) {
938
970
  this.state.ccLang = lang
939
- this.player.textTracks[i].mode = 'showing'
971
+ this.player.textTracks[i].mode = mode
940
972
 
941
973
  this.setCues(this.player.textTracks[i])
942
974
 
@@ -978,13 +1010,16 @@ export default {
978
1010
  onMediaProgress(e) {
979
1011
  this.$emit('progress', e)
980
1012
  },
981
- CCToggle() {
982
- this.state.cc = !this.state.cc
1013
+ onClickCCToggle() {
1014
+ // We can't read the opposite of !this.ccState because it's a computed off of props
1015
+ // So this.ccState = !this.ccState takes 1 tick to reflect the actual changes between the getter and setter
1016
+ const state = !this.ccState
1017
+ this.ccState = state
983
1018
 
984
- if (this.state.cc) {
1019
+ if (state) {
985
1020
  this.onSelectTrack(this.state.ccLang)
986
1021
  } else {
987
- this.onSelectTrack()
1022
+ this.onSelectTrack(this.state.ccLang, 'hidden')
988
1023
  }
989
1024
  },
990
1025
  onClickReplay(e) {
@@ -1014,10 +1049,19 @@ export default {
1014
1049
  },
1015
1050
  muteToggle() {
1016
1051
  if (this.player.muted) {
1052
+ // Restore the inital volume
1053
+ this.state.volume = this.state.unmuteVolume
1054
+ this.player.volume = this.state.unmuteVolume
1055
+ this.state.unmuteVolume = 0
1017
1056
  this.state.muted = false
1018
1057
  this.player.muted = false
1019
1058
  this.$emit('volumechange', this.state.volume)
1020
1059
  } else {
1060
+ // Store the initial volume
1061
+ this.state.unmuteVolume = this.state.volume
1062
+ this.state.volume = 0
1063
+ this.player.volume = 0
1064
+
1021
1065
  this.state.muted = true
1022
1066
  this.player.muted = true
1023
1067
  this.$emit('volumechange', 0)
@@ -1082,15 +1126,29 @@ export default {
1082
1126
  * The this.player.textTracks are now loaded
1083
1127
  */
1084
1128
  onLoadeddata(e) {
1129
+ let defaultTrackLang = null
1085
1130
  // Set the default captions since apparently the default attribute means nothing
1086
1131
  if (this.current.tracks && this.current.tracks.length > 0) {
1087
1132
  for (const track of this.current.tracks) {
1088
1133
  if (track.default) {
1134
+ defaultTrackLang = track.srclang
1089
1135
  this.onSelectTrack(track.srclang)
1090
1136
  }
1091
1137
  }
1092
1138
  }
1093
1139
 
1140
+ // Toggle the closed captions if the state is disabled
1141
+ if (!this.ccState) {
1142
+ this.onSelectTrack(defaultTrackLang, 'hidden')
1143
+ }
1144
+
1145
+ // We're starting muted so set the appropriate return volume / muted values
1146
+ if (this.state.volume === 0) {
1147
+ this.state.unmuteVolume = 0.5
1148
+ this.state.muted = true
1149
+ this.player.muted = true
1150
+ }
1151
+
1094
1152
  this.$emit('loadeddata', e)
1095
1153
  },
1096
1154
  onLoadedmetadata(e) {
@@ -1110,6 +1168,13 @@ export default {
1110
1168
  } else if (value < 0) {
1111
1169
  value = 0
1112
1170
  }
1171
+
1172
+ // Unmuted if we're adjusting the volume up
1173
+ if (value > 0 && (this.player.muted || this.state.muted)) {
1174
+ this.state.muted = false
1175
+ this.player.muted = false
1176
+ }
1177
+
1113
1178
  this.state.volume = value
1114
1179
  this.player.volume = value
1115
1180
  this.$emit('volumechange', value)
@@ -1128,10 +1193,23 @@ export default {
1128
1193
  this.player.currentTime = time
1129
1194
  },
1130
1195
  setCues(track) {
1196
+ // Filter out any cues / active cues that start after the video has already ended
1197
+ // This way we don't show captions that we can't skip to
1198
+ const cues = Object.keys(track.cues || {})
1199
+ .map((key) => track.cues[key])
1200
+ .filter((c) => {
1201
+ return c.startTime < this.player.duration
1202
+ })
1203
+ const activeCues = Object.keys(track.activeCues || {})
1204
+ .map((key) => track.activeCues[key])
1205
+ .filter((c) => {
1206
+ return c.startTime < this.player.duration
1207
+ })
1208
+
1131
1209
  // Create reactive fields
1132
1210
  this.$set(this.captions, 'language', track.language)
1133
- this.$set(this.captions, 'cues', track.cues)
1134
- this.$set(this.captions, 'activeCues', track.activeCues)
1211
+ this.$set(this.captions, 'cues', cues)
1212
+ this.$set(this.captions, 'activeCues', activeCues)
1135
1213
 
1136
1214
  // Required so the v-model will actually update.
1137
1215
  this.captions.nonce = Math.random()
@@ -2,7 +2,29 @@
2
2
  <div>
3
3
  <v-row tabindex="0">
4
4
  <v-col cols="12">
5
- <div v-if="parseSourceType(current.src.sources) === null">
5
+ <div v-if="loading">
6
+ <div class="player-skeleton--no-source">
7
+ <slot name="loading">
8
+ <div>
9
+ <v-progress-circular indeterminate />
10
+ <p>
11
+ {{ t(language, 'player.loading') }}
12
+ </p>
13
+ </div>
14
+ </slot>
15
+ </div>
16
+ <v-skeleton-loader
17
+ type="image, image, list-item-avatar"
18
+ class="player-skeleton"
19
+ ></v-skeleton-loader>
20
+ </div>
21
+
22
+ <div
23
+ v-if="
24
+ !loading &&
25
+ parseSourceType(current.src.sources) === null
26
+ "
27
+ >
6
28
  <div class="player-skeleton--no-source">
7
29
  <slot name="no-source">
8
30
  <div>
@@ -18,24 +40,35 @@
18
40
  class="player-skeleton"
19
41
  ></v-skeleton-loader>
20
42
  </div>
43
+
21
44
  <YoutubePlayer
22
45
  ref="youtubePlayer"
23
- v-if="parseSourceType(current.src.sources) === 'youtube'"
46
+ v-if="
47
+ !loading &&
48
+ parseSourceType(current.src.sources) === 'youtube'
49
+ "
24
50
  :language="language"
25
51
  :type="current.type"
26
52
  :attributes="current.attributes"
27
53
  :src="current.src"
54
+ :elevation="flat ? 0 : elevation"
28
55
  @focusin="onFocusin"
29
56
  @focusout="onFocusout"
30
57
  @click:fullscreen="onFullscreen"
31
58
  ></YoutubePlayer>
59
+
32
60
  <Html5Player
33
61
  ref="html5Player"
34
- v-if="parseSourceType(current.src.sources) === 'html5'"
62
+ v-if="
63
+ !loading &&
64
+ parseSourceType(current.src.sources) === 'html5'
65
+ "
35
66
  :language="language"
36
67
  :type="current.type"
37
68
  :attributes="current.attributes"
38
69
  :src="current.src"
70
+ :volume.sync="volumeState"
71
+ :cc.sync="ccState"
39
72
  :captions-expanded.sync="captionsExpandedState"
40
73
  :captions-hide-expand="captionsHideExpand"
41
74
  :captions-paragraph-view="captionsParagraphView"
@@ -43,6 +76,7 @@
43
76
  :captions-autoscroll="captionsAutoscroll"
44
77
  :captions-hide-autoscroll="captionsHideAutoscroll"
45
78
  :captions-visible.sync="captionsVisibleState"
79
+ :elevation="flat ? 0 : elevation"
46
80
  @load="$emit('load', $event)"
47
81
  @ended="onEnded"
48
82
  @loadeddata="onLoadeddata"
@@ -52,6 +86,7 @@
52
86
  @seeking="$emit('seeking', $event)"
53
87
  @timeupdate="$emit('timeupdate', $event)"
54
88
  @progress="$emit('progress', $event)"
89
+ @volumechange="onVolumeChange"
55
90
  @canplay="$emit('canplay', $event)"
56
91
  @waiting="$emit('waiting', $event)"
57
92
  @canplaythrough="$emit('canplaythrough', $event)"
@@ -155,9 +190,11 @@ export default {
155
190
  rewind: { type: Boolean, required: false, default: false }, // Enabled the rewind 10s button
156
191
  loop: { type: Boolean, required: false, default: false }, // Loop the video on completion
157
192
  muted: { type: Boolean, required: false, default: false }, // Start the video muted
193
+ volume: { type: Number, required: false, default: undefined }, // The initial volume level. Undefined will use the local value of 0.5
158
194
  playsinline: { Boolean: String, required: false, default: false }, // Force inline & disable fullscreen
159
195
  poster: { type: String, required: false, default: '' }, // Overridden with the playlist.poster if one is set there
160
196
  preload: { type: String, required: false, default: '' },
197
+ cc: { type: Boolean, required: false, default: undefined }, // The initial state of the closed captions (if available). Undefined will use the local value of false
161
198
  captionsmenu: { type: Boolean, required: false, default: true }, // Show the captions below the video
162
199
  captionsExpanded: {
163
200
  type: Boolean,
@@ -204,6 +241,8 @@ export default {
204
241
  return [0.5, 1, 1.5, 2]
205
242
  },
206
243
  }, // Default playback speeds
244
+ elevation: { type: [Number, String], required: false, default: 2 },
245
+ flat: { type: Boolean, required: false, default: false },
207
246
  },
208
247
  emits: [
209
248
  'load',
@@ -214,6 +253,7 @@ export default {
214
253
  'seeking',
215
254
  'timeupdate',
216
255
  'progress',
256
+ 'volumechange',
217
257
  'canplay',
218
258
  'waiting',
219
259
  'canplaythrough',
@@ -231,12 +271,24 @@ export default {
231
271
  'click:captions-paragraph-view',
232
272
  'click:captions-autoscroll',
233
273
  'click:captions-close',
274
+ 'update:volume',
275
+ 'update:cc',
234
276
  'update:captions-expanded',
235
277
  'update:captions-paragraph-view',
236
278
  'update:captions-autoscroll',
237
279
  'update:captions-visible',
238
280
  ],
239
- watch: {},
281
+ watch: {
282
+ playlist: {
283
+ handler(newValue, oldValue) {
284
+ // Make sure there was actual changes to prevent unnecessary reloads
285
+ if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
286
+ // Force-reload the media on playlist changes since we changed the source / tracks
287
+ this.reloadMedia()
288
+ }
289
+ },
290
+ },
291
+ },
240
292
  computed: {
241
293
  player() {
242
294
  if (this.parseSourceType(this.current.src.sources) === 'youtube') {
@@ -299,6 +351,32 @@ export default {
299
351
  return 8
300
352
  }
301
353
  },
354
+ ccState: {
355
+ get() {
356
+ if (typeof this.cc !== 'undefined') {
357
+ return this.cc
358
+ } else {
359
+ return this.captions.cc
360
+ }
361
+ },
362
+ set(v) {
363
+ this.$emit('update:cc', v)
364
+ this.captions.cc = v
365
+ },
366
+ },
367
+ volumeState: {
368
+ get() {
369
+ if (typeof this.volume !== 'undefined') {
370
+ return this.volume
371
+ } else {
372
+ return this.localVolume
373
+ }
374
+ },
375
+ set(v) {
376
+ this.player.volumeChange(v)
377
+ this.localVolume = v
378
+ },
379
+ },
302
380
  captionsVisibleState: {
303
381
  get() {
304
382
  if (typeof this.captionsVisible !== 'undefined') {
@@ -332,16 +410,25 @@ export default {
332
410
  data() {
333
411
  return {
334
412
  t,
413
+ loading: false,
335
414
  sourceIndex: 0,
336
415
  captions: {
416
+ cc: false,
337
417
  visible: true,
338
418
  expanded: false,
339
419
  },
420
+ localVolume: 0.5, // The initial volume level
340
421
  mediaFocus: false,
341
422
  keyListener: null,
342
423
  }
343
424
  },
344
425
  methods: {
426
+ reloadMedia() {
427
+ this.loading = true
428
+ setTimeout(() => {
429
+ this.loading = false
430
+ }, 500)
431
+ },
345
432
  onEnded(e) {
346
433
  if (
347
434
  this.playlistautoadvance &&
@@ -355,6 +442,10 @@ export default {
355
442
  // Loaded a new video
356
443
  this.$emit('loadeddata', e)
357
444
  },
445
+ onVolumeChange(e) {
446
+ this.$emit('update:volume', e)
447
+ this.$emit('volumechange', e)
448
+ },
358
449
  onRemoteplayback(el) {
359
450
  // Make sure the browser supports remote playback
360
451
  if (!el.remote || !el.remote.watchAvailability) {
package/src/i18n/en-US.js CHANGED
@@ -10,6 +10,7 @@ export default {
10
10
  next: 'Play next item in playlist',
11
11
  },
12
12
  player: {
13
+ loading: 'Loading...',
13
14
  not_configured: 'Media not configured',
14
15
  playback_speed: 'Playback Speed',
15
16
  playback_decrease: 'Decrease playback speed',
package/src/i18n/es-ES.js CHANGED
@@ -10,6 +10,7 @@ export default {
10
10
  next: 'Reproducir el siguiente elemento en la lista de reproducción',
11
11
  },
12
12
  player: {
13
+ loading: 'Cargando...',
13
14
  not_configured: 'Medios no configurados',
14
15
  playback_speed: 'Velocidad de reproducción',
15
16
  playback_decrease: 'Disminuir la velocidad de reproducción',
package/src/i18n/sv-SE.js CHANGED
@@ -10,6 +10,7 @@ export default {
10
10
  next: 'Spela nästa',
11
11
  },
12
12
  player: {
13
+ loading: 'Laddar...',
13
14
  not_configured: 'Media inte konfigurerad',
14
15
  playback_speed: 'Uppspelningshastighet',
15
16
  playback_decrease: 'Minska uppspelningshastigheten',