Vimeo Player
Vimeo is a video hosting platform that allows you to upload and share videos.
Nuxt Scripts provides a useScriptVimeoPlayer() composable and a headless <ScriptVimeoPlayer> a component to interact with the Vimeo Player.
Nuxt Config Setup
Add this to your nuxt.config.ts to load Vimeo Player globally. Alternatively you can use the useScriptVimeoPlayer composable for more control.
export default defineNuxtConfig({
scripts: {
registry: {
vimeoPlayer: {
trigger: 'onNuxtReady',
}
}
}
})This config automatically enables first-party mode (bundle + proxy). See below to customise.
useScriptVimeoPlayer()
The useScriptVimeoPlayer composable lets you have fine-grain control over when and how Vimeo Player is loaded on your site.
const { proxy } = useScriptVimeoPlayer()
const { Vimeo } = await proxyPlease follow the Registry Scripts guide to learn more about advanced usage.
First-Party Mode: Privacy Focused Proxy
No extra config needed. The script is bundled from your domain (faster loads, no extra DNS lookup) and runtime requests are reverse-proxied through your server with automatic anonymisation (user IPs stay hidden from Vimeo Player, works with ad blockers). Learn more.
export default defineNuxtConfig({
scripts: {
// ✅ First-party mode: bundled + proxied
registry: {
vimeoPlayer: {
trigger: 'onNuxtReady',
},
},
},
})Example
Using Vimeo Player in a component with the proxy to send events .
<script setup lang="ts">
const { proxy } = useScriptVimeoPlayer()
// noop in development, ssr
// just works in production, client
function handleAction() {
const { Vimeo } = await proxy
}
</script>
<template>
<div>
<button @click="handleAction">
Send Event
</button>
</div>
</template>Types
To use Video Player with full TypeScript support, you will need
to install the @vimeo/player dependency which includes its own types.
pnpm add -D @vimeo/player
<ScriptVimeoPlayer>
The <ScriptVimeoPlayer> component is a wrapper around the useScriptVimeoPlayer() composable. It provides a simple way to embed Vimeo videos in your Nuxt app.
It's optimized for performance by using the Element Event Triggers, only loading the Vimeo Player when the specific elements events happen.
By default, it will load on the mousedown event.
Demo
<script setup lang="ts">
const isLoaded = ref(false)
const isPlaying = ref(false)
const video = ref()
async function play() {
await video.value.play()
}
</script>
<template>
<div>
<div class="flex items-center justify-center p-5">
<ScriptVimeoPlayer :id="331567154" ref="video" class="group" @loaded="isLoaded = true" @play="isPlaying = true" @pause="isPlaying = false">
<template #awaitingLoad>
<div class="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-blue-500 group-hover:bg-blue-700 transition rounded px-6 py-2">
<svg width="24" height="24" viewBox="0 0 24 24" class="w-10 h-10 text-white" xmlns="http://www.w3.org/2000/svg"><path d="M19 12C19 12.3557 18.8111 12.6846 18.5039 12.8638L6.50387 19.8638C6.19458 20.0442 5.81243 20.0455 5.50194 19.8671C5.19145 19.6888 5 19.3581 5 19L5 5C5 4.64193 5.19145 4.3112 5.50194 4.13286C5.81243 3.95452 6.19458 3.9558 6.50387 4.13622L18.5039 11.1362C18.8111 11.3154 19 11.6443 19 12Z" fill="currentColor" /></svg>
</div>
</template>
</ScriptVimeoPlayer>
</div>
<div class="text-center">
<UAlert v-if="!isLoaded" class="mb-5" size="sm" color="blue" variant="soft" title="Clicks the video!" description="Clicking the video will load the Vimeo iframe and start the video." />
<UButton v-if="isLoaded && !isPlaying" @click="play">
Play Video
</UButton>
</div>
</div>
</template>
Eager Loading Placeholder
The Vimeo Video placeholder image is lazy-loaded by default. You should change this behavior if your video is above the fold
or consider using the #placeholder slot to customize the placeholder image.
<ScriptVimeoPlayer above-the-fold />
<ScriptVimeoPlayer>
<template #placeholder="{ placeholder }">
<img :src="placeholder" alt="Video Placeholder">
</template>
</ScriptVimeoPlayer>
Component API
See the Facade Component API for full props, events, and slots.
Events
The <ScriptVimeoPlayer> component emits all events from the Vimeo Player SDK. Please consult the Player Events for full documentation.
const emits = defineEmits<{
play: [e: EventMap['play'], player: Player]
playing: [e: EventMap['playing'], player: Player]
pause: [e: EventMap['pause'], player: Player]
ended: [e: EventMap['ended'], player: Player]
timeupdate: [e: EventMap['timeupdate'], player: Player]
progress: [e: EventMap['progress'], player: Player]
seeking: [e: EventMap['seeking'], player: Player]
seeked: [e: EventMap['seeked'], player: Player]
texttrackchange: [e: EventMap['texttrackchange'], player: Player]
chapterchange: [e: EventMap['chapterchange'], player: Player]
cuechange: [e: EventMap['cuechange'], player: Player]
cuepoint: [e: EventMap['cuepoint'], player: Player]
volumechange: [e: EventMap['volumechange'], player: Player]
playbackratechange: [e: EventMap['playbackratechange'], player: Player]
bufferstart: [e: EventMap['bufferstart'], player: Player]
bufferend: [e: EventMap['bufferend'], player: Player]
error: [e: EventMap['error'], player: Player]
loaded: [e: EventMap['loaded'], player: Player]
durationchange: [e: EventMap['durationchange'], player: Player]
fullscreenchange: [e: EventMap['fullscreenchange'], player: Player]
qualitychange: [e: EventMap['qualitychange'], player: Player]
camerachange: [e: EventMap['camerachange'], player: Player]
resize: [e: EventMap['resize'], player: Player]
enterpictureinpicture: [e: EventMap['enterpictureinpicture'], player: Player]
leavepictureinpicture: [e: EventMap['leavepictureinpicture'], player: Player]
}>()
Slots
As Nuxt provides the component headless, you can use slots to customize the player however you like before it loads.
default
The default slot displays content that will always be visible.
<template>
<ScriptVimeoPlayer :id="331567154">
<div class="bg-blue-500 text-white p-5">
Video by NuxtJS
</div>
</ScriptVimeoPlayer>
</template>
awaitingLoad
This slot displays content while the video is loading.
<template>
<ScriptVimeoPlayer :id="331567154">
<template #awaitingLoad>
<div class="bg-blue-500 text-white p-5">
Click to play!
</div>
</template>
</ScriptVimeoPlayer>
</template>
loading
This slot displays content while the video is loading.
<template>
<ScriptVimeoPlayer :id="331567154">
<template #loading>
<div class="bg-blue-500 text-white p-5">
Loading...
</div>
</template>
</ScriptVimeoPlayer>
</template>
placeholder
This slot displays a placeholder image before the video loads. By default, this will show the vimeo thumbnail for the video. You can display it however you like.
<template>
<ScriptVimeoPlayer :id="331567154">
<template #placeholder="{ placeholder }">
<img :src="placeholder" alt="Video Placeholder">
</template>
</ScriptVimeoPlayer>
</template>
useScriptVimeoPlayer()
The useScriptVimeoPlayer() composable lets you have fine-grain control over the Vimeo Player SDK. It provides a way to load the Vimeo Player SDK and interact with it programmatically.
export function useScriptVimeoPlayer<T extends VimeoPlayerApi>(_options?: VimeoPlayerInput) {}
Please follow the Registry Scripts guide to learn more about advanced usage.
type Constructor<T extends new (...args: any) => any> = T extends new (...args: infer A) => infer R ? new (...args: A) => R : neverExample
Loading the Vimeo Player SDK and interacting with it programmatically.
<script setup lang="ts">
const video = ref()
const { onLoaded } = useScriptVimeoPlayer()
let player
onLoaded(({ Vimeo }) => {
player = new Vimeo.Player(video.value, {
id: 331567154
})
})
</script>
<template>
<div>
<div ref="video" />
<button @click="player.play()">
Play
</button>
</div>
</template>