Added plyr as video player.
This commit is contained in:
parent
f0eb924185
commit
bed10cabf4
4 changed files with 71 additions and 32 deletions
33
frontend/package-lock.json
generated
33
frontend/package-lock.json
generated
|
|
@ -16,6 +16,7 @@
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"hls.js": "^1.4.12",
|
"hls.js": "^1.4.12",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
"plyr": "^3.7.8",
|
||||||
"socket.io-client": "^4.7.2",
|
"socket.io-client": "^4.7.2",
|
||||||
"vue": "^3.3.9",
|
"vue": "^3.3.9",
|
||||||
"vue-toastification": "^2.0.0-rc.5"
|
"vue-toastification": "^2.0.0-rc.5"
|
||||||
|
|
@ -4967,6 +4968,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/custom-event-polyfill": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w=="
|
||||||
|
},
|
||||||
"node_modules/debounce": {
|
"node_modules/debounce": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
|
||||||
|
|
@ -7512,6 +7518,11 @@
|
||||||
"json5": "lib/cli.js"
|
"json5": "lib/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/loadjs": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA=="
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||||
|
|
@ -8746,6 +8757,18 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/plyr": {
|
||||||
|
"version": "3.7.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/plyr/-/plyr-3.7.8.tgz",
|
||||||
|
"integrity": "sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^3.26.1",
|
||||||
|
"custom-event-polyfill": "^1.0.7",
|
||||||
|
"loadjs": "^4.2.0",
|
||||||
|
"rangetouch": "^2.0.1",
|
||||||
|
"url-polyfill": "^1.1.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/portfinder": {
|
"node_modules/portfinder": {
|
||||||
"version": "1.0.32",
|
"version": "1.0.32",
|
||||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
|
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
|
||||||
|
|
@ -9501,6 +9524,11 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rangetouch": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rangetouch/-/rangetouch-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA=="
|
||||||
|
},
|
||||||
"node_modules/raw-body": {
|
"node_modules/raw-body": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||||
|
|
@ -10907,6 +10935,11 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/url-polyfill": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A=="
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"hls.js": "^1.4.12",
|
"hls.js": "^1.4.12",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
"plyr": "^3.7.8",
|
||||||
"socket.io-client": "^4.7.2",
|
"socket.io-client": "^4.7.2",
|
||||||
"vue": "^3.3.9",
|
"vue": "^3.3.9",
|
||||||
"vue-toastification": "^2.0.0-rc.5"
|
"vue-toastification": "^2.0.0-rc.5"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<div class="modal is-active" v-if="video_link">
|
<div class="modal is-active" v-if="video_link">
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
<div class="modal-content">
|
<div class="modal-content" style="width:auto;">
|
||||||
<VideoPlayer type="default" :link="video_link" :isMuted="false" autoplay="true" :isControls="true"
|
<VideoPlayer type="default" :link="video_link" :isMuted="false" autoplay="true" :isControls="true"
|
||||||
class="is-fullwidth" />
|
class="is-fullwidth" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<video @pause="pause" @ended="pause" @keyup="changeSpeed" ref="video" :poster="previewImageLink" :controls="isControls"
|
<video ref="video" :poster="previewImageLink" :controls="isControls" :title="title">
|
||||||
:title="title">
|
|
||||||
<source :src="link" type="application/x-mpegURL" />
|
<source :src="link" type="application/x-mpegURL" />
|
||||||
</video>
|
</video>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onUpdated, ref, defineProps, defineEmits } from 'vue'
|
import { onMounted, onUpdated, ref, defineProps, onUnmounted } from 'vue'
|
||||||
import Hls from 'hls.js'
|
import Hls from 'hls.js'
|
||||||
|
import Plyr from 'plyr'
|
||||||
|
import 'plyr/dist/plyr.css'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
previewImageLink: {
|
previewImageLink: {
|
||||||
|
|
@ -18,26 +19,19 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
progress: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
isMuted: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
isControls: {
|
isControls: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['pause', 'test'])
|
|
||||||
const video = ref(null)
|
const video = ref(null)
|
||||||
|
const player = ref(null)
|
||||||
|
const hls = ref(null)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
prepareVideoPlayer()
|
prepareVideoPlayer()
|
||||||
|
|
@ -47,35 +41,46 @@ onUpdated(() => {
|
||||||
prepareVideoPlayer()
|
prepareVideoPlayer()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
player.value.destroy()
|
||||||
|
hls.value.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
const prepareVideoPlayer = () => {
|
const prepareVideoPlayer = () => {
|
||||||
let hls = new Hls({
|
player.value = new Plyr(video.value, {
|
||||||
|
clickToPlay: true,
|
||||||
|
keyboard: { focused: true, global: true },
|
||||||
|
controls: [
|
||||||
|
'play-large', 'play', 'progress', 'current-time', 'duration', 'mute', 'volume', 'pip', 'airplay', 'fullscreen'
|
||||||
|
],
|
||||||
|
fullscreen: {
|
||||||
|
enabled: true,
|
||||||
|
fallback: true,
|
||||||
|
iosNative: true,
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
enabled: true,
|
||||||
|
key: 'plyr_volume'
|
||||||
|
},
|
||||||
|
mediaMetadata: {
|
||||||
|
title: props.title.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
hls.value = new Hls({
|
||||||
debug: false,
|
debug: false,
|
||||||
enableWorker: true,
|
enableWorker: true,
|
||||||
lowLatencyMode: true,
|
lowLatencyMode: true,
|
||||||
backBufferLength: 90,
|
backBufferLength: 90,
|
||||||
});
|
});
|
||||||
|
|
||||||
hls.loadSource(props.link)
|
hls.value.loadSource(props.link)
|
||||||
|
|
||||||
if (video.value) {
|
if (video.value) {
|
||||||
hls.attachMedia(video.value)
|
hls.value.attachMedia(video.value)
|
||||||
video.value.muted = props.isMuted
|
|
||||||
video.value.currentTime = props.progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pause = () => {
|
|
||||||
const currentTime = video?.value?.currentTime || 0
|
|
||||||
|
|
||||||
emit('pause', currentTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeSpeed = (e) => {
|
|
||||||
if (e.key === 'w' && video.value) {
|
|
||||||
video.value.playbackRate = video.value.playbackRate + 0.25
|
|
||||||
} else if (e.key === 's' && video.value) {
|
|
||||||
video.value.playbackRate = video.value.playbackRate - 0.25
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue