Media player
Plays video and audio files with a single control bar that matches the theme, instead of the built-in controls that differ from browser to browser: play/pause, seek bar, time, volume, speed, and full screen. If JavaScript does not run, the browser's own controls appear and the file can still be played.
Video
src is the file to play, poster is the image shown before playback starts, and title is the player's name for screen readers. The frame fills the width of its container at a 16:9 ratio; for a different ratio, pass class="aspect-square" or class="aspect-[4/3]". Clicking the video plays or pauses it. During playback, the controls disappear if the mouse does not move for a few seconds; moving the mouse over the player or moving to a control with the keyboard brings them back.
<acun:media-player
src="../assets/media/sample-video.mp4"
poster="../assets/media/sample-poster.jpg"
title="Intro video"
/>
| Prop | Values |
|---|---|
src | File URL |
poster | Cover image (video only) |
title | Screen reader name; default "Video player" |
Audio
With audio, the player turns into a single-row bar: play button, elapsed time, seek bar, total time, volume, and speed. As the space gets narrower, the volume slider is hidden first, then the speed selector; this is decided by the width of the player itself, not the screen, so it also looks right in a narrow side column. It adapts to the light and dark themes. The audio layout has no cover image, full screen, or captions button.
<acun:media-player audio src="../assets/media/sample-audio.wav" title="Chord sample" />
| Prop | Values |
|---|---|
audio | true | false |
title | Screen reader name; default "Audio player" |
Captions and sources
Write WebVTT caption files inside the component as <track> elements. If there is a track of kind captions or subtitles, a captions button appears in the control bar; the track marked default is shown when the page opens. If several tracks are given, the button turns the default one on and off, or the first one if none is marked. The player draws the captions itself: they sit above the control bar and move down when the bar hides. To offer the same video in several formats, pass sources instead of src; the browser plays the first file in the list that it supports.
<acun:media-player
:sources="[
['src' => '../assets/media/sample-video.webm', 'type' => 'video/webm'],
['src' => '../assets/media/sample-video.mp4', 'type' => 'video/mp4'],
]"
poster="../assets/media/sample-poster.jpg"
title="Intro with captions"
>
<track kind="captions" src="../assets/media/sample-captions-tr.vtt" srclang="tr" label="Turkish" default>
</acun:media-player>
| Prop | Values |
|---|---|
sources | [['src' => …, 'type' => 'video/webm'], …] or a plain array of URLs |
(content) | <track> elements; the track marked default starts on |
Keyboard and accessibility
While focus is inside the player (after clicking the video or tabbing to a control), Space or K plays and pauses, ← → skip back or forward five seconds, ↑ ↓ change the volume by 10%, M mutes and unmutes, F switches to full screen, C turns captions on and off, and Home and End jump to the start or the end. On the volume slider the arrow keys, and on the speed selector all keys, do that control's own job. The screen reader names of the buttons change with the state ("Play" / "Pause", "Mute" / "Unmute", "Full screen" / "Exit full screen"); the seek bar announces its value in the form "1:05 / 3:20". Focus rings are always visible while navigating with the keyboard; if reduced motion is turned on in the operating system, transition animations are turned off. speeds sets the values in the speed selector, and muted and loop are passed to the media element as they are.
<acun:media-player
src="../assets/media/sample-video.mp4"
poster="../assets/media/sample-poster.jpg"
title="Keyboard test"
:speeds="[1, 1.5, 2]"
muted
loop
/>
| Prop | Values |
|---|---|
speeds | Speed list, e.g. [1, 1.5, 2]; [] removes the speed selector |
muted · loop · autoplay | Passed to the media element; browsers usually block autoplay with sound |
Inside Livewire
The component's root has wire:ignore: when another part of the page updates, Livewire leaves the player alone, playback is not interrupted, and the browser's built-in controls do not come back. To change the source, give the player a wire:key that changes with the source; Livewire removes the old player and adds the new one. Media events such as ended, play, and pause do not bubble, so add listeners to the root with .capture; in the example, a method of the component is called when the video ends. Extra attributes such as id, class, wire:key, x-on:*, and data-* are added to the root element.
<div>
<acun:media-player
:src="$lesson->video_url"
:poster="$lesson->cover_url"
:title="$lesson->title"
wire:key="lesson-video-{{ $lesson->id }}"
x-on:ended.capture="$wire.markCompleted()"
/>
<acun:button wire:click="nextLesson" class="mt-4">Next lesson</acun:button>
</div>
Props and slots
The values the component accepts.
| Prop | Default | Description |
|---|---|---|
src | null | URL of the media file |
sources | [] | Several formats: [['src' => …, 'type' => 'video/mp4'], …] or a plain array of URLs; the browser plays the first one it supports |
poster | null | Image shown before playback starts (video only) |
audio | false | A single-row audio bar instead of the video frame |
title | null | Screen reader name; if omitted, "Video player" or "Audio player" |
preload | metadata | none | metadata | auto; passed to the media element |
autoplay | false | Starts playing when the page opens; most browsers block autoplay with sound, so use it with muted |
muted | false | Starts muted |
loop | false | Starts over when it ends |
speeds | [0.5, 0.75, 1, 1.25, 1.5, 2] | Values in the speed selector; [] hides the speed selector |
(attributes) | — | id, class, wire:key, x-on:*, data-* … are added to the root element (class is merged); if class contains aspect-*, the 16:9 ratio is not applied |