@grfzhl/vue-hls-player 1.0.7 → 1.0.8

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
@@ -172,7 +172,21 @@ example:
172
172
  }]
173
173
  ```
174
174
 
175
+ **isMuted**:
176
+ 1 value: true or false, type: Boolean
177
+
178
+ it makes the video muted
179
+
180
+ **autoplay**:
181
+ 1. value: true or false, type Boolean
182
+
183
+ it will set the native <video> autoplay property
184
+
175
185
  ### Last release:
186
+ v1.0.8
187
+ - Add slots to inject own elements nearby video element
188
+ - Add prop for autoplay video
189
+
176
190
  v1.0.7
177
191
  - Add function to handle own logic for fullscreen
178
192
 
@@ -1,38 +1,45 @@
1
1
  <template>
2
2
  <div class="video-container">
3
- <media-theme-sutro class="video-player-theme-container">
4
- <video
5
- class="hls-player"
6
- slot="media"
7
- @pause="pause"
8
- @keyup="changeSpeed"
9
- @ended="onVideoEnd"
10
- @seek="seekVideo"
11
- ref="video"
12
- :poster="previewImageLink"
13
- :controls="false"
14
- :title="title"
15
- controlslist="nodownload"
16
- playsinline
17
- crossorigin
18
- >
19
- <source
20
- :src="link"
21
- type="application/x-mpegURL"
22
- />
23
- <track
24
- v-if="subtitles.length"
25
- v-for="(subtitle, i) in subtitles"
26
- :src="subtitle.link"
27
- kind="subtitles"
28
- :srclang="subtitle.lang"
29
- :label="subtitle.label" :default="i === 0" />
30
- </video>
31
- </media-theme-sutro>
32
- <div class="custom-subtitles" v-show="!showTranscriptBlock">
33
- <div class="subtitle-text" ref="subtitlesContainer" style="display: none;"></div>
3
+ <div class="media-container" id="hls-player-media-container">
4
+ <slot name="before-media"></slot>
5
+ <media-theme-sutro class="video-player-theme-container">
6
+ <video
7
+ class="hls-player"
8
+ slot="media"
9
+ @pause="pause"
10
+ @keyup="changeSpeed"
11
+ @ended="onVideoEnd"
12
+ @seek="seekVideo"
13
+ ref="video"
14
+ :poster="previewImageLink"
15
+ :controls="false"
16
+ :title="title"
17
+ controlslist="nodownload"
18
+ playsinline
19
+ crossorigin
20
+ :muted="mutedAttr"
21
+ :autoplay="autoplay && isMuted"
22
+ >
23
+ <source
24
+ :src="link"
25
+ type="application/x-mpegURL"
26
+ />
27
+ <track
28
+ v-if="subtitles.length"
29
+ v-for="(subtitle, i) in subtitles"
30
+ :src="subtitle.link"
31
+ kind="subtitles"
32
+ :srclang="subtitle.lang"
33
+ :label="subtitle.label" :default="i === 0" />
34
+ </video>
35
+ </media-theme-sutro>
36
+ <div class="custom-subtitles" v-show="(isFullscreen) || (!showTranscriptBlock)">
37
+ <div class="subtitle-text" ref="subtitlesContainer" style="display: none;"></div>
38
+ </div>
39
+ <slot name="after-media"></slot>
34
40
  </div>
35
41
  </div>
42
+ <slot name="before-transcripts"></slot>
36
43
  <SubtitleBlock
37
44
  :subtitle="currentSubtitle"
38
45
  :cursor="videoCursor"
@@ -40,10 +47,12 @@
40
47
  @seek="seekVideo"
41
48
  @toggleTranscript="toggleTranscript">
42
49
  </SubtitleBlock>
50
+ <slot name="after-transcripts"></slot>
51
+ <slot name="default"></slot>
43
52
  </template>
44
53
 
45
54
  <script setup>
46
- import { onMounted, onUpdated, ref, onUnmounted, computed } from 'vue'
55
+ import { onMounted, onUpdated, ref, onUnmounted, computed, watch } from 'vue'
47
56
  import Hls from 'hls.js'
48
57
  import 'player.style/sutro';
49
58
  import SubtitleBlock from './SubtitleBlock.vue';
@@ -69,6 +78,10 @@ const props = defineProps({
69
78
  type: Boolean,
70
79
  default: false
71
80
  },
81
+ autoplay: {
82
+ type: Boolean,
83
+ default: false
84
+ },
72
85
  /**
73
86
  * array of object, for
74
87
  * subtitles to append:
@@ -99,10 +112,17 @@ const currentSubtitleLang = ref(null)
99
112
  const videoCursor = ref(0)
100
113
  const isFullscreen = ref(false);
101
114
 
115
+ const videoElement = defineModel()
116
+
102
117
  onMounted(() => {
103
118
  prepareVideoPlayer()
104
119
  if (video.value) {
105
- checkFullscreen();
120
+
121
+ // pass video element as reference to model
122
+ if (!videoElement.value) {
123
+ videoElement.value = video.value;
124
+ }
125
+
106
126
  video.value.addEventListener('timeupdate', updateCurrentTime);
107
127
  document.addEventListener('fullscreenchange', onFullscreenChange);
108
128
 
@@ -135,6 +155,7 @@ onMounted(() => {
135
155
  })
136
156
 
137
157
  onUpdated(() => {
158
+
138
159
  })
139
160
 
140
161
  onUnmounted(() => {
@@ -144,6 +165,11 @@ onUnmounted(() => {
144
165
  }
145
166
  });
146
167
 
168
+ const mutedAttr = computed(() => {
169
+ // autoplay is only possible when muted
170
+ return (props.autoplay || props.isMuted);
171
+ })
172
+
147
173
  const currentSubtitle = computed(() => {
148
174
  if(props.subtitles) {
149
175
  const current = props.subtitles.filter((subt) => {
@@ -154,12 +180,17 @@ const currentSubtitle = computed(() => {
154
180
  return null
155
181
  })
156
182
 
157
- function checkFullscreen() {
158
- isFullscreen.value = !!document.fullscreenElement;
159
- };
183
+ watch([props, videoElement], (a) => {
184
+ if(a[0].autoplay && a[1]) {
185
+ // autoplay is only possible when muted
186
+ a[1].muted = true
187
+ setTimeout(() => {
188
+ a[1].play();
189
+ }, 200)
190
+ }
191
+ })
160
192
 
161
193
  function onFullscreenChange() {
162
- checkFullscreen();
163
194
  emit('video-fullscreen-change', document.fullscreenElement)
164
195
  };
165
196
 
@@ -194,25 +225,31 @@ function prepareVideoPlayer() {
194
225
  track.addEventListener("cuechange", () => {
195
226
  const activeCues = track.activeCues;
196
227
  currentSubtitleLang.value = track.language
197
- if (activeCues && activeCues.length > 0) {
198
- subtitlesContainer.value.textContent = activeCues[0].text
199
- subtitlesContainer.value.style.display = "block";
200
- } else {
201
- subtitlesContainer.value.style.display = "none";
228
+ if(subtitlesContainer.value) {
229
+ if (activeCues && activeCues.length > 0) {
230
+ subtitlesContainer.value.textContent = activeCues[0].text
231
+ subtitlesContainer.value.style.display = "block";
232
+ } else {
233
+ subtitlesContainer.value.style.display = "none";
234
+ }
202
235
  }
203
236
  });
204
237
  if (track.mode !== previousModes[index]) {
205
238
  if (track.mode === "showing") {
206
239
  const activeCues = track.activeCues;
207
240
  currentSubtitleLang.value = track.language
208
- if (activeCues && activeCues.length > 0) {
209
- subtitlesContainer.value.style.display = "block";
210
- subtitlesContainer.value.textContent = activeCues[0].text
211
- } else {
212
- subtitlesContainer.value.style.display = "none";
241
+ if(subtitlesContainer.value) {
242
+ if (activeCues && activeCues.length > 0) {
243
+ subtitlesContainer.value.style.display = "block";
244
+ subtitlesContainer.value.textContent = activeCues[0].text
245
+ } else {
246
+ subtitlesContainer.value.style.display = "none";
247
+ }
213
248
  }
214
249
  } else {
215
- subtitlesContainer.value.style.display = "none";
250
+ if(subtitlesContainer.value) {
251
+ subtitlesContainer.value.style.display = "none";
252
+ }
216
253
  }
217
254
  previousModes[index] = track.mode;
218
255
  }
@@ -4,6 +4,7 @@
4
4
  :link="link"
5
5
  :progress="progress"
6
6
  :isMuted="isMuted"
7
+ :autoplay="autoplay"
7
8
  :isControls="isControls"
8
9
  :onVideoEnd="onVideoEnd"
9
10
  :isFullscreen="isFullscreen"
@@ -12,14 +13,23 @@
12
13
  @video-ended="onVideoEnd"
13
14
  @video-fullscreen-change="onFullscreenChange"
14
15
  @video-fullscreen-action="oVideoFullscreenAction"
15
- />
16
+ v-model="videoElement"
17
+ >
18
+ <template v-slot:before-media><slot name="before-media"></slot></template>
19
+ <template v-slot:after-media><slot name="after-media"></slot></template>
20
+ <template v-slot:before-transcripts><slot name="before-transcripts"></slot></template>
21
+ <template v-slot:after-transcripts><slot name="after-transcripts"></slot></template>
22
+ </BasePlayer>
16
23
  </template>
17
24
 
18
25
  <script setup>
19
26
  import BasePlayer from './BasePlayer.vue'
27
+ import { ref } from 'vue'
20
28
 
21
29
  const emit = defineEmits(['pause', 'video-ended', 'video-fullscreen-change'])
22
30
 
31
+ const videoElement = ref(null);
32
+
23
33
  defineProps({
24
34
  previewImageLink: {
25
35
  type: String,
@@ -37,6 +47,10 @@ defineProps({
37
47
  type: Boolean,
38
48
  default: false
39
49
  },
50
+ autoplay: {
51
+ type: Boolean,
52
+ default: false
53
+ },
40
54
  isControls: {
41
55
  type: Boolean,
42
56
  default: true
@@ -11,8 +11,15 @@
11
11
  :link="link"
12
12
  :progress="progress"
13
13
  :isMuted="isMuted"
14
- />
15
-
14
+ :autoplay="autoplay"
15
+ v-model="videoElement"
16
+ >
17
+ <template v-slot:before-media><slot name="before-media"></slot></template>
18
+ <template v-slot:after-media><slot name="after-media"></slot></template>
19
+ <template v-slot:before-transcripts><slot name="before-transcripts"></slot></template>
20
+ <template v-slot:after-transcripts><slot name="after-transcripts"></slot></template>
21
+ </VDefaultVideoPlayer>
22
+
16
23
  <VPreviewVideoPlayer
17
24
  v-else-if="type === 'preview'"
18
25
  :previewImageLink="previewImageLink"
@@ -23,9 +30,12 @@
23
30
  <script setup>
24
31
  import VDefaultVideoPlayer from './VDefaultVideoPlayer.vue'
25
32
  import VPreviewVideoPlayer from './VPreviewVideoPlayer.vue'
33
+ import { ref } from 'vue'
26
34
 
27
35
  const emit = defineEmits(['pause', 'video-ended', 'video-fullscreen-change', 'video-fullscreen-action'])
28
36
 
37
+ const videoElement = ref(null);
38
+
29
39
  defineProps({
30
40
  previewImageLink: {
31
41
  type: String,
@@ -47,6 +57,10 @@ defineProps({
47
57
  type: Boolean,
48
58
  default: false
49
59
  },
60
+ autoplay: {
61
+ type: Boolean,
62
+ default: false
63
+ },
50
64
  isControls: {
51
65
  type: Boolean,
52
66
  default: true
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@grfzhl/vue-hls-player",
3
3
  "private": false,
4
- "version": "1.0.7",
4
+ "version": "1.0.8",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"