BunnyPlayer component with Svelte 5 runes. It renders the Bunny Player iframe, passes its events to callback props, and hands you a player.js Player for controlling playback.
SvelteKit renders it on the server without changes. The component imports player.js in onMount, since the library reads window on import, and holds the iframe back until the library is ready.
SvelteKit example on GitHub
A SvelteKit app with custom controls and an event log.
Quickstart
1
Install player.js
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
src/lib/components/BunnyPlayer.svelte
{#key src} replaces the iframe when the video changes, and the effect runs again with a fresh Player. Callback props are read inside the event handlers, which means a new inline function won’t re-create the player.3
Add your library ID
Create Declare it in
.env with the library ID from your library’s API page..env
src/env.ts. public: true lets browser code import it, and static: true inlines it at build time.src/env.ts
4
Render a video
Load the video ID in The page reads it from The library ID is public in every embed URL, so it is safe to send to the browser.
+page.server.ts.src/routes/lessons/[id]/+page.server.ts
data.src/routes/lessons/[id]/+page.svelte
params takes any player parameter, such as captions, t, or muted.Control playback
onready hands you the Player. Keep it in state for your own controls.
send() covers the gap. The build we host adds setPlaybackRate(), getPlaybackRate() and playbackratechange (Methods).
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, here through an API route.
t parameter to resume.
Load player.js from the CDN instead
To drop the npm dependency, load our hosted build from the component.src/lib/load-playerjs.ts
onMount for the loader.
src/lib/components/BunnyPlayer.svelte
Troubleshooting
ReferenceError: window is not defined
ReferenceError: window is not defined
player.js is being imported during server rendering. Keep
import("player.js") inside onMount. A static import playerjs from "player.js" at the top of the script block runs on the server in SvelteKit.onready never fires
onready never fires
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.The iframe shows a 403
The iframe shows a 403
The library’s allowed domains, direct access block, or token authentication is rejecting the embed. See Embedding restrictions.