nuxt-media
v1.0.0
Published
Accessible Nuxt media players, adaptive streaming, galleries, and Media Session controllers
Readme
Nuxt Media
Accessible, SSR-safe media players and a mixed-media viewer for Nuxt 4. Progressive files use the browser directly; DASH and HLS load Shaka Player only in the client when they need it.
Requirements
- Nuxt
>=4.4.0 <5and Vue>=3.5.0 <4. - Node
^22.19.0 || ^24.11.0 || >=26.0.0. shaka-player ^5.1.12as a required peer dependency.- A browser-supported source, or a DASH/HLS source supported by Shaka Player.
Nuxt Media uses Nuxt UI, Tailwind CSS, Nuxt Image, VueUse, and Lucide internally. It inherits the consuming app's design system; it does not install a global color theme.
Install
pnpm add [email protected] shaka-player@^5.1.12// nuxt.config.ts
export default defineNuxtConfig({
modules: ["nuxt-media"],
media: {
player: {
autoplay: false,
controls: true,
loop: false,
muted: false,
playsinline: true,
preload: "metadata",
showQuality: true,
showStatus: true,
},
mediaSession: {
enabled: true,
},
viewer: {
loop: false,
maxZoom: 3,
},
},
});Nuxt Media viewer dialogs use Nuxt UI's overlay context. If the application is not already wrapped in UApp, add it once at the app root:
<!-- app.vue -->
<template>
<UApp>
<NuxtPage />
</UApp>
</template>Do not add a second nested UApp when the application already has one.
All options live under the top-level media key. Nuxt Media creates its private serialized runtime configuration; do not configure runtimeConfig.public.nuxtMedia yourself.
A 60-second example
<script setup lang="ts">
import type { MediaViewerItem } from "nuxt-media/types";
const items = [
{
id: "launch-photo",
kind: "image",
src: "/media/launch.webp",
alt: "The launch team standing beside the finished project",
thumbnail: {
src: "/media/launch-thumb.webp",
alt: "",
width: 640,
height: 426,
},
summary: "Launch day",
caption: "The team after the first production release.",
download: {
href: "/media/launch-original.jpg",
filename: "launch-day.jpg",
},
},
] satisfies MediaViewerItem[];
</script>
<template>
<main>
<MediaVideoPlayer
source="/media/demo.mp4"
poster="/media/demo-poster.webp"
/>
<MediaAudioPlayer
source="/media/interview.mp3"
title="Release interview"
artwork="/media/interview-cover.webp"
/>
<MediaViewerGallery
:items="items"
/>
</main>
</template>Native controls are enabled by default. Loading, buffering, ready, recoverable error, retry, and quality states are available without replacing the native playback UI.
The viewer isolates unexpected active-renderer failures. A failed image, player, or application-owned custom renderer shows the typed error surface while close, navigation, focus restoration, and later slides remain functional.
Choose a use case
| You need | Start here |
| --- | --- |
| Progressive MP4/WebM, DASH/HLS, qualities, captions, or player events | Video guide |
| MP3/AAC/Opus, artwork, qualities, or audio events | Audio guide |
| Image-only or mixed galleries, downloads, custom cards, maps, PDFs, or deep links | Viewer guide |
| Lock-screen metadata and controls, automatic binding, manual control, or playlists | Media Session guide |
| Every public prop, event, slot, method, composable, type, and module option | API reference |
| CORS, MIME, autoplay, streaming, SSR, or retry problems | Troubleshooting |
| Keyboard, screen reader, touch, RTL, reduced motion, and browser behavior | Accessibility and browsers |
| Upgrading from 0.1.7 | Migration to 1.0 |
The documentation index also groups common recipes by scenario.
Configuration
export default defineNuxtConfig({
modules: ["nuxt-media"],
media: {
enabled: true,
player: {
autoplay: false,
controls: true,
loop: false,
muted: false,
playsinline: true,
preload: "metadata",
showQuality: true,
showStatus: true,
labels: {},
},
shaka: {
configuration: {},
preferredAudioLanguage: "en",
preferredTextLanguage: "en",
},
mediaSession: {
enabled: true,
defaultArtwork: [],
seekOffsetSeconds: 10,
positionUpdateIntervalMs: 1000,
},
viewer: {
loop: false,
maxZoom: 3,
preloadDistance: 1,
closeOnBackdrop: true,
labels: {},
},
},
});Set media.enabled to false to make the module inert: it registers no styles, dependency modules, plugins, components, or auto-imports.
Theming and customization
Nuxt Media uses the consuming Nuxt UI and Tailwind theme. Customize a component with its root class, mediaClass for the native <video> or <audio>, typed ui parts, localized labels, and documented slots. The viewer's independent previous and next slots replace either complete navigation control; use the supplied label, disabled state, and navigate() action while retaining semantic button and focus behavior. No rose palette or other global token override is applied.
See the API reference for the complete surfaces.
Public API and support policy
Nuxt auto-imports MediaVideoPlayer, MediaAudioPlayer, MediaViewerGallery, useVideoPlayer, useAudioPlayer, and useMediaSession. Import public contracts from nuxt-media/types and runtime APIs from nuxt-media/runtime when explicit imports are preferable. The package root exports only the Nuxt module.
After the stable release, 1.x follows semantic versioning. Public APIs are the documented package exports and the components/composables registered by the module. Viewer implementation composables, raw Shaka helpers, renderer internals, and undocumented deep paths are not supported. Security fixes target the current minor release; feature and compatibility work targets supported Nuxt 4 releases.
Nuxt Media 1.0.0-rc.1 is a release candidate for the clean 1.0 API and intentionally has no 0.1.7 aliases. RC feedback may still lead to fixes before stable 1.0.0; follow the migration guide before upgrading. This repository prepares the RC but does not tag or publish it automatically.
