{"version":3,"file":"PlayerVideoHls-jOa02CyD.mjs","names":[],"sources":["../src/components/misc/player/video/PlayerVideoHls.vue","../src/components/misc/player/video/PlayerVideoHls.vue"],"sourcesContent":["<template>\n  <div\n    id=\"player-video-hls\"\n    class=\"video-player\"\n    :class=\"responsive ? 'video-responsive-wrapper' : ''\"\n  >\n    <div v-if=\"errorPlay.length\" class=\"video-live-error\">{{ errorPlay }}</div>\n    <video\n      id=\"video-element-hls\"\n      ref=\"videoelement\"\n      class=\"video-js\"\n      playsinline\n    ></video>\n  </div>\n</template>\n<script setup lang=\"ts\">\nimport { usePlayerStore } from \"../../../../stores/PlayerStore\";\nimport {usePlayerLogicProgress} from \"../../../composable/player/usePlayerLogicProgress\";\nimport videojs, { VideoJsPlayer } from \"video.js\";\nimport qualitySelectorHls from \"videojs-quality-selector-hls\";\nif (undefined === videojs.getPlugin(\"qualitySelectorHls\")) {\n  videojs.registerPlugin(\"qualitySelectorHls\", qualitySelectorHls);\n}\nimport { computed, onMounted, onUnmounted, Ref, ref, useTemplateRef } from \"vue\";\nimport { useAuthStore } from \"../../../../stores/AuthStore\";\nimport { useI18n } from \"vue-i18n\";\n\n//Props \nconst props = defineProps({\n  hlsUrl: { default: \"\", type: String },\n  responsive: { default: false, type: Boolean },\n  isSecured: { default: true, type: Boolean },\n})\n\n//Data\nconst errorPlay = ref(\"\");\nconst useVideoSrc = ref(false);\nconst player: Ref<VideoJsPlayer | undefined> = ref(false);\nconst playing = ref(false);\nconst isPaused = ref(false);\nconst stalledTimout: Ref<ReturnType<typeof setTimeout> | undefined> = ref(undefined);\nconst videoElementRef = useTemplateRef('videoelement');\n\n\n//Composables\nconst { t } = useI18n();\nconst { downloadId, initLiveDownloadId, onTimeUpdateProgress, endListeningProgress} = usePlayerLogicProgress();\nconst authStore = useAuthStore();\nconst playerStore = usePlayerStore();\n\n\n\n//Computed\nconst videoElement = computed(() => {\n  return videoElementRef?.value as HTMLVideoElement;\n});\nconst videoOptions = computed(() => {\n  return {\n    autoplay: true,\n    controls: true,\n    liveui: true,\n    sources: [\n      {\n        src: props.hlsUrl,\n        type: \"application/x-mpegURL\",\n      },\n    ],\n    html5: {\n      vhs: {\n        overrideNative: !videojs.browser.IS_SAFARI,\n      },\n      nativeAudioTracks: false,\n      nativeVideoTracks: false,\n    },\n  };\n});\n\n\nonMounted(()=>{\n  playerStore.playerUpdatePlayerHlsUrl(props.hlsUrl);\n  useVideoSrc.value =\n    \"\" !== videoElement.value.canPlayType(\"application/vnd.apple.mpegurl\") &&\n    !navigator.userAgent.includes(\"Android\");\n  playLive();\n})\n\nonUnmounted(()=>{\n  if (playing.value) {\n    stopLive();\n  }\n})\n\n\n//Methods\nfunction definedStalledTimeout() {\n  isPaused.value = false;\n  stalledTimout.value = setTimeout(() => {\n    if (isPaused.value) {\n      return;\n    }\n    videoClean();\n    playLive();\n  }, 15000);\n}\nasync function playLive(): Promise<void> {\n  clearTimeout(stalledTimout.value);\n  definedStalledTimeout();\n  await initLiveDownloadId();\n  if (useVideoSrc.value) {\n    playLiveIos();\n    return;\n  }\n  if (props.isSecured && authStore.authParam.accessToken) {\n    const globalXhrRequestHook = (options: any) => {\n      options.beforeSend = (xhr: XMLHttpRequest) => {\n        xhr.setRequestHeader(\"Authorization\", \"Bearer \"+authStore.authParam.accessToken);\n      };\n      return options;\n    };\n    videojs.Vhs.xhr.onRequest(globalXhrRequestHook);\n  }\n  player.value = videojs(\n    document.getElementById(\"video-element-hls\") as Element,\n    videoOptions.value,\n    () => {\n      player.value.qualitySelectorHls({ displayCurrentQuality: true });\n      errorPlay.value = \"\";\n      playing.value = true;\n    },\n  );\n  player.value.on(\"error\", (error: any) => {\n    stopLive();\n    if (error.description?.includes(\"403\")) {\n      errorPlay.value = t(\"Video is unavailable\");\n    } else {\n      errorPlay.value = t(\"Podcast play error\");\n    }\n  });\n  player.value.on(\"seeking\", () => {\n    playerStore.playerUpdateSeekTime(player.value?.currentTime() ?? 0);\n  });\n  player.value.on(\"pause\", () => {\n    isPaused.value = true;\n  });\n  player.value.on(\"timeupdate\", () => {\n    clearTimeout(stalledTimout.value);\n    definedStalledTimeout();\n    onTimeUpdateVideo();\n  });\n  player.value.on(\"seeking\", () => {\n    playerStore.playerUpdateSeekTime(player.value?.currentTime() ?? 0);\n  });\n}\n\nasync function playLiveIos(): Promise<void> {\n  videoElement.value.onloadedmetadata = () => {\n    const playPromise = videoElement.value.play();\n    if (playPromise !== undefined) {\n      playPromise\n        .then(() => {\n          errorPlay.value = \"\";\n          playing.value = true;\n        })\n        .catch(() => {\n          playing.value = false;\n        });\n    }\n  };\n  videoElement.value.onerror = async () => {\n    stopLive();\n    errorPlay.value = t(\"Podcast play error\");\n  };\n  videoElement.value.ontimeupdate = async () => {\n    clearTimeout(stalledTimout.value);\n    definedStalledTimeout();\n    onTimeUpdateVideo();\n  };\n  videoElement.value.onpause = async () => {\n    isPaused.value = true;\n  };\n  videoElement.value.onseeking = async () => {\n    playerStore.playerUpdateSeekTime(videoElement.value.currentTime);\n  };\n  if (props.isSecured && authStore.authParam.accessToken) {\n    videoElement.value.src = props.hlsUrl + \"access_token=\"+authStore.authParam.accessToken;\n  }else{\n    videoElement.value.src = props.hlsUrl;\n  }\n  videoElement.value.src = props.hlsUrl;\n}\n\nfunction videoClean(): void {\n  if (useVideoSrc.value) {\n    videoElement.value.pause();\n    videoElement.value.removeAttribute(\"src\");\n    videoElement.value.load();\n    return;\n  }\n  if (player.value) {\n    player.value.dispose();\n    //Redraw\n    const video_parent = document.getElementById(\"player-video-hls\");\n    if (video_parent) {\n      const video = document.createElement(\"video\");\n      video.id = \"video-element-hls\";\n      video.className = \"video-js\";\n      video.preload = \"auto\";\n      video.setAttribute(\"playsinline\", \"true\");\n      video_parent.appendChild(video);\n    }\n  }\n}\nfunction stopLive(): void {\n  clearTimeout(stalledTimout.value);\n  errorPlay.value = \"\";\n  videoClean();\n  playing.value = false;\n  endListeningProgress();\n}\nfunction onTimeUpdateVideo(): void {\n  if (!downloadId.value) {\n    return;\n  }\n  const currentTime =player.value?.currentTime() ?? videoElement.value.currentTime;\n  onTimeUpdateProgress(currentTime);\n}\n</script>\n\n<style lang=\"scss\">\n@use \"video.js\";\n@use \"../../../../style/videoPlayer\";\n\n.octopus-app {\n  .video-live-error {\n    text-align: center;\n    width: 100%;\n    font-size: 1rem;\n    font-weight: bold;\n    padding: 0.2rem 0;\n    color: white;\n    position: absolute;\n    top: 0;\n    background: var(--octopus-danger);\n    z-index: 1;\n  }\n\n  .video-js {\n    width: 500px;\n    height: 281px;\n  }\n}\n</style>\n","<template>\n  <div\n    id=\"player-video-hls\"\n    class=\"video-player\"\n    :class=\"responsive ? 'video-responsive-wrapper' : ''\"\n  >\n    <div v-if=\"errorPlay.length\" class=\"video-live-error\">{{ errorPlay }}</div>\n    <video\n      id=\"video-element-hls\"\n      ref=\"videoelement\"\n      class=\"video-js\"\n      playsinline\n    ></video>\n  </div>\n</template>\n<script setup lang=\"ts\">\nimport { usePlayerStore } from \"../../../../stores/PlayerStore\";\nimport {usePlayerLogicProgress} from \"../../../composable/player/usePlayerLogicProgress\";\nimport videojs, { VideoJsPlayer } from \"video.js\";\nimport qualitySelectorHls from \"videojs-quality-selector-hls\";\nif (undefined === videojs.getPlugin(\"qualitySelectorHls\")) {\n  videojs.registerPlugin(\"qualitySelectorHls\", qualitySelectorHls);\n}\nimport { computed, onMounted, onUnmounted, Ref, ref, useTemplateRef } from \"vue\";\nimport { useAuthStore } from \"../../../../stores/AuthStore\";\nimport { useI18n } from \"vue-i18n\";\n\n//Props \nconst props = defineProps({\n  hlsUrl: { default: \"\", type: String },\n  responsive: { default: false, type: Boolean },\n  isSecured: { default: true, type: Boolean },\n})\n\n//Data\nconst errorPlay = ref(\"\");\nconst useVideoSrc = ref(false);\nconst player: Ref<VideoJsPlayer | undefined> = ref(false);\nconst playing = ref(false);\nconst isPaused = ref(false);\nconst stalledTimout: Ref<ReturnType<typeof setTimeout> | undefined> = ref(undefined);\nconst videoElementRef = useTemplateRef('videoelement');\n\n\n//Composables\nconst { t } = useI18n();\nconst { downloadId, initLiveDownloadId, onTimeUpdateProgress, endListeningProgress} = usePlayerLogicProgress();\nconst authStore = useAuthStore();\nconst playerStore = usePlayerStore();\n\n\n\n//Computed\nconst videoElement = computed(() => {\n  return videoElementRef?.value as HTMLVideoElement;\n});\nconst videoOptions = computed(() => {\n  return {\n    autoplay: true,\n    controls: true,\n    liveui: true,\n    sources: [\n      {\n        src: props.hlsUrl,\n        type: \"application/x-mpegURL\",\n      },\n    ],\n    html5: {\n      vhs: {\n        overrideNative: !videojs.browser.IS_SAFARI,\n      },\n      nativeAudioTracks: false,\n      nativeVideoTracks: false,\n    },\n  };\n});\n\n\nonMounted(()=>{\n  playerStore.playerUpdatePlayerHlsUrl(props.hlsUrl);\n  useVideoSrc.value =\n    \"\" !== videoElement.value.canPlayType(\"application/vnd.apple.mpegurl\") &&\n    !navigator.userAgent.includes(\"Android\");\n  playLive();\n})\n\nonUnmounted(()=>{\n  if (playing.value) {\n    stopLive();\n  }\n})\n\n\n//Methods\nfunction definedStalledTimeout() {\n  isPaused.value = false;\n  stalledTimout.value = setTimeout(() => {\n    if (isPaused.value) {\n      return;\n    }\n    videoClean();\n    playLive();\n  }, 15000);\n}\nasync function playLive(): Promise<void> {\n  clearTimeout(stalledTimout.value);\n  definedStalledTimeout();\n  await initLiveDownloadId();\n  if (useVideoSrc.value) {\n    playLiveIos();\n    return;\n  }\n  if (props.isSecured && authStore.authParam.accessToken) {\n    const globalXhrRequestHook = (options: any) => {\n      options.beforeSend = (xhr: XMLHttpRequest) => {\n        xhr.setRequestHeader(\"Authorization\", \"Bearer \"+authStore.authParam.accessToken);\n      };\n      return options;\n    };\n    videojs.Vhs.xhr.onRequest(globalXhrRequestHook);\n  }\n  player.value = videojs(\n    document.getElementById(\"video-element-hls\") as Element,\n    videoOptions.value,\n    () => {\n      player.value.qualitySelectorHls({ displayCurrentQuality: true });\n      errorPlay.value = \"\";\n      playing.value = true;\n    },\n  );\n  player.value.on(\"error\", (error: any) => {\n    stopLive();\n    if (error.description?.includes(\"403\")) {\n      errorPlay.value = t(\"Video is unavailable\");\n    } else {\n      errorPlay.value = t(\"Podcast play error\");\n    }\n  });\n  player.value.on(\"seeking\", () => {\n    playerStore.playerUpdateSeekTime(player.value?.currentTime() ?? 0);\n  });\n  player.value.on(\"pause\", () => {\n    isPaused.value = true;\n  });\n  player.value.on(\"timeupdate\", () => {\n    clearTimeout(stalledTimout.value);\n    definedStalledTimeout();\n    onTimeUpdateVideo();\n  });\n  player.value.on(\"seeking\", () => {\n    playerStore.playerUpdateSeekTime(player.value?.currentTime() ?? 0);\n  });\n}\n\nasync function playLiveIos(): Promise<void> {\n  videoElement.value.onloadedmetadata = () => {\n    const playPromise = videoElement.value.play();\n    if (playPromise !== undefined) {\n      playPromise\n        .then(() => {\n          errorPlay.value = \"\";\n          playing.value = true;\n        })\n        .catch(() => {\n          playing.value = false;\n        });\n    }\n  };\n  videoElement.value.onerror = async () => {\n    stopLive();\n    errorPlay.value = t(\"Podcast play error\");\n  };\n  videoElement.value.ontimeupdate = async () => {\n    clearTimeout(stalledTimout.value);\n    definedStalledTimeout();\n    onTimeUpdateVideo();\n  };\n  videoElement.value.onpause = async () => {\n    isPaused.value = true;\n  };\n  videoElement.value.onseeking = async () => {\n    playerStore.playerUpdateSeekTime(videoElement.value.currentTime);\n  };\n  if (props.isSecured && authStore.authParam.accessToken) {\n    videoElement.value.src = props.hlsUrl + \"access_token=\"+authStore.authParam.accessToken;\n  }else{\n    videoElement.value.src = props.hlsUrl;\n  }\n  videoElement.value.src = props.hlsUrl;\n}\n\nfunction videoClean(): void {\n  if (useVideoSrc.value) {\n    videoElement.value.pause();\n    videoElement.value.removeAttribute(\"src\");\n    videoElement.value.load();\n    return;\n  }\n  if (player.value) {\n    player.value.dispose();\n    //Redraw\n    const video_parent = document.getElementById(\"player-video-hls\");\n    if (video_parent) {\n      const video = document.createElement(\"video\");\n      video.id = \"video-element-hls\";\n      video.className = \"video-js\";\n      video.preload = \"auto\";\n      video.setAttribute(\"playsinline\", \"true\");\n      video_parent.appendChild(video);\n    }\n  }\n}\nfunction stopLive(): void {\n  clearTimeout(stalledTimout.value);\n  errorPlay.value = \"\";\n  videoClean();\n  playing.value = false;\n  endListeningProgress();\n}\nfunction onTimeUpdateVideo(): void {\n  if (!downloadId.value) {\n    return;\n  }\n  const currentTime =player.value?.currentTime() ?? videoElement.value.currentTime;\n  onTimeUpdateProgress(currentTime);\n}\n</script>\n\n<style lang=\"scss\">\n@use \"video.js\";\n@use \"../../../../style/videoPlayer\";\n\n.octopus-app {\n  .video-live-error {\n    text-align: center;\n    width: 100%;\n    font-size: 1rem;\n    font-weight: bold;\n    padding: 0.2rem 0;\n    color: white;\n    position: absolute;\n    top: 0;\n    background: var(--octopus-danger);\n    z-index: 1;\n  }\n\n  .video-js {\n    width: 500px;\n    height: 281px;\n  }\n}\n</style>\n"],"mappings":"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"}