Skip to content
Sponsored by

MagicPlayer

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

Poster
<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

vue
<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.

js
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.

js
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.

js
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

sh
pnpm install @nuxt/kit @vueuse/core defu hls.js
sh
npm install @nuxt/kit @vueuse/core defu hls.js
sh
yarn add @nuxt/kit @vueuse/core defu hls.js
sh
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

PropTypeRequired
id
MaybeRef<string>true
options
MagicPlayerOptionsfalse

Options

To customize the player override the necessary options. Any custom options will be merged with the default options.

OptionTypeDefault
src
string
mode
PlayerMode
video
srcType
string
native
preload
string
metadata
autoplaybooleanfalse
playback
string[]
['viewport'] | ['viewport', 'window']
loop
booleanfalse
transition.videoControls
stringmagic-player-video-controls
transition.overlay
stringmagic-player-overlay
transition.icons
stringmagic-player-icons

CSS Variables

VariableDefault
--magic-player-provider-heightauto
--magic-player-provider-aspect-ratio16 / 9
--magic-player-provider-background#000

MagicPlayerOverlay

CSS Variables

VariableDefault
--magic-player-overlay-backgroundrgba(0, 0, 0, 0.3)
--magic-player-overlay-colorrgba(255, 255, 255, 1)
--magic-player-overlay-button-size2rem

MagicPlayerVideoControls

Props

PropTypeRequired
id
MaybeRef<string>false
standalone
booleanfalse
transition.overlay
stringfalse
transition.icons
stringfalse

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.

css
@import '@maas/vue-equipment/MagicPlayer/css/magic-player-video-controls.css';

MagicPlayerMuxPopover

Props

PropTypeRequired
playbackId
stringfalse

CSS Variables

VariableDefault
--magic-player-popover-border-radius0.25rem

MagicPlayerAudioControls

Props

PropTypeRequired
id
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.

css
@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

PropTypeRequired
type
string
false

Examples

Audio Player

Loveless
0:00
0:00
<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

Poster
<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

Poster
<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>