# Video Player
A reusable, accessible video player component for embedding and controlling video playback. The component supports various aspect ratios, customizable accessibility labels, and follows form field patterns for error display.
# Rendered Example
# Usage
<template>
<div>
<ci-video-player
src="https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"
:controls="true"
:autoplay="false"
:muted="false"
:loop="false"
poster="https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"
aria-label="Demo video player"
aspect-ratio="16:9"
ref="videoPlayer"
@play="onPlay"
@pause="onPause"
@ended="onEnded"
@error="onError"
@ready="onReady"
@timeupdate="onTimeUpdate"
@canplay="onCanPlay"
@waiting="onWaiting"
/>
<!-- Event feedback example -->
<div v-if="lastEvent" style="margin-top: 1rem; padding: 0.5rem; background: #e8f5e8; border-radius: 4px;">
Last event: {{ lastEvent }}
</div>
<!-- Current time display -->
<div v-if="currentTime > 0" style="margin-top: 0.5rem; font-size: 0.875rem; color: #666;">
Current time: {{ formatTime(currentTime) }}
</div>
</div>
</template>
<script setup>
import { CiVideoPlayer } from '@ci/stratus-components'
import { ref } from 'vue'
const lastEvent = ref('')
const currentTime = ref(0)
const lastTimeUpdate = ref(0)
function formatTime(seconds) {
const mins = Math.floor(seconds / 60)
const secs = Math.floor(seconds % 60)
return `${mins}:${secs.toString().padStart(2, '0')}`
}
function onPlay() {
lastEvent.value = 'Video started playing'
console.log('Video started playing')
}
function onPause() {
lastEvent.value = 'Video paused'
console.log('Video paused')
}
function onEnded() {
lastEvent.value = 'Video playback ended'
console.log('Video ended')
}
function onError() {
lastEvent.value = 'Error occurred while playing video'
console.log('Video error')
}
function onReady() {
lastEvent.value = 'Video is ready to play'
console.log('Video ready')
}
function onCanPlay() {
lastEvent.value = 'Video can start playing'
console.log('Video can play')
}
function onWaiting() {
lastEvent.value = 'Video is buffering'
console.log('Video waiting')
}
function onTimeUpdate(event) {
const time = event.target.currentTime
// Update current time display
currentTime.value = time
// Only update last event every 5 seconds for regular playback
const timeFloor = Math.floor(time)
if (timeFloor !== lastTimeUpdate.value && timeFloor % 5 === 0) {
lastTimeUpdate.value = timeFloor
lastEvent.value = `Current time: ${formatTime(time)}`
}
}
// Programmatic seek example:
// this.$refs.videoPlayer.seekTo(120) // Seek to 2:00
</script>
# Props
Name | Type | Default | Description |
---|---|---|---|
src | String | β | Video source URL (required) |
controls | Boolean | true | Show native video controls |
autoplay | Boolean | false | Autoplay video |
muted | Boolean | false | Mute video |
loop | Boolean | false | Loop video |
poster | String | '' | Poster image URL |
currentTime | Number | 0 | Seek to this time (seconds) |
ariaLabel | String | 'Video player' | ARIA label for accessibility |
aspectRatio | String | '16:9' | Video aspect ratio (16:9, 4:3, 1:1, 21:9) |
# Events
Name | Payload | Description |
---|---|---|
play | β | Video started playing |
pause | β | Video paused |
ended | β | Video playback ended |
error | β | Error loading/playing video |
ready | β | Video metadata loaded |
timeupdate | Event | Native timeupdate event |
canplay | β | Video can start playing |
waiting | β | Video is buffering |
# TimeUpdate Event
The timeupdate
event is the native HTML5 video event that fires when the current playback position of the video changes. The event payload is the standard Event
object, and you can access the current time via event.target.currentTime
.
function onTimeUpdate(event) {
const currentTime = event.target.currentTime
console.log(`Current time: ${currentTime} seconds`)
}
# Methods (via ref)
seekTo(time: number)
β Seek to a specific time in seconds.video
β Access the underlying HTMLVideoElement.
# Accessibility
- Keyboard and screen reader accessible.
- ARIA label on the video element.
# Aspect Ratios
The video player supports different aspect ratios to accommodate various video formats and use cases:
<!-- Standard 16:9 aspect ratio (default) -->
<ci-video-player src="video.mp4" aspect-ratio="16:9" />
<!-- Traditional 4:3 aspect ratio -->
<ci-video-player src="video.mp4" aspect-ratio="4:3" />
<!-- Square aspect ratio -->
<ci-video-player src="video.mp4" aspect-ratio="1:1" />
<!-- Ultra-wide 21:9 aspect ratio -->
<ci-video-player src="video.mp4" aspect-ratio="21:9" />
The component uses CSS aspect-ratio
to maintain the specified ratio regardless of the video's natural dimensions. The video will scale to fill the container while maintaining the aspect ratio.
# Error Handling
The video player displays error messages below the video player, following form field patterns for consistent styling:
<template>
<div>
<!-- Error will appear below the video player -->
<ci-video-player
src="invalid-video-url.mp4"
aria-label="Video with error"
@error="onError"
/>
</div>
</template>
<script setup>
function onError() {
console.log('Video failed to load')
}
</script>
# Error Message Styling
Error messages follow the same styling pattern as form field errors:
- Appears below the video player (not as an overlay)
- Uses error color (
$error-color
) - Small text size (
$font-size-xs
) - Left margin for alignment (
$space-xs
)
# Accessibility
- Keyboard and screen reader accessible
- Customizable ARIA label via the
ariaLabel
prop - Error messages appear below the video player following form field patterns
- Loading indicator handles its own positioning for optimal accessibility
Replace the src
prop with your own video URL as needed.