Skip to content

Instance Events ​

Player events are divided into two types: native events of the video (prefixed with video:), and custom events.

Listening to events:

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('video:canplay', () => {
    console.info('video:canplay');
});

Listening to an event only once:

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.once('video:canplay', () => {
    console.info('video:canplay');
});

Manually triggering an event:

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.emit('focus');

Removing an event:

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

const onReady = () => {
    console.info('ready');
    art.off('ready', onReady);
}

art.on('ready', onReady);

For a complete list of events, please refer to:

artplayer/types/events.d.ts

Subscription and synchronous dispatch ​

Players inherit Artplayer.Emitter. on(name, callback, ctx?), once, off, and emit(name, ...args) all return the current instance. They are neither DOM addEventListener nor a Promise-based message queue.

  • on keeps registration order. Registering the same function twice invokes it twice. ctx is passed unchanged as an ordinary function's this; omission means undefined, not an automatic player binding. Arrows retain their lexical this.
  • emit synchronously walks a snapshot taken at dispatch start. Added listeners wait until a later dispatch; removed ordinary listeners already in the snapshot still run. Arguments retain their references; callback return values are ignored.
  • once removes itself before invoking the callback and prevents nested dispatch from consuming the same registration twice, even if the callback throws. off(name, callback) removes all ordinary/once registrations for that function regardless of ctx; off(name) removes every listener for the name.
  • A synchronous throw stops subsequent listeners in that dispatch and propagates through the call stack. Async callbacks are not awaited; handle their failures yourself. The name error has no special Node EventEmitter behavior.
  • e is the lazily created registry of fn/ctx records and remains a visible historical interface. A fresh standalone Emitter may not have it yet. Use on/off rather than editing the table. Numeric keys share their string-equivalent channel; symbols have separate keys. The root player's historical overloads accept narrower names than the accurate entry or a generic Emitter.

Manual emit only sends a notification; it does not replace player methods. Emitting built-in names may also trigger internal listeners. Destruction releases core-owned DOM/internal subscriptions but does not clear every user registration; remove unwanted subscriptions if you retain the instance. The advanced-properties guide explains the separate DOM listener manager, art.events.

Native forwarding ​

The default media events below are forwarded with a video: prefix and the original Event object. The browser or proxy determines when they occur:

abort, canplay, canplaythrough, durationchange, emptied, ended, error, loadeddata, loadedmetadata, loadstart, pause, play, playing, progress, ratechange, seeked, seeking, stalled, suspend, timeupdate, volumechange, waiting.

The video:error argument is not a MediaError or Error instance; inspect art.video.error when needed. Historical types include video:complete and video:encrypted, but neither appears in the default config.events, so the core does not automatically forward them. An adapter must provide forwarding or configure the event inventory before construction. A declared name does not prove an event is produced at runtime.

Global forwarding uses the player's currently bound document/window and passes the original Event:

PrefixDefault names
document:click, mouseup, keydown, touchend, touchcancel, touchmove, mousemove, pointerup, contextmenu, pointermove, visibilitychange, webkitfullscreenchange
window:resize, scroll, orientationchange

These are not restricted to interactions inside the player. events.bindGlobalEvents can rebind them to the owning window. Destruction stops native forwarding. Arguments preserve native subtypes such as KeyboardEvent/MouseEvent; forwarding does not guarantee that a browser produces every event.

Custom payloads and timing ​

Internal and user listeners share synchronous dispatch. Internal listeners registered during construction can emit a custom event before later user listeners receive the native forwarding event. Do not assume one total ordering across all browsers and proxies.

Media and lifecycle ​

EventPayload and actual stage
readyNo arguments; once in the first successfully handled video:canplay, after isReady is set. Does not wait for async plugins, subtitles, or SDKs
restartSubmitted URL; for a ready player with an existing URL, the active source change emits at canplay when the actual media URL changed. Assigning the same URL need not emit it
playNo arguments; art.play emits after the media play call succeeds while its operation remains current. Direct video.play does not generate this custom event, though native video:play can occur
pauseNo arguments; art.pause emits synchronously after calling media pause and updating the notice, even if already paused. Separate from video:pause
destroyNo arguments; after native resources/template cleanup, instance removal, and setting isDestroy true. Do not assume mounted DOM inside the callback; destroy(false) separately preserves DOM
errorOriginal error value and retry count; emitted when reconnection submits a retry after waiting, not on every native error or every async failure
seekcurrentTime after assignment and the original requested time (number or string), not native seeked completion
mutedBoolean supplied to art.muted, including repeated assignments. Observe video:volumechange for direct video.muted changes
screenshotPNG data URI after image capture and an attempted download, not proof a file was saved. getDataURL/getBlobUrl alone do not emit it
airplayNo arguments; after invoking an available native picker, not confirmation of remote connection or playback
rafNo arguments; emitted during playback when USE_RAF was enabled before construction. Not a decoded-video-frame callback

UI and input ​

EventPayload and actual stage
info, layer, loading, mask, subtitle, contextmenu, control, settingBoolean assigned to show; repeated identical assignments can emit again. Not animation completion
focus / blurOriginal document click/contextmenu event, classified by whether its path includes the player. Not DOM focus/blur; can emit even without a state change
click / dblclickVideo click event. Double-click is counted within DBCLICK_TIME; the first click emits immediately, before playback/fullscreen actions
hoverEnter/leave boolean and original mouseenter/mouseleave event
mousemoveMouseEvent from the player node, not throttled document coordinates
hotkeyKeyboardEvent after matching shortcut callbacks, subject to focus/input filtering
keydownKeyboardEvent after desktop shortcut dispatch, even without a matching key or player focus. Mobile does not automatically install this shortcut dispatcher; use document:keydown for the raw global event
resizeNo arguments; window debounce, metadata, display-mode changes, or explicit layout paths, not just window:resize
viewViewport-intersection boolean after leading scroll throttling, not complete visibility or occlusion detection
lockBoolean after the built-in lock plugin updates state, not an observer of direct isLock assignment
setBarType, fraction, and optional original mouse/touch event. Built-in types are loaded/played/hover; programmatic and keyboard updates may omit the third argument. A progress UI protocol, not playback completion

Size, display, and subtitles ​

EventPayload and actual stage
aspectRatio / flipString after the setter normalizes an empty value; not necessarily a member of the built-in selector list
autoHeight / autoSizeHeight number / {width, height} after valid media dimensions allow layout. No event when calculation is unavailable
fullscreen / fullscreenWeb / mini / pipBoolean from the display adapter's observation or transition. Duplicate-assignment behavior varies by mode; not a universal replacement for request completion
fullscreenErrorOwned native fullscreen error event/adapter value. A request Promise rejection may instead only update the notice; this does not collect every fullscreen failure
subtitleOffsetOriginal requested offset; stored offset clamps to[-10,10]. No event without cues
subtitleBeforeUpdate / subtitleAfterUpdateCue arrays, not individual cues, synchronously before/after rendering. Neither emits without active cues
subtitleLoadCurrent cue array and the subtitle manager's current options (possibly null), after native track load. Not an alias for switch fulfillment

TypeScript event views ​

The root entry retains historical declarations and custom augmentation: video:error was typed as Error and subtitle updates as one VTTCue. It also has array overloads through SubtitleUpdateEvents. Use artplayer/runtime for accurate contextual inference: Event for native media payloads, SubtitleCue arrays for updates, unknown for error/fullscreenError, and a string-capable second seek argument. Unknown custom events retain unknown arrays without runtime payload validation. A generic Emitter can declare its own event tuples:

ts
import Artplayer from 'artplayer/runtime';
import type { Events, SubtitleCue } from 'artplayer/runtime';

const bus = new Artplayer.Emitter<{ progress: [value: number] }>();
const context = { total: 0 };
bus.on('progress', function (value) { this.total += value; }, context);
bus.emit('progress', 2);

const art = new Artplayer({ container: '.artplayer-app', url: '/assets/sample/video.mp4' });
art.on('video:error', (event: Event) => console.info(event.type));
art.on('subtitleBeforeUpdate', (cues: SubtitleCue[]) => console.info(cues.length));
const seekArgs: Events['seek'] = [0, '0'];
void seekArgs;

ready ​

Triggered when the player is ready for the first time.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('ready', () => {
    console.info('ready');
});

restart ​

Triggered when the player switches URLs and becomes ready to play.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('ready', () => {
    art.url = '/assets/sample/video.mp4'
});

art.on('restart', (url) => {
    console.info('restart', url);
});

pause ​

Triggered when the player is paused.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('pause', () => {
    console.info('pause');
});

play ​

Triggered when the player starts playing.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('play', () => {
    console.info('play');
});

hotkey ​

Triggered when a player hotkey is pressed.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('hotkey', (event) => {
    console.info('hotkey', event);
});

destroy ​

Triggered when the player is destroyed.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('ready', () => {
    art.destroy();
});

art.on('destroy', () => {
    console.info('destroy');
});

focus ​

Triggered when the player gains focus.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('focus', (event) => {
    console.info('focus', event);
});

blur ​

Triggered when the player loses focus.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('blur', (event) => {
    console.info('blur', event);
});

dblclick ​

Triggered when the player is double-clicked.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('dblclick', (event) => {
    console.info('dblclick', event);
});

click ​

Triggered when the player is clicked.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('click', (event) => {
    console.info('click', event);
});

error ​

Triggered when an error occurs while the player is loading a video.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/404.mp4',
});

art.on('error', (error, reconnectTime) => {
    console.info(error, reconnectTime);
});

hover ​

Triggered when the mouse enters or leaves the player.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('hover', (state, event) => {
    console.info('hover', state, event);
});

mousemove ​

Triggered when the mouse moves over the player.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('mousemove', (event) => {
    console.info('mousemove', event);
});

resize ​

Triggered when the player's dimensions change.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('resize', () => {
    console.info('resize');
});

view ​

Triggered when the player enters the viewport.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('view', (state) => {
    console.info('view', state);
});

lock ​

Triggered when the lock state changes on mobile devices.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    lock: true,
});

art.on('lock', (state) => {
    console.info('lock', state);
});

aspectRatio ​

Triggered when the player's aspect ratio changes.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    aspectRatio: true,
    setting: true,
});

art.on('aspectRatio', (aspectRatio) => {
    console.info('aspectRatio', aspectRatio);
});

autoHeight ​

Triggered when the player's height is automatically set.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('ready', () => {
    art.autoHeight();
});

art.on('autoHeight', (height) => {
    console.info('autoHeight', height);
});

autoSize ​

Triggered when the player's size is automatically set.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    autoSize: true,
});

art.on('autoSize', () => {
    console.info('autoSize');
});

flip ​

Triggered when the player is flipped.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    flip: true,
    setting: true,
});

art.on('flip', (flip) => {
    console.info('flip', flip);
});

fullscreen ​

Triggered when the player enters or exits windowed fullscreen mode.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    fullscreen: true,
});

art.on('fullscreen', (state) => {
    console.info('fullscreen', state);
});

fullscreenError ​

Triggered when a windowed fullscreen error occurs.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('ready', () => {
	art.fullscreen = true;
});

art.on('fullscreenError', (event) => {
    console.info('fullscreenError', event);
});

fullscreenWeb ​

Triggered when the player enters or exits web fullscreen mode.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    fullscreenWeb: true,
});

art.on('fullscreenWeb', (state) => {
    console.info('fullscreenWeb', state);
});

mini ​

Triggered when the player enters or exits mini mode.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('ready', () => {
    art.mini = true;
});

art.on('mini', (state) => {
    console.info('mini', state);
});

pip ​

Triggered when the player enters or exits Picture-in-Picture mode.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    pip: true,
});

art.on('pip', (state) => {
    console.info('pip', state);
});

screenshot ​

Triggered when the player takes a screenshot.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    screenshot: true,
});

art.on('screenshot', (dataUri) => {
    console.info('screenshot', dataUri);
});

seek ​

Triggered when the player performs a time seek.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('seek', (currentTime) => {
    console.info('seek', currentTime);
});

subtitleOffset ​

Triggered when the subtitle offset changes in the player.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    subtitleOffset: true,
    subtitle: {
        url: '/assets/sample/subtitle.srt',
    },
    setting: true,
});

art.on('subtitleOffset', (offset) => {
    console.info('subtitleOffset', offset);
});

subtitleBeforeUpdate ​

Triggered before subtitles are updated.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    subtitle: {
        url: '/assets/sample/subtitle.srt',
    },
});

art.on('subtitleBeforeUpdate', (cues) => {
    console.info('subtitleBeforeUpdate', cues);
});

subtitleAfterUpdate ​

Triggered after subtitles are updated.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    subtitle: {
        url: '/assets/sample/subtitle.srt',
    },
});

art.on('subtitleAfterUpdate', (cues) => {
    console.info('subtitleAfterUpdate', cues);
});

subtitleLoad ​

Triggered when subtitles are loaded.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    subtitle: {
        url: '/assets/sample/subtitle.srt',
    },
});

art.on('subtitleLoad', (option, cues) => {
    console.info('subtitleLoad', cues, option);
});

info ​

Triggered when the info panel is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('info', (state) => {
    console.log(state);
});

layer ​

Triggered when a custom layer is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('layer', (state) => {
    console.log(state);
});

loading ​

Triggered when the loader is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('loading', (state) => {
    console.log(state);
});

mask ​

Triggered when the mask layer is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('mask', (state) => {
    console.log(state);
});

subtitle ​

Triggered when the subtitle layer is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('subtitle', (state) => {
    console.log(state);
});

contextmenu ​

Triggered when the context menu is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('contextmenu', (state) => {
    console.log(state);
});

control ​

Triggered when the control bar is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('control', (state) => {
    console.log(state);
});

setting ​

Triggered when the settings panel is shown or hidden.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
    setting: true,
});

art.on('setting', (state) => {
    console.log(state);
});

muted ​

Triggered when the muted state changes.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('muted', (state) => {
    console.log(state);
});

keydown ​

Listens for the keydown event from the document.

▶ Run Code
js
var art = new Artplayer({
    container: '.artplayer-app',
    url: '/assets/sample/video.mp4',
});

art.on('keydown', (event) => {
    console.log(event.code);
});

video:canplay ​

The browser can start playing the media, but estimates there is not enough data to play through to the end without stopping for further buffering.

video:canplaythrough ​

The browser estimates it can play the media through to the end without stopping for buffering.

video:complete ​

Historical declared name; not forwarded by the default video event inventory. Use video:ended for media reaching its end.

video:durationchange ​

Triggered when the value of the duration property changes.

video:emptied ​

The media has become empty; for example, this event is sent when the media has already been loaded (or partially loaded), and the load() method is called to reload it.

video:ended ​

Playback has stopped because the media has reached its end.

video:error ​

An error occurred while fetching the media data, or the resource type is not a supported media format.

video:loadeddata ​

The first frame of the media has finished loading.

video:loadedmetadata ​

Metadata has been loaded.

video:pause ​

Playback has been paused.

video:play ​

Playback has begun.

video:playing ​

Playback is ready to start after having been paused or delayed due to lack of data.

video:progress ​

Fired periodically as the browser loads the resource.

video:ratechange ​

The playback rate has changed.

video:seeked ​

A seek operation has completed.

video:seeking ​

A seek operation has begun.

video:stalled ​

The user agent is trying to fetch media data, but data is unexpectedly not forthcoming.

video:suspend ​

Media data loading has been suspended.

video:timeupdate ​

The time indicated by the currentTime property has changed.

video:volumechange ​

The volume has changed.

video:waiting ​

Playback has stopped because of a temporary lack of data.