Getting started
This guide assumes an existing Vue 3.5+ application with a build tool that supports Vue single-file components.
Install
pnpm add videojs-vue vue@videojs/html@10.0.1 is included as a dependency. Install the optional HLS adapter only when you need it.
Render a player
Add this to a Vue component:
<script setup lang="ts">
import { VideoPlayer } from 'videojs-vue/video/default'
</script>
<template>
<VideoPlayer
src="/demo.mp4"
poster="/poster.webp"
title="Product demo"
/>
</template>Place demo.mp4 and poster.webp in your application's public directory, or replace the paths with accessible media URLs. The player displays a poster and packaged controls; start playback with the play button.
Registration and skin styles are included. No plugin installation or Vue isCustomElement configuration is needed when using these Vue components. Direct use of upstream HTML custom element tags requires separate compiler configuration.
Choose a skin
The default skin supplies controls and keyboard interaction. For a fixed neutral skin, import VideoPlayer from videojs-vue/video/neutral. To switch skins with a prop, import VideoPlayer from the aggregate videojs-vue entry (which includes both skins):
<VideoPlayer src="/demo.mp4" skin="neutral" />Both skins default to full width and a 16:9 aspect ratio. class, style, and other fallthrough attributes target the visible skin. See skins and styling to change sizing or slot content.
Two-way settings
Bind the settings your application needs to control:
<script setup lang="ts">
import { shallowRef } from 'vue'
import { VideoPlayer } from 'videojs-vue/video/default'
const volume = shallowRef(0.7)
const muted = shallowRef(false)
const playbackRate = shallowRef(1)
</script>
<template>
<VideoPlayer
src="/demo.mp4"
v-model:volume="volume"
v-model:muted="muted"
v-model:playback-rate="playbackRate"
/>
</template>Changing a bound value requests a media setting update. Media confirmation events emit the actual value. Unbound settings remain under player control.
Volume is clamped to 0–1. Non-finite volume and non-positive or non-finite playback rates are ignored. The browser may reject otherwise valid rates; use actions to handle command failures explicitly.
There is no v-model:currentTime or v-model:playing. Read state and call seek(), play(), or pause() instead.
For lightweight core, composable, and control imports, see bundle size and imports.
Next steps
- Try native video, HLS, and custom controls in the Playground.
- Add captions and a poster.
- Connect application UI with state and actions.
- Look up all VideoPlayer props, events, and slots.
Audio playback
Import AudioPlayer from videojs-vue/audio/default for native audio with packaged skins. See the audio example and API.