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.
unmute is emitted once when the viewer first activates audible playback in
an autoplay-muted session. Muting and unmuting again does not create another
funnel engagement event for the same telemetry session. It is an observable
player event; it does not expose viewer identity or conversion data.
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. |
| unmute | { volume: number } | Fires once when the viewer activates audible playback. |
| 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. |
| ctaimpression | { ctaId: string } | Fires after a call-to-action is at least 50% visible for 500ms. |
| ctaclick | { id: string; href: string } | Fires when a viewer clicks a call-to-action overlay. |
| searchopen | — | Fires when the in-player search field opens. |
| searchclose | — | Fires when the in-player search field closes. |
| aimenuopen | — | Fires when the AI features menu opens. |
| aimenuclose | — | Fires when the AI features menu closes. |
| quizopen | — | Fires when the interactive quiz panel opens. |
| quizclose | — | Fires when the interactive quiz panel closes. |
| quizcomplete | { correct: number, incorrect: number, total: number } | Fires when the viewer answers every question and the quiz summary is shown. |
| variantchange | { variantId: string | null } | Fires when the active playback variant changes — e.g. switching between the full-length video and a condensed "Versão Express". |
| summaryopen | — | Fires when the in-player AI summary panel opens. |
| summaryclose | — | Fires when the in-player AI summary panel closes. |
| ebookopen | — | Fires when the in-player AI ebook panel opens. |
| ebookclose | — | Fires when the in-player AI ebook panel closes. |
| tutoropen | { tutorId?: string | null } | Fires when the in-player AI tutor chat opens. |
| tutorclose | { tutorId?: string | null } | Fires when the in-player AI tutor chat closes. |
| tutormessage | { tutorId: string; messageId?: string; role: "user" | "assistant"; content?: string; references?: PlayerTutorReference[] } | Fires when the viewer sends a tutor message or receives a streamed answer. |
| tutorerror | { tutorId?: string | null; code: string; message: string } | Fires when the tutor cannot answer from the selected video knowledge. |
| soundhookshow | { template: string; custom: boolean; banner: boolean } | Fires when the sound activation prompt takes over a muted autoplay. |
| soundhookdismiss | { template: string; action: "unmute" | "restart" } | Fires when the viewer dismisses the sound prompt by activating audio. |
| clickgateshow | void | Fires when the browser refused autoplay and the click-to-play prompt is shown. |
| clickgateplay | void | Fires when the viewer starts playback from the click-to-play prompt. |
| resumegateshow | { kind: PlayerResumeGateKind; position: number } | Fires when a returning viewer is offered the position where they stopped. |
| resumegatechoice | { action: PlayerResumeChoice; position: number } | Fires when the returning viewer resolves the resume prompt. |
| pauseboostshow | { slot: PlayerPauseBoostSlot } | Fires when the pause offer takes over the frame. |
| pauseboosthide | { slot: PlayerPauseBoostSlot } | Fires when the pause offer is dismissed and the video is available again. |
| sessionidleshow | { position: number } | Fires when a long-idle session is paused and asks the viewer to continue. |
| sessionidleresume | { position: number } | Fires when the viewer resumes an idle session from the exact position. |
| blockingshow | { cause: PlayerBlockingCause } | Fires when a blocking screen replaces the player and states the cause. |
| bufferingshow | { afterMs: number } | Fires when playback stalls long enough to show the loading indicator. |
| bufferinghide | { afterMs: number } | Fires when playback resumes and the loading indicator is dismissed. |
| preciseseekenter | { via: PlayerPreciseSeekEntry } | Fires when the viewer enters precise seek with the thumbnail strip. |
| preciseseekexit | { committed: boolean } | Fires when the viewer leaves precise seek. |
| settingsopen | void | Fires when the settings menu opens. |
| settingsclose | void | Fires when the settings menu closes. |
| chromevisibilitychange | { visible: boolean } | Fires when the controls auto-hide during playback or come back. |
| minihookexpire | void | Fires when the countdown chip reaches zero. |
| mindmapopen | void | Fires when the mind map opens. |
| mindmapclose | void | Fires when the mind map closes. |
| dubbingchange | { track: string; kind: PlayerDubbingKind } | Fires after the active audio track changes, preserving position and play state. |
| drminfoopen | void | Fires when the viewer opens the content-protection explanation. |
| drminfoclose | void | Fires when the content-protection explanation is closed. |
| drmstamprestored | { reason: PlayerDrmTamper; count: number } | Fires when the mark was interfered with and the player put it back. |
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.