@grfzhl/vue-hls-player 1.1.4 → 1.1.6

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.
@@ -144,21 +144,17 @@ const isFullscreen = ref(false);
144
144
  const orientation = ref(null)
145
145
  const autoHideIntroTitle = ref(false);
146
146
  const initialPlayButton = ref(false);
147
- const hideInitialPlayButton = ref(false)
148
- const transcriptRef = ref(null)
149
- const link = toRef(props, 'link');
147
+ const hideInitialPlayButton = ref(false);
148
+ const transcriptRef = ref(null);
150
149
  const previewImageLink = toRef(props, 'previewImageLink');
150
+ const link = toRef(props, 'link');
151
151
  let currentTime = 0
152
152
  let hls = null
153
153
 
154
154
  const videoElement = defineModel()
155
155
 
156
156
  onMounted(() => {
157
- prepareVideoPlayer()
158
- })
159
-
160
- onUpdated(() => {
161
-
157
+ prepareVideoPlayer(props.link)
162
158
  })
163
159
 
164
160
  onUnmounted(() => {
@@ -178,7 +174,11 @@ const mutedAttr = computed(() => {
178
174
  const currentSubtitle = computed(() => {
179
175
  if(props.subtitles) {
180
176
  const current = props.subtitles.filter((subt) => {
181
- return subt.lang === currentSubtitleLang.value
177
+ if(currentSubtitleLang.value) {
178
+ return subt.lang === currentSubtitleLang.value
179
+ } else {
180
+ return subt.lang === "en"
181
+ }
182
182
  })
183
183
  return current.length ? current[0] : null
184
184
  }
@@ -195,10 +195,11 @@ watch([props, videoElement], (a) => {
195
195
  }
196
196
  })
197
197
 
198
- watch(link, (newLink, oldLink) => {
198
+ watch(
199
+ () => props.link,
200
+ (newLink, oldLink) => {
199
201
  if (newLink !== oldLink) {
200
- console.log("prepare new src " + newLink)
201
- prepareVideoPlayer();
202
+ prepareVideoPlayer(newLink);
202
203
  }
203
204
  })
204
205
 
@@ -307,15 +308,18 @@ function seekVideo(time) {
307
308
  video.value.play()
308
309
  }
309
310
 
310
- function prepareVideoPlayer() {
311
+ function prepareVideoPlayer(link) {
312
+ let initiallyLoaded = true;
311
313
  if (video.value) {
312
314
  if (hls) {
315
+ hls.detachMedia();
313
316
  hls.destroy();
317
+ initiallyLoaded = false;
314
318
  }
315
319
  hls = new Hls();
316
- let stream = props.link
317
- hls.loadSource(stream)
320
+ hls.loadSource(link)
318
321
  hls.attachMedia(video.value)
322
+ hls.recoverMediaError()
319
323
 
320
324
  video.value.muted = props.isMuted
321
325
  video.value.currentTime = props.progress
@@ -28,7 +28,7 @@
28
28
  <span
29
29
  v-for="(word, wordIndex) in txtCue.dialog[0].text.split('')"
30
30
  :key="wordIndex"
31
- :class="{ 'active-word': isWordActive(txtCue, word, wordIndex, index) && isTxtCueActive(txtCue) }"
31
+ :class="{ 'active-word': isWordActive(txtCue, word, wordIndex, index, currentCue) && isTxtCueActive(txtCue) }"
32
32
  >
33
33
  {{ word }}
34
34
  </span>
@@ -111,7 +111,7 @@
111
111
  </style>
112
112
 
113
113
  <script setup>
114
- import { onMounted, watch, ref } from 'vue';
114
+ import { onMounted, watch, ref, nextTick } from 'vue';
115
115
 
116
116
  const props = defineProps({
117
117
  subtitle: {
@@ -137,6 +137,7 @@ const subtitlesContainer = ref(null);
137
137
  const vttCues = ref([]);
138
138
  const txtCues = ref([]);
139
139
  const currentCue = ref(null);
140
+ const videoCursor = ref(0);
140
141
 
141
142
 
142
143
  const loadCues = async () => {
@@ -158,8 +159,9 @@ watch(
158
159
  );
159
160
 
160
161
  const onTimeUpdate = (video) => {
161
- if (video) {
162
+ if (video && txtCues?.value?.length && vttCues?.value?.length) {
162
163
  const currentTime = video.currentTime;
164
+ videoCursor.value = currentTime;
163
165
  props.cursor = currentTime;
164
166
  highlightActiveCue(currentTime);
165
167
  checkCurrentCue(currentTime);
@@ -195,7 +197,7 @@ function seekTo(time) {
195
197
  * @param txtCue
196
198
  */
197
199
  function isTxtCueActive(txtCue) {
198
- return props.cursor >= txtCue.start && props.cursor <= txtCue.end;
200
+ return videoCursor.value >= txtCue.start && videoCursor.value <= txtCue.end;
199
201
  }
200
202
 
201
203
  /**
@@ -206,24 +208,23 @@ function isTxtCueActive(txtCue) {
206
208
  * @param wordIndex
207
209
  * @param txtIndex
208
210
  */
209
- function isWordActive(txtCue, word, wordIndex, txtIndex) {
210
- console.log("check word active ", txtCue, word, wordIndex, currentCue.value)
211
- if(!currentCue.value || !word || !txtCue) {
211
+ function isWordActive(txtCue, word, wordIndex, txtIndex, currentCue) {
212
+ if(!currentCue || !word || !txtCue) {
212
213
  return false
213
214
  }
214
- const startPos = txtCue.dialog[0].text.indexOf(currentCue.value)
215
- const endPos = startPos + currentCue.value.length
216
- console.log("can word marked", startPos, endPos, wordIndex)
215
+ const startPos = txtCue.dialog[0].text.indexOf(currentCue)
216
+ const endPos = startPos + currentCue.length
217
217
  if(wordIndex >= startPos && wordIndex < endPos) {
218
218
  return true;
219
219
  }
220
220
  return false;
221
221
  }
222
222
 
223
- function checkCurrentCue(currentCursor) {
224
- Array.from(vttCues.value).forEach((a, index) => {
225
- if(currentCursor >= a.start && currentCursor <= a.end) {
223
+ async function checkCurrentCue(currentCursor) {
224
+ Array.from(vttCues.value).forEach(async (a, index) => {
225
+ if(videoCursor.value >= a.start && videoCursor.value <= a.end) {
226
226
  currentCue.value = a.text
227
+ await nextTick()
227
228
  }
228
229
  });
229
230
  }
@@ -237,7 +238,7 @@ async function parseVTT(fileUrl) {
237
238
  const response = await fetch(fileUrl);
238
239
  const text = await response.text();
239
240
  const cues = [];
240
- const lines = text.split('\n');
241
+ const lines = text.replace(/\r/g, '').split('\n');
241
242
  let cue = null;
242
243
 
243
244
  for (let i = 0; i < lines.length; i++) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@grfzhl/vue-hls-player",
3
3
  "private": false,
4
- "version": "1.1.4",
4
+ "version": "1.1.6",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"