Player APIListen to events
Listen to events
Subscribe to lifecycle events with on, once and off.
The Moviie Player emits a stable set of events that mirror the underlying playback lifecycle. Use them to drive analytics, sync your UI with the viewer's actions, or trigger downstream behaviour.
Subscribing
Use on(event, handler) to subscribe and off(event, handler) to
unsubscribe. on returns an unsubscribe function for convenience.
const unsubscribe = window.Moviie.on("play", () => {
console.log("playback started")
})
// later
unsubscribe()For one-shot subscriptions (e.g. waiting for the first ready event),
prefer once:
window.Moviie.once("ready", () => {
console.log("player ready")
})Reading payloads
Some events carry a payload — see the table below for the exact shape.
window.Moviie.on("timeupdate", ({ currentTime }) => {
progressBar.value = currentTime
})Events without a documented payload fire with no arguments.
Event reference
| Event | Payload | Description |
|---|---|---|
| readyonce | — | Fires once per session when the player has loaded enough metadata to begin playback. Use this to register listeners that depend on the player being initialised. |
| play | — | Fires every time playback starts or resumes after being paused. |
| pause | — | Fires every time playback is paused, including when the viewer reaches the end. |
| ended | — | Fires when playback reaches the end of the video. Pair with `pause` if you also need to react to manual pauses. |
| waiting | — | Fires when the player stalls waiting for more data — typically a buffering condition on slow networks. |
| playing | — | Fires when playback resumes after a `waiting` event. |
| timeupdate | { currentTime: number } | Fires periodically (~250ms) while the video is playing. Throttle any heavy work — this is the highest-frequency event. |
| durationchange | { duration: number } | Fires when the duration becomes available or changes (e.g. live stream metadata refresh). |
| seeking | { from: number; to: number } | Fires when a seek operation starts. |
| seeked | { currentTime: number } | Fires when a seek operation completes and playback can resume. |
| volumechange | { volume: number; muted: boolean } | Fires when the volume level or muted state changes. |
| fullscreenenter | — | Fires when the player enters fullscreen mode. |
| fullscreenexit | — | Fires when the player exits fullscreen mode. |
| pipenter | — | Fires when the player enters Picture-in-Picture mode. |
| pipexit | — | Fires when the player exits Picture-in-Picture mode. |
| qualitychange | { quality: string } | Fires when the active video quality changes — either by viewer choice or by the adaptive bitrate logic. |
| loadstart | — | Fires when the player begins loading the video manifest. |
| canplay | — | Fires when enough data has been buffered to begin playback. |
| progress | { buffered: number } | Fires when the buffered range advances. |
| error | { code: string; message: string } | Fires when an error occurs during loading or playback. The payload exposes a stable error code and a localized message. |
| ctashow | { id: string } | Fires when a call-to-action overlay becomes visible. |
| ctahide | { id: string } | Fires when a call-to-action overlay is dismissed. |
| ctaclick | { id: string; href: string } | Fires when a viewer clicks a call-to-action overlay. |
Tips
- Throttle high-frequency handlers —
timeupdatefires every ~250ms. Coalesce expensive work (analytics flushes, layout reads) before reacting. - Always unsubscribe — long-lived listeners outlive the player when
you destroy and recreate the embed (e.g. between routes). Call
unsubscribe()oroff(event, handler)in your cleanup path. - Combine with
getState()— events tell you when something happens;getState()tells you what the player looks like at that moment. See getState.