Skip to main content
This guide builds a Vue BunnyPlayer component that renders the Bunny Player iframe, emits its events, and exposes a player.js Player for controlling playback. Nuxt can server-render it as is. player.js reads window on import, which is why the component imports it in onMounted, and the iframe waits for the library before it renders.

Vue example on GitHub

A Vite app with custom controls and an event log.

Nuxt example on GitHub

The same component in a Nuxt 4 app.

Quickstart

1

Install player.js

player.js ships without types. Add a declaration file anywhere your tsconfig.json includes, for example player.js.d.ts. It covers the methods and events the Bunny Player supports:
player.js.d.ts
2

Create the component

components/BunnyPlayer.vue
In Nuxt, save it under components/ and it’s auto-imported. Skip <ClientOnly>: the server renders the placeholder and the browser swaps in the iframe.
3

Render a video

The library ID and video GUID are on the video’s page in the dashboard.
params takes any player parameter, such as captions, t, or muted.

Control playback

The ready event carries the Player. Keep it in a shallowRef, which stops Vue wrapping it in a deep reactive proxy.
Getters answer through a callback, since the value comes back from the iframe.
Playback speed is missing from the npm build (0.1.0), and send() covers the gap. The build we host adds setPlaybackRate(), getPlaybackRate() and playbackratechange (Methods).
Browsers block unmuted play() before the viewer has clicked anything. Call mute() first if playback has to start on its own. The Playback control API lists every method and event.

Track progress

timeupdate fires several times a second. Throttle it before it reaches your backend.
Pass the saved position back as the t parameter to resume.

Load player.js from the CDN instead

To drop the npm dependency, load our hosted build from the component.
lib/load-playerjs.ts
Swap the dynamic import in onMounted for the loader.
components/BunnyPlayer.vue

Troubleshooting

player.js is being imported during server rendering. Keep import("player.js") inside onMounted. A static import playerjs from "player.js" at the top of <script setup> runs on the server in Nuxt.
The iframe loaded before player.js. Render it only once player.js has loaded, as the component above does.A hidden tab also holds ready back until the viewer switches to it.
Nuxt parses NUXT_PUBLIC_* variables as it loads them, and a numeric library ID such as 12345 arrives as a number. Convert the IDs to strings first.
The library’s allowed domains, direct access block, or token authentication is rejecting the embed. See Embedding restrictions.
Last modified on October 7, 2026