MagicPlayer
MagicPlayer is a collection of components made to build a flexible, streaming ready media player for video as well as audio playback.

<template>
<div class="aspect-[16/9] w-full">
<magic-player-provider
id="magic-player-default-demo"
:options="{
src: 'https://stream.mux.com/3wVFr42nN3VqIVv01ugl00oSJTzKlhsZ01ep2yKz5vqeZ8.m3u8',
srcType: 'hls',
}"
>
<magic-player-video />
<magic-player-poster>
<magic-player-provider
id="magic-player-default-demo-poster"
:options="{
src: 'https://stream.mux.com/kj7uNjRztuyNotBkAI55oUeVKSSN1C4ONrIYuYcRKxo/highest.mp4',
autoplay: true,
loop: true,
}"
>
<magic-player-video />
<magic-player-poster>
<img
src="https://image.mux.com/kj7uNjRztuyNotBkAI55oUeVKSSN1C4ONrIYuYcRKxo/thumbnail.png?time=0"
alt="Poster"
/>
</magic-player-poster>
</magic-player-provider>
</magic-player-poster>
<magic-player-overlay />
<magic-player-video-controls>
<template #popover>
<magic-player-mux-popover />
</template>
</magic-player-video-controls>
</magic-player-provider>
</div>
</template>
<style>
@import '@maas/vue-equipment/plugins/MagicPlayer/css/magic-player-video-controls.css';
</style>
Overview
Anatomy
<template>
<magic-player-provider id="your-player-id" src="your-src.m3u8">
<magic-player-video />
<magic-player-poster>
<!-- your content -->
</magic-player-poster>
<magic-player-overlay />
<magic-player-video-controls>
<template #seek-popover>
<magic-player-mux-popover />
</template>
</magic-player-video-controls>
</magic-player-provider>
</template>
<script>
const { playerApi } = useMagicPlayer('your-player-id')
</script>
<style>
@import '@maas/vue-equipment/MagicPlayer/css/magic-player-video-controls.css';
</style>
Overview
Vue
If you are using Vue, import and add MagicPlayerPlugin
to your app.
import { createApp } from 'vue'
import { MagicPlayerPlugin } from '@maas/vue-equipment/plugins'
const app = createApp({})
app.use(MagicPlayerPlugin)
Nuxt
The player is available as a Nuxt module. In your Nuxt config file add @maas/vue-equipment/nuxt
to your modules and add MagicPlayer
to the plugins in your configuration.
export default defineNuxtConfig({
modules: ['@maas/vue-equipment/nuxt'],
vueEquipment: {
plugins: ['MagicPlayer'],
},
})
Composable
In order to interact with the player from anywhere within your app, we provide a useMagicPlayer
composable. Import it directly when needed.
import { useMagicPlayer } from '@maas/vue-equipment/plugins'
const { playerApi } = useMagicPlayer('your-player-id')
function handleClick() {
playerApi.play()
}
TIP
If you have installed the component as a Nuxt module, the composable will be auto-imported and is automatically available in your Nuxt app.
Peer Dependencies
If you haven’t installed the required peer dependencies automatically, you’ll need to install the following packages manually.
Installation
pnpm install @nuxt/kit @vueuse/core defu hls.js
npm install @nuxt/kit @vueuse/core defu hls.js
yarn add @nuxt/kit @vueuse/core defu hls.js
bun install @nuxt/kit @vueuse/core defu hls.js
API Reference
MagicPlayerProvider
The MagicPlayerProvider wraps the menu and configures all child components according to the provided options.
Props
Prop | Type | Required |
---|---|---|
MaybeRef<string> | true | |
MagicPlayerOptions | false |
Options
To customize the player override the necessary options. Any custom options will be merged with the default options.
Option | Type | Default |
---|---|---|
string | – | |
mode | video | |
native | ||
preload | metadata | |
autoplay | boolean | false |
boolean | false | |
string | magic-player-video-controls | |
string | magic-player-overlay | |
string | magic-player-icons |
CSS Variables
Variable | Default |
---|---|
--magic-player-provider-height | auto |
--magic-player-provider-aspect-ratio | 16 / 9 |
--magic-player-provider-background | #000 |
MagicPlayerOverlay
CSS Variables
Variable | Default |
---|---|
--magic-player-overlay-background | rgba(0, 0, 0, 0.3) |
--magic-player-overlay-color | rgba(255, 255, 255, 1) |
--magic-player-overlay-button-size | 2rem |
MagicPlayerVideoControls
Props
Prop | Type | Required |
---|---|---|
MaybeRef<string> | false | |
boolean | false | |
string | false | |
string | false |
CSS
Due to their complexity and opinionated nature, we have externalized the styles for this component. Make sure to import them if needed. If not style the component manually.
@import '@maas/vue-equipment/MagicPlayer/css/magic-player-video-controls.css';
MagicPlayerMuxPopover
Props
Prop | Type | Required |
---|---|---|
string | false |
CSS Variables
Variable | Default |
---|---|
--magic-player-popover-border-radius | 0.25rem |
MagicPlayerAudioControls
Props
Prop | Type | Required |
---|---|---|
MaybeRef<string> | false |
CSS
Due to their complexity and opinionated nature, we have externalized the styles for this component. Make sure to import them if needed. If not style the component manually.
@import '@maas/vue-equipment/MagicPlayer/css/magic-player-audio-controls.css';
MagicPlayerDisplayTime
This component is used internally by both the video and audio controls components. You are most likely not going to need it directly, unless you want to implement your own custom controls.
Props
Prop | Type | Required |
---|---|---|
type | false |
Examples
Audio Player
<template>
<div class="w-full">
<magic-player-provider
id="magic-player-audio-demo"
:options="{ mode: 'audio', src: '/demo/magic-player/loveless.mp3' }"
class="bg-surface-elevation-high rounded-surface-sm flex flex-col gap-2 p-2"
>
<span
class="bg-surface-elevation-base rounded-surface-sm-inset type-surface-callout-md block w-full p-4"
>
Loveless
</span>
<magic-player-audio-controls class="px-4" />
<magic-player-audio />
</magic-player-provider>
</div>
</template>
<style>
@import '@maas/vue-equipment/plugins/MagicPlayer/css/magic-player-audio-controls.css';
</style>
Autoplay
<template>
<div class="aspect-[16/9] w-full">
<magic-player-provider
id="magic-player-autoplay-demo"
:options="{
autoplay: true,
loop: true,
src: 'https://stream.mux.com/kj7uNjRztuyNotBkAI55oUeVKSSN1C4ONrIYuYcRKxo/highest.mp4',
}"
>
<magic-player-video />
</magic-player-provider>
</div>
</template>
Autoplay with Controls
<template>
<div class="aspect-[16/9] w-full">
<magic-player-provider
id="magic-player-autoplay-controls-demo"
:options="{
src: 'https://stream.mux.com/3wVFr42nN3VqIVv01ugl00oSJTzKlhsZ01ep2yKz5vqeZ8.m3u8',
srcType: 'hls',
autoplay: true,
}"
>
<magic-player-video />
<magic-player-overlay />
<magic-player-video-controls>
<template #popover>
<magic-player-mux-popover />
</template>
</magic-player-video-controls>
</magic-player-provider>
</div>
</template>
<style>
@import '@maas/vue-equipment/plugins/MagicPlayer/css/magic-player-video-controls.css';
</style>
Controls without Overlay
<template>
<div class="aspect-[16/9] w-full">
<magic-player-provider
id="magic-player-omit-overlay-demo"
:options="{
src: 'https://stream.mux.com/3wVFr42nN3VqIVv01ugl00oSJTzKlhsZ01ep2yKz5vqeZ8.m3u8',
srcType: 'hls',
}"
>
<magic-player-video />
<magic-player-video-controls>
<template #popover>
<magic-player-mux-popover />
</template>
</magic-player-video-controls>
</magic-player-provider>
</div>
</template>
<style>
@import '@maas/vue-equipment/plugins/MagicPlayer/css/magic-player-video-controls.css';
</style>
Standalone Controls

<template>
<div class="flex w-full flex-col">
<magic-player-provider
id="magic-player-standalone-controls-demo"
:options="{
src: 'https://stream.mux.com/3wVFr42nN3VqIVv01ugl00oSJTzKlhsZ01ep2yKz5vqeZ8.m3u8',
srcType: 'hls',
}"
>
<magic-player-video />
<magic-player-poster>
<img
src="https://image.mux.com/3wVFr42nN3VqIVv01ugl00oSJTzKlhsZ01ep2yKz5vqeZ8/thumbnail.jpg?time=4"
alt="Poster"
/>
</magic-player-poster>
<magic-player-overlay />
</magic-player-provider>
<div class="relative flex w-full items-center pt-4">
<magic-player-video-controls
id="magic-player-standalone-controls-demo"
class="bg-black"
standalone
>
<template #timeline-before>
<magic-player-display-time type="current" />
</template>
<template #timeline-after>
<magic-player-display-time type="duration" />
</template>
</magic-player-video-controls>
</div>
</div>
</template>
<style>
@import '@maas/vue-equipment/plugins/MagicPlayer/css/magic-player-video-controls.css';
</style>
Native Controls
<template>
<div class="aspect-[16/9] w-full">
<magic-player-provider
id="magic-player-native-controls-demo"
:options="{
src: 'https://stream.mux.com/3wVFr42nN3VqIVv01ugl00oSJTzKlhsZ01ep2yKz5vqeZ8.m3u8',
srcType: 'hls',
}"
>
<magic-player-video controls />
</magic-player-provider>
</div>
</template>
Poster Image

<template>
<div class="aspect-[9/16] w-full">
<magic-player-provider
id="magic-player-image-poster-demo"
:style="{ '--magic-player-provider-aspect-ratio': '9/16' }"
:options="{
src: 'https://stream.mux.com/PniSBG6rbyou2x5jExB9EwYQAgBXGyqxXA023GC6JeXQ/highest.mp4',
}"
>
<magic-player-video />
<magic-player-poster>
<img
src="https://image.mux.com/PniSBG6rbyou2x5jExB9EwYQAgBXGyqxXA023GC6JeXQ/thumbnail.jpg?time=8"
alt="Poster"
/>
</magic-player-poster>
<magic-player-overlay />
</magic-player-provider>
</div>
</template>
Composable
<template>
<div class="flex w-full flex-col items-center gap-4">
<div class="aspect-[16/9] w-full">
<magic-player-provider
id="magic-player-composable-demo"
:options="{
autoplay: true,
loop: true,
src: 'https://stream.mux.com/kj7uNjRztuyNotBkAI55oUeVKSSN1C4ONrIYuYcRKxo/highest.mp4',
}"
>
<magic-player-video />
</magic-player-provider>
</div>
<div class="flex gap-4">
<m-button @click="playerApi.videoApi.togglePlay()">
Toggle Play
</m-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { useMagicPlayer } from '@maas/vue-equipment/plugins'
const playerApi = useMagicPlayer('magic-player-composable-demo')
</script>