Files
BRETT/app/components/VideoPlayer.vue
T
FliesentischKingandDevin 0decdf415a Loop uploaded videos during playback
Enable Plyr's loop option so videos restart automatically instead of
stopping at the end.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-04 19:54:13 +02:00

69 lines
1.6 KiB
Vue

<script setup lang="ts">
import type Plyr from 'plyr'
import 'plyr/dist/plyr.css'
defineProps<{
src: string
autoplay?: boolean
}>()
const videoEl = ref<HTMLVideoElement | null>(null)
const aspect = ref<number | null>(null)
let player: Plyr | null = null
onMounted(async () => {
if (!videoEl.value) return
// SSR: Metadaten können vor der Hydration schon geladen sein —
// das loadedmetadata-Event feuert dann nicht mehr
if (videoEl.value.readyState >= HTMLMediaElement.HAVE_METADATA) {
onLoadedMetadata()
}
const { default: PlyrClass } = await import('plyr')
player = new PlyrClass(videoEl.value, {
disableContextMenu: false,
loop: { active: true },
storage: { enabled: true, key: '4brett-player' },
})
})
onBeforeUnmount(() => {
player?.destroy()
player = null
})
function onLoadedMetadata() {
const v = videoEl.value
if (v?.videoWidth && v.videoHeight) {
aspect.value = v.videoWidth / v.videoHeight
}
}
</script>
<template>
<div
class="video-player mx-auto w-full max-w-4xl"
:style="aspect ? { maxWidth: `min(100%, 56rem, calc(80vh * ${aspect}))` } : undefined"
>
<video
ref="videoEl"
:src="src"
:autoplay="autoplay"
playsinline
controls
class="mx-auto max-h-[80vh] w-auto max-w-full rounded-md"
@loadedmetadata="onLoadedMetadata"
/>
</div>
</template>
<style scoped>
.video-player {
--plyr-color-main: var(--accent);
--plyr-border-radius: var(--radius-md);
}
.video-player :deep(.plyr__control--overlaid),
.video-player :deep(.plyr__control) {
border-radius: var(--radius-md);
}
</style>