Player object for talking to it over postMessage. This guide builds a BunnyPlayer component that renders the iframe, forwards its events, and hands you that object.
The examples assume a client-rendered app, such as one built with Vite. For server rendering, including Remix and React Router framework mode, follow the Next.js guide.
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
The component builds the embed URL, renders the iframe, and creates a
Player once the iframe is in the DOM. Callbacks are read through a ref, so inline props don’t re-create the player on every render.components/bunny-player.tsx
3
Render a video
Pass the library ID and video GUID from the video’s page in the dashboard:
params accepts any player parameter, such as captions, t, or muted.Control playback
onReady hands you the Player. Keep it in state and call its methods from your own controls:
player.js package on npm has no playback speed method, so send the command directly. The build bunny.net hosts adds setPlaybackRate() and getPlaybackRate(); see Methods.
play() until the viewer has interacted with the page, so call player.mute() first if playback has to start without a click. Playback control API lists every method and event.
Track progress
timeupdate fires several times a second with { seconds, duration }. Throttle it before writing to your backend:
params={{ t: savedSeconds }} to resume from there.
Multiple players on one page
player.js matches theready message to an iframe by its src, so two iframes with identical URLs confuse it. Give each one a parameter the player ignores:
Load player.js from the CDN instead
To skip the npm dependency, load the build bunny.net hosts:index.html
<head> so it has loaded before your components mount. Replace import playerjs from "player.js" with const playerjs = window.playerjs and declare the global:
Troubleshooting
onReady never fires
onReady never fires
The
Player has to exist before the iframe finishes loading. Creating it in useEffect in the render that mounts the iframe is early enough in a client-rendered app. Server-rendered iframe HTML can finish loading before your JavaScript runs; the Next.js guide handles that case.Events fire twice after changing the video
Events fire twice after changing the video
Every
Player adds a message listener to window that is never removed. The active flag in the effect cleanup keeps stale instances quiet, so check that yours flips 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.