mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:46:16 -08:00
11420 lines
304 KiB
Plaintext
11420 lines
304 KiB
Plaintext
ArtPlayer documentation source bundle
|
||
Generated offline by yarn build:llm. Source text is preserved after LF normalization.
|
||
These are source references, not proof that every example or documented feature has passed release review.
|
||
|
||
===== Documentation Summary =====
|
||
|
||
===== packages/artplayer-vitepress/docs/en/advanced/built-in.md =====
|
||
|
||
# Advanced Properties
|
||
|
||
The `Advanced Properties` here refer to the `secondary properties` attached to the `instance`, which are less commonly used.
|
||
|
||
## `option`
|
||
|
||
The player's options.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info(art.option);
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
If you directly modify this `option` object, the player will not respond immediately.
|
||
|
||
:::
|
||
|
||
## `template`
|
||
|
||
Manages all `DOM` elements of the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info(art.template);
|
||
console.info(art.template.$video);
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
To easily distinguish between `DOM` elements and regular objects, all `DOM` elements within the player are named with a `$` prefix.
|
||
|
||
This is the definition of all `DOM` elements: [artplayer/types/template.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/template.d.ts)
|
||
|
||
:::
|
||
|
||
## `events`
|
||
|
||
Manages all `DOM` events for the player. It essentially proxies `addEventListener` and `removeEventListener`. When using the following methods to handle events, the events will also be automatically destroyed when the player is destroyed.
|
||
|
||
- The `proxy` method is used to proxy `DOM` events.
|
||
- The `hover` method is used to proxy custom `hover` events.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var container = document.querySelector('.artplayer-app');
|
||
|
||
var art = new Artplayer({
|
||
container: container,
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.events.proxy(container, 'click', event => {
|
||
console.info('click', event);
|
||
});
|
||
|
||
art.events.hover(container, (event) => {
|
||
console.info('mouseenter', event);
|
||
}, (event) => {
|
||
console.info('mouseleave', event);
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
If you need `DOM` events that should only exist during the player's lifecycle, it is strongly recommended to use these functions to avoid memory leaks.
|
||
|
||
:::
|
||
|
||
## `storage`
|
||
|
||
Manages the player's local storage.
|
||
|
||
- The `name` property is used to set the cache `key`.
|
||
- The `set` method is used to set a cache.
|
||
- The `get` method is used to retrieve a cache.
|
||
- The `del` method is used to delete a cache.
|
||
- The `clear` method is used to clear all caches.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.storage.set('test', { foo: 'bar' });
|
||
const test = art.storage.get('test');
|
||
console.info(test);
|
||
art.storage.del('test');
|
||
art.storage.clear();
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
By default, all player instances share the same `localStorage`, and the default `key` is `artplayer_settings`.
|
||
|
||
If you want different players to use different `localStorage`, you can modify `art.storage.name`.
|
||
|
||
:::
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.storage.name = 'your-storage-key';
|
||
art.storage.set('test', { foo: 'bar' });
|
||
```
|
||
|
||
## `icons`
|
||
|
||
Manages all `svg` icons for the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info(art.icons.loading);
|
||
```
|
||
|
||
:::warning This is the definition of all icons:
|
||
|
||
[artplayer/types/icons.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/icons.d.ts)
|
||
|
||
:::
|
||
|
||
## `i18n`
|
||
|
||
Manages the player's `i18n`.
|
||
|
||
- The `get` method is used to retrieve an `i18n` value.
|
||
- The `update` method is used to update the `i18n` object.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info(art.i18n.get('Play'));
|
||
|
||
art.i18n.update({
|
||
'zh-cn': {
|
||
Play: 'Your Play'
|
||
}
|
||
});
|
||
```
|
||
|
||
:::warning
|
||
|
||
Using `art.i18n.update` can only update the `i18n` after instantiation. If you want to update `i18n` before instantiation, please use the `i18n` option in the basic settings.
|
||
|
||
:::
|
||
|
||
## `notice`
|
||
|
||
Manages the player's notifications. It only has a `show` property for displaying notifications.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.notice.show = 'Video Ready To Play';
|
||
})
|
||
```
|
||
|
||
:::warning
|
||
|
||
If you want to hide the `notice` immediately: `art.notice.show = '';`
|
||
|
||
:::
|
||
|
||
## `layers`
|
||
|
||
Manages the player's layers.
|
||
|
||
- The `add` method is used to dynamically add a layer.
|
||
- The `remove` method is used to dynamically remove a layer.
|
||
- The `update` method is used to dynamically update a layer.
|
||
- The `show` property is used to set whether all layers are displayed.
|
||
- The `toggle` method is used to toggle the display of all layers.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.layers.add({
|
||
html: 'Some Text',
|
||
});
|
||
|
||
setTimeout(() => {
|
||
art.layers.show = false;
|
||
}, 1000);
|
||
});
|
||
```
|
||
|
||
:::warning For `Component Configuration`, please refer to:
|
||
|
||
[/component/layers.html](/component/layers.html)
|
||
|
||
:::
|
||
|
||
## `controls`
|
||
|
||
Manages the player's controls.
|
||
|
||
- The `add` method is used to dynamically add a control.
|
||
- The `remove` method is used to dynamically remove a control.
|
||
|
||
- The `update` method is used to dynamically update controls
|
||
- The `show` property is used to set whether to display all controls
|
||
- The `toggle` method is used to toggle the display of all controls
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.controls.add({
|
||
html: 'Some Text',
|
||
position: 'left',
|
||
});
|
||
|
||
setTimeout(() => {
|
||
art.controls.show = false;
|
||
}, 1000);
|
||
});
|
||
```
|
||
|
||
:::warning For `Component Configuration`, please refer to:
|
||
|
||
[/component/controls.html](/component/controls.html)
|
||
|
||
:::
|
||
|
||
## `contextmenu`
|
||
|
||
Manages the player's context menu
|
||
|
||
- The `add` method is used to dynamically add menu items
|
||
- The `remove` method is used to dynamically remove menu items
|
||
- The `update` method is used to dynamically update menu items
|
||
- The `show` property is used to set whether to display all menu items
|
||
- The `toggle` method is used to toggle the display of all menu items
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.contextmenu.add({
|
||
html: 'Some Text',
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
setTimeout(() => {
|
||
art.contextmenu.show = false;
|
||
}, 1000);
|
||
});
|
||
```
|
||
|
||
:::warning For `Component Configuration`, please refer to:
|
||
|
||
[/component/contextmenu.html](/component/contextmenu.html)
|
||
|
||
:::
|
||
|
||
## `subtitle`
|
||
|
||
Manages the player's subtitle functionality
|
||
|
||
- The `url` property sets and returns the current subtitle URL
|
||
- The `style` method sets the style of the current subtitle
|
||
- The `switch` method sets the current subtitle URL and options
|
||
- `textTrack` gets the current text track
|
||
- `activeCues` gets the list of currently active cues
|
||
- `cues` gets the overall list of cues
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.subtitle.url = '/assets/sample/subtitle.srt'
|
||
art.subtitle.style({
|
||
color: 'red',
|
||
});
|
||
});
|
||
```
|
||
|
||
## `info`
|
||
|
||
Manages the player's information panel, commonly used to view the current status of the player and video, such as version number, resolution, duration, etc.
|
||
|
||
- Control the panel's visibility via `art.info.show`
|
||
- The triggered event is named `info` (see the event documentation for details)
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.info.show = true;
|
||
|
||
setTimeout(() => {
|
||
art.info.show = false;
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `loading`
|
||
|
||
Manages the player's loading layer
|
||
|
||
- The `show` property is used to set whether to display the loading layer
|
||
- The `toggle` property is used to toggle the display of the loading layer
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.loading.show = true;
|
||
setTimeout(() => {
|
||
art.loading.show = false;
|
||
}, 1000);
|
||
});
|
||
```
|
||
|
||
## `hotkey`
|
||
|
||
Manages the player's hotkey functionality
|
||
|
||
- The `add` method is used to add hotkeys
|
||
- The `remove` method is used to remove hotkeys
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
function hotkeyEvent(event) {
|
||
console.info('click', event);
|
||
}
|
||
|
||
art.on('ready', () => {
|
||
art.hotkey.add(32, hotkeyEvent);
|
||
setTimeout(() => {
|
||
art.hotkey.remove(32, hotkeyEvent);
|
||
}, 5000);
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
These hotkeys only take effect after the player gains focus (e.g., after clicking on the player)
|
||
|
||
:::
|
||
|
||
## `mask`
|
||
|
||
Manages the player's mask layer
|
||
|
||
- The `show` property is used to set whether to display the mask layer
|
||
- The `toggle` property is used to toggle the display of the mask layer
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.mask.show = false;
|
||
setTimeout(() => {
|
||
art.mask.show = true;
|
||
}, 1000);
|
||
});
|
||
```
|
||
|
||
## `setting`
|
||
|
||
Manages the player's settings panel
|
||
|
||
- The `add` method is used to dynamically add settings items
|
||
- The `remove` method is used to dynamically remove settings items
|
||
- The `update` method is used to dynamically update settings items
|
||
- The `show` property is used to set whether to display all settings items
|
||
- The `toggle` method is used to toggle the display of all settings items
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
subtitleOffset: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.setting.show = true;
|
||
setTimeout(() => {
|
||
art.setting.show = false;
|
||
}, 1000);
|
||
});
|
||
```
|
||
|
||
:::warning For `Settings Panel`, please refer to
|
||
|
||
[/component/setting.html](/component/setting.html)
|
||
|
||
:::
|
||
|
||
## `plugins`
|
||
|
||
Manages the player's plugin functionality, with only one method `add` for dynamically adding plugins
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
function myPlugin(art) {
|
||
console.info(art);
|
||
return {
|
||
name: 'myPlugin',
|
||
something: 'something',
|
||
doSomething: function () {
|
||
console.info('doSomething');
|
||
},
|
||
};
|
||
}
|
||
|
||
art.on('ready', () => {
|
||
art.plugins.add(myPlugin);
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/advanced/class.md =====
|
||
|
||
# Static Properties
|
||
|
||
Here, `static properties` refer to the `first-level properties` attached to the `constructor`, which are rarely used.
|
||
|
||
## `instances`
|
||
|
||
Returns an array of all player instances. This property can be useful when you need to manage multiple players simultaneously.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info([...Artplayer.instances]);
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info([...Artplayer.instances]);
|
||
```
|
||
|
||
## `version`
|
||
|
||
Returns the version information of the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.version);
|
||
```
|
||
|
||
## `env`
|
||
|
||
Returns the environment variables of the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.env);
|
||
```
|
||
|
||
## `build`
|
||
|
||
Returns the build timestamp of the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.build);
|
||
```
|
||
|
||
## `config`
|
||
|
||
Returns the default configuration for videos.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.config);
|
||
```
|
||
|
||
## `utils`
|
||
|
||
Returns the collection of utility functions for the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.utils);
|
||
```
|
||
|
||
:::warning For all utility functions, please refer to the following address:
|
||
|
||
[artplayer/types/utils.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/utils.d.ts)
|
||
|
||
:::
|
||
|
||
## `scheme`
|
||
|
||
Returns the validation schema for player options.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.scheme);
|
||
```
|
||
|
||
## `Emitter`
|
||
|
||
Returns the constructor of the event emitter.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.Emitter);
|
||
```
|
||
|
||
## `validator`
|
||
|
||
Returns the validation function for options.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.validator);
|
||
```
|
||
|
||
## `kindOf`
|
||
|
||
Returns the type detection utility function.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.kindOf);
|
||
```
|
||
|
||
## `html`
|
||
|
||
Returns the `html` string required by the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.html);
|
||
```
|
||
|
||
## `option`
|
||
|
||
Returns the default options of the player.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.info(Artplayer.option);
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/advanced/event.md =====
|
||
|
||
# Instance Events
|
||
|
||
Player events are divided into two types: `native events` of the video (prefixed with `video:`), and `custom events`.
|
||
|
||
Listening to events:
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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:
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.once('video:canplay', () => {
|
||
console.info('video:canplay');
|
||
});
|
||
```
|
||
|
||
Manually triggering an event:
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.emit('focus');
|
||
```
|
||
|
||
Removing an event:
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
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);
|
||
```
|
||
|
||
:::warning For a complete list of events, please refer to:
|
||
|
||
[artplayer/types/events.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/events.d.ts)
|
||
|
||
:::
|
||
|
||
## `ready`
|
||
|
||
Triggered when the player is ready for the first time.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{10}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{10}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{10}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{10}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{11}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
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`
|
||
|
||
The OfflineAudioContext rendering is complete.
|
||
|
||
## `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.
|
||
|
||
===== packages/artplayer-vitepress/docs/en/advanced/global.md =====
|
||
|
||
# Global Properties
|
||
|
||
The `global properties` here refer to the `top-level properties` mounted on the `constructor`. All property names are in uppercase. These are subject to change in the future and are rarely used.
|
||
|
||
## DEBUG
|
||
|
||
Whether to enable `debug` mode, which can print all built-in video events. Default is off.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.DEBUG = true;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## STYLE
|
||
|
||
Returns the player style text.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
console.log(Artplayer.STYLE);
|
||
```
|
||
|
||
## CONTEXTMENU
|
||
|
||
Whether to enable the context menu. Default is on.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.CONTEXTMENU = false;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## NOTICE_TIME
|
||
|
||
The display duration of notification messages, in milliseconds. Default is `2000`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.NOTICE_TIME = 5000;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## SETTING_WIDTH
|
||
|
||
The default width of the settings panel, in pixels. Default is `250`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.SETTING_WIDTH = 300;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
loop: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
});
|
||
```
|
||
|
||
## SETTING_ITEM_WIDTH
|
||
|
||
The default width of a setting item in the settings panel, in pixels. Default is `200`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.SETTING_ITEM_WIDTH = 300;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
loop: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
});
|
||
```
|
||
|
||
## SETTING_ITEM_HEIGHT
|
||
|
||
The default height of a setting item in the settings panel, in pixels. Default is `35`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.SETTING_ITEM_HEIGHT = 40;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
loop: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
});
|
||
```
|
||
|
||
## RESIZE_TIME
|
||
|
||
The throttle time for the `resize` event, in milliseconds. Default is `200`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.RESIZE_TIME = 500;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('resize', () => {
|
||
console.log('resize');
|
||
});
|
||
```
|
||
|
||
## SCROLL_TIME
|
||
|
||
The throttle time for the `scroll` event, in milliseconds. Default is `200`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.SCROLL_TIME = 500;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('scroll', () => {
|
||
console.log('scroll');
|
||
});
|
||
```
|
||
|
||
## SCROLL_GAP
|
||
|
||
The boundary tolerance distance for the `view` event, in pixels. Default is `50`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.SCROLL_GAP = 100;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('scroll', () => {
|
||
console.log('scroll');
|
||
});
|
||
```
|
||
|
||
## AUTO_PLAYBACK_MAX
|
||
|
||
The maximum record count for the auto-playback feature. Default is `10`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.AUTO_PLAYBACK_MAX = 20;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoPlayback: true,
|
||
});
|
||
```
|
||
|
||
## AUTO_PLAYBACK_MIN
|
||
|
||
The minimum record duration for the auto-playback feature, in seconds. Default is `5`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.AUTO_PLAYBACK_MIN = 10;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoPlayback: true,
|
||
});
|
||
```
|
||
|
||
## AUTO_PLAYBACK_TIMEOUT
|
||
|
||
The hide delay duration for the auto-playback feature, in milliseconds. Default is `3000`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.AUTO_PLAYBACK_TIMEOUT = 5000;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoPlayback: true,
|
||
});
|
||
```
|
||
|
||
## RECONNECT_TIME_MAX
|
||
|
||
The maximum number of automatic reconnection attempts when a connection error occurs. Default is `5`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.RECONNECT_TIME_MAX = 10;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/404.mp4',
|
||
});
|
||
```
|
||
|
||
## RECONNECT_SLEEP_TIME
|
||
|
||
The delay time for automatic reconnection when a connection error occurs, in milliseconds. Default is `1000`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.RECONNECT_SLEEP_TIME = 3000;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/404.mp4',
|
||
});
|
||
|
||
```
|
||
|
||
## CONTROL_HIDE_TIME
|
||
|
||
The auto-hide delay time for the bottom control bar, in milliseconds. Default is `3000`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.CONTROL_HIDE_TIME = 5000;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## DBCLICK_TIME
|
||
|
||
The delay time for the double-click event, in milliseconds. Default is `300`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.DBCLICK_TIME = 500;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('dblclick', () => {
|
||
console.log('dblclick');
|
||
});
|
||
```
|
||
|
||
## DBCLICK_FULLSCREEN
|
||
|
||
On desktop, whether double-click toggles fullscreen. Default is `true`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.DBCLICK_FULLSCREEN = false;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## MOBILE_DBCLICK_PLAY
|
||
|
||
On mobile, whether double-click toggles play/pause. Default is `true`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.MOBILE_DBCLICK_PLAY = false;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## MOBILE_CLICK_PLAY
|
||
|
||
On mobile, whether single-click toggles play/pause. Default is `false`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.MOBILE_CLICK_PLAY = true;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## AUTO_ORIENTATION_TIME
|
||
|
||
On mobile, the delay time for auto-rotation, in milliseconds. Default is `200`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.AUTO_ORIENTATION_TIME = 500;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoOrientation: true,
|
||
});
|
||
```
|
||
|
||
## INFO_LOOP_TIME
|
||
|
||
The refresh interval for the info panel, in milliseconds. Default is `1000`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.INFO_LOOP_TIME = 2000;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.info.show = true;
|
||
```
|
||
|
||
## FAST_FORWARD_VALUE
|
||
|
||
On mobile, the speed multiplier for long-press fast-forward. Default is `3`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.FAST_FORWARD_VALUE = 5;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fastForward: true,
|
||
});
|
||
```
|
||
|
||
## FAST_FORWARD_TIME
|
||
|
||
On mobile, the delay time for long-press fast-forward, in milliseconds. Default is `1000`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.FAST_FORWARD_TIME = 2000;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fastForward: true,
|
||
});
|
||
```
|
||
|
||
## TOUCH_MOVE_RATIO
|
||
|
||
On mobile, the speed multiplier for left/right swipe to seek. Default is `0.5`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.TOUCH_MOVE_RATIO = 1;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## VOLUME_STEP
|
||
|
||
The step size for volume adjustment via keyboard shortcuts. Default is `0.1`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.VOLUME_STEP = 0.2;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## SEEK_STEP
|
||
|
||
The step size for seeking via keyboard shortcuts, in seconds. Default is `5`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.SEEK_STEP = 10;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## PLAYBACK_RATE
|
||
|
||
The built-in list of playback rates. Default is `[0.5, 0.75, 1, 1.25, 1.5, 2]`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.PLAYBACK_RATE = [0.5, 1, 2, 3, 4, 5];
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
playbackRate: true,
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
art.setting.show = true;
|
||
```
|
||
|
||
## ASPECT_RATIO
|
||
|
||
The built-in list of video aspect ratios. Default is `['default', '4:3', '16:9']`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.ASPECT_RATIO = ['default', '1:1', '2:1', '4:3', '6:5'];
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
aspectRatio: true,
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
art.setting.show = true;
|
||
```
|
||
|
||
## FLIP
|
||
|
||
The built-in list of video flip options. Default is `['normal', 'horizontal', 'vertical']`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.FLIP = ['normal', 'horizontal'];
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
flip: true,
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
art.setting.show = true;
|
||
|
||
```
|
||
|
||
## FULLSCREEN_WEB_IN_BODY
|
||
|
||
Whether to mount the player under the `body` element during web fullscreen mode. Default is `true`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.FULLSCREEN_WEB_IN_BODY = false;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreenWeb: true,
|
||
});
|
||
```
|
||
|
||
## LOG_VERSION
|
||
|
||
Sets whether to print the player version. Default is `true`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.LOG_VERSION = false;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## USE_RAF
|
||
|
||
Sets whether to use `requestAnimationFrame`. Default is `false`. Currently, it is primarily used for smooth progress bar effects.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.USE_RAF = true;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
miniProgressBar: true,
|
||
});
|
||
```
|
||
|
||
## REMOVE_SRC_WHEN_DESTROY
|
||
|
||
Whether to remove the video's `src` attribute and call `load()` to actively release media resources when destroying the player. Default is `true`.
|
||
|
||
Enabling this can reduce video resource usage in single-page applications or scenarios where players are frequently created/destroyed. If you wish to preserve the state of the video element and only remove the UI, you can set this to `false`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
Artplayer.REMOVE_SRC_WHEN_DESTROY = false;
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
// Only destroy the UI, do not actively clear the src
|
||
art.destroy();
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/advanced/plugin.md =====
|
||
|
||
# Writing Plugins
|
||
|
||
Once you are familiar with the player's `properties`, `methods`, and `events`, writing a plugin becomes a very straightforward task.
|
||
|
||
You can load a plugin function during instantiation.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{15}
|
||
function myPlugin(art) {
|
||
console.info(art);
|
||
return {
|
||
name: 'myPlugin',
|
||
something: 'something',
|
||
doSomething: function () {
|
||
console.info('doSomething');
|
||
},
|
||
};
|
||
}
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [myPlugin],
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.plugins.myPlugin);
|
||
});
|
||
```
|
||
|
||
You can also load a plugin function after instantiation.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{17}
|
||
function myPlugin(art) {
|
||
console.info(art);
|
||
return {
|
||
name: 'myPlugin',
|
||
something: 'something',
|
||
doSomething: function () {
|
||
console.info('doSomething');
|
||
},
|
||
};
|
||
}
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.plugins.add(myPlugin);
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.plugins.myPlugin);
|
||
});
|
||
```
|
||
|
||
For example, let's say I want to write a plugin that displays an image ad when the video is paused.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
function adsPlugin(option) {
|
||
return (art) => {
|
||
art.layers.add({
|
||
name: 'ads',
|
||
html: `<img style="width: 100px" src="${option.url}">`,
|
||
style: {
|
||
display: 'none',
|
||
position: 'absolute',
|
||
top: '20px',
|
||
right: '20px',
|
||
},
|
||
});
|
||
|
||
function show() {
|
||
art.layers.ads.style.display = 'block';
|
||
}
|
||
|
||
function hide() {
|
||
art.layers.ads.style.display = 'none';
|
||
}
|
||
|
||
art.controls.add({
|
||
name: 'hide-ads',
|
||
position: 'right',
|
||
html: 'Hide Ads',
|
||
tooltip: 'Hide Ads',
|
||
click: hide,
|
||
style: {
|
||
marginRight: '20px'
|
||
}
|
||
});
|
||
|
||
art.controls.add({
|
||
name: 'show-ads',
|
||
position: 'right',
|
||
html: 'Show Ads',
|
||
tooltip: 'Show Ads',
|
||
click: show,
|
||
});
|
||
|
||
art.on('play', hide);
|
||
art.on('pause', show);
|
||
|
||
return {
|
||
name: 'adsPlugin',
|
||
show,
|
||
hide
|
||
};
|
||
}
|
||
}
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [
|
||
adsPlugin({
|
||
url: '/assets/sample/layer.png'
|
||
})
|
||
],
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/advanced/property.md =====
|
||
|
||
# Instance Properties
|
||
|
||
Here, `Instance Properties` refer to the `first-level properties` mounted on the `instance`, which are commonly used.
|
||
|
||
## `play`
|
||
|
||
- Type: `Function`
|
||
|
||
Play the video.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.play();
|
||
});
|
||
```
|
||
|
||
## `pause`
|
||
|
||
- Type: `Function`
|
||
|
||
Pause the video.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{11}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.play();
|
||
|
||
setTimeout(() => {
|
||
art.pause();
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `toggle`
|
||
|
||
- Type: `Function`
|
||
|
||
Toggle video play and pause.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{11}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.toggle();
|
||
|
||
setTimeout(() => {
|
||
art.toggle();
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `destroy`
|
||
|
||
- Type: `Function`
|
||
- Parameter: `Boolean`
|
||
|
||
Destroy the player. Accepts a parameter indicating whether to also remove the player's `html` after destruction. Defaults to `true`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.destroy();
|
||
});
|
||
```
|
||
|
||
## `reset`
|
||
|
||
- Type: `Function`
|
||
|
||
Reset the player's video element: removes the current `src` and calls `load()` once. Commonly used to manually release media resources or reinitialize the video tag in single-page applications.
|
||
|
||
> Note: The global configuration `Artplayer.REMOVE_SRC_WHEN_DESTROY` will also automatically execute similar logic when `destroy()` is called.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
// Only reset the video, do not remove the interface
|
||
art.reset();
|
||
});
|
||
```
|
||
|
||
## `seek`
|
||
|
||
- Type: `Setter`
|
||
- Parameter: `Number`
|
||
|
||
Seek to a specific time in the video, in seconds.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.seek = 5;
|
||
});
|
||
```
|
||
|
||
## `forward`
|
||
|
||
- Type: `Setter`
|
||
- Parameter: `Number`
|
||
|
||
Fast-forward the video time, in seconds.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.forward = 5;
|
||
});
|
||
```
|
||
|
||
## `backward`
|
||
|
||
- Type: `Setter`
|
||
- Parameter: `Number`
|
||
|
||
Rewind the video time, in seconds.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{10}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.seek = 5;
|
||
|
||
setTimeout(() => {
|
||
art.backward = 2;
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `volume`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Number`
|
||
|
||
Set and get the video volume, range: `[0, 1]`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.volume);
|
||
art.volume = 0.5;
|
||
console.info(art.volume);
|
||
});
|
||
```
|
||
|
||
## `url`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Set and get the video URL.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.url = '/assets/sample/video.mp4?t=0';
|
||
});
|
||
```
|
||
|
||
## `switch`
|
||
|
||
- Type: `Setter`
|
||
- Parameter: `String`
|
||
|
||
Set the video URL. Similar to `art.url` when setting, but performs some optimization operations.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.seek = 10;
|
||
setTimeout(() => {
|
||
art.switch = '/assets/sample/video.mp4?t=0';
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `switchUrl`
|
||
|
||
- Type: `Function`
|
||
- Parameter: `String`
|
||
|
||
Set the video URL. Similar to `art.url` when setting, but performs some optimization operations.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.seek = 10;
|
||
setTimeout(() => {
|
||
art.switchUrl('/assets/sample/video.mp4?t=0');
|
||
}, 3000);
|
||
});
|
||
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
`art.switch` and `art.switchUrl` have the same functionality, but the `art.switchUrl` method returns a `Promise`. It `resolve`s when the new URL is playable and `reject`s when the new URL fails to load.
|
||
|
||
:::
|
||
|
||
## `switchQuality`
|
||
|
||
- Type: `Function`
|
||
- Parameter: `String`
|
||
|
||
Sets the video quality URL. Similar to `art.switchUrl`, but retains the previous playback progress.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.seek = 10;
|
||
setTimeout(() => {
|
||
art.switchQuality('/assets/sample/video.mp4?t=0');
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `muted`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Boolean`
|
||
|
||
Sets or gets whether the video is muted.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.muted);
|
||
art.muted = true;
|
||
console.info(art.muted);
|
||
});
|
||
```
|
||
|
||
## `currentTime`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Number`
|
||
|
||
Sets or gets the current playback time of the video. Setting the time is similar to `seek`, but it does not trigger additional events.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.currentTime);
|
||
art.currentTime = 5;
|
||
console.info(art.currentTime);
|
||
});
|
||
```
|
||
|
||
## `duration`
|
||
|
||
- Type: `Getter`
|
||
|
||
Gets the duration of the video.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.duration);
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Some videos may not have a duration, such as live streams or videos that have not been fully decoded. In such cases, the obtained duration will be `0`.
|
||
|
||
:::
|
||
|
||
## `screenshot`
|
||
|
||
- Type: `Function`
|
||
|
||
Downloads a screenshot of the current video frame. An optional parameter specifies the screenshot filename.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.screenshot('your-name');
|
||
});
|
||
```
|
||
|
||
## `getDataURL`
|
||
|
||
- Type: `Function`
|
||
|
||
Gets the `base64` URL of a screenshot of the current video frame. Returns a `Promise`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', async () => {
|
||
const url = await art.getDataURL();
|
||
console.info(url)
|
||
});
|
||
```
|
||
|
||
## `getBlobUrl`
|
||
|
||
- Type: `Function`
|
||
|
||
Gets the `blob` URL of a screenshot of the current video frame. Returns a `Promise`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', async () => {
|
||
const url = await art.getBlobUrl();
|
||
console.info(url);
|
||
});
|
||
```
|
||
|
||
## `fullscreen`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Boolean`
|
||
|
||
Sets or gets the player's window fullscreen state.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
position: 'right',
|
||
html: 'Fullscreen Switch',
|
||
click: function () {
|
||
art.fullscreen = !art.fullscreen;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Due to browser security mechanisms, a user interaction (e.g., a click on the page) must occur before triggering window fullscreen.
|
||
|
||
:::
|
||
|
||
## `fullscreenWeb`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Boolean`
|
||
|
||
Sets or gets the player's web page fullscreen state.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8,11}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreenWeb: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.fullscreenWeb = true;
|
||
|
||
setTimeout(() => {
|
||
art.fullscreenWeb = false;
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## `pip`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Boolean`
|
||
|
||
Sets or gets the player's Picture-in-Picture (PIP) mode.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
position: 'right',
|
||
html: 'PIP',
|
||
click: function () {
|
||
art.pip = !art.pip;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Due to browser security mechanisms, a user interaction (e.g., a click on the page) must occur before triggering Picture-in-Picture.
|
||
|
||
:::
|
||
|
||
## `poster`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Sets and gets the video poster. The poster effect is only visible before the video starts playing.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
poster: '/assets/sample/poster.jpg',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.poster);
|
||
art.poster = '/assets/sample/poster.jpg?t=0';
|
||
console.info(art.poster);
|
||
});
|
||
```
|
||
|
||
## `mini`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Boolean`
|
||
|
||
Sets and gets the player's mini mode.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.mini = true;
|
||
});
|
||
```
|
||
|
||
## `playing`
|
||
|
||
- Type: `Getter`
|
||
- Parameter: `Boolean`
|
||
|
||
Gets whether the video is currently playing.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.playing);
|
||
});
|
||
```
|
||
|
||
## `state`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Gets or sets the player's current state. Supported values: `standard` (normal), `mini` (mini window), `pip` (picture-in-picture), `fullscreen` (window fullscreen), `fullscreenWeb` (webpage fullscreen).
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.state); // Default is 'standard'
|
||
art.state = 'mini';
|
||
});
|
||
```
|
||
|
||
## `autoSize`
|
||
|
||
- Type: `Function`
|
||
|
||
Sets whether the video adapts its size automatically.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.autoSize();
|
||
});
|
||
```
|
||
|
||
## `rect`
|
||
|
||
- Type: `Getter`
|
||
|
||
Gets the player's dimensions and coordinate information.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(JSON.stringify(art.rect));
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
The dimension and coordinate information is obtained via `getBoundingClientRect`.
|
||
|
||
:::
|
||
|
||
## `bottom` / `top` / `left` / `right` / `x` / `y` / `width` / `height`
|
||
|
||
- Type: `Getter`
|
||
|
||
These properties provide quick access to `rect`:
|
||
|
||
- `bottom`, `top`, `left`, `right`, `x`, `y`: Correspond to the fields of the same name in `DOMRect`.
|
||
- `width`, `height`: The player's current visible width and height.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.width, art.height, art.left, art.top);
|
||
});
|
||
```
|
||
|
||
## `flip`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Sets and gets the player's flip state. Supported values: `normal`, `horizontal`, `vertical`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.flip);
|
||
art.flip = 'horizontal';
|
||
console.info(art.flip);
|
||
});
|
||
```
|
||
|
||
## `playbackRate`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Number`
|
||
|
||
Sets and gets the player's playback speed.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.playbackRate);
|
||
art.playbackRate = 2;
|
||
console.info(art.playbackRate);
|
||
});
|
||
```
|
||
|
||
## `aspectRatio`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Sets and gets the player's aspect ratio.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.aspectRatio);
|
||
art.aspectRatio = '16:9';
|
||
console.info(art.aspectRatio);
|
||
});
|
||
```
|
||
|
||
## `autoHeight`
|
||
|
||
- Type: `Function`
|
||
|
||
When the container only has a defined width, this property can automatically calculate and set the video's height.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7,11}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.autoHeight();
|
||
});
|
||
|
||
art.on('resize', () => {
|
||
art.autoHeight();
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
This property is useful when your container has only a width but the exact height is unknown. It can automatically calculate the video height, but you need to determine the timing for setting this property.
|
||
|
||
:::
|
||
|
||
## `attr`
|
||
|
||
- Type: `Function`
|
||
- Parameter: `String`
|
||
|
||
Dynamically get and set attributes of the video element.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.attr('playsInline'));
|
||
art.attr('playsInline', true);
|
||
console.info(art.attr('playsInline'));
|
||
});
|
||
```
|
||
|
||
## `type`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Dynamically get and set the video type.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.type);
|
||
art.type = 'm3u8';
|
||
console.info(art.type);
|
||
});
|
||
```
|
||
|
||
## `theme`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `String`
|
||
|
||
Dynamically get and set the player's theme color.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.theme);
|
||
art.theme = '#000';
|
||
console.info(art.theme);
|
||
});
|
||
```
|
||
|
||
## `airplay`
|
||
|
||
- Type: `Function`
|
||
|
||
Initiate AirPlay.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
position: 'right',
|
||
html: 'AirPlay',
|
||
click: function () {
|
||
art.airplay();
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## `loaded`
|
||
|
||
- Type: `Getter`
|
||
|
||
The proportion of video buffered, ranging from `[0, 1]`. Often used with the `video:timeupdate` event.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('video:timeupdate', () => {
|
||
console.info(art.loaded);
|
||
});
|
||
```
|
||
|
||
## `loadedTime`
|
||
|
||
- Type: `Getter`
|
||
|
||
The buffered media duration in seconds. Typically used alongside `loaded` to display detailed buffering progress.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('video:timeupdate', () => {
|
||
console.info(art.loadedTime);
|
||
});
|
||
```
|
||
|
||
## `played`
|
||
|
||
- Type: `Getter`
|
||
|
||
The proportion of video played, ranging from `[0, 1]`. Often used with the `video:timeupdate` event.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('video:timeupdate', () => {
|
||
console.info(art.played);
|
||
});
|
||
```
|
||
|
||
## `proxy`
|
||
|
||
- Type: `Function`
|
||
|
||
A proxy function for `DOM` events, essentially proxying `addEventListener` and `removeEventListener`. When using `proxy` to handle events, the event is automatically cleaned up when the player is destroyed.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8-10}
|
||
var container = document.querySelector('.artplayer-app');
|
||
|
||
var art = new Artplayer({
|
||
container: container,
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.proxy(container, 'click', event => {
|
||
console.info(event);
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
If you need certain `DOM` events to exist only for the player's lifecycle, it is strongly recommended to use this function to avoid memory leaks.
|
||
|
||
:::
|
||
|
||
## `query`
|
||
|
||
- Type: `Function`
|
||
|
||
A `DOM` query function, similar to `document.querySelector`, but the search is scoped to the current player, preventing errors with duplicate class names.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info(art.query('.art-video'));
|
||
```
|
||
|
||
## `video`
|
||
|
||
- Type: `Element`
|
||
|
||
Quickly returns the player's `video` element.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
console.info(art.video);
|
||
```
|
||
|
||
## `cssVar`
|
||
|
||
- Type: `Function`
|
||
|
||
Dynamically get or set `CSS` variables.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
console.log(art.cssVar('--art-theme'));
|
||
art.cssVar('--art-theme', 'green');
|
||
console.log(art.cssVar('--art-theme'));
|
||
});
|
||
```
|
||
|
||
## `quality`
|
||
|
||
- Type: `Setter`
|
||
- Parameter: `Array`
|
||
|
||
Dynamically set the quality list.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{19-29}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
quality: [
|
||
{
|
||
default: true,
|
||
html: 'SD 480P',
|
||
url: '/assets/sample/video.mp4',
|
||
},
|
||
{
|
||
html: 'HD 720P',
|
||
url: '/assets/sample/video.mp4',
|
||
},
|
||
],
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
art.quality = [
|
||
{
|
||
default: true,
|
||
html: '1080P',
|
||
url: '/assets/sample/video.mp4',
|
||
},
|
||
{
|
||
html: '4K',
|
||
url: '/assets/sample/video.mp4',
|
||
},
|
||
];
|
||
}, 3000);
|
||
})
|
||
|
||
```
|
||
|
||
## `thumbnails`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Object`
|
||
|
||
Dynamically set thumbnails.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.thumbnails = {
|
||
url: '/assets/sample/thumbnails.png',
|
||
number: 60,
|
||
column: 10,
|
||
};
|
||
});
|
||
```
|
||
|
||
## `subtitleOffset`
|
||
|
||
- Type: `Setter/Getter`
|
||
- Parameter: `Number`
|
||
|
||
Dynamically set subtitle offset.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
subtitle: {
|
||
url: '/assets/sample/subtitle.srt',
|
||
},
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.subtitleOffset = 1;
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/component/contextmenu.md =====
|
||
|
||
# Context Menu
|
||
|
||
## Configuration
|
||
|
||
| Property | Type | Description |
|
||
| --------- | ------------------- | ------------------------------------ |
|
||
| `disable` | `Boolean` | Whether to disable the component |
|
||
| `name` | `String` | Unique component name for CSS class |
|
||
| `index` | `Number` | Component index for display priority |
|
||
| `html` | `String`, `Element` | DOM element of the component |
|
||
| `style` | `Object` | Component style object |
|
||
| `click` | `Function` | Component click event |
|
||
| `mounted` | `Function` | Triggered after component mount |
|
||
| `tooltip` | `String` | Tooltip text for the component |
|
||
|
||
## Creation
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-13}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
contextmenu: [
|
||
{
|
||
name: 'your-menu',
|
||
html: 'Your Menu',
|
||
click: function (...args) {
|
||
console.info(args);
|
||
art.contextmenu.show = false;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
|
||
// Get the Element of contextmenu by name
|
||
console.info(art.contextmenu['your-menu']);
|
||
```
|
||
|
||
## Addition
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6-13}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.contextmenu.add({
|
||
name: 'your-menu',
|
||
html: 'Your Menu',
|
||
click: function (...args) {
|
||
console.info(args);
|
||
art.contextmenu.show = false;
|
||
},
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
|
||
// Get the Element of contextmenu by name
|
||
console.info(art.contextmenu['your-menu']);
|
||
```
|
||
|
||
## Deletion
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{21}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
contextmenu: [
|
||
{
|
||
name: 'your-menu',
|
||
html: 'Your Menu',
|
||
click: function (...args) {
|
||
console.info(args);
|
||
art.contextmenu.show = false;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Delete the contextmenu by name
|
||
art.contextmenu.remove('your-menu')
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## Update
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{21-24}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
contextmenu: [
|
||
{
|
||
name: 'your-menu',
|
||
html: 'Your Menu',
|
||
click: function (...args) {
|
||
console.info(args);
|
||
art.contextmenu.show = false;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
art.contextmenu.show = true;
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Update the contextmenu by name
|
||
art.contextmenu.update({
|
||
name: 'your-menu',
|
||
html: 'Your New Menu',
|
||
})
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/component/controls.md =====
|
||
|
||
# Controls
|
||
|
||
## Configuration
|
||
|
||
| Property | Type | Description |
|
||
| ---------- | ------------------- | ------------------------------------------------ |
|
||
| `disable` | `Boolean` | Whether to disable the control |
|
||
| `name` | `String` | Unique name of the control, used for class marking |
|
||
| `index` | `Number` | Control index, determines display priority |
|
||
| `html` | `String`, `Element` | DOM element of the control |
|
||
| `style` | `Object` | Style object for the control |
|
||
| `click` | `Function` | Click event handler for the control |
|
||
| `mounted` | `Function` | Triggered after the control is mounted |
|
||
| `tooltip` | `String` | Tooltip text for the control |
|
||
| `position` | `String` | `left` or `right` - controls which side the control appears on |
|
||
| `selector` | `Array` | Array of objects for selection list |
|
||
| `onSelect` | `Function` | Function triggered when a selection list item is clicked |
|
||
|
||
## Creation
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
name: 'your-button',
|
||
index: 10,
|
||
position: 'left',
|
||
html: 'Your Button',
|
||
tooltip: 'Your Button',
|
||
style: {
|
||
color: 'red',
|
||
},
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
},
|
||
mounted: function (...args) {
|
||
console.info('mounted', args);
|
||
},
|
||
},
|
||
{
|
||
name: 'subtitle',
|
||
position: 'right',
|
||
html: 'Subtitle',
|
||
selector: [
|
||
{
|
||
default: true,
|
||
html: '<span style="color:red">subtitle 01</span>',
|
||
},
|
||
{
|
||
html: '<span style="color:yellow">subtitle 02</span>',
|
||
},
|
||
],
|
||
onSelect: function (item, $dom) {
|
||
console.info(item, $dom);
|
||
return 'Your ' + item.html;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
// Get the Element of control by name
|
||
console.info(art.controls['your-button']);
|
||
console.info(art.controls['subtitle']);
|
||
```
|
||
|
||
## Adding
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6-21}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.controls.add({
|
||
name: 'button1',
|
||
index: 10,
|
||
position: 'left',
|
||
html: 'Your Button',
|
||
tooltip: 'Your Button',
|
||
style: {
|
||
color: 'red',
|
||
},
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
},
|
||
mounted: function (...args) {
|
||
console.info('mounted', args);
|
||
},
|
||
});
|
||
|
||
// Get the Element of control by name
|
||
console.info(art.controls['button1']);
|
||
```
|
||
|
||
## Removal
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{21}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
name: 'button1',
|
||
index: 10,
|
||
position: 'right',
|
||
html: 'Your Button',
|
||
tooltip: 'Your Button',
|
||
style: {
|
||
color: 'red',
|
||
},
|
||
}
|
||
]
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Delete the control by name
|
||
art.controls.remove('button1');
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## Updating
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{26-40}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
name: 'button1',
|
||
index: 10,
|
||
position: 'right',
|
||
html: 'Subtitle',
|
||
selector: [
|
||
{
|
||
default: true,
|
||
html: 'subtitle 01',
|
||
},
|
||
{
|
||
html: 'subtitle 02',
|
||
},
|
||
],
|
||
}
|
||
]
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Update the control by name
|
||
art.controls.update({
|
||
name: 'button1',
|
||
index: 10,
|
||
position: 'right',
|
||
html: 'New Subtitle',
|
||
selector: [
|
||
{
|
||
default: true,
|
||
html: 'new subtitle 01',
|
||
},
|
||
{
|
||
html: 'new subtitle 02',
|
||
},
|
||
],
|
||
});
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/component/layers.md =====
|
||
|
||
# Layers
|
||
|
||
## Configuration
|
||
|
||
| Property | Type | Description |
|
||
| --------- | ------------------- | ------------------------------------ |
|
||
| `disable` | `Boolean` | Whether to disable the component |
|
||
| `name` | `String` | Unique component name for CSS class |
|
||
| `index` | `Number` | Component index for display priority |
|
||
| `html` | `String`, `Element` | Component DOM element |
|
||
| `style` | `Object` | Component style object |
|
||
| `click` | `Function` | Component click event |
|
||
| `mounted` | `Function` | Triggered after component mount |
|
||
| `tooltip` | `String` | Component tooltip text |
|
||
|
||
## Creation
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{5-22}
|
||
var img = '/assets/sample/layer.png';
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
layers: [
|
||
{
|
||
name: 'potser',
|
||
html: `<img style="width: 100px" src="${img}">`,
|
||
tooltip: 'Potser Tip',
|
||
style: {
|
||
position: 'absolute',
|
||
top: '50px',
|
||
right: '50px',
|
||
},
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
},
|
||
mounted: function (...args) {
|
||
console.info('mounted', args);
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
// Get the Element of layer by name
|
||
console.info(art.layers['potser']);
|
||
```
|
||
|
||
## Addition
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7-22}
|
||
var img = '/assets/sample/layer.png';
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
|
||
art.layers.add({
|
||
name: 'potser',
|
||
html: `<img style="width: 100px" src="${img}">`,
|
||
tooltip: 'Potser Tip',
|
||
style: {
|
||
position: 'absolute',
|
||
top: '50px',
|
||
right: '50px',
|
||
},
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
},
|
||
mounted: function (...args) {
|
||
console.info('mounted', args);
|
||
},
|
||
});
|
||
|
||
// Get the Element of layer by name
|
||
console.info(art.layers['potser']);
|
||
```
|
||
|
||
## Removal
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{21}
|
||
var img = '/assets/sample/layer.png';
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
layers: [
|
||
{
|
||
name: 'potser',
|
||
html: `<img style="width: 100px" src="${img}">`,
|
||
style: {
|
||
position: 'absolute',
|
||
top: '50px',
|
||
right: '50px',
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Delete the layer by name
|
||
art.layers.remove('potser');
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## Update
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{21-29}
|
||
var img = '/assets/sample/layer.png';
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
layers: [
|
||
{
|
||
name: 'potser',
|
||
html: `<img style="width: 100px" src="${img}">`,
|
||
style: {
|
||
position: 'absolute',
|
||
top: '50px',
|
||
right: '50px',
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Update the layer by name
|
||
art.layers.update({
|
||
name: 'potser',
|
||
html: `<img style="width: 200px" src="${img}">`,
|
||
style: {
|
||
position: 'absolute',
|
||
top: '50px',
|
||
left: '50px',
|
||
},
|
||
});
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/component/setting.md =====
|
||
|
||
# Settings Panel
|
||
|
||
## Built-in
|
||
|
||
First, you need to open the settings panel. It comes with four built-in items: `flip`, `playbackRate`, `aspectRatio`, `subtitleOffset`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
subtitleOffset: true,
|
||
});
|
||
```
|
||
|
||
## Create - Button
|
||
|
||
| Property | Type | Description |
|
||
| ---------- | ------------------- | -------------------- |
|
||
| `html` | `String`, `Element` | The DOM element |
|
||
| `icon` | `String`, `Element` | The icon element |
|
||
| `onClick` | `Function` | The click event |
|
||
| `width` | `Number` | The list width |
|
||
| `tooltip` | `String` | The tooltip text |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
html: 'Button',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
tooltip: 'tooltip',
|
||
onClick(item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
return 'new tooltip';
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## Create - Selection List
|
||
|
||
| Property | Type | Description |
|
||
| ---------- | ------------------- | -------------------- |
|
||
| `html` | `String`, `Element` | The DOM element |
|
||
| `icon` | `String`, `Element` | The icon element |
|
||
| `selector` | `Array` | The list of elements |
|
||
| `onSelect` | `Function` | The click event |
|
||
| `width` | `Number` | The list width |
|
||
| `tooltip` | `String` | The tooltip text |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
html: 'Subtitle',
|
||
width: 250,
|
||
tooltip: 'Subtitle 01',
|
||
selector: [
|
||
{
|
||
default: true,
|
||
html: '<span style="color:red">Subtitle 01</span>',
|
||
url: '/assets/sample/subtitle.srt?id=1',
|
||
},
|
||
{
|
||
html: '<span style="color:yellow">Subtitle 02</span>',
|
||
url: '/assets/sample/subtitle.srt?id=2',
|
||
},
|
||
],
|
||
onSelect: function (item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
art.subtitle.url = item.url;
|
||
return item.html;
|
||
},
|
||
},
|
||
{
|
||
html: 'Quality',
|
||
width: 150,
|
||
tooltip: '1080P',
|
||
selector: [
|
||
{
|
||
default: true,
|
||
html: '1080P',
|
||
url: '/assets/sample/video.mp4?id=1080',
|
||
},
|
||
{
|
||
html: '720P',
|
||
url: '/assets/sample/video.mp4?id=720',
|
||
},
|
||
{
|
||
html: '360P',
|
||
url: '/assets/sample/video.mp4?id=360',
|
||
},
|
||
],
|
||
onSelect: function (item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
art.switchQuality(item.url, item.html);
|
||
return item.html;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## Create - Nested List
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
html: 'Multi-level',
|
||
selector: [
|
||
{
|
||
html: 'Setting 01',
|
||
width: 150,
|
||
selector: [
|
||
{
|
||
html: 'Setting 01 - 01',
|
||
},
|
||
{
|
||
html: 'Setting 01 - 02',
|
||
},
|
||
],
|
||
onSelect: function (item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
return item.html;
|
||
},
|
||
},
|
||
{
|
||
html: 'Setting 02',
|
||
width: 150,
|
||
selector: [
|
||
{
|
||
html: 'Setting 02 - 01',
|
||
},
|
||
{
|
||
html: 'Setting 02 - 02',
|
||
},
|
||
],
|
||
onSelect: function (item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
return item.html;
|
||
},
|
||
},
|
||
],
|
||
},
|
||
],
|
||
});
|
||
|
||
```
|
||
|
||
## Create - Toggle Button
|
||
|
||
| Property | Type | Description |
|
||
| ---------- | ------------------- | -------------------------- |
|
||
| `html` | `String`, `Element` | DOM element for the item |
|
||
| `icon` | `String`, `Element` | Icon for the item |
|
||
| `switch` | `Boolean` | Default state of the button |
|
||
| `onSwitch` | `Function` | Button toggle event |
|
||
| `tooltip` | `String` | Tooltip text |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
html: 'PIP Mode',
|
||
tooltip: 'Close',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
switch: false,
|
||
onSwitch: function (item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
const nextState = !item.switch;
|
||
art.pip = nextState;
|
||
item.tooltip = nextState ? 'Open' : 'Close';
|
||
return nextState;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## Create - Range Slider
|
||
|
||
| Property | Type | Description |
|
||
| ---------- | ------------------- | -------------------------- |
|
||
| `html` | `String`, `Element` | DOM element for the item |
|
||
| `icon` | `String`, `Element` | Icon for the item |
|
||
| `range` | `Array` | Default state array |
|
||
| `onRange` | `Function` | Event triggered on completion |
|
||
| `onChange` | `Function` | Event triggered on change |
|
||
| `tooltip` | `String` | Tooltip text |
|
||
|
||
```js
|
||
const range = [5, 1, 10, 1];
|
||
const value = range[0];
|
||
const min = range[1];
|
||
const max = range[2];
|
||
const step = range[3];
|
||
```
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
html: 'Slider',
|
||
tooltip: '5x',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
range: [5, 1, 10, 1],
|
||
onChange: function (item, $dom, event) {
|
||
console.info(item, $dom, event);
|
||
return item.range[0] + 'x';
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## Add
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{9-14}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
});
|
||
|
||
art.setting.show = true;
|
||
|
||
art.setting.add({
|
||
html: 'Slider',
|
||
tooltip: '5x',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
range: [5, 1, 10, 1],
|
||
});
|
||
```
|
||
|
||
## Remove
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{22}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
flip: true,
|
||
settings: [
|
||
{
|
||
name: 'slider',
|
||
html: 'Slider',
|
||
tooltip: '5x',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
range: [5, 1, 10, 1],
|
||
},
|
||
],
|
||
});
|
||
|
||
art.setting.show = true;
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Delete the setting by name
|
||
art.setting.remove('slider');
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
## Update
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{21-27}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
name: 'slider',
|
||
html: 'Slider',
|
||
tooltip: '5x',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
range: [5, 1, 10, 1],
|
||
},
|
||
],
|
||
});
|
||
|
||
art.setting.show = true;
|
||
|
||
art.on('ready', () => {
|
||
setTimeout(() => {
|
||
// Update the setting by name
|
||
art.setting.update({
|
||
name: 'slider',
|
||
html: 'PIP Mode',
|
||
tooltip: 'Close',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
switch: false,
|
||
});
|
||
}, 3000);
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/index.md =====
|
||
|
||
# Installation and Usage
|
||
|
||
## Installation
|
||
|
||
::: code-group
|
||
|
||
```bash [npm]
|
||
npm install artplayer
|
||
```
|
||
|
||
```bash [yarn]
|
||
yarn add artplayer
|
||
```
|
||
|
||
```bash [pnpm]
|
||
pnpm add artplayer
|
||
```
|
||
|
||
```bash [bun]
|
||
bun add artplayer
|
||
```
|
||
|
||
```html [script]
|
||
<script src="path/to/artplayer.js"></script>
|
||
```
|
||
|
||
:::
|
||
|
||
## `CDN`
|
||
|
||
::: code-group
|
||
|
||
```bash [jsdelivr.net]
|
||
https://cdn.jsdelivr.net/npm/artplayer/dist/artplayer.js
|
||
```
|
||
|
||
```bash [unpkg.com]
|
||
https://unpkg.com/artplayer/dist/artplayer.js
|
||
```
|
||
|
||
:::
|
||
|
||
## Usage
|
||
|
||
::: code-group
|
||
|
||
```html [index.html]
|
||
<html>
|
||
<head>
|
||
<title>ArtPlayer Demo</title>
|
||
<meta charset="UTF-8" />
|
||
<style>
|
||
.artplayer-app {
|
||
width: 400px;
|
||
height: 300px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="artplayer-app"></div>
|
||
<script src="path/to/artplayer.js"></script>
|
||
<script>
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'path/to/video.mp4',
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
:::
|
||
|
||
::: warning Note
|
||
|
||
The player's dimensions depend on the dimensions of its `container`. Therefore, your `container` must have defined dimensions.
|
||
|
||
:::
|
||
|
||
::: tip See more usage examples at the following link
|
||
|
||
[/example](https://github.com/zhw2590582/ArtPlayer/tree/master/example)
|
||
|
||
:::
|
||
|
||
## `Vue.js`
|
||
|
||
::: code-group
|
||
|
||
```vue [Artplayer.vue]
|
||
<template>
|
||
<div ref="$container" />
|
||
</template>
|
||
|
||
<script setup>
|
||
import Artplayer from 'artplayer'
|
||
import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue'
|
||
|
||
const props = defineProps({
|
||
option: {
|
||
type: Object,
|
||
required: true,
|
||
},
|
||
})
|
||
|
||
const emit = defineEmits(['getInstance'])
|
||
|
||
const art = shallowRef(null)
|
||
const $container = ref(null)
|
||
|
||
onMounted(() => {
|
||
art.value = new Artplayer({
|
||
...props.option,
|
||
container: $container.value,
|
||
})
|
||
emit('getInstance', art.value)
|
||
})
|
||
|
||
onBeforeUnmount(() => {
|
||
art.value.destroy(false)
|
||
})
|
||
</script>
|
||
```
|
||
|
||
```vue [app.vue]
|
||
<template>
|
||
<Artplayer :option="option" :style="style" @get-instance="getInstance" />
|
||
</template>
|
||
|
||
<script setup>
|
||
import { reactive } from 'vue'
|
||
import Artplayer from './Artplayer.vue'
|
||
|
||
const option = reactive({
|
||
url: 'path/to/video.mp4',
|
||
})
|
||
|
||
const style = reactive({
|
||
width: '600px',
|
||
height: '400px',
|
||
margin: '60px auto 0',
|
||
})
|
||
|
||
function getInstance(art) {
|
||
console.log(art)
|
||
}
|
||
</script>
|
||
```
|
||
|
||
:::
|
||
|
||
::: warning Artplayer is not reactive:
|
||
|
||
Directly modifying the `option` in `Vue.js` will not update the player.
|
||
|
||
:::
|
||
|
||
## `React.js`
|
||
|
||
::: code-group
|
||
|
||
```jsx [Artplayer.jsx]
|
||
import Artplayer from 'artplayer'
|
||
import { useEffect, useRef } from 'react'
|
||
|
||
export default function Player({ option, getInstance, ...rest }) {
|
||
const $container = useRef()
|
||
|
||
useEffect(() => {
|
||
const art = new Artplayer({
|
||
...option,
|
||
container: $container.current,
|
||
})
|
||
|
||
if (typeof getInstance === 'function') {
|
||
getInstance(art)
|
||
}
|
||
|
||
return () => art.destroy(false)
|
||
}, [])
|
||
|
||
return <div ref={$container} {...rest}></div>
|
||
}
|
||
```
|
||
|
||
```jsx [app.jsx]
|
||
import Artplayer from './Artplayer.jsx'
|
||
|
||
function App() {
|
||
return (
|
||
<div>
|
||
<Artplayer
|
||
option={{
|
||
url: 'path/to/video.mp4',
|
||
}}
|
||
style={{
|
||
width: '600px',
|
||
height: '400px',
|
||
margin: '60px auto 0',
|
||
}}
|
||
getInstance={art => console.log(art)}
|
||
/>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default App
|
||
```
|
||
|
||
:::
|
||
|
||
::: warning Artplayer is not reactive:
|
||
|
||
Directly modifying the `option` in `React.js` will not update the player.
|
||
|
||
:::
|
||
|
||
## TypeScript
|
||
|
||
The `artplayer.d.ts` file is automatically imported when you import `Artplayer`.
|
||
|
||
### Vue.js
|
||
|
||
```vue{3}
|
||
<script setup>
|
||
import Artplayer from 'artplayer';
|
||
const art = shallowRef<Artplayer>(null);
|
||
art.value = new Artplayer();
|
||
</script>
|
||
```
|
||
|
||
### React.js
|
||
|
||
```jsx{2}
|
||
import Artplayer from 'artplayer';
|
||
const art = useRef<Artplayer>(null);
|
||
art.current = new Artplayer();
|
||
```
|
||
|
||
### Option
|
||
|
||
You can also use the type for the options.
|
||
|
||
```ts{3}
|
||
import Artplayer, { type Option } from 'artplayer';
|
||
|
||
const option: Option = {
|
||
container: '.artplayer-app',
|
||
url: './assets/sample/video.mp4',
|
||
};
|
||
|
||
option.volume = 0.5;
|
||
|
||
const art = new Artplayer(option);
|
||
```
|
||
|
||
::: tip Full TypeScript Definitions
|
||
|
||
[packages/artplayer/types](https://github.com/zhw2590582/ArtPlayer/tree/master/packages/artplayer/types)
|
||
|
||
:::
|
||
|
||
## JavaScript
|
||
|
||
Sometimes your `js` files may lose `TypeScript` type hints. In such cases, you can manually import the types.
|
||
|
||
Variable:
|
||
|
||
```js{1-3}
|
||
/**
|
||
* @type {import("artplayer")}
|
||
*/
|
||
let art = null;
|
||
```
|
||
|
||
Parameter:
|
||
|
||
```js{1-3}
|
||
/**
|
||
* @param {import("artplayer")} art
|
||
*/
|
||
function getInstance(art) {
|
||
//
|
||
}
|
||
```
|
||
|
||
Property:
|
||
|
||
```js{4-6}
|
||
export default {
|
||
data() {
|
||
return {
|
||
/**
|
||
* @type {import("artplayer")}
|
||
*/
|
||
art: null,
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Option:
|
||
|
||
```js{1-3}
|
||
/**
|
||
* @type {import("artplayer/types/option").Option}
|
||
*/
|
||
|
||
const option = {
|
||
container: '.artplayer-app',
|
||
url: './assets/sample/video.mp4',
|
||
};
|
||
|
||
option.volume = 0.5;
|
||
|
||
const art8 = new Artplayer(option);
|
||
```
|
||
|
||
## Legacy Browsers
|
||
|
||
The production build `artplayer.js` only supports the latest major version of `Chrome`: `last 1 Chrome version`.
|
||
|
||
For legacy browsers, you can use the `artplayer.legacy.js` file, which is compatible down to: `IE 11`.
|
||
|
||
```js
|
||
import Artplayer from 'artplayer/legacy'
|
||
```
|
||
|
||
::: code-group
|
||
|
||
```bash [jsdelivr.net]
|
||
https://cdn.jsdelivr.net/npm/artplayer/dist/artplayer.legacy.js
|
||
```
|
||
|
||
```bash [unpkg.com]
|
||
https://unpkg.com/artplayer/dist/artplayer.legacy.js
|
||
```
|
||
|
||
:::
|
||
|
||
::: tip If you need to support even older browsers, modify the following configuration and build it yourself:
|
||
|
||
Build configuration: [scripts/build.js](https://github.com/zhw2590582/ArtPlayer/blob/master/scripts/build.js#L29)
|
||
|
||
Reference documentation: [browserslist](https://github.com/browserslist/browserslist#full-list)
|
||
|
||
:::
|
||
|
||
## ECMAScript Module
|
||
|
||
::: tip ESM Demo:
|
||
|
||
[https://artplayer.org/esm.html](https://artplayer.org/esm.html)
|
||
|
||
:::
|
||
|
||
Starting from version `5.2.6`, `artplayer` and all plugins also provide an `ESM` version in `mjs` format, such as:
|
||
|
||
- `artplayer/dist/artplayer.mjs`
|
||
- `artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs`
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>ArtPlayer ESM with Import Map</title>
|
||
<style>
|
||
#player {
|
||
width: 640px;
|
||
height: 360px;
|
||
margin: 50px auto;
|
||
border: 1px solid #ccc;
|
||
}
|
||
</style>
|
||
<script type="importmap">
|
||
{
|
||
"imports": {
|
||
"artplayer": "https://unpkg.com/artplayer/dist/artplayer.esm.js"
|
||
}
|
||
}
|
||
</script>
|
||
</head>
|
||
|
||
<body>
|
||
<div id="player"></div>
|
||
<script type="module">
|
||
import Artplayer from 'artplayer';
|
||
|
||
const art = new Artplayer({
|
||
container: '#player',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|
||
```
|
||
|
||
## Custom userAgent
|
||
|
||
Currently, the detection of whether a device is mobile is not always accurate. Sometimes you may want to adjust the player's UI by changing the `userAgent`. Therefore, starting from version `5.2.4`, a global variable `globalThis.CUSTOM_USER_AGENT` has been added.
|
||
|
||
```html
|
||
<html>
|
||
<head>
|
||
<title>ArtPlayer Demo</title>
|
||
<meta charset="UTF-8" />
|
||
<style>
|
||
.artplayer-app {
|
||
width: 400px;
|
||
height: 300px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="artplayer-app"></div>
|
||
<script>globalThis.CUSTOM_USER_AGENT = 'iphone'</script>
|
||
<script src="path/to/artplayer.js"></script>
|
||
<script>
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'path/to/video.mp4',
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
::: warning Note
|
||
|
||
You need to modify it before importing the `Artplayer` dependency for it to take effect.
|
||
|
||
:::
|
||
|
||
===== packages/artplayer-vitepress/docs/en/plugin/audio-track.md =====
|
||
|
||
# Audio Track
|
||
|
||
[中文](../../plugin/audio-track.md)
|
||
|
||
Play a separate audio file in sync with a video. The plugin creates an `HTMLAudioElement` and follows the main video's playback, pause, position, volume and playback rate. It requires no additional SDK and does not add an audio-selection menu.
|
||
|
||
This page describes the current refactor branch. Its lifecycle fixes and precise `/runtime` types are not yet published; an unpinned npm or CDN installation does not select this branch.
|
||
|
||
## Installation
|
||
|
||
```sh
|
||
yarn add artplayer artplayer-plugin-audio-track
|
||
```
|
||
|
||
```js
|
||
import Artplayer from 'artplayer';
|
||
import artplayerPluginAudioTrack from 'artplayer-plugin-audio-track';
|
||
```
|
||
|
||
For script tags, load ArtPlayer before the plugin's `dist/artplayer-plugin-audio-track.js`. The global is `artplayerPluginAudioTrack`. Pin dependency versions and supply an audio URL the browser can access and decode.
|
||
|
||
## Complete example
|
||
|
||
This is the same code as the [online audio example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-audio-track/index.js&example=audio.track). The demo site supplies the media files and `.artplayer-app` container; replace both when integrating it into your application.
|
||
|
||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-audio-track/index.js"></div>
|
||
|
||
```js
|
||
// npm i artplayer-plugin-audio-track
|
||
// import artplayerPluginAudioTrack from 'artplayer-plugin-audio-track';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/sprite-fight.mp4',
|
||
plugins: [
|
||
artplayerPluginAudioTrack({
|
||
url: '/assets/sample/sprite-fight.aac',
|
||
offset: 0,
|
||
sync: 0.3,
|
||
}),
|
||
],
|
||
});
|
||
```
|
||
|
||
## Options and synchronization
|
||
|
||
`artplayerPluginAudioTrack(option)` returns a plugin factory. The options object is required.
|
||
|
||
| Field | Type and default | Behavior |
|
||
| --- | --- | --- |
|
||
| `url` | Required `string` | Separate audio URL. An empty string at construction leaves the source unloaded. |
|
||
| `offset` | `number`, default `0` | Target audio time is video time plus this value, in seconds. A positive offset reads further ahead in the audio file. |
|
||
| `sync` | `number`, default `0.3` | Adjust audio time only when its absolute difference from the target is strictly greater than this threshold, in seconds. |
|
||
|
||
For example, video time 10 with offset 0.25 targets audio time 10.25. This corrects media-time drift; it is not a sample-accurate audio clock. Use finite, reasonable offsets and a nonnegative threshold. Negative targets or targets beyond the audio duration depend on browser media behavior; the plugin adds no delayed start, looping or silence padding.
|
||
|
||
Playback, completed seeking and playback recovery synchronize the track. Ordinary playing timeupdate events also correct drift. Buffering, source emptying, native pause, starting a seek and reaching the video's end pause the separate audio. It resumes when the main video is playing and ready to recover; canplay alone does not start audio for a paused video.
|
||
|
||
## Result and updates
|
||
|
||
After installation, access the result at `art.plugins.artplayerPluginAudioTrack`:
|
||
|
||
| Member | Behavior |
|
||
| --- | --- |
|
||
| `name` | Always `artplayerPluginAudioTrack`. |
|
||
| `audio` | The actual `HTMLAudioElement`; source updates preserve its identity. |
|
||
| `update(option)` | Synchronously updates selected fields and returns `undefined`, not a loading Promise. |
|
||
|
||
```js
|
||
const track = art.plugins.artplayerPluginAudioTrack;
|
||
track.update({ offset: 0.25, sync: 0.1 });
|
||
track.update({ url: '/audio/another-language.m4a' });
|
||
```
|
||
|
||
Changing offset or sync does not immediately force a seek; the next synchronization event uses the new values. Only a different, nonempty URL replaces the source. Reusing the same URL does not reload it, and an empty URL is not a stop or clear command. Replacing a source while the main video is playing attempts playback; observe the exposed audio element for actual loading, decoding and errors.
|
||
|
||
`art.switchUrl()` changes only the main video. Your application must keep video and audio sources paired and select the new audio with `track.update()`. Use native media events when you need to wait for readiness; `await track.update(...)` does not wait for loading.
|
||
|
||
## Volume, playback failure and destruction
|
||
|
||
The plugin does not remove the video's original sound. Use a video source without its own audio track if the separate track should provide the only sound. Player volume, mute and playback rate also apply to the separate audio. Setting `art.muted = true` mutes both; it cannot selectively mute only the main video.
|
||
|
||
Browser playback policies still apply. While the instance is active, a rejected `audio.play()` is reported through `console.warn`; it does not become a rejection from update. Successful main-video playback does not prove that the separate audio is audible. Applications can observe native playing/error events on the audio element.
|
||
|
||
Destroying ArtPlayer removes plugin subscriptions, pauses audio, removes its src attribute and releases media loading. A retained result still points to the same element, but later update calls no longer reload or play it. Your application remains responsible for listeners it adds to audio. There is no separate plugin destroy method to call.
|
||
|
||
## TypeScript
|
||
|
||
The root and `/legacy` entries preserve the old `Result.update(Option)` declaration, including its required URL, to retain parameter extraction and function-assignment behavior. Runtime updates already support partial options. Use `/runtime` for accurate partial-update types over the same implementation:
|
||
|
||
```ts
|
||
import Artplayer from 'artplayer';
|
||
import audioTrack from 'artplayer-plugin-audio-track/runtime';
|
||
|
||
const installTrack = audioTrack({ url: '/audio/dialogue.m4a' });
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/video/silent.mp4',
|
||
plugins: [(player) => {
|
||
const track = installTrack(player);
|
||
track.update({ offset: 0.25 });
|
||
return track;
|
||
}],
|
||
});
|
||
```
|
||
|
||
Named types include `Option`, `UpdateOption`, the old `Result`, `RuntimeResult` and `RuntimeFactory`. The online editor's default global retains legacy inference too. To select precise update typing, explicitly use `artplayerPluginAudioTrack as artplayerPluginAudioTrack.RuntimeFactory`. This does not create a second plugin implementation.
|
||
|
||
Actual desktop tests cover audio/video playback, pause, seeking, updates and destruction. They do not establish support for every mobile device, proxy player, audio format or long-running synchronization combination. Check browser decoding capabilities and the project's validation records for the applicable scope.
|
||
|
||
|
||
===== packages/artplayer-vitepress/docs/en/plugin/danmuku.md =====
|
||
|
||
# Danmuku
|
||
|
||
[中文说明](../../plugin/danmuku.md)
|
||
|
||
Display timed comments over the video, with an input panel, display settings and an optional heatmap.
|
||
This guide describes the current refactor branch. The `/runtime` entrypoint and refactor fixes have not yet been published to npm; unversioned CDN links still load the published release.
|
||
|
||
## Demo
|
||
|
||
[Open the full example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-danmuku/index.js&example=danmuku).
|
||
Run Code examples below use the site's local plugin build and sample media. In your application, use your own container and media URLs.
|
||
|
||
## Installation
|
||
|
||
::: code-group
|
||
|
||
```sh [npm]
|
||
npm install artplayer artplayer-plugin-danmuku
|
||
```
|
||
|
||
```sh [yarn]
|
||
yarn add artplayer artplayer-plugin-danmuku
|
||
```
|
||
|
||
```sh [pnpm]
|
||
pnpm add artplayer artplayer-plugin-danmuku
|
||
```
|
||
|
||
```html [script]
|
||
<script src="path/to/artplayer.js"></script>
|
||
<script src="path/to/artplayer-plugin-danmuku.js"></script>
|
||
```
|
||
|
||
:::
|
||
|
||
JavaScript projects can import the default factory from `artplayer-plugin-danmuku`.
|
||
Script builds expose `artplayerPluginDanmuku`; pass its result to the player's `plugins` array.
|
||
|
||
## CDN
|
||
|
||
::: code-group
|
||
|
||
```text [jsDelivr]
|
||
https://cdn.jsdelivr.net/npm/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js
|
||
```
|
||
|
||
```text [unpkg]
|
||
https://unpkg.com/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js
|
||
```
|
||
|
||
:::
|
||
|
||
## Comment structure
|
||
|
||
Only `text` is required. Leading and trailing whitespace is removed; empty comments are ignored.
|
||
|
||
```js
|
||
({
|
||
text: 'Hello!',
|
||
time: 10, // Seconds; omitted time defaults to currentTime + 0.5
|
||
mode: 0, // 0: scrolling, 1: top, 2: bottom; defaults to option.mode
|
||
color: '#FFFFFF', // Defaults to option.color
|
||
border: false,
|
||
style: {}, // CSS properties for this comment
|
||
});
|
||
```
|
||
|
||
Explicit `time: 0` is preserved. Negative times are clamped to zero. Other than 0, 1 and 2, comment modes are ignored.
|
||
|
||
## All options
|
||
|
||
Pass an option object to the factory. At runtime, `{}` is valid and all fields have defaults.
|
||
The historical root declarations still require `danmuku`; existing TypeScript projects can keep providing it. See [TypeScript](#typescript) for accurate declarations.
|
||
|
||
```js
|
||
({
|
||
danmuku: [], // Array, XML URL, Promise of an array, or function returning an array/Promise
|
||
speed: 5, // Display duration in seconds, clamped to 1–10
|
||
margin: [10, '25%'], // Top/bottom spacing: pixels or percentages
|
||
opacity: 1, // Clamped to 0–1
|
||
color: '#FFFFFF', // Default comment color
|
||
mode: 0, // Default comment mode
|
||
modes: [0, 1, 2], // Visible modes
|
||
fontSize: 25, // Pixels or a percentage of player height
|
||
antiOverlap: true,
|
||
synchronousPlayback: false, // Follow video playbackRate when enabled
|
||
mount: undefined, // Defaults to the center of the player controls
|
||
heatmap: false, // Enable at construction: true or a heatmap options object
|
||
width: 512, // Below this width, the default input panel moves below the player
|
||
points: [], // Stored option; use the points event to draw custom data
|
||
filter: () => true, // Synchronous; do not return a Promise
|
||
beforeEmit: () => true, // Input-panel submissions only; may return a Promise
|
||
beforeVisible: () => true, // Called before display; may return a Promise
|
||
visible: true,
|
||
emitter: true, // Show the input panel's sending UI
|
||
maxLength: 200, // Input length, clamped to 1–1000
|
||
lockTime: 5, // Seconds between input-panel submissions, clamped to 1–60
|
||
theme: 'dark', // 'dark' or 'light' for an external mount
|
||
OPACITY: {},
|
||
FONT_SIZE: {},
|
||
MARGIN: {},
|
||
SPEED: {},
|
||
COLOR: [],
|
||
});
|
||
```
|
||
|
||
`OPACITY`, `FONT_SIZE`, `MARGIN` and `SPEED` override slider definitions with `min`, `max` and `steps`.
|
||
Each step can contain `name`, `value`, `hide` and `show`; margin values are pairs such as `[10, '50%']`.
|
||
`COLOR` replaces the palette with an array of CSS color strings; an empty array uses the built-in palette.
|
||
|
||
## Array, XML and asynchronous input
|
||
|
||
XML input uses Bilibili's comment format. Fetching a cross-origin XML URL requires that server to allow browser access.
|
||
An input function runs without the option object as its receiver. It may return an array directly or asynchronously.
|
||
|
||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-danmuku/index.js">
|
||
▶ Run Code
|
||
</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [
|
||
artplayerPluginDanmuku({
|
||
danmuku: [{ text: 'Hello from an array', time: 1 }],
|
||
// Alternatives:
|
||
// danmuku: '/assets/sample/danmuku.xml',
|
||
// danmuku: Promise.resolve([{ text: 'From a Promise', time: 1 }]),
|
||
// danmuku: async () => [{ text: 'From a function', time: 1 }],
|
||
}),
|
||
],
|
||
});
|
||
```
|
||
|
||
## Lifecycle callbacks
|
||
|
||
Input-panel submissions run `beforeEmit → filter → beforeVisible → artplayerPluginDanmuku:visible`.
|
||
Loaded comments and direct `emit` calls run `filter → beforeVisible → artplayerPluginDanmuku:visible`.
|
||
This describes accepted comments; callbacks can reject them, and scheduling still requires playback and an available track.
|
||
|
||
| Callback | Input | Acceptance |
|
||
| --- | --- | --- |
|
||
| `beforeEmit` | Input-panel comment | Only strict `true`, or a Promise resolving to `true`, sends it |
|
||
| `filter` | Comment with time, mode, color and style filled in | A synchronous truthy result adds it to the queue |
|
||
| `beforeVisible` | Queue item | A truthy result, including an awaited result, permits display |
|
||
|
||
Normal functions receive the current option object as `this` for all three callbacks. Arrow functions retain their lexical `this`.
|
||
`emit()` does not call `beforeEmit`: perform application validation before calling it when needed.
|
||
`beforeEmit` failures are logged in the console and leave the input available for another attempt.
|
||
|
||
An asynchronous `beforeVisible` rejection emits `artplayerPluginDanmuku:error` once for that item in the current run; other items continue.
|
||
Pause/resume, reset or replacing the callback permits a retry if the item is still eligible by time.
|
||
Pausing, seeking, hiding, resetting or destroying cancels unfinished visibility preparation.
|
||
|
||
## Methods and state
|
||
|
||
The registered plugin is available synchronously as `art.plugins.artplayerPluginDanmuku`.
|
||
|
||
| Member | Behavior and return value |
|
||
| --- | --- |
|
||
| `emit(comment)` | Processes one comment for the queue; returns a Promise |
|
||
| `load()` | Reads `option.danmuku` and replaces the queue; returns a Promise |
|
||
| `load(input)` | Appends comments from the input; returns a Promise |
|
||
| `config(partialOption)` | Synchronously merges configuration |
|
||
| `hide()` / `show()` | Synchronously hides or shows the comment layer |
|
||
| `reset()` | Clears displayed comments and returns queue items to waiting; does not delete the queue |
|
||
| `mount(target)` | Moves the panel to an existing element or selector; returns `undefined` |
|
||
| `option` | Live current configuration; use `config()` for validated updates |
|
||
| `isHide` | Read-only live visibility state: `true` when hidden |
|
||
| `isStop` | Read-only live stopped state; distinct from visibility and not a media-readiness signal |
|
||
|
||
`emit/load` Promises resolve to the internal Danmuku owner. `config/hide/show/reset` return that same owner synchronously.
|
||
The owner is **different from the registered plugin facade**. Keep using the registered facade for subsequent commands.
|
||
Awaiting `emit()` means queue processing has finished, not that the comment has appeared.
|
||
|
||
### Loading and configuration
|
||
|
||
Changing `config({ danmuku: input })` does not load the new input. Follow it with `load()` to replace the queue.
|
||
Input-read failures leave the existing queue intact; failures while filtering individual rows do not guarantee an atomic rollback of the entire batch.
|
||
Independent append operations do not cancel one another. A newer replacement cancels an unfinished older replacement.
|
||
Destroy cancels pending loads. Cancelled Promises resolve to the owner without a late `loaded` or `error` event.
|
||
|
||
Fetch and response-text failures emit `artplayerPluginDanmuku:error` and reject the corresponding public `load()` Promise.
|
||
Handle rejection with `await`/`try...catch` or `.catch(...)`. Initial automatic loading observes rejection and logs a warning.
|
||
Invalid configuration leaves the current option intact. Use `mount(target)` to move the panel; changing `option.mount` through `config()` does not perform a mount.
|
||
Enable heatmap when constructing the plugin; `config({ heatmap: true })` does not create it later.
|
||
|
||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-danmuku/index.js">
|
||
▶ Run Code
|
||
</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [artplayerPluginDanmuku({ danmuku: [], emitter: false })],
|
||
});
|
||
|
||
async function updateComments() {
|
||
var plugin = art.plugins.artplayerPluginDanmuku;
|
||
plugin.config({ danmuku: [{ text: 'Replacement', time: 1 }] });
|
||
await plugin.load();
|
||
await plugin.load([{ text: 'Appended', time: 2 }]);
|
||
await plugin.emit({ text: 'Scheduled from the current time' });
|
||
plugin.hide();
|
||
console.info('Hidden:', plugin.isHide);
|
||
plugin.show();
|
||
plugin.reset();
|
||
}
|
||
updateComments().catch(console.error);
|
||
```
|
||
|
||
## External mount
|
||
|
||
Create a separate mount element before constructing the plugin. The panel moves into the controls during player fullscreen or web fullscreen and returns to its configured mount on exit.
|
||
Use `theme: 'light'` on a light background. The live `mount(target)` method requires a valid target; omitting its argument does not select the default.
|
||
Destroy releases the plugin panel; the application owns any container it created.
|
||
|
||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-danmuku/index.js">
|
||
▶ Run Code
|
||
</div>
|
||
|
||
```js
|
||
var $danmu = document.createElement('div');
|
||
document.querySelector('.artplayer-app').after($danmu);
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreenWeb: true,
|
||
plugins: [artplayerPluginDanmuku({
|
||
danmuku: [{ text: 'External input panel', time: 1 }],
|
||
mount: $danmu,
|
||
theme: 'dark',
|
||
})],
|
||
});
|
||
art.on('destroy', () => $danmu.remove());
|
||
// Move it later with art.plugins.artplayerPluginDanmuku.mount(otherElement).
|
||
```
|
||
|
||
## Heatmap
|
||
|
||
Set `heatmap: true` at construction to sample the queue automatically. A live stream does not draw a heatmap.
|
||
Dense automatic curves now fit in the bottom quarter of the chart instead of covering the video (issue #958).
|
||
Explicit finite `yMin` or `yMax` and custom points retain their coordinate mapping.
|
||
|
||
An object can set `xMin`, `xMax`, `yMin`, `yMax`, `scale`, `opacity`, `minHeight`, `sampling`, `smoothing` and `flattening`.
|
||
Defaults are `xMin: 0`, `xMax: chartWidth`, `yMin: 0`, `yMax: 128`, `scale: 0.25`, `opacity: 0.2`,
|
||
`minHeight: floor(chartHeight * 0.05)`, `sampling: max(1, floor(chartWidth / 100))`, `smoothing: 0.2`, `flattening: 0.2`.
|
||
|
||
Send `art.emit('artplayerPluginDanmuku:points', points)` to draw custom `[x, value]` pairs.
|
||
The default x-axis uses chart pixels, not seconds. Set `xMin/xMax` explicitly if supplying another coordinate range.
|
||
Rendering mutates the inner point arrays for historical compatibility: copy each pair if reusing the original data.
|
||
The stored `points` option does not draw custom data. A resize or successful load redraws the automatic curve, so resend custom data after those events when needed.
|
||
|
||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-danmuku/index.js">
|
||
▶ Run Code
|
||
</div>
|
||
|
||
```js
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [artplayerPluginDanmuku({
|
||
danmuku: [{ text: 'Heatmap example', time: 1 }],
|
||
heatmap: true,
|
||
})],
|
||
});
|
||
var points = [[0, 5], [0.25, 12], [0.5, 30], [0.75, 10], [1, 5]];
|
||
function drawPoints() {
|
||
var width = art.controls.heatmap.offsetWidth;
|
||
art.emit('artplayerPluginDanmuku:points', points.map(([ratio, value]) => [ratio * width, value]));
|
||
}
|
||
art.on('ready', drawPoints);
|
||
art.on('resize', drawPoints);
|
||
art.on('artplayerPluginDanmuku:loaded', drawPoints);
|
||
```
|
||
|
||
## Events
|
||
|
||
Subscribe with `art.on(name, callback)` and remove subscriptions with `art.off(name, callback)`.
|
||
|
||
| Event | Payload / meaning |
|
||
| --- | --- |
|
||
| `artplayerPluginDanmuku:visible` | Queue item; its `$ref` is the displayed element |
|
||
| `artplayerPluginDanmuku:loaded` | Current full queue after a successful load, including appends |
|
||
| `artplayerPluginDanmuku:error` | Original error from loading or scheduling; handle public Promise rejections separately |
|
||
| `artplayerPluginDanmuku:config` | Current configuration |
|
||
| `artplayerPluginDanmuku:start` | No payload; scheduling starts |
|
||
| `artplayerPluginDanmuku:stop` | No payload; scheduling stops |
|
||
| `artplayerPluginDanmuku:hide` | No payload; layer hidden |
|
||
| `artplayerPluginDanmuku:show` | No payload; layer shown |
|
||
| `artplayerPluginDanmuku:reset` | No payload; displayed items reset |
|
||
| `artplayerPluginDanmuku:destroy` | No payload; plugin destroyed |
|
||
| `artplayerPluginDanmuku:points` | Application-sent custom points for the heatmap |
|
||
|
||
Events are not replayed to later listeners. In particular, an initially empty array can finish loading during construction.
|
||
Subscribe before invoking a later `load()` if you need to observe its completion event.
|
||
Use `$ref.textContent` when adding text in a `visible` handler.
|
||
|
||
## TypeScript
|
||
|
||
The root and `/legacy` entrypoints keep the npm 5.3.0 declaration shapes for compatibility, including historical inaccuracies about return values.
|
||
The current branch adds `/runtime` for accurate types while loading the same runtime factory:
|
||
|
||
```ts
|
||
import Artplayer from 'artplayer';
|
||
import danmuku from 'artplayer-plugin-danmuku/runtime';
|
||
import type { RuntimeOption, Point, EventMap } from 'artplayer-plugin-danmuku/runtime';
|
||
|
||
const option: RuntimeOption = { danmuku: [], heatmap: true };
|
||
const points: Point[] = [[0, 5], [100, 10]];
|
||
const onError = (...[error]: EventMap['artplayerPluginDanmuku:error']) => console.error(error);
|
||
const art = new Artplayer({ container: '#player', url: '/video.mp4', plugins: [danmuku(option)] });
|
||
art.on('artplayerPluginDanmuku:error', onError);
|
||
```
|
||
|
||
The explicit `EventMap` describes payloads; it does not augment the core's historical event declarations automatically.
|
||
The factory also exposes the existing `icons` object for customization. Package `README.md` and `ARCHITECTURE.md` describe module ownership, maintenance commands and remaining device/combination validation.
|
||
|
||
|
||
===== packages/artplayer-vitepress/docs/en/plugin/dash-control.md =====
|
||
|
||
# DASH Control
|
||
|
||
[中文说明](../../plugin/dash-control.md)
|
||
|
||
Add video quality and audio-track menus to a dash.js player. You create and attach the SDK instance at `art.dash`; the plugin controls that instance and releases its own menus and listeners.
|
||
|
||
This guide describes the current refactor branch. Its SDK adaptation, automatic refresh and lifecycle fixes have not yet been published. An unversioned npm/CDN install still uses the published release.
|
||
|
||
## Installation
|
||
|
||
```sh
|
||
yarn add artplayer dashjs artplayer-plugin-dash-control
|
||
```
|
||
|
||
```js
|
||
import Artplayer from 'artplayer';
|
||
import dashjs from 'dashjs';
|
||
import artplayerPluginDashControl from 'artplayer-plugin-dash-control';
|
||
```
|
||
|
||
For script tags, load ArtPlayer, dash.js and `dist/artplayer-plugin-dash-control.js` before setup. The plugin global is `artplayerPluginDashControl`. Pin your dependency versions and use a browser-accessible MPD and segments.
|
||
|
||
## Complete example
|
||
|
||
The example matches the [online DASH example](https://artplayer.org/?libs=https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js%0A./uncompiled/artplayer-plugin-dash-control/index.js&example=dash.control). Replace the site's container and media URL in your application.
|
||
|
||
<div className="run-code" data-libs="https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js
|
||
./uncompiled/artplayer-plugin-dash-control/index.js"></div>
|
||
|
||
```js
|
||
// npm i dashjs
|
||
// npm i artplayer-plugin-dash-control
|
||
|
||
// import dashjs from 'dashjs';
|
||
// import artplayerPluginDashControl from 'artplayer-plugin-dash-control';
|
||
|
||
const useDash = dashjs.supportsMediaSource()
|
||
let dash
|
||
|
||
function destroyDash() {
|
||
const previous = dash
|
||
dash = undefined
|
||
if (previous)
|
||
previous.destroy()
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://media.axprod.net/TestVectors/v7-Clear/Manifest_1080p.mpd',
|
||
setting: true,
|
||
plugins: useDash
|
||
? [
|
||
artplayerPluginDashControl({
|
||
quality: {
|
||
// Show quality choices in the controls
|
||
control: true,
|
||
// Show quality choices in settings
|
||
setting: true,
|
||
// Get the quality name from level
|
||
getName: level => `${level.height}P`,
|
||
// I18n
|
||
title: 'Quality',
|
||
auto: 'Auto',
|
||
},
|
||
audio: {
|
||
// Show audios in control
|
||
control: true,
|
||
// Show audios in setting
|
||
setting: true,
|
||
// Get the audio name from track
|
||
getName: track => track.lang?.toUpperCase() || String(track.id ?? 'Audio'),
|
||
// I18n
|
||
title: 'Audio',
|
||
auto: 'Auto',
|
||
},
|
||
}),
|
||
]
|
||
: [],
|
||
customType: {
|
||
mpd: function playMpd(video, url, art) {
|
||
destroyDash()
|
||
if (useDash) {
|
||
dash = dashjs.MediaPlayer().create()
|
||
art.dash = dash
|
||
dash.initialize(video, url, art.option.autoplay)
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: mpd'
|
||
}
|
||
},
|
||
},
|
||
})
|
||
|
||
art.on('destroy', destroyDash)
|
||
```
|
||
|
||
The example chooses its SDK capability path once per player. If dash.js cannot use MediaSource, it displays the existing unsupported-format notice without creating an SDK or installing its controls. This example does not provide a native DASH fallback.
|
||
|
||
## Configuration
|
||
|
||
`artplayerPluginDashControl(option?)` synchronously returns a plugin factory. Both `quality` and `audio` accept:
|
||
|
||
| Field | Meaning and default |
|
||
| --- | --- |
|
||
| `control` | Display a bottom control; omitted means hidden. |
|
||
| `setting` | Display a settings entry; omitted means hidden. Also enable the player's `setting: true`. |
|
||
| `title` | Menu title, default `Quality` or `Audio`. |
|
||
| `auto` | Fallback text, default `Auto`; quality also uses it for its automatic selection row. It does not create a synthetic audio track. |
|
||
| `getName(item)` | Return a string from the original SDK level or track. It receives one argument, with no player receiver or index. |
|
||
|
||
The default quality label is `level.height + 'p'`. Default audio labels use `track.lang` or `track.id`; metadata may be missing or null. A custom formatter should return a string fallback, as the complete example does. Empty title/Auto text uses the default.
|
||
|
||
Equal text labels collapse into one displayed choice. Include bitrate or other metadata when several variants have the same height and should remain separate choices. A selected duplicate keeps the actual selected SDK key or track object. Empty track lists remove their menus.
|
||
|
||
## Quality and audio selection
|
||
|
||
Manual quality selection disables video Auto switching, then selects the SDK quality. Auto enables video Auto switching without overwriting unrelated ABR settings. A synchronous menu selection does not mean buffering or decoding has completed.
|
||
|
||
The plugin detects the SDK's available method family:
|
||
|
||
| SDK interface | Quality list and selection |
|
||
| --- | --- |
|
||
| dash.js 4 style | `getBitrateInfoListFor('video')`, `getQualityFor('video')`, `setQualityFor('video', qualityIndex)` |
|
||
| dash.js 5 style | `getRepresentationsByType('video')`, `getCurrentRepresentationForType('video')`, `setRepresentationForTypeById('video', id)` |
|
||
|
||
For the representation interface, selection uses the representation ID, including numeric zero. Do not substitute the index of a filtered array. You do not need to configure a version switch in the plugin.
|
||
|
||
Audio selection calls `setCurrentTrack()` with the original SDK track object. It matches the current track by object identity or an unambiguous combination of available id/index/lang fields. There is no extra Auto audio row.
|
||
|
||
## Refresh after external changes
|
||
|
||
Player `ready`/`restart` and SDK quality, track and stream events refresh menus. SDK event refreshes are coalesced after the current synchronous selection. Unchanged playback-time events do not redraw menus; they can detect an external Auto-setting change.
|
||
|
||
When changing SDK configuration while paused without a subsequent SDK event, refresh explicitly:
|
||
|
||
```js
|
||
art.plugins.artplayerPluginDashControl.update();
|
||
```
|
||
|
||
`update()` is synchronous and returns `undefined`. It requires `art.dash` to be attached to the player's video and can throw if that contract is not met. Assigning a different `art.dash` alone does not subscribe to it immediately; call `update()` or use the normal ready/restart flow after attachment.
|
||
|
||
Automatic refresh preserves an open, plugin-owned quality or audio settings panel. Explicit `update()` keeps its existing rebuild behavior. Reserve `dash-quality` and `dash-audio` for the plugin's menu names.
|
||
|
||
If an asynchronous SDK getter or formatter fails, the plugin warns, stops that observation and clears its menus. Fix the formatter/SDK state and call `update()` to recover. Explicit update and synchronous selection errors keep their normal throwing behavior.
|
||
|
||
## SDK ownership and source switching
|
||
|
||
Use the existing player `switchUrl()` or `switchQuality()` and handle its Promise. The complete example destroys the replaced SDK, assigns the new instance before initialization, and keeps one final player cleanup listener. It does not accumulate a new destroy listener on every load or destroy replaced engines again at the end.
|
||
|
||
The plugin does not own your SDK: it never calls `dash.destroy()`, changes the manifest URL or removes listeners belonging to other consumers. Retained callbacks from old menus become inactive after replacement or player destruction. Your application remains responsible for DRM, SDK errors, autoplay decisions and any asynchronous SDK shutdown policy its integration requires.
|
||
|
||
## TypeScript
|
||
|
||
Default callback types include quality height/width/ID/bitrate and nullable audio id/index/lang. Use the generic factory for more specific metadata. This example declares only the fields it uses and does not require importing SDK declarations:
|
||
|
||
```ts
|
||
import dashControl from 'artplayer-plugin-dash-control';
|
||
|
||
interface Level { height: number; bitrateInKbit?: number }
|
||
interface Track { id?: string | number | null; lang?: string | null }
|
||
|
||
const plugin = dashControl<Level, Track>({
|
||
quality: {
|
||
control: true,
|
||
getName: level => level.height + 'p',
|
||
},
|
||
audio: {
|
||
setting: true,
|
||
getName: track => track.lang?.toUpperCase() || String(track.id ?? 'Audio'),
|
||
},
|
||
});
|
||
```
|
||
|
||
`Option`, `Config`, `QualityLevel`, `AudioTrack` and `Result` are exported from the root. Root and legacy paths remain available. If using actual SDK declarations, dash.js 4.5.2 exposes `BitrateInfo` for quality; 5.2.1 uses `Representation`. Its declarations have different compiler/module-resolution requirements, so test your actual SDK and TypeScript combination. Describe the externally attached `art.dash` in your application's integration types.
|
||
|
||
## Validation scope
|
||
|
||
The refactor tests fixed dash.js 4.5.2 and 5.2.1 with local adaptive media and old/new core combinations. Those are tested points, not a new blanket support range. The plugin includes a targeted 4.5.2 paused-seek recovery for stale empty-buffer metrics while preserving the caller's SDK settings and media time. Windows Playwright WebKit lacks the MSE path used by these tests; it is not Safari/device playback acceptance. Test your own MPDs, DRM and target devices before adopting the unpublished refactor.
|
||
|
||
|
||
===== packages/artplayer-vitepress/docs/en/plugin/hls-control.md =====
|
||
|
||
# HLS Control
|
||
|
||
[中文说明](../../plugin/hls-control.md)
|
||
|
||
Add quality and audio-track menus to an Hls.js player. This plugin controls the Hls.js instance you provide at `art.hls`; it does not download, create or destroy the SDK.
|
||
|
||
This guide describes the current refactor branch. The automatic refresh and lifecycle fixes described here have not yet been published. An unversioned npm/CDN install still uses the published release.
|
||
|
||
## Installation
|
||
|
||
```sh
|
||
yarn add artplayer hls.js artplayer-plugin-hls-control
|
||
```
|
||
|
||
```js
|
||
import Artplayer from 'artplayer';
|
||
import Hls from 'hls.js';
|
||
import artplayerPluginHlsControl from 'artplayer-plugin-hls-control';
|
||
```
|
||
|
||
For script tags, load ArtPlayer, Hls.js and the plugin's `dist/artplayer-plugin-hls-control.js` before running your setup. The plugin global is `artplayerPluginHlsControl`. Pin versions in your application and use media URLs that permit browser access.
|
||
|
||
## Complete example
|
||
|
||
The example uses the site's player container and the same source as the [online HLS example](https://artplayer.org/?libs=https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js%0A./uncompiled/artplayer-plugin-hls-control/index.js&example=hls.control). Replace the container and stream URL in your application.
|
||
|
||
<div className="run-code" data-libs="https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js
|
||
./uncompiled/artplayer-plugin-hls-control/index.js"></div>
|
||
|
||
```js
|
||
// npm i hls.js
|
||
// npm i artplayer-plugin-hls-control
|
||
|
||
// import Hls from 'hls.js';
|
||
// import artplayerPluginHlsControl from 'artplayer-plugin-hls-control';
|
||
|
||
const useHls = Hls.isSupported()
|
||
let hls
|
||
|
||
function destroyHls() {
|
||
const previous = hls
|
||
hls = undefined
|
||
if (previous)
|
||
previous.destroy()
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8',
|
||
setting: true,
|
||
plugins: useHls
|
||
? [
|
||
artplayerPluginHlsControl({
|
||
quality: {
|
||
// Show quality choices in the controls
|
||
control: true,
|
||
// Show quality choices in settings
|
||
setting: true,
|
||
// Get the quality name from level
|
||
getName: level => `${level.height}P`,
|
||
// I18n
|
||
title: 'Quality',
|
||
auto: 'Auto',
|
||
},
|
||
audio: {
|
||
// Show audios in control
|
||
control: true,
|
||
// Show audios in setting
|
||
setting: true,
|
||
// Get the audio name from track
|
||
getName: track => track.name || track.lang || 'Audio',
|
||
// I18n
|
||
title: 'Audio',
|
||
auto: 'Auto',
|
||
},
|
||
}),
|
||
]
|
||
: [],
|
||
customType: {
|
||
m3u8: function playM3u8(video, url, art) {
|
||
destroyHls()
|
||
if (useHls) {
|
||
hls = new Hls()
|
||
art.hls = hls
|
||
hls.loadSource(url)
|
||
hls.attachMedia(video)
|
||
}
|
||
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||
video.src = url
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: m3u8'
|
||
}
|
||
},
|
||
},
|
||
})
|
||
|
||
art.on('destroy', destroyHls)
|
||
```
|
||
|
||
Only install the control plugin when Hls.js is supported. If the browser instead plays HLS natively, the example assigns `video.src` without installing a plugin that requires `art.hls`. Native quality/audio selection is not supplied by this plugin. Keep `useHls` fixed for that player instance; recreate the player if the playback integration changes.
|
||
|
||
## Configuration
|
||
|
||
`artplayerPluginHlsControl(option?)` returns a synchronous plugin factory. Both `quality` and `audio` accept these fields:
|
||
|
||
| Field | Meaning and default |
|
||
| --- | --- |
|
||
| `control` | Show the bottom control; omitted means hidden. |
|
||
| `setting` | Show the settings entry; omitted means hidden. Enable the player's `setting: true` as well. |
|
||
| `title` | Menu title; quality defaults to `Quality`, audio to `Audio`. |
|
||
| `auto` | Fallback text, default `Auto`. Quality also uses it for its Auto option. Audio does not gain a synthetic Auto track. |
|
||
| `getName(item, index?)` | Return a string from the original SDK level or track. The current-label call omits `index`; list calls include it. |
|
||
|
||
Without a quality formatter, labels use `level.name` or `level.height + 'P'`. Audio labels use `track.name`, `track.lang`, then `track.language`. Empty titles/Auto text fall back to their defaults. Give formatters a string fallback when your source lacks metadata.
|
||
|
||
The formatter is a plain callback; it does not receive the player as `this`. Avoid using its optional index as a required field. Equal labels collapse into one displayed choice, so include bitrate or other distinguishing metadata when separate variants have the same height. Empty track lists remove their menus.
|
||
|
||
Choosing a quality writes `hls.currentLevel`; Auto writes `-1`. The selected label reflects automatic mode when `autoLevelEnabled` is true. Choosing audio writes `hls.audioTrack` with the SDK track ID. A menu selection is synchronous and does not mean the new stream has finished buffering or decoding.
|
||
|
||
## Refresh after external changes
|
||
|
||
The plugin updates on player `ready` and `restart`. When the SDK provides its event API, manifest, level, audio and destruction events also refresh or clear the menus. Current SDK state determines the selected choice.
|
||
|
||
After attaching a replacement instance to the same video and assigning `art.hls`, use the existing synchronous method when an immediate refresh is needed:
|
||
|
||
```js
|
||
art.plugins.artplayerPluginHlsControl.update();
|
||
```
|
||
|
||
`update()` returns `undefined`; it is not a Promise. Calling it without an attached Hls.js instance can throw. SDK-like integrations without supported event hooks must call it when their state changes. Reserve menu names `hls-quality` and `hls-audio` for this plugin.
|
||
|
||
## SDK ownership and source switching
|
||
|
||
Use the player's existing `switchUrl()` or `switchQuality()` for source changes and handle the returned Promise. The example's custom loader destroys the previous SDK before creating the next one, updates `art.hls`, and keeps one final cleanup listener per player. Each instance is destroyed once. Do not add a new player `destroy` listener on every load while also destroying replaced instances yourself.
|
||
|
||
The control plugin releases its own SDK subscriptions and makes retained menu callbacks inert after replacement or player destruction. It does not destroy the SDK, remove other consumers' SDK listeners, or implement Hls.js error recovery. Your application remains responsible for SDK fatal errors and playback policy.
|
||
|
||
## TypeScript
|
||
|
||
The default callback types include level height/name and audio id/name/language fields. Applications can specify their actual SDK metadata types through the existing generic factory. The example below uses only fields it needs and works without importing Hls.js declarations:
|
||
|
||
```ts
|
||
import hlsControl from 'artplayer-plugin-hls-control';
|
||
|
||
interface Level { height: number; bitrate: number }
|
||
interface Track { id: number; name: string; lang?: string }
|
||
|
||
const plugin = hlsControl<Level, Track>({
|
||
quality: {
|
||
control: true,
|
||
getName: level => level.height + 'p / ' + level.bitrate,
|
||
},
|
||
audio: {
|
||
setting: true,
|
||
getName: track => track.name || track.lang || 'Audio',
|
||
},
|
||
});
|
||
```
|
||
|
||
Public `Option`, `Config`, `QualityLevel`, `AudioTrack` and `Result` types are exported from the root entry. The root and legacy import paths remain available. The types do not pretend every ArtPlayer instance already owns an Hls.js engine; describe `art.hls` in your application's integration types.
|
||
|
||
## Validation scope
|
||
|
||
The refactor tests Hls.js 1.5.17 and 1.7.2 with local media and real workers; these are tested points, not a newly declared supported range. Firefox grouped-stream crashes and a separate switching stall remain under investigation. Windows Playwright WebKit lacks the MSE path used in those tests; it does not establish Safari/iOS native-HLS acceptance. Verify your actual streams and target devices before adopting the unpublished refactor.
|
||
|
||
|
||
===== packages/artplayer-vitepress/docs/en/plugin/vtt-thumbnail.md =====
|
||
|
||
# VTT Thumbnail
|
||
|
||
[中文](../../plugin/vtt-thumbnail.md)
|
||
|
||
Load a WebVTT thumbnail index and show the selected sprite region when hovering over the progress bar. Generate the index and images beforehand; this plugin does not scan the video or require another SDK.
|
||
|
||
This page describes the current refactor branch. Parser and lifecycle fixes and the precise `/runtime` types are not published yet. An unpinned npm or CDN installation is not evidence of this branch's behavior.
|
||
|
||
## Installation
|
||
|
||
```sh
|
||
yarn add artplayer artplayer-plugin-vtt-thumbnail
|
||
```
|
||
|
||
```js
|
||
import Artplayer from 'artplayer';
|
||
import artplayerPluginVttThumbnail from 'artplayer-plugin-vtt-thumbnail';
|
||
```
|
||
|
||
For script loading, load ArtPlayer first, followed by `dist/artplayer-plugin-vtt-thumbnail.js`. The global is `artplayerPluginVttThumbnail`. Pin dependency versions and make the VTT and images accessible. Cross-origin VTT requests require appropriate server CORS headers.
|
||
|
||
## Complete example
|
||
|
||
This is the exact code from the [online thumbnail example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vtt-thumbnail/index.js&example=vtt.thumbnail). The demo site supplies the media and `.artplayer-app` container; replace them in your application.
|
||
|
||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-vtt-thumbnail/index.js"></div>
|
||
|
||
```js
|
||
// npm i artplayer-plugin-vtt-thumbnail
|
||
// import artplayerPluginVttThumbnail from 'artplayer-plugin-vtt-thumbnail';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/bbb-video.mp4',
|
||
plugins: [
|
||
artplayerPluginVttThumbnail({
|
||
vtt: '/assets/sample/bbb-thumbnails.vtt',
|
||
}),
|
||
],
|
||
})
|
||
```
|
||
|
||
## Options
|
||
|
||
The options object passed to `artplayerPluginVttThumbnail(option)` is required.
|
||
|
||
| Field | Type | Behavior |
|
||
| --- | --- | --- |
|
||
| `vtt` | `string`, optional in the declaration | VTT file URL. Supply a valid URL in practice: omission fetches an empty URL, meaning the current page, rather than disabling the plugin. |
|
||
| `style` | Optional `Partial<CSSStyleDeclaration>` | Initial inline styles on the thumbnail control, such as `borderRadius: '4px'`. |
|
||
|
||
Rendering updates display, width, height, left, backgroundImage and backgroundPosition. Initial styles cannot permanently override these properties. Each cue supplies the crop dimensions; the plugin does not automatically scale the sprite.
|
||
|
||
## Index format and image paths
|
||
|
||
```text
|
||
WEBVTT
|
||
|
||
00:00.000 --> 00:05.000
|
||
bbb-sprite.jpg#xywh=0,0,128,72
|
||
|
||
00:05.000 --> 00:10.000
|
||
bbb-sprite.jpg#xywh=128,0,128,72
|
||
```
|
||
|
||
The four values `x,y,w,h` are the left position, top position, width and height within the image, in pixels. x/y must be nonnegative and w/h positive; all four must be finite numbers. Each cue has one image URL line with a crop fragment. Ordinary subtitle text is not a thumbnail index.
|
||
|
||
Relative images are joined to the directory of the **supplied VTT URL**. For example, `bbb-sprite.jpg` inside `/assets/sample/bbb-thumbnails.vtt` becomes `/assets/sample/bbb-sprite.jpg`. Root-relative URLs and full URLs with supported protocols are kept as supplied. The directory is not recalculated from a redirected HTTP response URL. Prefer explicit image URLs when redirects or complex relative paths are involved.
|
||
|
||
The parser supports a BOM, common line endings, optional cue identifiers and timing settings, and skips NOTE, STYLE and REGION blocks. It is a thumbnail index parser, not a complete WebVTT subtitle layout engine.
|
||
|
||
## Timing and display boundaries
|
||
|
||
For historical compatibility, start and end times are rounded down to whole seconds. Both interval endpoints are included, and the first matching cue in file order wins. At exactly 5 seconds in the example above, the first image still applies; the second appears after 5 seconds. Do not assume millisecond precision or exclusive end times.
|
||
|
||
Desktop hover selects a cue using the progress percentage multiplied by the video duration. Gaps hide the preview, and previews near the edges are aligned inward. The mobile path responds to progress dragging with an input event and hides about 500ms after the last drag update. Desktop coverage does not establish real touch-device support.
|
||
|
||
## Asynchronous registration, errors and cleanup
|
||
|
||
Registration fetches and parses the VTT and actually returns a Promise. Its success result contains only `name: 'artplayerPluginVttThumbnail'`. Installation through the constructor's plugins array is asynchronous; do not assume that the result is registered immediately after construction.
|
||
|
||
To wait explicitly and handle request or parse errors, call `art.plugins.add()` once after constructing the player:
|
||
|
||
```ts
|
||
import Artplayer from 'artplayer';
|
||
import thumbnails from 'artplayer-plugin-vtt-thumbnail/runtime';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/video/movie.mp4',
|
||
});
|
||
|
||
async function installThumbnails() {
|
||
try {
|
||
const result = await art.plugins.add(thumbnails({ vtt: '/video/movie.vtt' }));
|
||
console.log(result.name);
|
||
}
|
||
catch (error) {
|
||
console.error('Unable to load thumbnails', error);
|
||
}
|
||
}
|
||
void installThumbnails();
|
||
```
|
||
|
||
Request and format errors reject registration; format errors include a line number. Registration completion establishes that the VTT was parsed and the control created, not that every image has decoded. Images load when the browser displays them; a later image failure does not reject an already settled registration Promise.
|
||
|
||
There is no update, reload or independent destroy method. Switching the main video does not refetch the VTT. For a different video and thumbnail set, you can destroy and recreate the player. Removing a control is not a complete uninstall; repeated installation is not an update API.
|
||
|
||
Destroying the player cancels outstanding requests where AbortController is available, settles canceled registration, removes owned listeners and timers, and removes the control only if this installation still owns it. Cancellation still returns the name object, so the name alone does not prove an image is available. Late requests cannot remount the interface.
|
||
|
||
## TypeScript compatibility
|
||
|
||
The root and `/legacy` entrances preserve the latest published 1.1.0 synchronous return declaration and replacement-function shape, although registration is asynchronous at runtime. The `/runtime` entrance above uses the same JavaScript implementation and accurately declares the Promise and runtime `.default` self-alias. It also exposes `Option`, `Result`, `Factory` and `RuntimeFactory` types.
|
||
|
||
The older 1.0.x `export =` shape cannot preserve the same type extraction as the 1.1.0 default export. TypeScript consumers relying on those earlier CommonJS declarations should migrate to `/runtime`. NodeNext ESM consumers should also prefer this entrance to avoid the historical namespace shape retained by the root. Legal older JavaScript calls and distribution file entrances remain available.
|
||
|
||
Browser checks cover cropping and cleanup with published and candidate cores. Complete mobile, plugin combination and release-artifact acceptance remains tracked separately.
|
||
|
||
|
||
===== packages/artplayer-vitepress/docs/en/start/i18n.md =====
|
||
|
||
# Language Settings
|
||
|
||
::: danger
|
||
|
||
Due to the increasing number of bundled multilingual resources, starting from version `5.1.0`, the core `artplayer.js` code will no longer bundle any languages other than `Simplified Chinese` and `English`. You will need to manually import any other languages you require.
|
||
|
||
:::
|
||
|
||
:::warning
|
||
|
||
When a language cannot be matched, English will be displayed by default. For i18n syntax reference, see: [artplayer/types/i18n.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/i18n.d.ts)
|
||
|
||
:::
|
||
|
||
## Default Languages
|
||
|
||
The default languages are: `en`, `zh-cn`. No manual import is required.
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
lang: 'zh-cn', // or 'en'
|
||
});
|
||
```
|
||
|
||
## Importing Languages
|
||
|
||
Language files before bundling are located at: `artplayer/src/i18n/*.js`. Contributions for new languages are welcome.
|
||
|
||
Bundled language files are located at: `artplayer/dist/i18n/*.js`
|
||
|
||
::: code-group
|
||
|
||
```js [import]
|
||
import id from 'artplayer/i18n/id';
|
||
import zhTw from 'artplayer/i18n/zh-tw';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
i18n: {
|
||
id: id,
|
||
'zh-tw': zhTw,
|
||
},
|
||
lang: 'zh-tw',
|
||
});
|
||
```
|
||
|
||
```js [script]
|
||
<script src="artplayer/dist/i18n/id.js"></script>
|
||
<script src="artplayer/dist/i18n/zh-tw.js"></script>
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
i18n: {
|
||
id: window['artplayer-i18n-id'],
|
||
'zh-tw': window['artplayer-i18n-zh-tw'],
|
||
},
|
||
lang: 'zh-tw',
|
||
});
|
||
```
|
||
|
||
:::
|
||
|
||
## Adding a New Language
|
||
|
||
```js{4-9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
lang: 'your-lang',
|
||
i18n: {
|
||
'your-lang': {
|
||
Play: 'Your Play'
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
## Modifying a Language
|
||
|
||
```js
|
||
import zhTw from 'artplayer/i18n/zh-tw';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
i18n: {
|
||
// Change the default language
|
||
'zh-cn': {
|
||
Play: 'Your Play'
|
||
},
|
||
// Change the imported language
|
||
'zh-tw': {
|
||
...zhTw,
|
||
Play: 'Your Play'
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
===== packages/artplayer-vitepress/docs/en/start/option.md =====
|
||
|
||
# Basic Options
|
||
|
||
## `container`
|
||
|
||
- Type: `String, Element`
|
||
- Default: `#artplayer`
|
||
|
||
The `DOM` container where the player is mounted.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{2}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
// container: document.querySelector('.artplayer-app'),
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
You may need to set the size of the container element, for example:
|
||
|
||
```css{2-3}
|
||
.artplayer-app {
|
||
width: 400px;
|
||
height: 300px;
|
||
}
|
||
```
|
||
|
||
Or use `aspect-ratio`:
|
||
|
||
```css{2}
|
||
.artplayer-app {
|
||
aspect-ratio: 16/9;
|
||
}
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Among all options, only `container` is required.
|
||
|
||
:::
|
||
|
||
## `url`
|
||
|
||
- Type: `String`
|
||
- Default: `''`
|
||
|
||
The video source URL.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{3}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
Sometimes the `url` is not known immediately. In such cases, you can set the `url` asynchronously.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{6}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
});
|
||
|
||
setTimeout(() => {
|
||
art.url = '/assets/sample/video.mp4';
|
||
}, 1000);
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
By default, three video file formats are supported: `.mp4`, `.ogg`, `.webm`.
|
||
|
||
To play other formats like `.m3u8` or `.flv`, please refer to the `Third-party Libraries` section on the left.
|
||
|
||
:::
|
||
|
||
## `id`
|
||
|
||
- Type: `String`
|
||
- Default: `''`
|
||
|
||
The unique identifier for the player. Currently used only for playback memory `autoplayback`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{2}
|
||
var art = new Artplayer({
|
||
id: 'your-url-id',
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
});
|
||
```
|
||
|
||
## `onReady`
|
||
|
||
- Type: `Function`
|
||
- Default: `undefined`
|
||
|
||
The constructor accepts a function as the second parameter. This function is triggered when the player is successfully initialized and the video is ready to play, similar to the `ready` event.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7-9}
|
||
var art = new Artplayer(
|
||
{
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
},
|
||
function onReady(art) {
|
||
this.play()
|
||
},
|
||
);
|
||
```
|
||
|
||
Equivalent to:
|
||
|
||
```js{7-9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
});
|
||
|
||
art.on('ready', () => {
|
||
art.play();
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Inside the callback function, `this` refers to the player instance. However, if an arrow function is used for the callback, `this` will not point to the player instance.
|
||
|
||
:::
|
||
|
||
## `poster`
|
||
|
||
- Type: `String`
|
||
- Default: `''`
|
||
|
||
The video poster image, which only appears when the player is initialized and not yet playing.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
poster: '/assets/sample/poster.jpg',
|
||
});
|
||
```
|
||
|
||
## `theme`
|
||
|
||
- Type: `String`
|
||
- Default: `#f00`
|
||
|
||
The player's theme color, currently used for the `progress bar` and `highlighted elements`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
theme: '#ffad00',
|
||
});
|
||
```
|
||
|
||
## `volume`
|
||
|
||
- Type: `Number`
|
||
- Default: `0.7`
|
||
|
||
The player's default volume.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
volume: 0.5,
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
The player caches the last volume setting. Upon the next initialization (e.g., page refresh), the player will read this cached value.
|
||
|
||
:::
|
||
|
||
## `isLive`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Enable live streaming mode. This will hide the progress bar and playback time.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
isLive: true,
|
||
});
|
||
```
|
||
|
||
## `muted`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to start muted by default.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
muted: true,
|
||
});
|
||
```
|
||
|
||
## `autoplay`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to autoplay.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoplay: true,
|
||
muted: true,
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
If you want the video to autoplay immediately upon page load, `muted` must be set to `true`. For more information, please read [Autoplay Policy Changes](https://developers.google.com/web/updates/2017/09/autoplay-policy-changes).
|
||
|
||
:::
|
||
|
||
## `autoSize`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
By default, the player's dimensions fill the entire `container`, often resulting in black bars. This option automatically adjusts the player size to hide black bars, similar to `css`'s `object-fit: cover;`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoSize: true,
|
||
});
|
||
|
||
```
|
||
|
||
## `autoMini`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Automatically enters `Mini Player` mode when the player scrolls out of the browser viewport.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoMini: true,
|
||
});
|
||
```
|
||
|
||
## `loop`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to loop playback.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
loop: true,
|
||
});
|
||
```
|
||
|
||
## `flip`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the video flip function. Currently only appears in the `Settings Panel` and `Context Menu`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
flip: true,
|
||
setting: true,
|
||
});
|
||
```
|
||
|
||
## `playbackRate`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the video playback speed function. It will appear in the `Settings Panel` and `Context Menu`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
playbackRate: true,
|
||
setting: true,
|
||
});
|
||
```
|
||
|
||
## `aspectRatio`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the video aspect ratio function. It will appear in the `Settings Panel` and `Context Menu`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
aspectRatio: true,
|
||
setting: true,
|
||
});
|
||
```
|
||
|
||
## `screenshot`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the `Screenshot` function in the bottom control bar.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
screenshot: true,
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Due to browser security mechanisms, screenshotting may fail if the video source URL is cross-origin with the website.
|
||
|
||
:::
|
||
|
||
## `setting`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the toggle button for the `Settings Panel` in the bottom control bar.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
});
|
||
```
|
||
|
||
## `hotkey`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `true`
|
||
|
||
Whether to use hotkeys.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
hotkey: true,
|
||
});
|
||
```
|
||
|
||
| Hotkey | Description |
|
||
| ------- | -------------------- |
|
||
| `↑` | Increase volume |
|
||
| `↓` | Decrease volume |
|
||
| `←` | Seek forward |
|
||
| `→` | Seek backward |
|
||
| `space` | Toggle play/pause |
|
||
|
||
:::warning Note
|
||
|
||
These hotkeys only take effect after the player gains focus (e.g., after clicking on the player).
|
||
|
||
:::
|
||
|
||
## `pip`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the `Picture-in-Picture` toggle button in the bottom control bar.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
pip: true,
|
||
});
|
||
```
|
||
|
||
## `mutex`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `true`
|
||
|
||
If multiple players exist on the page simultaneously, whether only one player is allowed to play at a time.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
mutex: true,
|
||
});
|
||
```
|
||
|
||
## `backdrop`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `true`
|
||
|
||
Whether to enable the backdrop blur effect for the player UI. When enabled, overlays such as the settings panel, context menu, and volume bar will apply a `backdrop-filter` frosted glass effect for a more transparent look. However, this may cause performance or compatibility issues on some low-performance devices or older browsers.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
backdrop: false, // Disable frosted glass effect
|
||
});
|
||
```
|
||
|
||
## `fullscreen`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the player `Window Fullscreen` button in the bottom control bar.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreen: true,
|
||
});
|
||
```
|
||
|
||
## `fullscreenWeb`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the player `Web Fullscreen` button in the bottom control bar.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreenWeb: true,
|
||
});
|
||
```
|
||
|
||
## `subtitleOffset`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Subtitle time offset, ranging from `[-5s, 5s]`. Appears in the `Settings Panel`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
subtitleOffset: true,
|
||
subtitle: {
|
||
url: '/assets/sample/subtitle.srt',
|
||
},
|
||
setting: true,
|
||
});
|
||
|
||
```
|
||
|
||
## `miniProgressBar`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
A mini progress bar that only appears when the player loses focus and is playing.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
miniProgressBar: true,
|
||
});
|
||
```
|
||
|
||
## `useSSR`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to use SSR (Server-Side Rendering) mount mode. Useful if you want to pre-render the player's required HTML before the player is mounted.
|
||
|
||
You can access the player's required HTML via `Artplayer.html`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{7}
|
||
var $container = document.querySelector('.artplayer-app');
|
||
$container.innerHTML = Artplayer.html;
|
||
|
||
var art = new Artplayer({
|
||
container: $container,
|
||
url: '/assets/sample/video.mp4',
|
||
useSSR: true,
|
||
});
|
||
```
|
||
|
||
## `playsInline`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `true`
|
||
|
||
Whether to use `playsInline` mode on mobile devices.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
playsInline: true,
|
||
});
|
||
```
|
||
|
||
## `layers`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Initialize custom layers.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{5-23}
|
||
var img = '/assets/sample/layer.png';
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
layers: [
|
||
{
|
||
name: 'potser',
|
||
html: `<img style="width: 100px" src="${img}">`,
|
||
style: {
|
||
position: 'absolute',
|
||
top: '20px',
|
||
right: '20px',
|
||
opacity: '.9',
|
||
},
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
art.layers.show = false;
|
||
},
|
||
mounted: function (...args) {
|
||
console.info('mounted', args);
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
:::warning For `Component Configuration`, please refer to:
|
||
|
||
[/component/layers.html](/component/layers.html)
|
||
|
||
:::
|
||
|
||
## `settings`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Initialize custom settings panels.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{5-34}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
settings: [
|
||
{
|
||
html: 'setting01',
|
||
selector: [
|
||
{
|
||
html: 'setting01-01',
|
||
},
|
||
{
|
||
html: 'setting01-02',
|
||
},
|
||
],
|
||
onSelect: function (...args) {
|
||
console.info(args);
|
||
},
|
||
},
|
||
{
|
||
html: 'setting02',
|
||
selector: [
|
||
{
|
||
html: 'setting02-01',
|
||
},
|
||
{
|
||
html: 'setting02-02',
|
||
},
|
||
],
|
||
onSelect: function (...args) {
|
||
console.info(args);
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
:::warning For `Settings Panel`, please refer to:
|
||
|
||
[/component/setting.html](/component/setting.html)
|
||
|
||
:::
|
||
|
||
## `contextmenu`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Initialize custom context menus.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-12}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
contextmenu: [
|
||
{
|
||
html: 'your-menu',
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
art.contextmenu.show = false;
|
||
},
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
:::warning For `Component Configuration`, please refer to:
|
||
|
||
[/component/contextmenu.html](/component/contextmenu.html)
|
||
|
||
:::
|
||
|
||
## `controls`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Initialize custom bottom control bar.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-16}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
controls: [
|
||
{
|
||
position: 'left',
|
||
html: 'your-control',
|
||
tooltip: 'Your Control',
|
||
style: {
|
||
color: 'green',
|
||
},
|
||
click: function (...args) {
|
||
console.info('click', args);
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
```
|
||
|
||
:::warning For `Component Configuration`, please refer to the following address:
|
||
|
||
[/component/controls.html](/component/controls.html)
|
||
|
||
:::
|
||
|
||
## `quality`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Whether to display the `Quality Selection` list in the bottom control bar.
|
||
|
||
| Property | Type | Description |
|
||
| --------- | --------- | ---------------- |
|
||
| `default` | `Boolean` | Default quality |
|
||
| `html` | `String` | Quality name |
|
||
| `url` | `String` | Quality URL |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-14}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
quality: [
|
||
{
|
||
default: true,
|
||
html: 'SD 480P',
|
||
url: '/assets/sample/video.mp4',
|
||
},
|
||
{
|
||
html: 'HD 720P',
|
||
url: '/assets/sample/video.mp4',
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## `highlight`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Display `Highlight Information` on the progress bar.
|
||
|
||
| Property | Type | Description |
|
||
| -------- | -------- | ------------------------------- |
|
||
| `time` | `Number` | Highlight time (in seconds) |
|
||
| `text` | `String` | Highlight text |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-25}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
highlight: [
|
||
{
|
||
time: 60,
|
||
text: 'One more chance',
|
||
},
|
||
{
|
||
time: 120,
|
||
text: '谁でもいいはずなのに',
|
||
},
|
||
{
|
||
time: 180,
|
||
text: '夏の想い出がまわる',
|
||
},
|
||
{
|
||
time: 240,
|
||
text: 'こんなとこにあるはずもないのに',
|
||
},
|
||
{
|
||
time: 300,
|
||
text: '--终わり--',
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
## `plugins`
|
||
|
||
- Type: `Array`
|
||
- Default: `[]`
|
||
|
||
Initialize custom `plugins`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{15}
|
||
function myPlugin(art) {
|
||
console.info(art);
|
||
return {
|
||
name: 'myPlugin',
|
||
something: 'something',
|
||
doSomething: function () {
|
||
console.info('doSomething');
|
||
},
|
||
};
|
||
}
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [myPlugin],
|
||
});
|
||
```
|
||
|
||
## `thumbnails`
|
||
|
||
- Type: `Object`
|
||
- Default: `{}`
|
||
|
||
Set `Preview Thumbnails` on the progress bar.
|
||
|
||
| Property | Type | Description |
|
||
| -------- | -------- | -------------------------- |
|
||
| `url` | `String` | Thumbnail image URL |
|
||
| `number` | `Number` | Number of thumbnails |
|
||
| `column` | `Number` | Number of thumbnail columns|
|
||
| `width` | `Number` | Thumbnail width |
|
||
| `height` | `Number` | Thumbnail height |
|
||
| `scale` | `Number` | Thumbnail scale |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
thumbnails: {
|
||
url: '/assets/sample/thumbnails.png',
|
||
number: 60,
|
||
column: 10,
|
||
},
|
||
});
|
||
```
|
||
|
||
:::warning Generate Thumbnails Online
|
||
|
||
[artplayer-tool-thumbnail](https://artplayer.org/?libs=./uncompiled/artplayer-tool-thumbnail/index.js&example=thumbnail)
|
||
|
||
:::
|
||
|
||
## `subtitle`
|
||
|
||
- Type: `Object`
|
||
- Default: `{}`
|
||
|
||
Set video subtitles. Supported subtitle formats: `vtt`, `srt`, `ass`.
|
||
|
||
| Property | Type | Description |
|
||
| ----------- | ---------- | ------------------------------------------------ |
|
||
| `name` | `String` | Subtitle name |
|
||
| `url` | `String` | Subtitle URL |
|
||
| `type` | `String` | Subtitle type, options: `vtt`, `srt`, `ass` |
|
||
| `style` | `Object` | Subtitle style |
|
||
| `encoding` | `String` | Subtitle encoding, default `utf-8` |
|
||
| `escape` | `Boolean` | Whether to escape `html` tags, default `true` |
|
||
| `onVttLoad` | `Function` | Function for modifying `vtt` text |
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-12}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
subtitle: {
|
||
url: '/assets/sample/subtitle.srt',
|
||
type: 'srt',
|
||
encoding: 'utf-8',
|
||
escape: true,
|
||
style: {
|
||
color: '#03A9F4',
|
||
'font-size': '30px',
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
## `moreVideoAttr`
|
||
|
||
- Type: `Object`
|
||
- Default: `{'controls': false, 'preload': 'metadata'}` (In Safari, it will automatically adjust to `preload: 'auto'` for better loading experience.)
|
||
|
||
More video attributes. These attributes will be written directly into the video element.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
moreVideoAttr: {
|
||
'webkit-playsinline': true,
|
||
playsInline: true,
|
||
},
|
||
});
|
||
|
||
```
|
||
|
||
## `icons`
|
||
|
||
- Type: `Object`
|
||
- Default: `{}`
|
||
|
||
Used to replace default icons. Supports `Html` strings and `HTMLElement`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-7}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
icons: {
|
||
loading: '<img src="/assets/img/ploading.gif">',
|
||
state: '<img src="/assets/img/state.png">',
|
||
},
|
||
});
|
||
```
|
||
|
||
:::warning All Icon Definitions
|
||
|
||
[artplayer/types/icons.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/icons.d.ts)
|
||
|
||
:::
|
||
|
||
## `type`
|
||
|
||
- Type: `String`
|
||
- Default: `''`
|
||
|
||
Used to specify the video format. It needs to be used together with `customType`. By default, the video format is determined by the suffix of the video URL (e.g., `.m3u8`, `.mkv`, `.ts`). However, sometimes the video URL may not have the correct suffix, so it needs to be explicitly specified.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.m3u8',
|
||
type: 'm3u8',
|
||
});
|
||
```
|
||
|
||
:::warning Suffix Recognition
|
||
|
||
The player can only parse suffixes like this: `/assets/sample/video.m3u8`
|
||
|
||
But cannot parse suffixes like this: `/assets/sample/video?type=m3u8`
|
||
|
||
Therefore, if you use `customType`, it's best to also specify the `type`.
|
||
|
||
:::
|
||
|
||
## `customType`
|
||
|
||
- Type: `Object`
|
||
- Default: `{}`
|
||
|
||
Matches based on the video's `type` and delegates video decoding to third-party programs for processing. The processing function can receive three parameters:
|
||
|
||
- `video`: The video `DOM` element
|
||
- `url`: The video URL
|
||
- `art`: The current instance
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-8}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.m3u8',
|
||
customType: {
|
||
m3u8: function (video, url, art) {
|
||
//
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
## `lang`
|
||
|
||
- Type: `String`
|
||
- Default: `navigator.language.toLowerCase()`
|
||
|
||
The default display language. Currently supported: `en`, `zh-cn`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
lang: 'en',
|
||
});
|
||
```
|
||
|
||
:::warning More Language Settings
|
||
|
||
[/start/i18n.html](/start/i18n.html)
|
||
|
||
:::
|
||
|
||
## `i18n`
|
||
|
||
- Type: `Object`
|
||
- Default: `{}`
|
||
|
||
Custom `i18n` configuration. This configuration will be deeply merged with the built-in `i18n`.
|
||
|
||
Add your language:
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-9}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
lang: 'your-lang',
|
||
i18n: {
|
||
'your-lang': {
|
||
Play: 'Your Play'
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
Modify an existing language:
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-11}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
i18n: {
|
||
'zh-cn': {
|
||
Play: 'Your Play'
|
||
},
|
||
'zh-tw': {
|
||
Play: 'Your Play'
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
:::warning More Language Settings
|
||
|
||
[/start/i18n.html](/start/i18n.html)
|
||
|
||
:::
|
||
|
||
## `lock`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display a `lock button` on mobile devices to hide the bottom `control bar`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
lock: true,
|
||
});
|
||
```
|
||
|
||
## `gesture`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `true`
|
||
|
||
Whether to enable gesture events on the video element on mobile devices.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
gesture: false,
|
||
});
|
||
```
|
||
|
||
## `fastForward`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to add a long-press video fast-forward feature on mobile devices.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fastForward: true,
|
||
});
|
||
```
|
||
|
||
## `autoPlayback`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to use the automatic `playback feature`.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4-5}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
id: 'your-url-id',
|
||
autoPlayback: true,
|
||
});
|
||
```
|
||
|
||
:::warning Note
|
||
|
||
Because the player uses the `url` as the `key` to cache playback progress by default.
|
||
|
||
However, if the `url` for the same video is different, then you need to use `id` to identify the unique `key` for the video.
|
||
|
||
:::
|
||
|
||
## `autoOrientation`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to rotate the player in fullscreen mode on mobile web, based on the video dimensions and viewport dimensions.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoOrientation: true,
|
||
});
|
||
```
|
||
|
||
## `airplay`
|
||
|
||
- Type: `Boolean`
|
||
- Default: `false`
|
||
|
||
Whether to display the `airplay` button. Currently, only some browsers support this feature.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
airplay: true,
|
||
});
|
||
```
|
||
|
||
## `cssVar`
|
||
|
||
- Type: `Object`
|
||
- Default: `{}`
|
||
|
||
Used to modify the built-in CSS variables.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
cssVar: {
|
||
//
|
||
},
|
||
});
|
||
```
|
||
|
||
:::warning Reference for `cssVar` Syntax
|
||
|
||
[artplayer/types/cssVar.d.ts](https://github.com/zhw2590582/ArtPlayer/blob/master/packages/artplayer/types/cssVar.d.ts)
|
||
|
||
:::
|
||
|
||
## `proxy`
|
||
|
||
- Type: `function`
|
||
- Default: `undefined`
|
||
|
||
The function can return a third-party `HTMLCanvasElement` or `HTMLVideoElement`. For example, it can proxy an existing `video` DOM element.
|
||
|
||
<div className="run-code">▶ Run Code</div>
|
||
|
||
```js{4}
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
proxy: () => document.createElement('video')
|
||
});
|
||
```
|
||
|
||
===== Type Definitions Overview =====
|
||
|
||
===== docs/assets/ts/artplayer-plugin-ads.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginAds {
|
||
interface Translations {
|
||
close: string
|
||
countdown: string
|
||
detail: string
|
||
canBeClosed: string
|
||
}
|
||
/** Implemented options. Video takes precedence over HTML. */
|
||
interface Option {
|
||
html?: string
|
||
video?: string
|
||
url?: string
|
||
/** Seconds before the close button becomes available. @default 5 */
|
||
playDuration?: number
|
||
/** Total advertisement duration in seconds. @default 10 */
|
||
totalDuration?: number
|
||
/** Initial ad-video mute state. @default false */
|
||
muted?: boolean
|
||
/** All four fields replace the default translation object together. */
|
||
i18n?: Translations
|
||
}
|
||
/** Historical published declaration. String durations still fail runtime validation. */
|
||
interface LegacyOption extends Omit<Option, 'totalDuration'> {
|
||
/** @deprecated Incorrect in the old declaration; use a numeric duration. */
|
||
totalDuration?: string
|
||
}
|
||
/** Historical unpublished workspace declaration; these fields are not runtime aliases. */
|
||
interface WorkspaceOption extends Option {
|
||
/** @deprecated Ignored by the runtime. Use html or video instead. */
|
||
source: string
|
||
/** @deprecated Ignored by the runtime. Images are supplied through html. */
|
||
type: 'video' | 'image' | 'html'
|
||
}
|
||
/** Input acceptance for both historical declaration families. */
|
||
interface CompatOption extends Omit<Option, 'totalDuration'> {
|
||
/** @deprecated The string branch exists for old types only and is rejected at runtime. */
|
||
totalDuration?: number | string
|
||
/** @deprecated Ignored by the runtime. Use html or video instead. */
|
||
source?: string
|
||
/** @deprecated Ignored by the runtime. Images are supplied through html. */
|
||
type?: 'video' | 'image' | 'html'
|
||
}
|
||
interface Result {
|
||
name: 'artplayerPluginAds'
|
||
/** Complete once; before initialization this cancels the pending preroll. */
|
||
skip: () => void
|
||
/** Pause only the countdown, leaving ad video playback unchanged. */
|
||
pause: () => void
|
||
/** Resume only the countdown without adding extra timers. */
|
||
play: () => void
|
||
}
|
||
interface Callable {
|
||
(option?: Option): (art: Artplayer) => Result
|
||
/** @deprecated Compatibility with erroneous old string-duration declarations only. */
|
||
(option: LegacyOption): (art: Artplayer) => Result
|
||
(option: WorkspaceOption): (art: Artplayer) => Result
|
||
(option?: CompatOption): (art: Artplayer) => Result
|
||
/** Required final signature keeps Parameters extraction free of top-level undefined. */
|
||
(option: CompatOption): (art: Artplayer) => Result
|
||
}
|
||
interface Factory extends Callable {
|
||
/** Same function; supports historical require(package).default calls. */
|
||
readonly default: Callable
|
||
}
|
||
interface RuntimeCallable {
|
||
(option?: Option): (art: Artplayer) => Result
|
||
(option: Option): (art: Artplayer) => Result
|
||
}
|
||
/** Accurate typing for the identical implementation at /runtime. */
|
||
interface RuntimeFactory extends RuntimeCallable {
|
||
readonly default: RuntimeCallable
|
||
}
|
||
}
|
||
declare const artplayerPluginAds: artplayerPluginAds.Factory
|
||
export = artplayerPluginAds
|
||
export as namespace artplayerPluginAds;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-ambilight.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginAmbilightDefinitions {
|
||
export interface Option {
|
||
/** CSS blur radius. @default '50px' */
|
||
blur?: string
|
||
/** Grid cell opacity. @default 0.5 */
|
||
opacity?: number
|
||
/** Maximum sampling frequency in frames per second. @default 10 */
|
||
frequency?: number
|
||
/** Historical input retained for compatibility; runtime uses a fixed z-index of 9. */
|
||
zIndex?: number
|
||
/** Background color transition duration in seconds. @default 0.3 */
|
||
duration?: number
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginAmbilight'
|
||
/** Start sampling; does nothing after the player is destroyed. */
|
||
start: () => void
|
||
/** Stop sampling while retaining the last colors. */
|
||
stop: () => void
|
||
}
|
||
/** Published 1.1.0 factory shape; the options argument remains required. */
|
||
export type Callable = (option: Option) => (art: Artplayer) => Result
|
||
export type Factory = Callable
|
||
/** Accurate optional invocation and CommonJS self alias, exposed by /runtime. */
|
||
export interface RuntimeFactory {
|
||
(option?: Option): (art: Artplayer) => Result
|
||
readonly default: RuntimeFactory
|
||
}
|
||
export const artplayerPluginAmbilight: (option: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginAmbilight: typeof artplayerPluginAmbilightDefinitions.artplayerPluginAmbilight
|
||
declare namespace artplayerPluginAmbilight {
|
||
export type Option = artplayerPluginAmbilightDefinitions.Option
|
||
export type Result = artplayerPluginAmbilightDefinitions.Result
|
||
export type Callable = artplayerPluginAmbilightDefinitions.Callable
|
||
export type Factory = artplayerPluginAmbilightDefinitions.Factory
|
||
export type RuntimeFactory = artplayerPluginAmbilightDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginAmbilight
|
||
export as namespace artplayerPluginAmbilight;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-asr.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginAsrDefinitions {
|
||
export interface AudioChunk {
|
||
pcm: ArrayBuffer
|
||
wav: ArrayBuffer
|
||
}
|
||
export interface AsrPluginOption {
|
||
length?: number
|
||
interval?: number
|
||
sampleRate?: number
|
||
autoHideTimeout?: number
|
||
onAudioChunk?: (chunk: AudioChunk) => void | Promise<void>
|
||
}
|
||
export interface AsrPluginInstance {
|
||
name: 'artplayerPluginAsr'
|
||
stop: () => void
|
||
hide: () => void
|
||
append: (subtitle: string) => void
|
||
}
|
||
/** Historical factory shape, including void stop and callback results. */
|
||
export type Factory = (option?: AsrPluginOption) => (art: Artplayer) => AsrPluginInstance
|
||
/** Accurate asynchronous view available through the /runtime entry. */
|
||
export interface RuntimeOption extends Omit<AsrPluginOption, 'onAudioChunk'> {
|
||
/** Capture the media stream without taking ownership of its playback route. */
|
||
audioInput?: {
|
||
type: 'capture'
|
||
}
|
||
onAudioChunk?: (chunk: AudioChunk) => string | void | null | Promise<string | void | null>
|
||
}
|
||
export interface RuntimeResult extends Omit<AsrPluginInstance, 'stop'> {
|
||
stop: () => Promise<void>
|
||
}
|
||
export interface RuntimeFactory {
|
||
(option?: RuntimeOption): (art: Artplayer) => RuntimeResult
|
||
readonly default: RuntimeFactory
|
||
}
|
||
export function artplayerPluginAsr(option?: AsrPluginOption): (art: Artplayer) => AsrPluginInstance
|
||
}
|
||
declare const artplayerPluginAsr: typeof artplayerPluginAsrDefinitions.artplayerPluginAsr
|
||
declare namespace artplayerPluginAsr {
|
||
export type AudioChunk = artplayerPluginAsrDefinitions.AudioChunk
|
||
export type AsrPluginOption = artplayerPluginAsrDefinitions.AsrPluginOption
|
||
export type AsrPluginInstance = artplayerPluginAsrDefinitions.AsrPluginInstance
|
||
export type Factory = artplayerPluginAsrDefinitions.Factory
|
||
export type RuntimeOption = artplayerPluginAsrDefinitions.RuntimeOption
|
||
export type RuntimeResult = artplayerPluginAsrDefinitions.RuntimeResult
|
||
export type RuntimeFactory = artplayerPluginAsrDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginAsr
|
||
export as namespace artplayerPluginAsr;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-audio-track.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginAudioTrackDefinitions {
|
||
export interface Option {
|
||
/**
|
||
* Audio track URL
|
||
*/
|
||
url: string
|
||
/**
|
||
* Time offset in seconds between video and audio
|
||
* Positive value means audio plays ahead of video
|
||
* Negative value means audio plays behind video
|
||
* @default 0
|
||
*/
|
||
offset?: number
|
||
/**
|
||
* Synchronization threshold in seconds
|
||
* @default 0.3
|
||
*/
|
||
sync?: number
|
||
}
|
||
export type UpdateOption = Partial<Option>
|
||
export interface Result {
|
||
name: 'artplayerPluginAudioTrack'
|
||
/**
|
||
* The audio element
|
||
*/
|
||
audio: HTMLAudioElement
|
||
/**
|
||
* Historical update signature. Runtime also accepts partial options.
|
||
* Import the /runtime entry for the precise partial-update signature.
|
||
*/
|
||
update: (option: Option) => void
|
||
}
|
||
export interface RuntimeResult extends Result {
|
||
/** Update selected fields without replacing the audio element. */
|
||
update: (option: UpdateOption) => void
|
||
}
|
||
/** Precise typing for the same runtime factory, without changing legacy inference. */
|
||
export type RuntimeFactory = (option: Option) => (art: Artplayer) => RuntimeResult
|
||
export function artplayerPluginAudioTrack(option: Option): (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginAudioTrack: typeof artplayerPluginAudioTrackDefinitions.artplayerPluginAudioTrack
|
||
declare namespace artplayerPluginAudioTrack {
|
||
export type Option = artplayerPluginAudioTrackDefinitions.Option
|
||
export type UpdateOption = artplayerPluginAudioTrackDefinitions.UpdateOption
|
||
export type Result = artplayerPluginAudioTrackDefinitions.Result
|
||
export type RuntimeResult = artplayerPluginAudioTrackDefinitions.RuntimeResult
|
||
export type RuntimeFactory = artplayerPluginAudioTrackDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginAudioTrack
|
||
export as namespace artplayerPluginAudioTrack;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-auto-thumbnail.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginAutoThumbnailDefinitions {
|
||
export interface Option {
|
||
url?: string
|
||
width?: number
|
||
number?: number
|
||
scale?: number
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginAutoThumbnail'
|
||
}
|
||
export const artplayerPluginAutoThumbnail: (option: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginAutoThumbnail: typeof artplayerPluginAutoThumbnailDefinitions.artplayerPluginAutoThumbnail
|
||
declare namespace artplayerPluginAutoThumbnail { }
|
||
export = artplayerPluginAutoThumbnail
|
||
export as namespace artplayerPluginAutoThumbnail;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-chapter.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginChapterDefinitions {
|
||
export type Chapters = {
|
||
start: number
|
||
end: number
|
||
title: string
|
||
}[]
|
||
export interface Option {
|
||
chapters?: Chapters
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginChapter'
|
||
update: (option: Option) => void
|
||
}
|
||
export const artplayerPluginChapter: (option?: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginChapter: typeof artplayerPluginChapterDefinitions.artplayerPluginChapter
|
||
declare namespace artplayerPluginChapter {
|
||
export type Chapters = artplayerPluginChapterDefinitions.Chapters
|
||
export type Option = artplayerPluginChapterDefinitions.Option
|
||
export type Result = artplayerPluginChapterDefinitions.Result
|
||
}
|
||
export = artplayerPluginChapter
|
||
export as namespace artplayerPluginChapter;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-chromecast.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginChromecastDefinitions {
|
||
export interface Option {
|
||
url?: string
|
||
sdk?: string
|
||
icon?: string
|
||
mimeType?: string
|
||
}
|
||
export interface Chromecast {
|
||
name: 'artplayerPluginChromecast'
|
||
}
|
||
/** Published 1.1.0 result; actual registration is asynchronous. */
|
||
export type Result = Chromecast
|
||
export type Factory = (option: Option) => (art: Artplayer) => Chromecast
|
||
export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'disconnecting'
|
||
export interface RuntimeOption extends Option {
|
||
onStateChange?: (this: RuntimeOption, state: ConnectionState) => void
|
||
onCastAvailable?: (this: RuntimeOption, available: boolean) => void
|
||
onCastStart?: (this: RuntimeOption) => void
|
||
onError?: (this: RuntimeOption, error: unknown) => void
|
||
}
|
||
export interface RuntimeResult extends Chromecast {
|
||
/** Last raw SDK SessionState, initially null; not the normalized callback state. */
|
||
getCastState: () => string | null
|
||
/** Whether this controller retains a session; does not prove receiver playback. */
|
||
isCasting: () => boolean
|
||
}
|
||
export interface RuntimeFactory {
|
||
(option: RuntimeOption): (art: Artplayer) => Promise<RuntimeResult>
|
||
default: RuntimeFactory
|
||
}
|
||
export const artplayerPluginChromecast: (option: Option) => (art: Artplayer) => Chromecast
|
||
}
|
||
declare const artplayerPluginChromecast: typeof artplayerPluginChromecastDefinitions.artplayerPluginChromecast
|
||
declare namespace artplayerPluginChromecast {
|
||
export type Option = artplayerPluginChromecastDefinitions.Option
|
||
export type Chromecast = artplayerPluginChromecastDefinitions.Chromecast
|
||
export type Result = artplayerPluginChromecastDefinitions.Result
|
||
export type Factory = artplayerPluginChromecastDefinitions.Factory
|
||
export type ConnectionState = artplayerPluginChromecastDefinitions.ConnectionState
|
||
export type RuntimeOption = artplayerPluginChromecastDefinitions.RuntimeOption
|
||
export type RuntimeResult = artplayerPluginChromecastDefinitions.RuntimeResult
|
||
export type RuntimeFactory = artplayerPluginChromecastDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginChromecast
|
||
export as namespace artplayerPluginChromecast;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-danmuku-mask.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginDanmukuMaskDefinitions {
|
||
export interface Option {
|
||
solutionPath?: string
|
||
modelSelection?: number
|
||
smoothSegmentation?: boolean
|
||
minDetectionConfidence?: number
|
||
minTrackingConfidence?: number
|
||
selfieMode?: boolean
|
||
drawContour?: boolean
|
||
foregroundThreshold?: number
|
||
opacity?: number
|
||
maskBlurAmount?: number
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginDanmukuMask'
|
||
start: () => Promise<void>
|
||
stop: () => void
|
||
}
|
||
export const artplayerPluginDanmukuMask: (option?: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginDanmukuMask: typeof artplayerPluginDanmukuMaskDefinitions.artplayerPluginDanmukuMask
|
||
declare namespace artplayerPluginDanmukuMask { }
|
||
export = artplayerPluginDanmukuMask
|
||
export as namespace artplayerPluginDanmukuMask;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-danmuku.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginDanmukuDefinitions {
|
||
export type Mode = 0 | 1 | 2
|
||
export type Danmuku = Danmu[] | string // URL
|
||
| (() => Promise<Danmu[]>) | Promise<Danmu[]>
|
||
export interface Slider {
|
||
min?: number
|
||
max?: number
|
||
steps?: {
|
||
name?: string
|
||
value?: number | string
|
||
show?: boolean
|
||
}[]
|
||
}
|
||
export interface Danmu {
|
||
/**
|
||
* 弹幕文本
|
||
*/
|
||
text: string
|
||
/**
|
||
* 弹幕发送模式: 0: 滚动,1: 顶部,2: 底部
|
||
*/
|
||
mode?: Mode
|
||
/**
|
||
* 弹幕颜色
|
||
*/
|
||
color?: string
|
||
/**
|
||
* 弹幕出现的时间,单位为秒
|
||
*/
|
||
time?: number
|
||
/**
|
||
* 弹幕是否有描边, 默认为 false
|
||
*/
|
||
border?: boolean
|
||
/**
|
||
* 弹幕自定义样式
|
||
*/
|
||
style?: Partial<CSSStyleDeclaration>
|
||
}
|
||
export interface Option {
|
||
/**
|
||
* 弹幕数据: 函数,数组,Promise,URL
|
||
*/
|
||
danmuku: Danmuku
|
||
/**
|
||
* 弹幕持续时间,范围在[1 ~ 10]
|
||
*/
|
||
speed?: number
|
||
/**
|
||
* 弹幕上下边距,支持像素数字和百分比
|
||
*/
|
||
margin?: [
|
||
number | `${number}%`,
|
||
number | `${number}%`,
|
||
]
|
||
/**
|
||
* 弹幕透明度,范围在[0 ~ 1]
|
||
*/
|
||
opacity?: number
|
||
/**
|
||
* 默认弹幕颜色,可以被单独弹幕项覆盖
|
||
*/
|
||
color?: string
|
||
/**
|
||
* 弹幕模式: 0: 滚动,1: 顶部,2: 底部
|
||
*/
|
||
mode?: Mode
|
||
/**
|
||
* 弹幕可见的模式
|
||
*/
|
||
modes?: Mode[]
|
||
/**
|
||
* 弹幕字体大小,支持像素数字和百分比
|
||
*/
|
||
fontSize?: number | `${number}%`
|
||
/**
|
||
* 弹幕是否防重叠
|
||
*/
|
||
antiOverlap?: boolean
|
||
/**
|
||
* 是否同步播放速度
|
||
*/
|
||
synchronousPlayback?: boolean
|
||
/**
|
||
* 弹幕发射器挂载点, 默认为播放器控制栏中部
|
||
*/
|
||
mount?: HTMLDivElement | string
|
||
/**
|
||
* 是否开启弹幕热度图
|
||
*/
|
||
heatmap?: boolean | {
|
||
xMin?: number
|
||
xMax?: number
|
||
yMin?: number
|
||
yMax?: number
|
||
scale?: number
|
||
opacity?: number
|
||
minHeight?: number
|
||
sampling?: number
|
||
smoothing?: number
|
||
flattening?: number
|
||
}
|
||
/**
|
||
* 当播放器宽度小于此值时,弹幕发射器置于播放器底部
|
||
*/
|
||
width?: number
|
||
/**
|
||
* 热力图数据
|
||
*/
|
||
points?: {
|
||
time: number
|
||
value: number
|
||
}[]
|
||
/**
|
||
* 弹幕载入前的过滤器,只支持返回布尔值
|
||
*/
|
||
filter?: (danmu: Danmu) => boolean
|
||
/**
|
||
* 弹幕发送前的过滤器,支持返回 Promise
|
||
*/
|
||
beforeEmit?: (danmu: Danmu) => boolean | Promise<boolean>
|
||
/**
|
||
* 弹幕显示前的过滤器,支持返回 Promise
|
||
*/
|
||
beforeVisible?: (danmu: Danmu) => boolean | Promise<boolean>
|
||
/**
|
||
* 弹幕是否可见
|
||
*/
|
||
visible?: boolean
|
||
/**
|
||
* 是否开启弹幕发射器
|
||
*/
|
||
emitter?: boolean
|
||
/**
|
||
* 弹幕输入框最大长度, 范围在[1 ~ 1000]
|
||
*/
|
||
maxLength?: number
|
||
/**
|
||
* 输入框锁定时间,范围在[1 ~ 60]
|
||
*/
|
||
lockTime?: number
|
||
/**
|
||
* 弹幕主题,只在自定义挂载时生效
|
||
*/
|
||
theme?: 'light' | 'dark'
|
||
/**
|
||
* 不透明度配置项
|
||
*/
|
||
OPACITY?: Slider
|
||
/**
|
||
* 弹幕速度配置项
|
||
*/
|
||
SPEED?: Slider
|
||
/**
|
||
* 显示区域配置项
|
||
*/
|
||
MARGIN?: Slider
|
||
/**
|
||
* 弹幕字号配置项
|
||
*/
|
||
FONT_SIZE?: Slider
|
||
/**
|
||
* 颜色列表配置项
|
||
*/
|
||
COLOR?: string[]
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginDanmuku'
|
||
/**
|
||
* 发送一条实时弹幕
|
||
*/
|
||
emit: (danmu: Danmu) => Result
|
||
/**
|
||
* 重载弹幕源,或者切换新弹幕
|
||
*/
|
||
load: (danmuku?: Danmuku) => Promise<Result>
|
||
/**
|
||
* 实时改变弹幕配置
|
||
*/
|
||
config: (option: Option) => Result
|
||
/**
|
||
* 隐藏弹幕层
|
||
*/
|
||
hide: () => Result
|
||
/**
|
||
* 显示弹幕层
|
||
*/
|
||
show: () => Result
|
||
/**
|
||
* 挂载弹幕输入框
|
||
*/
|
||
mount: (el?: HTMLDivElement | string) => void
|
||
/**
|
||
* 重置弹幕
|
||
*/
|
||
reset: () => Result
|
||
/**
|
||
* 弹幕配置
|
||
*/
|
||
option: Option
|
||
/**
|
||
* 是否隐藏弹幕层
|
||
*/
|
||
isHide: boolean
|
||
/**
|
||
* 是否弹幕层停止状态
|
||
*/
|
||
isStop: boolean
|
||
}
|
||
export const artplayerPluginDanmuku: (option: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginDanmuku: typeof artplayerPluginDanmukuDefinitions.artplayerPluginDanmuku
|
||
declare namespace artplayerPluginDanmuku {
|
||
export type Mode = artplayerPluginDanmukuDefinitions.Mode
|
||
export type Danmuku = artplayerPluginDanmukuDefinitions.Danmuku
|
||
export type Slider = artplayerPluginDanmukuDefinitions.Slider
|
||
export type Danmu = artplayerPluginDanmukuDefinitions.Danmu
|
||
export type Option = artplayerPluginDanmukuDefinitions.Option
|
||
export type Result = artplayerPluginDanmukuDefinitions.Result
|
||
}
|
||
export = artplayerPluginDanmuku
|
||
export as namespace artplayerPluginDanmuku;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-dash-control.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginDashControlDefinitions {
|
||
export interface QualityLevel {
|
||
height: number
|
||
width?: number
|
||
id?: string | number
|
||
qualityIndex?: number
|
||
bitrate?: number
|
||
bitrateInKbit?: number
|
||
}
|
||
export interface AudioTrack {
|
||
id?: string | number | null
|
||
index?: number | null
|
||
lang?: string | null
|
||
}
|
||
export interface Config<Item extends object = object> {
|
||
control?: boolean
|
||
setting?: boolean
|
||
title?: string
|
||
auto?: string
|
||
/** Called without a receiver or index, with the original SDK object. */
|
||
getName?: (item: Item) => string
|
||
}
|
||
export interface Option<Level extends object = QualityLevel, Track extends object = AudioTrack> {
|
||
quality?: Config<Level>
|
||
audio?: Config<Track>
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginDashControl'
|
||
update: () => void
|
||
}
|
||
export function artplayerPluginDashControl<Level extends object = QualityLevel, Track extends object = AudioTrack>(option?: Option<Level, Track>): (art: Artplayer) => Result
|
||
// Preserve the required last signature for historical Parameters<typeof factory>[0] consumers.
|
||
export function artplayerPluginDashControl<Level extends object = QualityLevel, Track extends object = AudioTrack>(option: Option<Level, Track>): (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginDashControl: typeof artplayerPluginDashControlDefinitions.artplayerPluginDashControl
|
||
declare namespace artplayerPluginDashControl {
|
||
export type QualityLevel = artplayerPluginDashControlDefinitions.QualityLevel
|
||
export type AudioTrack = artplayerPluginDashControlDefinitions.AudioTrack
|
||
export type Config<Item extends object = object> = artplayerPluginDashControlDefinitions.Config<Item>
|
||
export type Option<Level extends object = QualityLevel, Track extends object = AudioTrack> = artplayerPluginDashControlDefinitions.Option<Level, Track>
|
||
export type Result = artplayerPluginDashControlDefinitions.Result
|
||
}
|
||
export = artplayerPluginDashControl
|
||
export as namespace artplayerPluginDashControl;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-document-pip.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginDocumentPipDefinitions {
|
||
export interface Option {
|
||
/** Requested window width. @default 480 */
|
||
width?: number
|
||
/** Requested window height. @default 270 */
|
||
height?: number
|
||
/** Text displayed in the original player container while the window is active. */
|
||
placeholder?: string
|
||
/** Use the core video PiP property when Document PiP is unavailable. @default true */
|
||
fallbackToVideoPiP?: boolean
|
||
}
|
||
/** Historical assignable result; preserved for direct and extracted return types. */
|
||
export interface Result {
|
||
name: 'artplayerPluginDocumentPip'
|
||
/** Runtime is a readonly capability snapshot; the published field stays assignable. */
|
||
isSupported: boolean
|
||
/** Runtime is a readonly live getter; the published field stays assignable. */
|
||
isActive: boolean
|
||
/** Runtime returns Promise<void>; the published void action remains assignable here. */
|
||
open: () => void
|
||
/** Runtime returns Promise<void>; the published void action remains assignable here. */
|
||
close: () => void
|
||
toggle: () => void
|
||
}
|
||
/** Exact view of an unmodified runtime result. */
|
||
export interface AsyncResult extends Omit<Result, 'isSupported' | 'isActive' | 'open' | 'close'> {
|
||
readonly isSupported: boolean
|
||
readonly isActive: boolean
|
||
open: () => Promise<void>
|
||
close: () => Promise<void>
|
||
}
|
||
/** Exact published factory signature, including compatibility with replacement functions. */
|
||
export type Factory = (option: Option) => (art: Artplayer) => Result
|
||
/** Opt-in runtime view with omitted options, self default and precise async actions. */
|
||
export interface RuntimeFactory {
|
||
(option?: Option): (art: Artplayer) => AsyncResult
|
||
readonly default: RuntimeFactory
|
||
}
|
||
/** Keep the published callable type; use RuntimeFactory explicitly for its broader runtime shape. */
|
||
export function artplayerPluginDocumentPip(option: Option): (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginDocumentPip: typeof artplayerPluginDocumentPipDefinitions.artplayerPluginDocumentPip
|
||
declare namespace artplayerPluginDocumentPip {
|
||
export type Option = artplayerPluginDocumentPipDefinitions.Option
|
||
export type Result = artplayerPluginDocumentPipDefinitions.Result
|
||
export type AsyncResult = artplayerPluginDocumentPipDefinitions.AsyncResult
|
||
export type Factory = artplayerPluginDocumentPipDefinitions.Factory
|
||
export type RuntimeFactory = artplayerPluginDocumentPipDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginDocumentPip
|
||
export as namespace artplayerPluginDocumentPip;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-hls-control.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginHlsControlDefinitions {
|
||
export interface QualityLevel {
|
||
height: number
|
||
name?: string
|
||
}
|
||
export interface AudioTrack {
|
||
id: number
|
||
name: string
|
||
lang?: string
|
||
language?: string
|
||
}
|
||
export interface Config<Item extends object = object> {
|
||
control?: boolean
|
||
setting?: boolean
|
||
title?: string
|
||
auto?: string
|
||
/** Plain callback; current-label calls omit index. SDK objects retain their identity. */
|
||
getName?: (item: Item, index?: number) => string
|
||
}
|
||
export interface Option<Level extends object = QualityLevel, Track extends object = AudioTrack> {
|
||
quality?: Config<Level>
|
||
audio?: Config<Track>
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginHlsControl'
|
||
update: () => void
|
||
}
|
||
export function artplayerPluginHlsControl<Level extends object = QualityLevel, Track extends object = AudioTrack>(option?: Option<Level, Track>): (art: Artplayer) => Result
|
||
// Keep the required last signature for historical Parameters<typeof factory>[0] consumers.
|
||
export function artplayerPluginHlsControl<Level extends object = QualityLevel, Track extends object = AudioTrack>(option: Option<Level, Track>): (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginHlsControl: typeof artplayerPluginHlsControlDefinitions.artplayerPluginHlsControl
|
||
declare namespace artplayerPluginHlsControl {
|
||
export type QualityLevel = artplayerPluginHlsControlDefinitions.QualityLevel
|
||
export type AudioTrack = artplayerPluginHlsControlDefinitions.AudioTrack
|
||
export type Config<Item extends object = object> = artplayerPluginHlsControlDefinitions.Config<Item>
|
||
export type Option<Level extends object = QualityLevel, Track extends object = AudioTrack> = artplayerPluginHlsControlDefinitions.Option<Level, Track>
|
||
export type Result = artplayerPluginHlsControlDefinitions.Result
|
||
}
|
||
export = artplayerPluginHlsControl
|
||
export as namespace artplayerPluginHlsControl;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-jassub.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginJassubDefinitions {
|
||
export interface JassubOption {
|
||
workerUrl: string
|
||
wasmUrl: string
|
||
modernWasmUrl: string
|
||
subUrl?: string
|
||
subContent?: string
|
||
timeOffset?: number
|
||
debug?: boolean
|
||
prescaleFactor?: number
|
||
prescaleHeightLimit?: number
|
||
maxRenderHeight?: number
|
||
fonts?: string[] | Uint8Array[]
|
||
availableFonts?: Record<string, Uint8Array | string>
|
||
fallbackFont?: string
|
||
useLocalFonts?: boolean
|
||
libassMemoryLimit?: number
|
||
libassGlyphLimit?: number
|
||
[key: string]: any
|
||
}
|
||
export interface JassubInstance {
|
||
resize: (force?: boolean, width?: number, height?: number, top?: number, left?: number) => Promise<void>
|
||
setVideo: (video: HTMLVideoElement) => Promise<void>
|
||
destroy: () => Promise<void>
|
||
[key: string]: any
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginJassub'
|
||
instance: JassubInstance
|
||
}
|
||
export const artplayerPluginJassub: (option: JassubOption) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginJassub: typeof artplayerPluginJassubDefinitions.artplayerPluginJassub
|
||
declare namespace artplayerPluginJassub {
|
||
export type JassubOption = artplayerPluginJassubDefinitions.JassubOption
|
||
export type JassubInstance = artplayerPluginJassubDefinitions.JassubInstance
|
||
}
|
||
export = artplayerPluginJassub
|
||
export as namespace artplayerPluginJassub;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-multiple-subtitles.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginMultipleSubtitlesDefinitions {
|
||
export interface TrackOption {
|
||
url?: string
|
||
name?: string
|
||
type?: 'vtt' | 'srt' | 'ass'
|
||
encoding?: string
|
||
onParser?: (...args: object[]) => object
|
||
}
|
||
export interface Option {
|
||
subtitles: TrackOption[]
|
||
}
|
||
export interface RuntimeOption {
|
||
subtitles?: TrackOption[]
|
||
}
|
||
export interface LegacyResult {
|
||
name: 'multipleSubtitles'
|
||
}
|
||
export interface Result extends LegacyResult {
|
||
tracks: (names?: string[]) => void
|
||
reset: () => void
|
||
}
|
||
/** Historical synchronous extraction; actual registration is asynchronous. */
|
||
export type Factory = (option: Option) => (art: Artplayer) => LegacyResult
|
||
/** Accurate runtime view available through the /runtime entry. */
|
||
export interface RuntimeFactory {
|
||
(option: RuntimeOption): (art: Artplayer) => Promise<Result>
|
||
default: RuntimeFactory
|
||
}
|
||
/** Preserve existing parameter extraction and replacement-function compatibility. */
|
||
export function artplayerPluginMultipleSubtitles(option: Option): (art: Artplayer) => LegacyResult
|
||
}
|
||
declare const artplayerPluginMultipleSubtitles: typeof artplayerPluginMultipleSubtitlesDefinitions.artplayerPluginMultipleSubtitles
|
||
declare namespace artplayerPluginMultipleSubtitles {
|
||
export type TrackOption = artplayerPluginMultipleSubtitlesDefinitions.TrackOption
|
||
export type Option = artplayerPluginMultipleSubtitlesDefinitions.Option
|
||
export type RuntimeOption = artplayerPluginMultipleSubtitlesDefinitions.RuntimeOption
|
||
export type LegacyResult = artplayerPluginMultipleSubtitlesDefinitions.LegacyResult
|
||
export type Result = artplayerPluginMultipleSubtitlesDefinitions.Result
|
||
export type Factory = artplayerPluginMultipleSubtitlesDefinitions.Factory
|
||
export type RuntimeFactory = artplayerPluginMultipleSubtitlesDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginMultipleSubtitles
|
||
export as namespace artplayerPluginMultipleSubtitles;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-vast.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-use-before-define, ts/consistent-type-definitions -- Preserve historical export ordering and private aliases. */
|
||
export = artplayerPluginVast
|
||
export as namespace artplayerPluginVast;
|
||
type Option = (params: {
|
||
art: Artplayer
|
||
id: string
|
||
ima: any
|
||
imaPlayer: any
|
||
$container: HTMLDivElement
|
||
playUrl: (url: string) => void
|
||
playRes: (res: string) => void
|
||
}) => void
|
||
type Result = {
|
||
name: 'artplayerPluginVast'
|
||
}
|
||
declare const artplayerPluginVast: (option: Option) => (art: Artplayer) => Result
|
||
|
||
|
||
===== docs/assets/ts/artplayer-plugin-vtt-thumbnail.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerPluginVttThumbnailDefinitions {
|
||
export interface Option {
|
||
vtt?: string
|
||
style?: Partial<CSSStyleDeclaration>
|
||
}
|
||
export interface Result {
|
||
name: 'artplayerPluginVttThumbnail'
|
||
}
|
||
/** Historical factory type. Actual registration is asynchronous. */
|
||
export type Factory = (option: Option) => (art: Artplayer) => Result
|
||
/** Accurate runtime view available without casts through the /runtime entry. */
|
||
export interface RuntimeFactory {
|
||
(option: Option): (art: Artplayer) => Promise<Result>
|
||
default: RuntimeFactory
|
||
}
|
||
/** Preserve historical extraction and replacement-function compatibility. */
|
||
export function artplayerPluginVttThumbnail(option: Option): (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerPluginVttThumbnail: typeof artplayerPluginVttThumbnailDefinitions.artplayerPluginVttThumbnail
|
||
declare namespace artplayerPluginVttThumbnail {
|
||
export type Option = artplayerPluginVttThumbnailDefinitions.Option
|
||
export type Result = artplayerPluginVttThumbnailDefinitions.Result
|
||
export type Factory = artplayerPluginVttThumbnailDefinitions.Factory
|
||
export type RuntimeFactory = artplayerPluginVttThumbnailDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerPluginVttThumbnail
|
||
export as namespace artplayerPluginVttThumbnail;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-proxy-canvas.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerProxyCanvasDefinitions {
|
||
/** Runs after drawing and bitmap release, before the draw event. */
|
||
export type Option = (ctx: CanvasRenderingContext2D, video: HTMLVideoElement) => void
|
||
/** Preserve the exact published 1.1.0 return type and its assignability. */
|
||
export type Result = HTMLCanvasElement
|
||
export type Factory = (option?: Option) => (art: Artplayer) => Result
|
||
export type Callable = Factory
|
||
/** Explicit view of forwarded media members; native Canvas members win. */
|
||
export type MediaCanvas = HTMLCanvasElement & Pick<HTMLVideoElement, Exclude<keyof HTMLVideoElement, keyof HTMLCanvasElement>>
|
||
/** Opt-in runtime identity; the historical root factory has no required properties. */
|
||
export interface RuntimeFactory extends Factory {
|
||
readonly default: RuntimeFactory
|
||
}
|
||
export const artplayerProxyCanvas: (option?: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerProxyCanvas: typeof artplayerProxyCanvasDefinitions.artplayerProxyCanvas
|
||
declare namespace artplayerProxyCanvas {
|
||
export type Option = artplayerProxyCanvasDefinitions.Option
|
||
export type Result = artplayerProxyCanvasDefinitions.Result
|
||
export type Factory = artplayerProxyCanvasDefinitions.Factory
|
||
export type Callable = artplayerProxyCanvasDefinitions.Callable
|
||
export type MediaCanvas = artplayerProxyCanvasDefinitions.MediaCanvas
|
||
export type RuntimeFactory = artplayerProxyCanvasDefinitions.RuntimeFactory
|
||
}
|
||
export = artplayerProxyCanvas
|
||
export as namespace artplayerProxyCanvas;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-proxy-mediabunny.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace artplayerProxyMediabunnyDefinitions {
|
||
export interface Option {
|
||
m3u8?: {
|
||
quality?: {
|
||
control?: boolean
|
||
setting?: boolean
|
||
title?: string
|
||
auto?: string
|
||
getName?: (level: {
|
||
id: number
|
||
index: number
|
||
name: null | string
|
||
height: number
|
||
bitrate: number
|
||
}) => string
|
||
}
|
||
audio?: {
|
||
control?: boolean
|
||
setting?: boolean
|
||
title?: string
|
||
auto?: string
|
||
getName?: (track: {
|
||
id: number
|
||
index: number
|
||
name: null | string
|
||
lang: string
|
||
language: string
|
||
bitrate: number
|
||
}) => string
|
||
}
|
||
}
|
||
/**
|
||
* Timeout for loading media in milliseconds
|
||
* @default 0
|
||
*/
|
||
loadTimeout?: number
|
||
/**
|
||
* Interval for timeupdate events in milliseconds
|
||
* @default 250
|
||
*/
|
||
timeupdateInterval?: number
|
||
/**
|
||
* Audio-video synchronization tolerance in seconds
|
||
* @default 0.12
|
||
*/
|
||
avSyncTolerance?: number
|
||
/**
|
||
* Whether to drop late video frames
|
||
* @default false
|
||
*/
|
||
dropLateFrames?: boolean
|
||
/**
|
||
* Poster image URL
|
||
*/
|
||
poster?: string
|
||
/**
|
||
* Media source (URL, Blob, or ReadableStream)
|
||
*/
|
||
source?: string | Blob | ReadableStream<Uint8Array>
|
||
/**
|
||
* Check if server supports range requests before loading
|
||
* @default false
|
||
*/
|
||
preflightRange?: boolean
|
||
/**
|
||
* Initial volume (0-1)
|
||
* @default 0.7
|
||
*/
|
||
volume?: number
|
||
/**
|
||
* Initial muted state
|
||
* @default false
|
||
*/
|
||
muted?: boolean
|
||
/**
|
||
* Autoplay
|
||
* @default false
|
||
*/
|
||
autoplay?: boolean
|
||
/**
|
||
* Loop playback
|
||
* @default false
|
||
*/
|
||
loop?: boolean
|
||
/**
|
||
* Cross-origin setting
|
||
*/
|
||
crossOrigin?: string
|
||
}
|
||
export type Result = HTMLCanvasElement
|
||
export interface HlsLevel {
|
||
id: number
|
||
index: number
|
||
name: string | null
|
||
height: number
|
||
bitrate: number
|
||
/** SDK object; narrow with the SDK version used by your application. */
|
||
track: unknown
|
||
}
|
||
export interface HlsAudio {
|
||
id: number
|
||
index: number
|
||
name: string | null
|
||
lang: string
|
||
language: string
|
||
bitrate: number
|
||
/** SDK object; narrow with the SDK version used by your application. */
|
||
track: unknown
|
||
}
|
||
export interface HlsState {
|
||
levels: HlsLevel[]
|
||
audios: HlsAudio[]
|
||
currentLevel: HlsLevel | null
|
||
currentAudio: HlsAudio | null
|
||
videoMode: 'auto' | 'manual'
|
||
audioMode: 'auto' | 'manual'
|
||
}
|
||
/** Historical RAF estimates, not decoded-frame or network timing measurements. */
|
||
export interface SyntheticFrameMetadata {
|
||
/** Historical media time in seconds, unlike the native video API. */
|
||
presentationTime: number
|
||
expectedDisplayTime: number
|
||
width: number
|
||
height: number
|
||
mediaTime: number
|
||
presentedFrames: number
|
||
processingDuration: number
|
||
captureTime: number
|
||
receiveTime: number
|
||
rtpTimestamp: number
|
||
}
|
||
export type SyntheticFrameCallback = (now: number, metadata: SyntheticFrameMetadata) => void
|
||
export type MediaListener = (event: Event & {
|
||
detail: unknown
|
||
}) => unknown
|
||
/** Opt-in media surface of art.mediabunny; decoder internals are not part of this view. */
|
||
export interface MediaBunnyShim {
|
||
canvas: HTMLCanvasElement
|
||
/** Runtime also accepts SDK sources; the default Option keeps its historical input union. */
|
||
src: unknown
|
||
readonly currentSrc: unknown
|
||
currentTime: number
|
||
readonly duration: number
|
||
/** Synthetic full-duration/current-time ranges, not measured network buffers. */
|
||
readonly buffered: TimeRanges
|
||
readonly played: TimeRanges
|
||
readonly seekable: TimeRanges
|
||
readonly paused: boolean
|
||
readonly playing: boolean
|
||
readonly ended: boolean
|
||
readonly seeking: boolean
|
||
readonly readyState: number
|
||
readonly networkState: number
|
||
readonly error: {
|
||
code: number
|
||
message: string
|
||
} | null
|
||
volume: number
|
||
muted: boolean
|
||
playbackRate: number
|
||
readonly videoWidth: number
|
||
readonly videoHeight: number
|
||
poster: string
|
||
/** The following setters are inert; use Option for autoplay/loop/crossOrigin. */
|
||
autoplay: boolean
|
||
loop: boolean
|
||
controls: boolean
|
||
playsInline: boolean
|
||
crossOrigin: string
|
||
preload: string
|
||
defaultMuted: boolean
|
||
defaultPlaybackRate: number
|
||
play: () => Promise<void>
|
||
pause: () => void
|
||
load: () => void
|
||
/** Always returns "maybe"; it does not probe codec/browser support. */
|
||
canPlayType: (type: string) => 'maybe'
|
||
getM3u8State: () => Promise<HlsState | null>
|
||
switchM3u8Quality: (value: unknown) => Promise<void>
|
||
switchM3u8Audio: (value: unknown) => Promise<void>
|
||
createTimeRanges: (start: number, end: number) => TimeRanges
|
||
requestVideoFrameCallback: (callback: SyntheticFrameCallback) => number
|
||
cancelVideoFrameCallback: (id: number) => void
|
||
addEventListener: (type: string, listener: MediaListener) => void
|
||
removeEventListener: (type: string, listener: MediaListener) => void
|
||
getBoundingClientRect: () => DOMRect
|
||
setAttribute: (name: string, value: unknown) => void
|
||
destroy: () => void
|
||
}
|
||
/** Native Canvas methods win collisions, including DOM event and attribute methods. */
|
||
export type MediaBunnyCanvas = HTMLCanvasElement & Omit<MediaBunnyShim, keyof HTMLCanvasElement>
|
||
/** The alias is installed by the proxy and removed on player destruction. */
|
||
export type MediaBunnyPlayer = Artplayer & {
|
||
mediabunny?: MediaBunnyShim
|
||
}
|
||
export const artplayerProxyMediabunny: (option?: Option) => (art: Artplayer) => Result
|
||
}
|
||
declare const artplayerProxyMediabunny: typeof artplayerProxyMediabunnyDefinitions.artplayerProxyMediabunny
|
||
declare namespace artplayerProxyMediabunny {
|
||
export type Option = artplayerProxyMediabunnyDefinitions.Option
|
||
export type Result = artplayerProxyMediabunnyDefinitions.Result
|
||
export type HlsLevel = artplayerProxyMediabunnyDefinitions.HlsLevel
|
||
export type HlsAudio = artplayerProxyMediabunnyDefinitions.HlsAudio
|
||
export type HlsState = artplayerProxyMediabunnyDefinitions.HlsState
|
||
export type SyntheticFrameMetadata = artplayerProxyMediabunnyDefinitions.SyntheticFrameMetadata
|
||
export type SyntheticFrameCallback = artplayerProxyMediabunnyDefinitions.SyntheticFrameCallback
|
||
export type MediaListener = artplayerProxyMediabunnyDefinitions.MediaListener
|
||
export type MediaBunnyShim = artplayerProxyMediabunnyDefinitions.MediaBunnyShim
|
||
export type MediaBunnyCanvas = artplayerProxyMediabunnyDefinitions.MediaBunnyCanvas
|
||
export type MediaBunnyPlayer = artplayerProxyMediabunnyDefinitions.MediaBunnyPlayer
|
||
}
|
||
export = artplayerProxyMediabunny
|
||
export as namespace artplayerProxyMediabunny;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-tool-iframe.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||
declare namespace ArtplayerToolIframeDefinitions {
|
||
export interface Option {
|
||
iframe: HTMLIFrameElement
|
||
url: string
|
||
}
|
||
/** Historical open envelope. data remains required in the default class API. */
|
||
export interface Message<T = any> {
|
||
type: string
|
||
data: T
|
||
id?: number
|
||
}
|
||
export interface Callbacks {
|
||
resove: (...args: any[]) => any
|
||
reject: (...args: any[]) => any
|
||
}
|
||
/** Public notifications omit the request id and all private session metadata. */
|
||
export interface Notification<T = unknown> {
|
||
type: string
|
||
data: T
|
||
}
|
||
export type MessageCallback = (this: ArtplayerToolIframe, message: Notification) => void
|
||
/** Actual outgoing calls allow an omitted data field. Custom message types remain valid. */
|
||
export interface OutboundMessage<T = unknown> {
|
||
type: string
|
||
data?: T
|
||
id?: number
|
||
}
|
||
/** Known built-in envelopes; use Message/OutboundMessage for application protocols. */
|
||
export type ProtocolMessage<T = unknown> = {
|
||
type: 'inject'
|
||
data?: undefined
|
||
id?: number
|
||
} | {
|
||
type: 'commit'
|
||
data: string
|
||
id: number
|
||
} | {
|
||
type: 'response'
|
||
data: T
|
||
id: number
|
||
} | {
|
||
type: 'error'
|
||
data: unknown
|
||
id: number
|
||
}
|
||
export type Resolve<T> = (value: T | PromiseLike<T>) => void
|
||
export type ResolverCallback<T> = (resolve: Resolve<T>) => void
|
||
/** Opt-in view. Response T is supplied by the application's protocol, not validated at runtime. */
|
||
export interface RuntimeInstance extends Omit<ArtplayerToolIframe, 'messageCallback' | 'postMessage' | 'message'> {
|
||
messageCallback: MessageCallback | null
|
||
postMessage: <T = unknown>(message: OutboundMessage) => Promise<T>
|
||
message: (callback: MessageCallback) => void
|
||
}
|
||
/** For the existing serialized resolve(...) protocol; callback bodies must use that exact name. */
|
||
export interface ResolverInstance extends Omit<RuntimeInstance, 'commit'> {
|
||
commit: <T>(callback: ResolverCallback<T>) => Promise<T>
|
||
}
|
||
/** Opt-in static async/optional-data view. There is no runtime self-default property. */
|
||
export interface RuntimeConstructor {
|
||
new (option: Option): RuntimeInstance
|
||
readonly prototype: RuntimeInstance
|
||
readonly iframe: boolean
|
||
postMessage: (message: OutboundMessage) => void
|
||
onMessage: (event: MessageEvent<OutboundMessage>) => Promise<void>
|
||
inject: () => void
|
||
}
|
||
export class ArtplayerToolIframe {
|
||
constructor(option: Option)
|
||
static iframe: boolean
|
||
static postMessage(message: Message): void
|
||
static onMessage(event: MessageEvent & {
|
||
data: Message
|
||
}): void
|
||
static inject(): void
|
||
readonly promises: Record<number, Callbacks>
|
||
readonly injected: boolean
|
||
readonly destroyed: boolean
|
||
readonly $iframe: HTMLIFrameElement
|
||
readonly url: string
|
||
readonly messageCallback: (...args: any[]) => any
|
||
onMessage(event: MessageEvent & {
|
||
data: Message
|
||
}): void
|
||
postMessage(message: Message): Promise<any>
|
||
commit<T extends (...args: any[]) => any>(callback: T): Promise<ReturnType<T>>
|
||
message(callback: (...args: any[]) => any): void
|
||
destroy(): void
|
||
}
|
||
}
|
||
declare const ArtplayerToolIframe: typeof ArtplayerToolIframeDefinitions.ArtplayerToolIframe
|
||
type ArtplayerToolIframe = ArtplayerToolIframeDefinitions.ArtplayerToolIframe
|
||
declare namespace ArtplayerToolIframe {
|
||
export type Option = ArtplayerToolIframeDefinitions.Option
|
||
export type Message<T = any> = ArtplayerToolIframeDefinitions.Message<T>
|
||
export type Callbacks = ArtplayerToolIframeDefinitions.Callbacks
|
||
export type Notification<T = unknown> = ArtplayerToolIframeDefinitions.Notification<T>
|
||
export type MessageCallback = ArtplayerToolIframeDefinitions.MessageCallback
|
||
export type OutboundMessage<T = unknown> = ArtplayerToolIframeDefinitions.OutboundMessage<T>
|
||
export type ProtocolMessage<T = unknown> = ArtplayerToolIframeDefinitions.ProtocolMessage<T>
|
||
export type Resolve<T> = ArtplayerToolIframeDefinitions.Resolve<T>
|
||
export type ResolverCallback<T> = ArtplayerToolIframeDefinitions.ResolverCallback<T>
|
||
export type RuntimeInstance = ArtplayerToolIframeDefinitions.RuntimeInstance
|
||
export type ResolverInstance = ArtplayerToolIframeDefinitions.ResolverInstance
|
||
export type RuntimeConstructor = ArtplayerToolIframeDefinitions.RuntimeConstructor
|
||
}
|
||
export = ArtplayerToolIframe
|
||
export as namespace ArtplayerToolIframe;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-tool-thumbnail.d.ts =====
|
||
|
||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||
/** Extract PNG thumbnail sheets from a locally selected video file. */
|
||
declare class ArtplayerToolThumbnail {
|
||
constructor(option?: ArtplayerToolThumbnail.Option)
|
||
static readonly DEFAULTS: ArtplayerToolThumbnail.SheetOptions
|
||
static ondragover(event: DragEvent): void
|
||
static creatVideo(): HTMLVideoElement
|
||
processing: boolean
|
||
option: ArtplayerToolThumbnail.ResolvedOption
|
||
video: HTMLVideoElement
|
||
duration: number
|
||
density: number | undefined
|
||
file: File | undefined
|
||
videoUrl: string | undefined
|
||
thumbnailUrl: string | undefined
|
||
e?: ArtplayerToolThumbnail.EventRegistry
|
||
setup(option?: ArtplayerToolThumbnail.Option): this
|
||
inputChange(event: Event): void
|
||
ondrop(event: DragEvent): void
|
||
loadVideo(file?: File | null): void
|
||
/** Ready-metadata preflight may throw synchronously. Cancellation rejects with AbortError. */
|
||
start(): Promise<void>
|
||
creatScreenshotDate(): ArtplayerToolThumbnail.ScreenshotPoint[]
|
||
creatCanvas(): HTMLCanvasElement
|
||
download(): this
|
||
errorHandle(condition: unknown, message: string): void
|
||
destroy(): void
|
||
on<Name extends PropertyKey, Custom extends unknown[], Context>(name: Name, callback: (this: Context, ...args: ArtplayerToolThumbnail.EventArgs<Name, Custom>) => unknown, ctx?: Context): this
|
||
once<Name extends PropertyKey, Custom extends unknown[], Context>(name: Name, callback: (this: Context, ...args: ArtplayerToolThumbnail.EventArgs<Name, Custom>) => unknown, ctx?: Context): this
|
||
emit<Name extends PropertyKey, Custom extends unknown[]>(name: Name, ...args: ArtplayerToolThumbnail.EventArgs<Name, Custom>): this
|
||
off<Name extends PropertyKey, Custom extends unknown[]>(name: Name, callback?: ArtplayerToolThumbnail.Listener<ArtplayerToolThumbnail.EventArgs<Name, Custom>>): this
|
||
}
|
||
declare namespace ArtplayerToolThumbnail {
|
||
interface SheetOptions {
|
||
number: number
|
||
width: number
|
||
height: number
|
||
column: number
|
||
begin: number
|
||
end: number
|
||
}
|
||
/** fileInput must be a file input or an Element wrapper when constructing. */
|
||
interface Option extends Partial<SheetOptions> {
|
||
fileInput?: Element
|
||
[name: string]: unknown
|
||
}
|
||
interface ResolvedOption extends SheetOptions {
|
||
fileInput: HTMLInputElement
|
||
[name: string]: unknown
|
||
}
|
||
interface ScreenshotPoint {
|
||
time: number
|
||
x: number
|
||
y: number
|
||
}
|
||
interface Events {
|
||
file: [
|
||
file: File,
|
||
]
|
||
video: [
|
||
video: HTMLVideoElement,
|
||
]
|
||
canvas: [
|
||
canvas: HTMLCanvasElement,
|
||
]
|
||
update: [
|
||
url: string,
|
||
progress: number,
|
||
]
|
||
done: [
|
||
]
|
||
download: [
|
||
name: string,
|
||
]
|
||
/** Built-in failures are strings; user callbacks may throw any message value. */
|
||
error: [
|
||
message: unknown,
|
||
]
|
||
destroy: [
|
||
]
|
||
}
|
||
type EventArgs<Name extends PropertyKey, Custom extends unknown[] = unknown[]> = Name extends keyof Events ? [
|
||
...Events[Name],
|
||
] : Custom
|
||
type Listener<Args extends unknown[]> = ((...args: Args) => unknown) & {
|
||
_?: (...args: Args) => unknown
|
||
}
|
||
/** Heterogeneous listener storage; dispatch through emit to retain event argument checks. */
|
||
type EventRegistry = Partial<Record<PropertyKey, {
|
||
fn: Listener<never[]>
|
||
ctx: unknown
|
||
}[]>>
|
||
}
|
||
export = ArtplayerToolThumbnail
|
||
export as namespace ArtplayerToolThumbnail;
|
||
|
||
|
||
===== docs/assets/ts/artplayer.d.ts =====
|
||
|
||
// Generated from packages/artplayer/public/artplayer.ts by yarn build:ts. Do not edit.
|
||
/* eslint-disable ts/no-redeclare -- UMD constructor and named types share the global export. */
|
||
declare namespace ArtplayerDefinitions {
|
||
export interface ComponentInput extends Omit<ComponentOption, 'html'> {
|
||
html?: string | HTMLElement | number
|
||
}
|
||
export interface Selector {
|
||
/**
|
||
* Whether the default is selected
|
||
*/
|
||
default?: boolean
|
||
/**
|
||
* Html string of selector
|
||
*/
|
||
html: string | HTMLElement
|
||
/**
|
||
* Value of selector item
|
||
*/
|
||
value?: string | number
|
||
/**
|
||
* Allow custom properties
|
||
*/
|
||
[key: string]: any
|
||
}
|
||
export interface Component {
|
||
/**
|
||
* Component self-increasing id
|
||
*/
|
||
readonly id: number
|
||
/**
|
||
* Component parent name
|
||
*/
|
||
readonly name: string | undefined
|
||
/**
|
||
* Component parent element
|
||
*/
|
||
readonly $parent: HTMLElement | undefined
|
||
/**
|
||
* Whether to show component parent
|
||
*/
|
||
get show(): boolean
|
||
/**
|
||
* Whether to show component parent
|
||
*/
|
||
set show(state: boolean)
|
||
/**
|
||
* Toggle the component parent
|
||
*/
|
||
toggle: () => void
|
||
/**
|
||
* Dynamic add a component
|
||
*/
|
||
add: {
|
||
(option: ComponentOption | ((art: Artplayer) => ComponentOption)): HTMLElement | undefined
|
||
(option: ComponentInput | ((art: Artplayer) => ComponentInput)): HTMLElement | undefined
|
||
}
|
||
/**
|
||
* Dynamic remove a component by name
|
||
*/
|
||
remove: (name: string) => void
|
||
/**
|
||
* Dynamic update a component
|
||
*/
|
||
update: {
|
||
(option: ComponentOption): HTMLElement | undefined
|
||
(option: ComponentInput): HTMLElement | undefined
|
||
}
|
||
}
|
||
export interface ComponentOption {
|
||
/**
|
||
* Html string or html element of component
|
||
*/
|
||
html?: string | HTMLElement
|
||
/**
|
||
* Whether to disable component
|
||
*/
|
||
disable?: boolean
|
||
/**
|
||
* Unique name for component
|
||
*/
|
||
name?: string
|
||
/**
|
||
* Component sort index
|
||
*/
|
||
index?: number
|
||
/**
|
||
* Component style object
|
||
*/
|
||
style?: Partial<CSSStyleDeclaration>
|
||
/**
|
||
* Component click event
|
||
*/
|
||
click?: (this: Artplayer, component: Component, event: Event) => void
|
||
/**
|
||
* When the component was mounted
|
||
*/
|
||
mounted?: (this: Artplayer, element: HTMLElement) => void
|
||
/**
|
||
* When the component was before unmount
|
||
*/
|
||
beforeUnmount?: (this: Artplayer, element: HTMLElement) => void
|
||
/**
|
||
* Component tooltip, use in controls
|
||
*/
|
||
tooltip?: string
|
||
/**
|
||
* Component position, use in controls
|
||
*/
|
||
position?: 'top' | 'left' | 'right' | (string & Record<never, never>)
|
||
/**
|
||
* Custom selector list, use in controls
|
||
*/
|
||
selector?: Selector[]
|
||
/**
|
||
* When selector item click, use in controls
|
||
*/
|
||
onSelect?: (this: Artplayer, selector: Selector, element: HTMLElement, event: Event) => void
|
||
}
|
||
export interface Config {
|
||
readonly properties: readonly [
|
||
'audioTracks',
|
||
'autoplay',
|
||
'buffered',
|
||
'controller',
|
||
'controls',
|
||
'crossOrigin',
|
||
'currentSrc',
|
||
'currentTime',
|
||
'defaultMuted',
|
||
'defaultPlaybackRate',
|
||
'duration',
|
||
'ended',
|
||
'error',
|
||
'loop',
|
||
'mediaGroup',
|
||
'muted',
|
||
'networkState',
|
||
'paused',
|
||
'playbackRate',
|
||
'played',
|
||
'preload',
|
||
'readyState',
|
||
'seekable',
|
||
'seeking',
|
||
'src',
|
||
'startDate',
|
||
'textTracks',
|
||
'videoTracks',
|
||
'volume',
|
||
]
|
||
readonly methods: readonly [
|
||
'addTextTrack',
|
||
'canPlayType',
|
||
'load',
|
||
'play',
|
||
'pause',
|
||
]
|
||
readonly events: readonly [
|
||
'abort',
|
||
'canplay',
|
||
'canplaythrough',
|
||
'durationchange',
|
||
'emptied',
|
||
'ended',
|
||
'error',
|
||
'loadeddata',
|
||
'loadedmetadata',
|
||
'loadstart',
|
||
'pause',
|
||
'play',
|
||
'playing',
|
||
'progress',
|
||
'ratechange',
|
||
'seeked',
|
||
'seeking',
|
||
'stalled',
|
||
'suspend',
|
||
'timeupdate',
|
||
'volumechange',
|
||
'waiting',
|
||
]
|
||
readonly prototypes: readonly [
|
||
'width',
|
||
'height',
|
||
'videoWidth',
|
||
'videoHeight',
|
||
'poster',
|
||
'webkitDecodedFrameCount',
|
||
'webkitDroppedFrameCount',
|
||
'playsInline',
|
||
'webkitSupportsFullscreen',
|
||
'webkitDisplayingFullscreen',
|
||
'onenterpictureinpicture',
|
||
'onleavepictureinpicture',
|
||
'disablePictureInPicture',
|
||
'cancelVideoFrameCallback',
|
||
'requestVideoFrameCallback',
|
||
'getVideoPlaybackQuality',
|
||
'requestPictureInPicture',
|
||
'webkitEnterFullScreen',
|
||
'webkitEnterFullscreen',
|
||
'webkitExitFullScreen',
|
||
'webkitExitFullscreen',
|
||
]
|
||
}
|
||
/** The event bus exposed by Artplayer.Emitter; no new runtime export. */
|
||
export interface Emitter<Events extends {
|
||
[Name in keyof Events]: readonly unknown[];
|
||
} = Record<PropertyKey, unknown[]>> {
|
||
e?: {
|
||
[Name in keyof Events]?: {
|
||
fn: (...args: [
|
||
...Events[Name],
|
||
]) => unknown
|
||
ctx: unknown
|
||
}[];
|
||
}
|
||
on: <Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [
|
||
...Events[Name],
|
||
]) => unknown, ctx?: Context) => this
|
||
once: <Name extends keyof Events, Context>(name: Name, fn: (this: Context, ...args: [
|
||
...Events[Name],
|
||
]) => unknown, ctx?: Context) => this
|
||
emit: <Name extends keyof Events>(name: Name, ...args: [
|
||
...Events[Name],
|
||
]) => this
|
||
off: <Name extends keyof Events>(name: Name, fn?: (...args: [
|
||
...Events[Name],
|
||
]) => unknown) => this
|
||
}
|
||
export interface CssVar {
|
||
'--art-theme': string
|
||
'--art-font-color': string
|
||
'--art-background-color': string
|
||
'--art-text-shadow-color': string
|
||
'--art-transition-duration': string
|
||
'--art-padding': string
|
||
'--art-border-radius': string
|
||
'--art-progress-height': string
|
||
'--art-progress-color': string
|
||
'--art-progress-top-gap': string
|
||
'--art-hover-color': string
|
||
'--art-loaded-color': string
|
||
'--art-state-size': string
|
||
'--art-state-opacity': number
|
||
'--art-bottom-height': string
|
||
'--art-bottom-offset': string
|
||
'--art-bottom-gap': string
|
||
'--art-highlight-width': string
|
||
'--art-highlight-color': string
|
||
'--art-control-height': string
|
||
'--art-control-opacity': number
|
||
'--art-control-icon-size': string
|
||
'--art-control-icon-scale': number
|
||
'--art-volume-height': string
|
||
'--art-volume-handle-size': string
|
||
'--art-lock-size': string
|
||
'--art-indicator-scale': number
|
||
'--art-indicator-size': string
|
||
'--art-fullscreen-web-index': 9999
|
||
'--art-settings-icon-size': string
|
||
'--art-settings-max-height': string
|
||
'--art-selector-max-height': string
|
||
'--art-contextmenus-min-width': string
|
||
'--art-subtitle-font-size': string
|
||
'--art-subtitle-gap': string
|
||
'--art-subtitle-bottom': string
|
||
'--art-subtitle-border': string
|
||
'--art-widget-background': string
|
||
'--art-tip-background': string
|
||
'--art-scrollbar-size': string
|
||
'--art-scrollbar-background': string
|
||
'--art-scrollbar-background-hover': string
|
||
'--art-mini-progress-height': string
|
||
}
|
||
export type I18nKeys = 'en' | 'zh-cn' | 'zh-tw' | 'pl' | 'cs' | 'es' | 'fa' | 'fr' | 'id' | 'ru' | 'tr' | 'ar' | 'vi' | (string & Record<never, never>)
|
||
export interface I18nValue {
|
||
'Context Menu'?: string
|
||
'Lock'?: string
|
||
'Video Info': string
|
||
'Close': string
|
||
'Video Load Failed': string
|
||
'Volume': string
|
||
'Progress'?: string
|
||
'Back'?: string
|
||
'Settings'?: string
|
||
'Play': string
|
||
'Pause': string
|
||
'Rate': string
|
||
'Mute': string
|
||
'Video Flip': string
|
||
'Horizontal': string
|
||
'Vertical': string
|
||
'Reconnect': string
|
||
'Show Setting': string
|
||
'Hide Setting': string
|
||
'Screenshot': string
|
||
'Play Speed': string
|
||
'Aspect Ratio': string
|
||
'Default': string
|
||
'Normal': string
|
||
'Open': string
|
||
'Switch Video': string
|
||
'Switch Subtitle': string
|
||
'Fullscreen': string
|
||
'Exit Fullscreen': string
|
||
'Web Fullscreen': string
|
||
'Exit Web Fullscreen': string
|
||
'Mini Player': string
|
||
'PIP Mode': string
|
||
'Exit PIP Mode': string
|
||
'PIP Not Supported': string
|
||
'Fullscreen Not Supported': string
|
||
'Subtitle Offset': string
|
||
'Last Seen': string
|
||
'Jump Play': string
|
||
'AirPlay': string
|
||
'AirPlay Not Available': string
|
||
}
|
||
export type I18n = Partial<Record<I18nKeys, Partial<I18nValue>>>
|
||
export interface Icons {
|
||
readonly loading: HTMLDivElement
|
||
readonly state: HTMLDivElement
|
||
readonly play: HTMLDivElement
|
||
readonly pause: HTMLDivElement
|
||
readonly check: HTMLDivElement
|
||
readonly volume: HTMLDivElement
|
||
readonly volumeClose: HTMLDivElement
|
||
readonly screenshot: HTMLDivElement
|
||
readonly setting: HTMLDivElement
|
||
readonly pip: HTMLDivElement
|
||
readonly arrowLeft: HTMLDivElement
|
||
readonly arrowRight: HTMLDivElement
|
||
readonly playbackRate: HTMLDivElement
|
||
readonly aspectRatio: HTMLDivElement
|
||
readonly config: HTMLDivElement
|
||
readonly lock: HTMLDivElement
|
||
readonly flip: HTMLDivElement
|
||
readonly unlock: HTMLDivElement
|
||
readonly fullscreenOff: HTMLDivElement
|
||
readonly fullscreenOn: HTMLDivElement
|
||
readonly fullscreenWebOff: HTMLDivElement
|
||
readonly fullscreenWebOn: HTMLDivElement
|
||
readonly switchOn: HTMLDivElement
|
||
readonly switchOff: HTMLDivElement
|
||
readonly error: HTMLDivElement
|
||
readonly close: HTMLDivElement
|
||
readonly airplay: HTMLDivElement
|
||
readonly [key: string]: HTMLDivElement
|
||
}
|
||
export type PluginFactory<Host = Artplayer, Result = unknown> = (this: Host, art: Host) => Result
|
||
/** Augment this interface with installed plugin results; augmentation does not register a plugin. */
|
||
export interface Plugins {
|
||
/** Legacy signature: synchronous factories return this registry; Promise factories return a Promise of it. */
|
||
add: (plugin: PluginFactory) => Promise<Plugins>
|
||
[name: string]: unknown
|
||
}
|
||
export interface Quality {
|
||
/**
|
||
* Whether the default is selected
|
||
*/
|
||
default?: boolean
|
||
/**
|
||
* Html string of quality
|
||
*/
|
||
html: string | HTMLElement
|
||
/**
|
||
* Video quality url
|
||
*/
|
||
url: string
|
||
}
|
||
export interface SettingOption extends Omit<Setting, 'html' | 'icon' | 'tooltip'> {
|
||
html: string
|
||
icon: string | undefined
|
||
tooltip: string | undefined
|
||
$item: HTMLDivElement
|
||
$icon: HTMLDivElement | undefined
|
||
$html: HTMLDivElement
|
||
$tooltip: HTMLDivElement | undefined
|
||
$switch: HTMLDivElement | undefined
|
||
$range: HTMLInputElement | undefined
|
||
$parent: SettingOption | undefined
|
||
$parents: SettingOption[]
|
||
$option: SettingOption[]
|
||
$events: Array<() => void>
|
||
$formatted: boolean
|
||
}
|
||
export interface Setting {
|
||
/**
|
||
* Html string or html element of setting name
|
||
*/
|
||
html: string | HTMLElement
|
||
/**
|
||
* Html string or html element of setting icon
|
||
*/
|
||
icon?: string | HTMLElement
|
||
/**
|
||
* The width of setting
|
||
*/
|
||
width?: number
|
||
/**
|
||
* The tooltip of setting
|
||
*/
|
||
tooltip?: string | HTMLElement
|
||
/**
|
||
* Whether the default is selected
|
||
*/
|
||
default?: boolean
|
||
/**
|
||
* Custom selector list
|
||
*/
|
||
selector?: Setting[]
|
||
/**
|
||
* When the setting was mounted
|
||
*/
|
||
mounted?: (this: Artplayer, panel: HTMLDivElement, item: Setting) => void
|
||
/**
|
||
* When selector item click
|
||
*/
|
||
onSelect?: (this: Artplayer, item: SettingOption, element: HTMLDivElement, event: Event) => void
|
||
/**
|
||
* Custom switch item
|
||
*/
|
||
switch?: boolean
|
||
/**
|
||
* When switch item click
|
||
*/
|
||
onSwitch?: (this: Artplayer, item: SettingOption, element: HTMLDivElement, event: Event) => void
|
||
/**
|
||
* Custom range item
|
||
*/
|
||
range?: [
|
||
value?: number,
|
||
min?: number,
|
||
max?: number,
|
||
step?: number,
|
||
]
|
||
/**
|
||
* When range item change
|
||
*/
|
||
onRange?: (this: Artplayer, item: SettingOption, element: HTMLDivElement, event: Event) => void
|
||
/**
|
||
* When range item change in real time
|
||
*/
|
||
onChange?: (this: Artplayer, item: SettingOption, element: HTMLDivElement, event: Event) => void
|
||
/**
|
||
* When range item change in real time
|
||
*/
|
||
onClick?: (this: Artplayer, item: SettingOption, element: HTMLDivElement, event: Event) => void
|
||
/**
|
||
* Allow custom properties
|
||
*/
|
||
[key: string]: any
|
||
}
|
||
export interface Subtitle {
|
||
/**
|
||
* The subtitle url
|
||
*/
|
||
url?: string
|
||
/**
|
||
* The subtitle name
|
||
*/
|
||
name?: string
|
||
/**
|
||
* The subtitle type
|
||
*/
|
||
type?: 'vtt' | 'srt' | 'ass' | (string & Record<never, never>)
|
||
/**
|
||
* The subtitle style object
|
||
*/
|
||
style?: Partial<CSSStyleDeclaration>
|
||
/**
|
||
* The subtitle encoding, default utf-8
|
||
*/
|
||
encoding?: string
|
||
/**
|
||
* Whether use escape, default true
|
||
*/
|
||
escape?: boolean
|
||
/**
|
||
* Change the vtt text
|
||
*/
|
||
onVttLoad?: (vtt: string) => string
|
||
}
|
||
export type CustomType = 'flv' | 'm3u8' | 'hls' | 'ts' | 'mpd' | 'torrent' | (string & Record<never, never>)
|
||
export interface Thumbnails {
|
||
/**
|
||
* The thumbnail image url
|
||
*/
|
||
url: string
|
||
/**
|
||
* The thumbnail item number
|
||
*/
|
||
number?: number
|
||
/**
|
||
* The thumbnail column size
|
||
*/
|
||
column?: number
|
||
/**
|
||
* The thumbnail width
|
||
*/
|
||
width?: number
|
||
/**
|
||
* The thumbnail height
|
||
*/
|
||
height?: number
|
||
/**
|
||
* The thumbnail scale
|
||
*/
|
||
scale?: number
|
||
}
|
||
/** Constructor input; Option retains its historical required URL/read types. */
|
||
export interface OptionInput extends Omit<Option$1, 'url' | 'controls' | 'layers' | 'contextmenu'> {
|
||
url?: string
|
||
controls?: ComponentInput[]
|
||
layers?: ComponentInput[]
|
||
contextmenu?: ComponentInput[]
|
||
}
|
||
export interface Option$1 {
|
||
/**
|
||
* The player id
|
||
*/
|
||
id?: string
|
||
/**
|
||
* The container mounted by the player
|
||
*/
|
||
container: string | HTMLDivElement
|
||
/**
|
||
* Video url
|
||
*/
|
||
url: string
|
||
/**
|
||
* Video poster image url
|
||
*/
|
||
poster?: string
|
||
/**
|
||
* Video url type
|
||
*/
|
||
type?: CustomType
|
||
/**
|
||
* Player color theme
|
||
*/
|
||
theme?: string
|
||
/**
|
||
* Player language
|
||
*/
|
||
lang?: keyof I18n
|
||
/**
|
||
* Player default volume
|
||
*/
|
||
volume?: number
|
||
/**
|
||
* Whether live broadcast mode
|
||
*/
|
||
isLive?: boolean
|
||
/**
|
||
* Whether video muted
|
||
*/
|
||
muted?: boolean
|
||
/**
|
||
* Whether video auto play
|
||
*/
|
||
autoplay?: boolean
|
||
/**
|
||
* Whether player auto resize
|
||
*/
|
||
autoSize?: boolean
|
||
/**
|
||
* Whether player auto run mini mode
|
||
*/
|
||
autoMini?: boolean
|
||
/**
|
||
* Whether video auto loop
|
||
*/
|
||
loop?: boolean
|
||
/**
|
||
* Whether show video flip button
|
||
*/
|
||
flip?: boolean
|
||
/**
|
||
* Whether show video playback rate button
|
||
*/
|
||
playbackRate?: boolean
|
||
/**
|
||
* Whether show video aspect ratio button
|
||
*/
|
||
aspectRatio?: boolean
|
||
/**
|
||
* Whether show video screenshot button
|
||
*/
|
||
screenshot?: boolean
|
||
/**
|
||
* Whether show video setting button
|
||
*/
|
||
setting?: boolean
|
||
/**
|
||
* Whether to enable player hotkey
|
||
*/
|
||
hotkey?: boolean
|
||
/**
|
||
* Whether show video pip button
|
||
*/
|
||
pip?: boolean
|
||
/**
|
||
* Do you want to run only one player at a time
|
||
*/
|
||
mutex?: boolean
|
||
/**
|
||
* Whether use backdrop in UI
|
||
*/
|
||
backdrop?: boolean
|
||
/**
|
||
* Whether show video window fullscreen button
|
||
*/
|
||
fullscreen?: boolean
|
||
/**
|
||
* Whether show video web fullscreen button
|
||
*/
|
||
fullscreenWeb?: boolean
|
||
/**
|
||
* Whether to enable player subtitle offset
|
||
*/
|
||
subtitleOffset?: boolean
|
||
/**
|
||
* Whether to enable player mini progress bar
|
||
*/
|
||
miniProgressBar?: boolean
|
||
/**
|
||
* Whether use SSR function
|
||
*/
|
||
useSSR?: boolean
|
||
/**
|
||
* Whether use playsInline in mobile
|
||
*/
|
||
playsInline?: boolean
|
||
/**
|
||
* Whether use lock in mobile
|
||
*/
|
||
lock?: boolean
|
||
/**
|
||
* Whether use gesture in mobile
|
||
*/
|
||
gesture?: boolean
|
||
/**
|
||
* Whether use fast forward in mobile
|
||
*/
|
||
fastForward?: boolean
|
||
/**
|
||
* Whether use auto playback
|
||
*/
|
||
autoPlayback?: boolean
|
||
/**
|
||
* Whether use auto orientation in mobile
|
||
*/
|
||
autoOrientation?: boolean
|
||
/**
|
||
* Whether use airplay
|
||
*/
|
||
airplay?: boolean
|
||
/**
|
||
* Custom video proxy
|
||
*/
|
||
proxy?: (this: Artplayer, art: Artplayer) => HTMLCanvasElement | HTMLVideoElement | undefined
|
||
/**
|
||
* Custom plugin list
|
||
*/
|
||
plugins?: PluginFactory[]
|
||
/**
|
||
* Custom layer list
|
||
*/
|
||
layers?: ComponentOption[]
|
||
/**
|
||
* Custom contextmenu list
|
||
*/
|
||
contextmenu?: ComponentOption[]
|
||
/**
|
||
* Custom control list
|
||
*/
|
||
controls?: ComponentOption[]
|
||
/**
|
||
* Custom setting list
|
||
*/
|
||
settings?: Setting[]
|
||
/**
|
||
* Custom video quality list
|
||
*/
|
||
quality?: Quality[]
|
||
/**
|
||
* Custom highlight list
|
||
*/
|
||
highlight?: {
|
||
/**
|
||
* The highlight time
|
||
*/
|
||
time: number
|
||
/**
|
||
* The highlight text
|
||
*/
|
||
text: string
|
||
}[]
|
||
/**
|
||
* Custom thumbnail
|
||
*/
|
||
thumbnails?: Thumbnails
|
||
/**
|
||
* Custom subtitle option
|
||
*/
|
||
subtitle?: Subtitle
|
||
/**
|
||
* Other video attribute
|
||
*/
|
||
moreVideoAttr?: Partial<Readonly<{
|
||
[K in keyof HTMLVideoElement as HTMLVideoElement[K] extends (...args: unknown[]) => unknown ? never : K]: HTMLVideoElement[K];
|
||
}>>
|
||
/**
|
||
* Custom i18n
|
||
*/
|
||
i18n?: I18n
|
||
/**
|
||
* Custom default icons
|
||
*/
|
||
icons?: {
|
||
[key in keyof Icons]?: HTMLElement | string;
|
||
}
|
||
/**
|
||
* Custom css variables
|
||
*/
|
||
cssVar?: Partial<CssVar>
|
||
/**
|
||
* Custom video type function
|
||
*/
|
||
customType?: Partial<Record<CustomType, (this: Artplayer, video: HTMLVideoElement, url: string, art: Artplayer) => unknown | Promise<unknown>>>
|
||
}
|
||
export type AspectRatio = 'default' | '4:3' | '16:9' | (`${number}:${number}` & Record<never, never>)
|
||
export type PlaybackRate = 0.5 | 0.75 | 1 | 1.25 | 1.5 | 1.75 | 2 | (number & Record<never, never>)
|
||
export type Flip = 'normal' | 'horizontal' | 'vertical' | (string & Record<never, never>)
|
||
export type State = 'standard' | 'mini' | 'pip' | 'fullscreen' | 'fullscreenWeb'
|
||
export class Player {
|
||
get aspectRatio(): AspectRatio
|
||
set aspectRatio(ratio: AspectRatio)
|
||
get state(): State
|
||
set state(state: State)
|
||
get type(): CustomType
|
||
set type(name: CustomType)
|
||
get playbackRate(): PlaybackRate
|
||
set playbackRate(rate: PlaybackRate)
|
||
get currentTime(): number
|
||
set currentTime(time: number)
|
||
get duration(): number
|
||
get played(): number
|
||
get playing(): boolean
|
||
get flip(): Flip
|
||
set flip(state: Flip)
|
||
get fullscreen(): boolean
|
||
set fullscreen(state: boolean)
|
||
get fullscreenWeb(): boolean
|
||
set fullscreenWeb(state: boolean)
|
||
get loaded(): number
|
||
get loadedTime(): number
|
||
get mini(): boolean
|
||
set mini(state: boolean)
|
||
get pip(): boolean
|
||
set pip(state: boolean)
|
||
get poster(): string
|
||
set poster(url: string)
|
||
get rect(): DOMRect
|
||
get bottom(): number
|
||
get height(): number
|
||
get left(): number
|
||
get right(): number
|
||
get top(): number
|
||
get width(): number
|
||
get x(): number
|
||
get y(): number
|
||
set seek(time: number)
|
||
get seek(): number
|
||
set forward(time: number)
|
||
get forward(): number
|
||
set backward(time: number)
|
||
get backward(): number
|
||
get url(): string
|
||
set url(url: string)
|
||
get volume(): number
|
||
set volume(percentage: number)
|
||
get muted(): boolean
|
||
set muted(state: boolean)
|
||
get theme(): string
|
||
set theme(theme: string)
|
||
get subtitleOffset(): number
|
||
set subtitleOffset(time: number)
|
||
get switch(): string
|
||
set switch(url: string)
|
||
get quality(): Quality[]
|
||
set quality(quality: Quality[])
|
||
get thumbnails(): Thumbnails
|
||
set thumbnails(thumbnails: Thumbnails)
|
||
pause(): void
|
||
play(): Promise<void>
|
||
/** Legacy signature; runtime preserves pause's synchronous result or play's Promise. */
|
||
toggle(): void
|
||
attr(key: string, value?: unknown): unknown
|
||
cssVar<T extends keyof CssVar>(key: T, value?: CssVar[T]): CssVar[T]
|
||
switchUrl(url: string): Promise<void>
|
||
switchQuality(url: string): Promise<void>
|
||
getDataURL(): Promise<string>
|
||
getBlobUrl(): Promise<string>
|
||
screenshot(name?: string): Promise<string>
|
||
airplay(): void
|
||
autoSize(): void
|
||
autoHeight(): void
|
||
reset(): void
|
||
}
|
||
export type Bar = 'loaded' | 'played' | 'hover'
|
||
/** Actual built-in subtitle update payloads; legacy Events keeps its scalar types. */
|
||
export interface SubtitleUpdateEvents {
|
||
subtitleBeforeUpdate: [
|
||
cues: VTTCue[],
|
||
]
|
||
subtitleAfterUpdate: [
|
||
cues: VTTCue[],
|
||
]
|
||
}
|
||
export interface Events {
|
||
'document:click': [
|
||
event: Event,
|
||
]
|
||
'document:mouseup': [
|
||
event: Event,
|
||
]
|
||
'document:keydown': [
|
||
event: Event,
|
||
]
|
||
'document:touchend': [
|
||
event: Event,
|
||
]
|
||
'document:touchcancel': [
|
||
event: Event,
|
||
]
|
||
'document:touchmove': [
|
||
event: Event,
|
||
]
|
||
'document:mousemove': [
|
||
event: Event,
|
||
]
|
||
'document:pointerup': [
|
||
event: Event,
|
||
]
|
||
'document:contextmenu': [
|
||
event: Event,
|
||
]
|
||
'document:pointermove': [
|
||
event: Event,
|
||
]
|
||
'document:visibilitychange': [
|
||
event: Event,
|
||
]
|
||
'document:webkitfullscreenchange': [
|
||
event: Event,
|
||
]
|
||
'window:resize': [
|
||
event: Event,
|
||
]
|
||
'window:scroll': [
|
||
event: Event,
|
||
]
|
||
'window:orientationchange': [
|
||
event: Event,
|
||
]
|
||
'video:abort': [
|
||
event: Event,
|
||
]
|
||
'video:canplay': [
|
||
event: Event,
|
||
]
|
||
'video:canplaythrough': [
|
||
event: Event,
|
||
]
|
||
'video:complete': [
|
||
event: Event,
|
||
]
|
||
'video:durationchange': [
|
||
event: Event,
|
||
]
|
||
'video:emptied': [
|
||
event: Event,
|
||
]
|
||
'video:encrypted': [
|
||
event: Event,
|
||
]
|
||
'video:ended': [
|
||
event: Event,
|
||
]
|
||
'video:error': [
|
||
error: Error,
|
||
]
|
||
'video:loadeddata': [
|
||
event: Event,
|
||
]
|
||
'video:loadedmetadata': [
|
||
event: Event,
|
||
]
|
||
'video:loadstart': [
|
||
event: Event,
|
||
]
|
||
'video:pause': [
|
||
event: Event,
|
||
]
|
||
'video:play': [
|
||
event: Event,
|
||
]
|
||
'video:playing': [
|
||
event: Event,
|
||
]
|
||
'video:progress': [
|
||
event: Event,
|
||
]
|
||
'video:ratechange': [
|
||
event: Event,
|
||
]
|
||
'video:seeked': [
|
||
event: Event,
|
||
]
|
||
'video:seeking': [
|
||
event: Event,
|
||
]
|
||
'video:stalled': [
|
||
event: Event,
|
||
]
|
||
'video:suspend': [
|
||
event: Event,
|
||
]
|
||
'video:timeupdate': [
|
||
event: Event,
|
||
]
|
||
'video:volumechange': [
|
||
event: Event,
|
||
]
|
||
'video:waiting': [
|
||
event: Event,
|
||
]
|
||
'info': [
|
||
state: boolean,
|
||
]
|
||
'layer': [
|
||
state: boolean,
|
||
]
|
||
'loading': [
|
||
state: boolean,
|
||
]
|
||
'mask': [
|
||
state: boolean,
|
||
]
|
||
'subtitle': [
|
||
state: boolean,
|
||
]
|
||
'contextmenu': [
|
||
state: boolean,
|
||
]
|
||
'control': [
|
||
state: boolean,
|
||
]
|
||
'setting': [
|
||
state: boolean,
|
||
]
|
||
'hotkey': [
|
||
event: KeyboardEvent,
|
||
]
|
||
'destroy': [
|
||
]
|
||
'subtitleOffset': [
|
||
offset: number,
|
||
]
|
||
/** Legacy contextual type; annotate listeners with VTTCue[] for the runtime payload. */
|
||
'subtitleBeforeUpdate': [
|
||
cue: VTTCue,
|
||
]
|
||
/** Legacy contextual type; annotate listeners with VTTCue[] for the runtime payload. */
|
||
'subtitleAfterUpdate': [
|
||
cue: VTTCue,
|
||
]
|
||
'subtitleLoad': [
|
||
cues: VTTCue[],
|
||
option: Subtitle,
|
||
]
|
||
'focus': [
|
||
event: Event,
|
||
]
|
||
'blur': [
|
||
event: Event,
|
||
]
|
||
'dblclick': [
|
||
event: Event,
|
||
]
|
||
'click': [
|
||
event: Event,
|
||
]
|
||
'hover': [
|
||
state: boolean,
|
||
event: Event,
|
||
]
|
||
'mousemove': [
|
||
event: Event,
|
||
]
|
||
'resize': [
|
||
]
|
||
'view': [
|
||
state: boolean,
|
||
]
|
||
'lock': [
|
||
state: boolean,
|
||
]
|
||
'aspectRatio': [
|
||
aspectRatio: AspectRatio,
|
||
]
|
||
'autoHeight': [
|
||
height: number,
|
||
]
|
||
'autoSize': [
|
||
size: {
|
||
width: number
|
||
height: number
|
||
},
|
||
]
|
||
'ready': [
|
||
]
|
||
'airplay': [
|
||
]
|
||
'raf': [
|
||
]
|
||
'error': [
|
||
error: Error,
|
||
reconnectTime: number,
|
||
]
|
||
'flip': [
|
||
flip: Flip,
|
||
]
|
||
'fullscreen': [
|
||
state: boolean,
|
||
]
|
||
'fullscreenError': [
|
||
event: Event,
|
||
]
|
||
'fullscreenWeb': [
|
||
state: boolean,
|
||
]
|
||
'mini': [
|
||
state: boolean,
|
||
]
|
||
'pause': [
|
||
]
|
||
'pip': [
|
||
state: boolean,
|
||
]
|
||
'play': [
|
||
]
|
||
'screenshot': [
|
||
dataUri: string,
|
||
]
|
||
'seek': [
|
||
currentTime: number,
|
||
time: number,
|
||
]
|
||
'restart': [
|
||
url: string,
|
||
]
|
||
'muted': [
|
||
state: boolean,
|
||
]
|
||
'setBar': [
|
||
type: Bar,
|
||
percentage: number,
|
||
event?: Event | undefined,
|
||
]
|
||
'keydown': [
|
||
event: KeyboardEvent,
|
||
]
|
||
}
|
||
/** Accurate playback method view; assign an existing player without a runtime wrapper. */
|
||
export interface PlaybackControls {
|
||
play: () => Promise<void>
|
||
pause: () => void
|
||
toggle: () => Promise<void> | void
|
||
}
|
||
export interface Template {
|
||
readonly html: string
|
||
readonly $container: HTMLDivElement
|
||
readonly $player: HTMLDivElement
|
||
readonly $video: HTMLVideoElement
|
||
readonly $track: HTMLTrackElement
|
||
readonly $poster: HTMLDivElement
|
||
readonly $subtitle: HTMLDivElement
|
||
readonly $danmuku: HTMLDivElement
|
||
readonly $bottom: HTMLDivElement
|
||
readonly $progress: HTMLDivElement
|
||
readonly $controls: HTMLDivElement
|
||
readonly $controlsLeft: HTMLDivElement
|
||
readonly $controlsCenter: HTMLDivElement
|
||
readonly $controlsRight: HTMLDivElement
|
||
readonly $layer: HTMLDivElement
|
||
readonly $loading: HTMLDivElement
|
||
readonly $notice: HTMLDivElement
|
||
readonly $noticeInner: HTMLDivElement
|
||
readonly $mask: HTMLDivElement
|
||
readonly $state: HTMLDivElement
|
||
readonly $setting: HTMLDivElement
|
||
readonly $info: HTMLDivElement
|
||
readonly $infoPanel: HTMLDivElement
|
||
readonly $infoClose: HTMLDivElement
|
||
readonly $contextmenu: HTMLDivElement
|
||
}
|
||
export interface Utils {
|
||
isBrowser: boolean
|
||
userAgent: string
|
||
isMobile: boolean
|
||
isSafari: boolean
|
||
isIOS: boolean
|
||
isIOS13: boolean
|
||
query: <T extends Element = Element>(selector: string, parent?: Document | HTMLElement) => T | null
|
||
queryAll: <T extends Element = Element>(selector: string, parent?: Document | HTMLElement) => T[]
|
||
addClass: (target: HTMLElement, className: string) => void
|
||
removeClass: (target: HTMLElement, className: string) => void
|
||
hasClass: (target: HTMLElement, className: string) => boolean
|
||
append: (target: HTMLElement, child: HTMLElement | string) => Element | ChildNode
|
||
remove: (target: HTMLElement) => HTMLElement
|
||
replaceElement: (newChild: HTMLElement, oldChild: HTMLElement) => HTMLElement
|
||
siblings: (target: HTMLElement) => HTMLElement[]
|
||
inverseClass: (target: HTMLElement, className: string) => void
|
||
createElement: <K extends keyof HTMLElementTagNameMap>(tag: K) => HTMLElementTagNameMap[K]
|
||
setStyle: <T extends keyof CSSStyleDeclaration>(element: HTMLElement, key: T, value: string | CSSStyleDeclaration[T]) => HTMLElement
|
||
setStyles: (element: HTMLElement, styles: Partial<CSSStyleDeclaration>) => HTMLElement
|
||
getStyle: {
|
||
(element: HTMLElement, key: keyof CSSStyleDeclaration, numberType?: true): number
|
||
(element: HTMLElement, key: keyof CSSStyleDeclaration, numberType: false): string
|
||
}
|
||
setStyleText: (id: string, cssText: string) => void
|
||
getRect: (el: HTMLElement) => {
|
||
top: number
|
||
left: number
|
||
width: number
|
||
height: number
|
||
}
|
||
tooltip: (target: HTMLElement, msg: string, pos?: string) => void
|
||
isInViewport: (target: HTMLElement, offset?: number) => boolean
|
||
includeFromEvent: (event: Event, target: HTMLElement) => boolean
|
||
getSafeAreaInsets: () => {
|
||
top: number
|
||
right: number
|
||
bottom: number
|
||
left: number
|
||
}
|
||
srtToVtt: (srtText: string) => string
|
||
vttToBlob: (vttText: string) => string
|
||
assToVtt: (assText: string) => string
|
||
getExt: (url: string) => string
|
||
download: (url: string, name: string) => void
|
||
loadImg: (url: string, scale?: number) => Promise<HTMLImageElement>
|
||
errorHandle: <T extends boolean>(condition: T, msg: string) => T extends true ? T : never
|
||
silencePromise: <T>(value: T) => T extends Promise<infer R> ? Promise<R | undefined> : T
|
||
def: {
|
||
/** Historical string-key signature; runtime returns obj. */
|
||
(obj: object, name: string, value: unknown): void
|
||
<T>(obj: T, name: PropertyKey, value: PropertyDescriptor & ThisType<T>): T
|
||
}
|
||
has: (obj: object, name: PropertyKey) => boolean
|
||
get: (obj: object, name: PropertyKey) => PropertyDescriptor | undefined
|
||
mergeDeep: <T extends object[]>(...args: T) => T[number]
|
||
sleep: (ms?: number) => Promise<void>
|
||
/** Historical return type; runtime discards the callback result and ignores context. */
|
||
debounce: <F extends (...args: any[]) => any>(func: F, wait: number, context?: object) => (...args: Parameters<F>) => ReturnType<F>
|
||
/** Historical return type; runtime discards the callback result. */
|
||
throttle: <F extends (...args: any[]) => any>(func: F, wait: number) => (...args: Parameters<F>) => ReturnType<F>
|
||
clamp: (num: number, a: number, b: number) => number
|
||
secondToTime: (second: number) => string
|
||
escape: (str: string) => string
|
||
unescape: (str: string) => string
|
||
capitalize: (str: string) => string
|
||
ArtPlayerError: new (message?: string, context?: ((...args: never[]) => unknown) | (abstract new (...args: never[]) => object)) => Error
|
||
getIcon: (key?: string, html?: string | HTMLElement) => HTMLElement
|
||
getComposedPath: (event: Event) => EventTarget[]
|
||
supportsFlex: () => boolean
|
||
}
|
||
export class Artplayer extends Player {
|
||
constructor(option: Option$1, readyCallback?: (this: Artplayer, art: Artplayer) => unknown)
|
||
constructor(option: OptionInput, readyCallback?: (this: Artplayer, art: Artplayer) => unknown)
|
||
static readonly instances: Artplayer[]
|
||
static readonly version: string
|
||
static readonly env: 'development' | 'production'
|
||
static readonly build: string
|
||
static readonly config: Config
|
||
static readonly utils: Utils
|
||
static readonly scheme: Record<keyof Option$1, unknown>
|
||
static readonly Emitter: new <Events extends {
|
||
[Name in keyof Events]: readonly unknown[];
|
||
} = Record<PropertyKey, unknown[]>>(...args: unknown[]) => Emitter<Events>
|
||
|
||
static readonly validator: <T extends object>(option: T, scheme: object) => T
|
||
static readonly kindOf: (item: unknown) => string
|
||
static readonly html: Artplayer['template']['html']
|
||
static readonly option: Option$1
|
||
static STYLE: string
|
||
static DEBUG: boolean
|
||
static CONTEXTMENU: boolean
|
||
static NOTICE_TIME: number
|
||
static SETTING_WIDTH: number
|
||
static SETTING_ITEM_WIDTH: number
|
||
static SETTING_ITEM_HEIGHT: number
|
||
static RESIZE_TIME: number
|
||
static SCROLL_TIME: number
|
||
static SCROLL_GAP: number
|
||
static AUTO_PLAYBACK_MAX: number
|
||
static AUTO_PLAYBACK_MIN: number
|
||
static AUTO_PLAYBACK_TIMEOUT: number
|
||
static RECONNECT_TIME_MAX: number
|
||
static RECONNECT_SLEEP_TIME: number
|
||
static CONTROL_HIDE_TIME: number
|
||
static DBCLICK_TIME: number
|
||
static DBCLICK_FULLSCREEN: boolean
|
||
static MOBILE_DBCLICK_PLAY: boolean
|
||
static MOBILE_CLICK_PLAY: boolean
|
||
static AUTO_ORIENTATION_TIME: number
|
||
static INFO_LOOP_TIME: number
|
||
static FAST_FORWARD_VALUE: number
|
||
static FAST_FORWARD_TIME: number
|
||
static TOUCH_MOVE_RATIO: number
|
||
static VOLUME_STEP: number
|
||
static SEEK_STEP: number
|
||
static PLAYBACK_RATE: number[]
|
||
static ASPECT_RATIO: string[]
|
||
static FLIP: string[]
|
||
static FULLSCREEN_WEB_IN_BODY: boolean
|
||
static LOG_VERSION: boolean
|
||
static USE_RAF: boolean
|
||
static REMOVE_SRC_WHEN_DESTROY: boolean
|
||
readonly id: number
|
||
readonly option: Option$1
|
||
readonly isLock: boolean
|
||
readonly isReady: boolean
|
||
readonly isFocus: boolean
|
||
readonly isInput: boolean
|
||
readonly isRotate: boolean
|
||
readonly isDestroy: boolean
|
||
flv?: unknown
|
||
m3u8?: unknown
|
||
hls?: unknown
|
||
ts?: unknown
|
||
mpd?: unknown
|
||
torrent?: unknown
|
||
on<T extends keyof Events>(name: T, fn: (...args: Events[T]) => unknown, ctx?: object): this
|
||
on<T extends keyof SubtitleUpdateEvents>(name: T, fn: (...args: SubtitleUpdateEvents[T]) => unknown, ctx?: object): this
|
||
on(name: string, fn: (...args: unknown[]) => unknown, ctx?: object): this
|
||
once<T extends keyof Events>(name: T, fn: (...args: Events[T]) => unknown, ctx?: object): this
|
||
once<T extends keyof SubtitleUpdateEvents>(name: T, fn: (...args: SubtitleUpdateEvents[T]) => unknown, ctx?: object): this
|
||
once(name: string, fn: (...args: unknown[]) => unknown, ctx?: object): this
|
||
emit<T extends keyof Events>(name: T, ...args: Events[T]): this
|
||
emit<T extends keyof SubtitleUpdateEvents>(name: T, ...args: SubtitleUpdateEvents[T]): this
|
||
emit(name: string, ...args: unknown[]): this
|
||
off<T extends keyof Events>(name: T, callback?: (...args: Events[T]) => unknown): this
|
||
off<T extends keyof SubtitleUpdateEvents>(name: T, callback?: (...args: SubtitleUpdateEvents[T]) => unknown): this
|
||
off(name: string, callback?: (...args: unknown[]) => unknown): this
|
||
query: Artplayer['template']['query']
|
||
proxy: Artplayer['events']['proxy']
|
||
video: Artplayer['template']['$video']
|
||
e: {
|
||
[K in keyof Events]?: {
|
||
fn: (...args: Events[K]) => unknown
|
||
ctx: unknown
|
||
}[];
|
||
}
|
||
|
||
destroy(removeHtml?: boolean): void
|
||
reset(): void
|
||
readonly template: {
|
||
get html(): string
|
||
query: <T extends Element = Element>(selector: string) => T | null
|
||
} & Template
|
||
|
||
readonly events: {
|
||
proxy: {
|
||
(target: EventTarget, eventName: string, handler: (event: Event) => void, options?: boolean | AddEventListenerOptions): () => void
|
||
(target: EventTarget, eventName: string[], handler: (event: Event) => void, options?: boolean | AddEventListenerOptions): Array<() => void>
|
||
}
|
||
hover: (element: HTMLElement, mouseenter?: (event: Event) => any, mouseleave?: (event: Event) => any) => void
|
||
remove: (destroyEvent: () => void) => void
|
||
destroy: () => void
|
||
bindGlobalEvents: (source?: {
|
||
window?: Window
|
||
document?: Document
|
||
}) => void
|
||
}
|
||
|
||
readonly storage: {
|
||
name: string
|
||
settings: Record<string, unknown>
|
||
get: {
|
||
(key: string): unknown
|
||
(): Record<string, unknown>
|
||
}
|
||
set: (key: string, value: unknown) => void
|
||
del: (key: string) => void
|
||
clear: () => void
|
||
}
|
||
|
||
readonly icons: Icons
|
||
readonly i18n: {
|
||
languages: I18n
|
||
language: Partial<Record<string, string>>
|
||
init: () => void
|
||
get: (key: string) => string
|
||
update: (language: Partial<I18n>) => void
|
||
}
|
||
|
||
readonly notice: {
|
||
timer: number | null
|
||
get show(): string | Error | false | ''
|
||
set show(msg: string | Error | false | '')
|
||
destroy: () => void
|
||
}
|
||
|
||
readonly layers: Record<string, HTMLElement | undefined> & Component
|
||
readonly controls: Record<string, HTMLElement | undefined> & Component
|
||
readonly contextmenu: Record<string, HTMLElement | undefined> & Component
|
||
readonly subtitle: {
|
||
get url(): string
|
||
set url(url: string)
|
||
get textTrack(): TextTrack | undefined
|
||
get activeCues(): VTTCue[]
|
||
get cues(): VTTCue[]
|
||
style: (name: string | Partial<CSSStyleDeclaration>, value?: string) => void
|
||
switch: (url: string, option?: Subtitle) => Promise<string>
|
||
init: (subtitle: Subtitle) => Promise<string | null | undefined>
|
||
} & Component
|
||
|
||
readonly info: Component
|
||
readonly loading: Component
|
||
readonly hotkey: {
|
||
keys: Record<string, ((event: KeyboardEvent) => any)[]>
|
||
add: (key: string, callback: (this: Artplayer, event: KeyboardEvent) => any) => Artplayer['hotkey']
|
||
remove: (key: string, callback: (event: KeyboardEvent) => any) => Artplayer['hotkey']
|
||
}
|
||
|
||
readonly mask: Component
|
||
readonly setting: {
|
||
option: SettingOption[]
|
||
updateStyle: (width?: number) => void
|
||
/** Legacy return signature; a missing runtime entry is null. */
|
||
find: (name: string) => SettingOption | undefined
|
||
/** Legacy return signature; runtime returns the formatted input item. */
|
||
add: (setting: Setting) => Artplayer['setting']
|
||
/** Legacy return signature; runtime returns the updated or added item. */
|
||
update: (settings: Setting) => Artplayer['setting']
|
||
/** Legacy return signature; runtime returns undefined. */
|
||
remove: (name: string) => Artplayer['setting']
|
||
} & Component
|
||
|
||
readonly plugins: Plugins
|
||
}
|
||
}
|
||
declare const Artplayer: typeof ArtplayerDefinitions.Artplayer
|
||
type Artplayer = ArtplayerDefinitions.Artplayer
|
||
declare namespace Artplayer {
|
||
export type Config = ArtplayerDefinitions.Config
|
||
export type Emitter<Events extends {
|
||
[Name in keyof Events]: readonly unknown[];
|
||
} = Record<PropertyKey, unknown[]>> = ArtplayerDefinitions.Emitter<Events>
|
||
export type I18n = ArtplayerDefinitions.I18n
|
||
export type Icons = ArtplayerDefinitions.Icons
|
||
export type PluginFactory<Host = Artplayer, Result = unknown> = ArtplayerDefinitions.PluginFactory<Host, Result>
|
||
export type Plugins = ArtplayerDefinitions.Plugins
|
||
export type SettingOption = ArtplayerDefinitions.SettingOption
|
||
export type Setting = ArtplayerDefinitions.Setting
|
||
export type Subtitle = ArtplayerDefinitions.Subtitle
|
||
export type OptionInput = ArtplayerDefinitions.OptionInput
|
||
export type Player = ArtplayerDefinitions.Player
|
||
export type SubtitleUpdateEvents = ArtplayerDefinitions.SubtitleUpdateEvents
|
||
export type Events = ArtplayerDefinitions.Events
|
||
export type PlaybackControls = ArtplayerDefinitions.PlaybackControls
|
||
export type Template = ArtplayerDefinitions.Template
|
||
export type Utils = ArtplayerDefinitions.Utils
|
||
export type Option = ArtplayerDefinitions.Option$1
|
||
}
|
||
export = Artplayer
|
||
export as namespace Artplayer;
|
||
|
||
|
||
===== docs/assets/ts/artplayer-i18n.d.ts =====
|
||
|
||
declare module 'artplayer/i18n/*' {
|
||
const language: NonNullable<Artplayer.I18n['en']>
|
||
export default language
|
||
}
|
||
|
||
|
||
===== Examples Summary =====
|
||
|
||
===== docs/assets/example/ads.js =====
|
||
|
||
// npm i artplayer-plugin-ads
|
||
// import artplayerPluginAds from 'artplayer-plugin-ads';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
plugins: [
|
||
artplayerPluginAds({
|
||
// html广告,假如是视频广告则忽略该值
|
||
html: '<img src="/assets/sample/poster.jpg">',
|
||
|
||
// 视频广告的地址
|
||
video: '/assets/sample/test1.mp4',
|
||
|
||
// 广告跳转网址,为空则不跳转
|
||
url: 'http://artplayer.org',
|
||
|
||
// 必须观看的时长,期间不能被跳过,单位为秒
|
||
// 当该值大于或等于totalDuration时,不能提前关闭广告
|
||
// 当该值等于或小于0时,则随时都可以关闭广告
|
||
playDuration: 5,
|
||
|
||
// 广告总时长,单位为秒
|
||
totalDuration: 10,
|
||
|
||
// 多语言支持
|
||
i18n: {
|
||
close: '关闭广告',
|
||
countdown: '%s秒',
|
||
detail: '查看详情',
|
||
canBeClosed: '%s秒后可关闭广告',
|
||
},
|
||
}),
|
||
],
|
||
})
|
||
|
||
// 广告被点击
|
||
art.on('artplayerPluginAds:click', (ads) => {
|
||
console.info('广告被点击', ads)
|
||
})
|
||
|
||
// 广告被跳过
|
||
art.on('artplayerPluginAds:skip', (ads) => {
|
||
console.info('广告被跳过', ads)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/ambilight.js =====
|
||
|
||
// npm i artplayer-plugin-ambilight
|
||
// import artplayerPluginAmbilight from 'artplayer-plugin-ambilight';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoSize: true,
|
||
plugins: [
|
||
artplayerPluginAmbilight({
|
||
blur: '50px',
|
||
opacity: 1,
|
||
frequency: 10,
|
||
duration: 0.3,
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/asr.js =====
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/steve-jobs.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
moreVideoAttr: {
|
||
// crossOrigin: 'anonymous',
|
||
},
|
||
plugins: [
|
||
artplayerPluginAsr({
|
||
length: 2,
|
||
interval: 40,
|
||
sampleRate: 16000,
|
||
autoHideTimeout: 10000,
|
||
// Use your AI tool to convert pcm into subtitles
|
||
onAudioChunk: ({ pcm }) => startAsr(pcm),
|
||
}),
|
||
],
|
||
})
|
||
|
||
let ws = null
|
||
let loading = false
|
||
|
||
function stopAsr() {
|
||
try {
|
||
ws.send(JSON.stringify({ type: 'end' }))
|
||
ws.close()
|
||
}
|
||
catch {}
|
||
ws = null
|
||
loading = false
|
||
}
|
||
|
||
async function startAsr(buffer) {
|
||
if (loading)
|
||
return
|
||
if (!ws) {
|
||
loading = true
|
||
const api = 'https://api.aimu.app/asr/tencent?engine_model_type=16k_en'
|
||
const { url } = await (await fetch(api)).json()
|
||
ws = new WebSocket(url)
|
||
ws.binaryType = 'arraybuffer'
|
||
ws.onmessage = (event) => {
|
||
const { code, result, message } = JSON.parse(event.data)
|
||
if (code === 0) {
|
||
art.plugins.artplayerPluginAsr.append(result?.voice_text_str)
|
||
}
|
||
else {
|
||
console.error(code, message)
|
||
stopAsr()
|
||
}
|
||
}
|
||
loading = false
|
||
}
|
||
if (ws?.readyState === WebSocket.OPEN) {
|
||
ws.send(buffer)
|
||
}
|
||
}
|
||
|
||
art.on('destroy', stopAsr)
|
||
|
||
|
||
===== docs/assets/example/asr.local.js =====
|
||
|
||
/* global Artplayer, artplayerPluginAsr */
|
||
// Local audio capture demo. The subtitles below are simulated, not recognized speech.
|
||
// No audio is uploaded; only the sample media is loaded from this local site.
|
||
const statistics = document.createElement('div')
|
||
statistics.textContent = 'Local ASR demo: press play. No recognition service is used.'
|
||
let chunks = 0
|
||
let pcmBytes = 0
|
||
let wavBytes = 0
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/steve-jobs.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
layers: [{
|
||
name: 'asr-local-statistics',
|
||
html: statistics,
|
||
style: {
|
||
position: 'absolute',
|
||
top: '12px',
|
||
left: '12px',
|
||
right: '12px',
|
||
padding: '8px 12px',
|
||
background: 'rgba(0, 0, 0, 0.65)',
|
||
color: '#fff',
|
||
fontSize: '12px',
|
||
whiteSpace: 'pre-line',
|
||
pointerEvents: 'none',
|
||
},
|
||
}],
|
||
controls: [{
|
||
name: 'asr-local-stop',
|
||
position: 'right',
|
||
html: 'Stop ASR',
|
||
tooltip: 'Stop capture; pause and play to restart',
|
||
async click() {
|
||
await art.plugins.artplayerPluginAsr.stop()
|
||
if (!art.isDestroy)
|
||
statistics.textContent = 'Local capture stopped. Pause and play to restart. Nothing was uploaded.'
|
||
},
|
||
}],
|
||
plugins: [artplayerPluginAsr({
|
||
length: 2,
|
||
interval: 250,
|
||
sampleRate: 16000,
|
||
autoHideTimeout: 5000,
|
||
onAudioChunk({ pcm, wav }) {
|
||
if (art.isDestroy)
|
||
return
|
||
chunks++
|
||
pcmBytes += pcm.byteLength
|
||
wavBytes += wav.byteLength
|
||
const sampleRate = new DataView(wav).getUint32(24, true)
|
||
const samples = new DataView(pcm)
|
||
let peak = 0
|
||
for (let offset = 0; offset < pcm.byteLength; offset += 2)
|
||
peak = Math.max(peak, Math.abs(samples.getInt16(offset, true)))
|
||
const duration = (pcmBytes / 2 / sampleRate).toFixed(2)
|
||
statistics.textContent = [
|
||
'Local capture only - simulated subtitles, no speech recognition',
|
||
`Chunks: ${chunks} | ${sampleRate} Hz mono PCM16 | ${duration} seconds captured`,
|
||
`PCM: ${pcmBytes} bytes | WAV: ${wavBytes} bytes | Current peak: ${peak}`,
|
||
].join('\n')
|
||
return `Simulated local subtitle: audio chunk ${chunks} received.`
|
||
},
|
||
})],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/audio.track.js =====
|
||
|
||
// npm i artplayer-plugin-audio-track
|
||
// import artplayerPluginAudioTrack from 'artplayer-plugin-audio-track';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/sprite-fight.mp4',
|
||
plugins: [
|
||
artplayerPluginAudioTrack({
|
||
url: '/assets/sample/sprite-fight.aac',
|
||
offset: 0,
|
||
sync: 0.3,
|
||
}),
|
||
],
|
||
});
|
||
|
||
===== docs/assets/example/auto.thumbnail.js =====
|
||
|
||
// npm i artplayer-plugin-auto-thumbnail
|
||
// import artplayerPluginAutoThumbnail from 'artplayer-plugin-auto-thumbnail';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [
|
||
artplayerPluginAutoThumbnail({
|
||
//
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/canvas.js =====
|
||
|
||
// npm i artplayer-proxy-canvas
|
||
// import artplayerProxyCanvas from 'artplayer-proxy-canvas';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
poster: '/assets/sample/poster.jpg',
|
||
volume: 0.5,
|
||
autoplay: false,
|
||
autoSize: false,
|
||
screenshot: true,
|
||
setting: true,
|
||
loop: true,
|
||
flip: true,
|
||
pip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
miniProgressBar: true,
|
||
autoPlayback: true,
|
||
autoOrientation: true,
|
||
subtitle: {
|
||
url: '/assets/sample/subtitle.srt',
|
||
},
|
||
thumbnails: {
|
||
url: '/assets/sample/thumbnails.png',
|
||
number: 60,
|
||
column: 10,
|
||
scale: 0.85,
|
||
},
|
||
proxy: artplayerProxyCanvas(),
|
||
})
|
||
|
||
|
||
===== docs/assets/example/chapter.js =====
|
||
|
||
// npm i artplayer-plugin-chapter
|
||
// import artplayerPluginChapter from 'artplayer-plugin-chapter';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
miniProgressBar: true,
|
||
autoOrientation: true,
|
||
thumbnails: {
|
||
url: '/assets/sample/thumbnails.png',
|
||
number: 60,
|
||
column: 10,
|
||
},
|
||
plugins: [
|
||
artplayerPluginChapter({
|
||
chapters: [
|
||
{ start: 0, end: 18, title: 'One more chance' },
|
||
{ start: 18, end: 36, title: '谁でもいいはずなのに' },
|
||
{ start: 36, end: 54, title: '夏の想い出がまわる' },
|
||
{ start: 54, end: 72, title: 'こんなとこにあるはずもないのに' },
|
||
{ start: 72, end: Infinity, title: '终わり' },
|
||
],
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/chromecast.js =====
|
||
|
||
// npm i artplayer-plugin-chromecast
|
||
// import artplayerPluginChromecast from 'artplayer-plugin-chromecast';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
plugins: [
|
||
artplayerPluginChromecast({
|
||
// sdk: '', // The URL of the Cast SDK
|
||
// mimeType: '', // The MIME type of the media
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/danmuku.js =====
|
||
|
||
// npm i artplayer-plugin-danmuku
|
||
// import artplayerPluginDanmuku from 'artplayer-plugin-danmuku';
|
||
// 使用文档 https://artplayer.org/document/plugin/danmuku.html
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
autoOrientation: true,
|
||
plugins: [
|
||
artplayerPluginDanmuku({
|
||
danmuku: '/assets/sample/danmuku.xml',
|
||
|
||
// 以下为非必填
|
||
speed: 5, // 弹幕持续时间,范围在[1 ~ 10]
|
||
margin: [10, '25%'], // 弹幕上下边距,支持像素数字和百分比
|
||
opacity: 1, // 弹幕透明度,范围在[0 ~ 1]
|
||
color: '#FFFFFF', // 默认弹幕颜色,可以被单独弹幕项覆盖
|
||
mode: 0, // 默认弹幕模式: 0: 滚动,1: 顶部,2: 底部
|
||
modes: [0, 1, 2], // 弹幕可见的模式
|
||
fontSize: 25, // 弹幕字体大小,支持像素数字和百分比
|
||
antiOverlap: true, // 弹幕是否防重叠
|
||
synchronousPlayback: false, // 是否同步播放速度
|
||
mount: undefined, // 弹幕发射器挂载点, 默认为播放器控制栏中部
|
||
heatmap: true, // 是否开启热力图
|
||
width: 512, // 当播放器宽度小于此值时,弹幕发射器置于播放器底部
|
||
points: [], // 热力图数据
|
||
filter: danmu => danmu.text.length <= 100, // 弹幕载入前的过滤器
|
||
beforeVisible: () => true, // 弹幕显示前的过滤器,返回 true 则可以发送
|
||
visible: true, // 弹幕层是否可见
|
||
emitter: true, // 是否开启弹幕发射器
|
||
maxLength: 200, // 弹幕输入框最大长度, 范围在[1 ~ 1000]
|
||
lockTime: 5, // 输入框锁定时间,范围在[1 ~ 60]
|
||
theme: 'dark', // 弹幕主题,支持 dark 和 light,只在自定义挂载时生效
|
||
OPACITY: {}, // 不透明度配置项
|
||
FONT_SIZE: {}, // 弹幕字号配置项
|
||
MARGIN: {}, // 显示区域配置项
|
||
SPEED: {}, // 弹幕速度配置项
|
||
COLOR: [], // 颜色列表配置项
|
||
|
||
// 手动发送弹幕前的过滤器,返回 true 则可以发送,可以做存库处理
|
||
beforeEmit(danmu) {
|
||
return new Promise((resolve) => {
|
||
console.log(danmu)
|
||
setTimeout(() => {
|
||
resolve(true)
|
||
}, 1000)
|
||
})
|
||
},
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/danmuku.mask.js =====
|
||
|
||
// npm i artplayer-plugin-danmuku-mask
|
||
// import artplayerPluginDanmukuMask from 'artplayer-plugin-danmuku-mask';
|
||
|
||
// npm i @mediapipe/selfie_segmentation
|
||
// 把 node_modules/@mediapipe/selfie_segmentation 目录复制到你的项目下
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/steve-jobs.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
autoOrientation: true,
|
||
plugins: [
|
||
artplayerPluginDanmuku({
|
||
danmuku: '/assets/sample/danmuku.xml',
|
||
}),
|
||
artplayerPluginDanmukuMask({
|
||
solutionPath: '/assets/@mediapipe/selfie_segmentation',
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/dash.control.js =====
|
||
|
||
// npm i dashjs
|
||
// npm i artplayer-plugin-dash-control
|
||
|
||
// import dashjs from 'dashjs';
|
||
// import artplayerPluginDashControl from 'artplayer-plugin-dash-control';
|
||
|
||
const useDash = dashjs.supportsMediaSource()
|
||
let dash
|
||
|
||
function destroyDash() {
|
||
const previous = dash
|
||
dash = undefined
|
||
if (previous)
|
||
previous.destroy()
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://media.axprod.net/TestVectors/v7-Clear/Manifest_1080p.mpd',
|
||
setting: true,
|
||
plugins: useDash
|
||
? [
|
||
artplayerPluginDashControl({
|
||
quality: {
|
||
// Show quality choices in the controls
|
||
control: true,
|
||
// Show quality choices in settings
|
||
setting: true,
|
||
// Get the quality name from level
|
||
getName: level => `${level.height}P`,
|
||
// I18n
|
||
title: 'Quality',
|
||
auto: 'Auto',
|
||
},
|
||
audio: {
|
||
// Show audios in control
|
||
control: true,
|
||
// Show audios in setting
|
||
setting: true,
|
||
// Get the audio name from track
|
||
getName: track => track.lang?.toUpperCase() || String(track.id ?? 'Audio'),
|
||
// I18n
|
||
title: 'Audio',
|
||
auto: 'Auto',
|
||
},
|
||
}),
|
||
]
|
||
: [],
|
||
customType: {
|
||
mpd: function playMpd(video, url, art) {
|
||
destroyDash()
|
||
if (useDash) {
|
||
dash = dashjs.MediaPlayer().create()
|
||
art.dash = dash
|
||
dash.initialize(video, url, art.option.autoplay)
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: mpd'
|
||
}
|
||
},
|
||
},
|
||
})
|
||
|
||
art.on('destroy', destroyDash)
|
||
|
||
|
||
===== docs/assets/example/dash.js =====
|
||
|
||
// npm i dashjs
|
||
// import dashjs from 'dashjs';
|
||
|
||
function playMpd(video, url, art) {
|
||
if (dashjs.supportsMediaSource()) {
|
||
if (art.dash)
|
||
art.dash.destroy()
|
||
const dash = dashjs.MediaPlayer().create()
|
||
dash.initialize(video, url, art.option.autoplay)
|
||
art.dash = dash
|
||
art.on('destroy', () => dash.destroy())
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: mpd'
|
||
}
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd',
|
||
type: 'mpd',
|
||
customType: {
|
||
mpd: playMpd,
|
||
},
|
||
})
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.dash)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/document.pip.js =====
|
||
|
||
// npm i artplayer-plugin-document-pip
|
||
// import artplayerPluginDocumentPip from 'artplayer-plugin-document-pip';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [
|
||
artplayerPluginDocumentPip({
|
||
width: 480,
|
||
height: 270,
|
||
fallbackToVideoPiP: true,
|
||
placeholder: `Playing in Document Picture-in-Picture`,
|
||
}),
|
||
],
|
||
})
|
||
|
||
art.on('document-pip', (state) => {
|
||
console.log('Document Picture-in-Picture', state)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/flv.js =====
|
||
|
||
// npm i flv.js
|
||
// import flvjs from 'flv.js';
|
||
|
||
function playFlv(video, url, art) {
|
||
if (flvjs.isSupported()) {
|
||
if (art.flv)
|
||
art.flv.destroy()
|
||
const flv = flvjs.createPlayer({ type: 'flv', url })
|
||
flv.attachMediaElement(video)
|
||
flv.load()
|
||
art.flv = flv
|
||
art.on('destroy', () => flv.destroy())
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: flv'
|
||
}
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.flv',
|
||
type: 'flv',
|
||
customType: {
|
||
flv: playFlv,
|
||
},
|
||
})
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.flv)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/hls.control.js =====
|
||
|
||
// npm i hls.js
|
||
// npm i artplayer-plugin-hls-control
|
||
|
||
// import Hls from 'hls.js';
|
||
// import artplayerPluginHlsControl from 'artplayer-plugin-hls-control';
|
||
|
||
const useHls = Hls.isSupported()
|
||
let hls
|
||
|
||
function destroyHls() {
|
||
const previous = hls
|
||
hls = undefined
|
||
if (previous)
|
||
previous.destroy()
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8',
|
||
setting: true,
|
||
plugins: useHls
|
||
? [
|
||
artplayerPluginHlsControl({
|
||
quality: {
|
||
// Show quality choices in the controls
|
||
control: true,
|
||
// Show quality choices in settings
|
||
setting: true,
|
||
// Get the quality name from level
|
||
getName: level => `${level.height}P`,
|
||
// I18n
|
||
title: 'Quality',
|
||
auto: 'Auto',
|
||
},
|
||
audio: {
|
||
// Show audios in control
|
||
control: true,
|
||
// Show audios in setting
|
||
setting: true,
|
||
// Get the audio name from track
|
||
getName: track => track.name || track.lang || 'Audio',
|
||
// I18n
|
||
title: 'Audio',
|
||
auto: 'Auto',
|
||
},
|
||
}),
|
||
]
|
||
: [],
|
||
customType: {
|
||
m3u8: function playM3u8(video, url, art) {
|
||
destroyHls()
|
||
if (useHls) {
|
||
hls = new Hls()
|
||
art.hls = hls
|
||
hls.loadSource(url)
|
||
hls.attachMedia(video)
|
||
}
|
||
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||
video.src = url
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: m3u8'
|
||
}
|
||
},
|
||
},
|
||
})
|
||
|
||
art.on('destroy', destroyHls)
|
||
|
||
|
||
===== docs/assets/example/hls.js =====
|
||
|
||
// npm i hls.js
|
||
// import Hls from 'hls.js';
|
||
|
||
function playM3u8(video, url, art) {
|
||
if (Hls.isSupported()) {
|
||
if (art.hls)
|
||
art.hls.destroy()
|
||
const hls = new Hls()
|
||
hls.loadSource(url)
|
||
hls.attachMedia(video)
|
||
art.hls = hls
|
||
art.on('destroy', () => hls.destroy())
|
||
}
|
||
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||
video.src = url
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: m3u8'
|
||
}
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
|
||
type: 'm3u8',
|
||
customType: {
|
||
m3u8: playM3u8,
|
||
},
|
||
})
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.hls)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/iframe.js =====
|
||
|
||
// npm i artplayer-tool-iframe
|
||
// import ArtplayerToolIframe from 'artplayer-tool-iframe';
|
||
|
||
const $iframe = document.createElement('iframe')
|
||
$iframe.allowFullscreen = true
|
||
$iframe.width = '100%'
|
||
$iframe.height = '100%'
|
||
|
||
const $container = document.querySelector('.artplayer-app')
|
||
$container.innerHTML = ''
|
||
$container.appendChild($iframe)
|
||
|
||
const iframe = new ArtplayerToolIframe({
|
||
iframe: $iframe,
|
||
url: '/iframe.html',
|
||
})
|
||
|
||
window.addEventListener('artplayer:example:cleanup', () => {
|
||
iframe.destroy()
|
||
$iframe.remove()
|
||
}, { once: true })
|
||
|
||
iframe.message(({ type, data }) => {
|
||
switch (type) {
|
||
case 'fullscreenWeb':
|
||
if (data) {
|
||
$iframe.classList.add('fullscreenWeb')
|
||
}
|
||
else {
|
||
$iframe.classList.remove('fullscreenWeb')
|
||
}
|
||
break
|
||
default:
|
||
break
|
||
}
|
||
})
|
||
|
||
iframe.commit(() => {
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
})
|
||
|
||
art.on('fullscreenWeb', (state) => {
|
||
ArtplayerToolIframe.postMessage({
|
||
type: 'fullscreenWeb',
|
||
data: state,
|
||
})
|
||
})
|
||
}).catch((error) => {
|
||
if (!iframe.destroyed)
|
||
console.error(error)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/index.js =====
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
poster: '/assets/sample/poster.jpg',
|
||
volume: 0.5,
|
||
isLive: false,
|
||
muted: false,
|
||
autoplay: false,
|
||
pip: true,
|
||
autoSize: true,
|
||
autoMini: true,
|
||
screenshot: true,
|
||
setting: true,
|
||
loop: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
subtitleOffset: true,
|
||
miniProgressBar: true,
|
||
mutex: true,
|
||
backdrop: true,
|
||
playsInline: true,
|
||
autoPlayback: true,
|
||
airplay: true,
|
||
theme: '#23ade5',
|
||
lang: navigator.language.toLowerCase(),
|
||
moreVideoAttr: {
|
||
crossOrigin: 'anonymous',
|
||
},
|
||
settings: [
|
||
{
|
||
width: 200,
|
||
html: 'Subtitle',
|
||
tooltip: 'Bilingual',
|
||
icon: '<img width="22" height="22" src="/assets/img/subtitle.svg">',
|
||
selector: [
|
||
{
|
||
html: 'Display',
|
||
tooltip: 'Show',
|
||
switch: true,
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? 'Hide' : 'Show'
|
||
art.subtitle.show = !item.switch
|
||
return !item.switch
|
||
},
|
||
},
|
||
{
|
||
default: true,
|
||
html: 'Bilingual',
|
||
url: '/assets/sample/subtitle.srt',
|
||
},
|
||
{
|
||
html: 'Chinese',
|
||
url: '/assets/sample/subtitle.cn.srt',
|
||
},
|
||
{
|
||
html: 'Japanese',
|
||
url: '/assets/sample/subtitle.jp.srt',
|
||
},
|
||
],
|
||
onSelect(item) {
|
||
art.subtitle.switch(item.url, {
|
||
name: item.html,
|
||
})
|
||
return item.html
|
||
},
|
||
},
|
||
{
|
||
html: 'Switcher',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
tooltip: 'OFF',
|
||
switch: false,
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? 'OFF' : 'ON'
|
||
console.info('You clicked on the custom switch', item.switch)
|
||
return !item.switch
|
||
},
|
||
},
|
||
{
|
||
html: 'Slider',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
tooltip: '5x',
|
||
range: [5, 1, 10, 0.1],
|
||
onRange(item) {
|
||
return `${item.range[0]}x`
|
||
},
|
||
},
|
||
{
|
||
html: 'Button',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
tooltip: 'tooltip',
|
||
onClick() {
|
||
return 'Button clicked'
|
||
},
|
||
},
|
||
],
|
||
contextmenu: [
|
||
{
|
||
html: 'Custom menu',
|
||
click(contextmenu) {
|
||
console.info('You clicked on the custom menu')
|
||
contextmenu.show = false
|
||
},
|
||
},
|
||
],
|
||
layers: [
|
||
{
|
||
html: '<img width="100" src="/assets/sample/layer.png">',
|
||
click() {
|
||
window.open('https://aimu.app')
|
||
console.info('You clicked on the custom layer')
|
||
},
|
||
style: {
|
||
position: 'absolute',
|
||
top: '20px',
|
||
right: '20px',
|
||
opacity: '.9',
|
||
},
|
||
},
|
||
],
|
||
quality: [
|
||
{
|
||
default: true,
|
||
html: 'SD 480P',
|
||
url: '/assets/sample/video.mp4?q=480',
|
||
},
|
||
{
|
||
html: 'HD 720P',
|
||
url: '/assets/sample/video.mp4?q=720',
|
||
},
|
||
],
|
||
thumbnails: {
|
||
url: '/assets/sample/thumbnails.png',
|
||
number: 60,
|
||
column: 10,
|
||
scale: 0.85,
|
||
},
|
||
subtitle: {
|
||
url: '/assets/sample/subtitle.srt',
|
||
type: 'srt',
|
||
style: {
|
||
color: '#fe9200',
|
||
fontSize: '20px',
|
||
},
|
||
encoding: 'utf-8',
|
||
},
|
||
highlight: [
|
||
{
|
||
time: 15,
|
||
text: 'One more chance',
|
||
},
|
||
{
|
||
time: 30,
|
||
text: '谁でもいいはずなのに',
|
||
},
|
||
{
|
||
time: 45,
|
||
text: '夏の想い出がまわる',
|
||
},
|
||
{
|
||
time: 60,
|
||
text: 'こんなとこにあるはずもないのに',
|
||
},
|
||
{
|
||
time: 75,
|
||
text: '终わり',
|
||
},
|
||
],
|
||
controls: [
|
||
{
|
||
position: 'right',
|
||
html: 'Control',
|
||
index: 1,
|
||
tooltip: 'Control Tooltip',
|
||
style: {
|
||
marginRight: '20px',
|
||
},
|
||
click() {
|
||
console.info('You clicked on the custom control')
|
||
},
|
||
},
|
||
],
|
||
icons: {
|
||
loading: '<img src="/assets/img/ploading.gif">',
|
||
state: '<img width="150" height="150" src="/assets/img/state.svg">',
|
||
indicator: '<img width="16" height="16" src="/assets/img/indicator.svg">',
|
||
},
|
||
})
|
||
|
||
|
||
===== docs/assets/example/jassub.js =====
|
||
|
||
// https://github.com/ThaUnknown/jassub
|
||
// npm i artplayer-plugin-jassub
|
||
// import artplayerPluginJassub from 'artplayer-plugin-jassub';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/jassub/FGOBD.mp4',
|
||
autoSize: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
plugins: [
|
||
artplayerPluginJassub({
|
||
subUrl: '/assets/jassub/FGOBD.ass',
|
||
workerUrl: '/assets/jassub/jassub-worker.js',
|
||
wasmUrl: '/assets/jassub/jassub-worker.wasm',
|
||
modernWasmUrl: '/assets/jassub/jassub-worker-modern.wasm',
|
||
availableFonts: {
|
||
'liberation sans': '/assets/jassub/default.woff2'
|
||
},
|
||
fonts: [
|
||
'/assets/jassub/fonts/Averia Sans Libre Light.ttf',
|
||
'/assets/jassub/fonts/Averia Serif Simple Light.ttf',
|
||
'/assets/jassub/fonts/Gramond.ttf'
|
||
],
|
||
timeOffset: -0.041
|
||
}),
|
||
],
|
||
});
|
||
|
||
===== docs/assets/example/mediabunny.js =====
|
||
|
||
// npm i artplayer-proxy-mediabunny
|
||
// import artplayerProxyMediabunny from 'artplayer-proxy-mediabunny';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
|
||
autoSize: true,
|
||
setting: true,
|
||
loop: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
miniProgressBar: true,
|
||
autoPlayback: true,
|
||
autoOrientation: true,
|
||
proxy: artplayerProxyMediabunny({
|
||
m3u8: {
|
||
quality: {
|
||
control: true,
|
||
setting: true,
|
||
getName: level => level.height ? `${level.height}P` : level.name,
|
||
title: 'Quality',
|
||
auto: 'Auto',
|
||
},
|
||
audio: {
|
||
control: true,
|
||
setting: true,
|
||
getName: track => track.name || track.language,
|
||
title: 'Audio',
|
||
auto: 'Auto',
|
||
},
|
||
},
|
||
}),
|
||
})
|
||
|
||
|
||
===== docs/assets/example/mobile.js =====
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
poster: '/assets/sample/poster.jpg',
|
||
autoSize: true,
|
||
loop: true,
|
||
mutex: true,
|
||
setting: true,
|
||
flip: true,
|
||
lock: true,
|
||
fastForward: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
theme: '#ff0057',
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
miniProgressBar: true,
|
||
autoOrientation: true,
|
||
airplay: true,
|
||
moreVideoAttr: {
|
||
'x5-video-player-type': 'h5',
|
||
'x5-video-player-fullscreen': false,
|
||
'x5-video-orientation': 'portraint',
|
||
'preload': 'metadata',
|
||
},
|
||
thumbnails: {
|
||
url: '/assets/sample/thumbnails.png',
|
||
number: 60,
|
||
column: 10,
|
||
scale: 0.6,
|
||
},
|
||
subtitle: {
|
||
name: '中日双语',
|
||
url: '/assets/sample/subtitle.srt',
|
||
style: {
|
||
color: '#48aff0',
|
||
fontSize: '16px',
|
||
},
|
||
},
|
||
layers: [
|
||
{
|
||
html: `<img width="50" src="/assets/sample/layer.png">`,
|
||
click() {
|
||
art.notice.show = '你点击了自定义层'
|
||
},
|
||
style: {
|
||
position: 'absolute',
|
||
top: '10px',
|
||
right: '10px',
|
||
opacity: '.9',
|
||
},
|
||
},
|
||
],
|
||
icons: {
|
||
loading: '<img src="/assets/img/ploading.gif">',
|
||
state: '<img width="150" height="150" src="/assets/img/state.svg">',
|
||
indicator: '<img width="16" height="16" src="/assets/img/indicator.svg">',
|
||
},
|
||
settings: [
|
||
{
|
||
width: 200,
|
||
html: '切换字幕',
|
||
tooltip: '双语',
|
||
icon: '<img width="22" height="22" src="/assets/img/subtitle.svg">',
|
||
selector: [
|
||
{
|
||
html: '开关',
|
||
switch: true,
|
||
tooltip: '显示',
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? '隐藏' : '显示'
|
||
art.subtitle.show = !item.switch
|
||
return !item.switch
|
||
},
|
||
},
|
||
{
|
||
default: true,
|
||
html: '双语',
|
||
url: '/assets/sample/subtitle.srt',
|
||
},
|
||
{
|
||
html: '中文',
|
||
url: '/assets/sample/subtitle.cn.srt',
|
||
},
|
||
{
|
||
html: '日文',
|
||
url: '/assets/sample/subtitle.jp.srt',
|
||
},
|
||
],
|
||
onSelect(item) {
|
||
art.subtitle.switch(item.url, {
|
||
name: item.html,
|
||
})
|
||
return item.html
|
||
},
|
||
},
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/mpegts.js =====
|
||
|
||
// npm i mpegts
|
||
// import mpegts from 'mpegts';
|
||
|
||
function playFlv(video, url, art) {
|
||
if (mpegts.isSupported()) {
|
||
if (art.flv)
|
||
art.flv.destroy()
|
||
|
||
const flv = mpegts.createPlayer({
|
||
type: 'flv',
|
||
url,
|
||
})
|
||
flv.attachMediaElement(video)
|
||
flv.load()
|
||
flv.play()
|
||
|
||
art.flv = flv
|
||
art.on('destroy', () => flv.destroy())
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: flv'
|
||
}
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.flv',
|
||
type: 'flv',
|
||
customType: {
|
||
flv: playFlv,
|
||
},
|
||
})
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.flv)
|
||
})
|
||
|
||
|
||
===== docs/assets/example/multiple.subtitles.js =====
|
||
|
||
// npm i artplayer-plugin-multiple-subtitles
|
||
// import artplayerPluginMultipleSubtitles from 'artplayer-plugin-multiple-subtitles';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
plugins: [
|
||
artplayerPluginMultipleSubtitles({
|
||
subtitles: [
|
||
{
|
||
name: 'chinese',
|
||
url: '/assets/sample/subtitle.cn.srt',
|
||
},
|
||
{
|
||
name: 'japanese',
|
||
url: '/assets/sample/subtitle.jp.srt',
|
||
},
|
||
],
|
||
}),
|
||
],
|
||
settings: [
|
||
{
|
||
width: 200,
|
||
html: 'Subtitle',
|
||
tooltip: 'Double',
|
||
icon: '<img width="22" height="22" src="/assets/img/subtitle.svg">',
|
||
selector: [
|
||
{
|
||
html: 'Display',
|
||
tooltip: 'Show',
|
||
switch: true,
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? 'Hide' : 'Show'
|
||
// 显示/隐藏字幕
|
||
// Show/hide subtitles
|
||
art.subtitle.show = !item.switch
|
||
return !item.switch
|
||
},
|
||
},
|
||
{
|
||
html: 'Reverse',
|
||
tooltip: 'Off',
|
||
switch: false,
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? 'Off' : 'On'
|
||
// 修改字幕顺序
|
||
// Change the order of subtitles
|
||
if (item.switch) {
|
||
art.plugins.multipleSubtitles.tracks(['chinese', 'japanese'])
|
||
}
|
||
else {
|
||
art.plugins.multipleSubtitles.tracks(['japanese', 'chinese'])
|
||
}
|
||
return !item.switch
|
||
},
|
||
},
|
||
{
|
||
default: true,
|
||
html: 'Double',
|
||
name: 'double',
|
||
},
|
||
{
|
||
html: 'Chinese',
|
||
name: 'chinese',
|
||
},
|
||
{
|
||
html: 'Japanese',
|
||
name: 'japanese',
|
||
},
|
||
],
|
||
onSelect(item) {
|
||
if (item.name === 'double') {
|
||
// 重置字幕
|
||
// Reset subtitles
|
||
art.plugins.multipleSubtitles.reset()
|
||
}
|
||
else {
|
||
// 显示单个字幕
|
||
// Show single subtitle
|
||
art.plugins.multipleSubtitles.tracks([item.name])
|
||
}
|
||
return item.html
|
||
},
|
||
},
|
||
],
|
||
})
|
||
|
||
// 自定义你自己的样式,请勿复制以下代码
|
||
// Customize your own style, please do not copy the following code
|
||
|
||
const style = `
|
||
.art-subtitle-chinese {
|
||
color: red;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.art-subtitle-japanese {
|
||
color: yellow;
|
||
font-size: 12px;
|
||
}
|
||
`
|
||
|
||
const $style = document.getElementById('artplayer-subtitle-style')
|
||
if ($style) {
|
||
$style.textContent = style
|
||
}
|
||
else {
|
||
const $style = document.createElement('style')
|
||
$style.id = 'artplayer-subtitle-style'
|
||
$style.textContent = style
|
||
document.head.appendChild($style)
|
||
}
|
||
|
||
|
||
===== docs/assets/example/setting.test.js =====
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
setting: true,
|
||
flip: true,
|
||
playbackRate: true,
|
||
aspectRatio: true,
|
||
subtitleOffset: true,
|
||
settings: [
|
||
{
|
||
width: 200,
|
||
html: 'Subtitle',
|
||
name: 'subtitle',
|
||
tooltip: 'Bilingual',
|
||
icon: '<img width="22" height="22" src="/assets/img/subtitle.svg">',
|
||
selector: [
|
||
{
|
||
html: 'Display',
|
||
tooltip: 'Show',
|
||
switch: true,
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? 'Hide' : 'Show'
|
||
art.subtitle.show = !item.switch
|
||
return !item.switch
|
||
},
|
||
},
|
||
{
|
||
default: true,
|
||
html: 'Bilingual',
|
||
url: '/assets/sample/subtitle.srt',
|
||
},
|
||
{
|
||
html: 'Chinese',
|
||
url: '/assets/sample/subtitle.cn.srt',
|
||
},
|
||
{
|
||
html: 'Japanese',
|
||
url: '/assets/sample/subtitle.jp.srt',
|
||
},
|
||
],
|
||
onSelect(item) {
|
||
art.subtitle.switch(item.url, {
|
||
name: item.html,
|
||
})
|
||
return item.html
|
||
},
|
||
mounted(...args) {
|
||
console.info(args)
|
||
},
|
||
},
|
||
{
|
||
html: 'Switcher',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
tooltip: 'OFF',
|
||
switch: false,
|
||
onSwitch(item) {
|
||
item.tooltip = item.switch ? 'OFF' : 'ON'
|
||
console.info('You clicked on the custom switch', item.switch)
|
||
return !item.switch
|
||
},
|
||
mounted(...args) {
|
||
console.info(args)
|
||
},
|
||
},
|
||
{
|
||
html: 'Slider',
|
||
icon: '<img width="22" height="22" src="/assets/img/state.svg">',
|
||
tooltip: '5x',
|
||
range: [5, 1, 10, 0.1],
|
||
onRange(item) {
|
||
return `${item.range[0]}x`
|
||
},
|
||
mounted(...args) {
|
||
console.info(args)
|
||
},
|
||
},
|
||
],
|
||
}, async () => {
|
||
const { sleep } = Artplayer.utils
|
||
art.setting.show = true
|
||
console.log(art.setting.builtin)
|
||
console.log(art.setting.find('aspect-ratio'))
|
||
console.log(art.setting.find('aspect-ratio2'))
|
||
await sleep(1000)
|
||
art.setting.resize()
|
||
await sleep(1000)
|
||
art.setting.inactivate(art.setting.find('subtitle'))
|
||
art.setting.remove('aspect-ratio')
|
||
try {
|
||
art.setting.remove('aspect-ratio2')
|
||
}
|
||
catch (error) {
|
||
console.log(error.message)
|
||
}
|
||
await sleep(1000)
|
||
art.setting.update({
|
||
name: 'subtitle-offset',
|
||
html: 'new offset',
|
||
range: [5, -11, 11, 1],
|
||
})
|
||
await sleep(1000)
|
||
art.setting.find('subtitle-offset').range = [0, -0, 10, 1]
|
||
await sleep(1000)
|
||
art.setting.update({
|
||
name: 'subtitle-offset2',
|
||
html: 'new offset 2',
|
||
range: [5, -11, 11, 1],
|
||
onChange(item) {
|
||
return `${item.range[0]}s`
|
||
},
|
||
})
|
||
await sleep(1000)
|
||
art.setting.update({
|
||
name: 'flip',
|
||
html: 'new flip',
|
||
tooltip: 'OFF',
|
||
switch: false,
|
||
})
|
||
await sleep(1000)
|
||
art.setting.find('flip').switch = true
|
||
await sleep(1000)
|
||
art.setting.update({
|
||
name: 'flip2',
|
||
html: 'new flip2',
|
||
tooltip: 'OFF',
|
||
switch: true,
|
||
})
|
||
await sleep(1000)
|
||
try {
|
||
art.setting.add({
|
||
name: 'flip2',
|
||
html: 'new flip2',
|
||
tooltip: 'OFF',
|
||
switch: true,
|
||
})
|
||
}
|
||
catch (error) {
|
||
console.log(error.message)
|
||
}
|
||
})
|
||
|
||
|
||
===== docs/assets/example/thumbnail.js =====
|
||
|
||
// npm i artplayer-plugin-thumbnail
|
||
// import artplayerPluginThumbnail from 'artplayer-plugin-thumbnail';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
plugins: [
|
||
artplayerPluginThumbnail({
|
||
width: 160,
|
||
number: 100,
|
||
scale: 1,
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/tool.thumbnail.js =====
|
||
|
||
if (window.lastThumbnail) {
|
||
window.lastThumbnail.destroy();
|
||
}
|
||
|
||
var $popups = document.querySelector('.popups');
|
||
var $popinner = document.querySelector('.popinner');
|
||
var $artplayer = document.querySelector('.artplayer-app');
|
||
|
||
$artplayer.innerHTML = 'Drop video file here or click to upload.';
|
||
var thumbnail = new ArtplayerToolThumbnail({
|
||
fileInput: $artplayer,
|
||
number: 60, // 数量
|
||
width: 160, // 宽度
|
||
column: 10, // 列数
|
||
begin: 0, // 开始
|
||
end: NaN, // 结束
|
||
});
|
||
|
||
window.lastThumbnail = thumbnail;
|
||
|
||
thumbnail.on('file', function (file) {
|
||
console.log('Read video successfully: ' + file.name);
|
||
});
|
||
|
||
thumbnail.on('video', function (video) {
|
||
console.log('Video size: ' + video.videoWidth + ' x ' + video.videoHeight);
|
||
console.log('Video duration: ' + video.duration + 's');
|
||
thumbnail.start();
|
||
});
|
||
|
||
thumbnail.on('canvas', function (canvas) {
|
||
console.log('Build canvas successfully');
|
||
console.log('Canvas size: ' + canvas.width + ' x ' + canvas.height);
|
||
console.log('Preview density: ' + thumbnail.density + ' p/s');
|
||
});
|
||
|
||
thumbnail.on('update', function (url, percentage) {
|
||
console.log('Processing: ' + Math.floor(percentage.toFixed(2) * 100) + '%');
|
||
$popups.style.display = 'flex';
|
||
$popinner.style.backgroundImage = 'url(' + url + ')';
|
||
});
|
||
|
||
thumbnail.on('download', function (name) {
|
||
console.log('Start download preview: ' + name);
|
||
});
|
||
|
||
thumbnail.on('done', function () {
|
||
$popups.style.display = 'none';
|
||
thumbnail.download();
|
||
console.log('Build preview image complete');
|
||
|
||
[...Artplayer.instances].forEach(function (art) {
|
||
art.destroy(true);
|
||
});
|
||
|
||
new Artplayer({
|
||
container: $artplayer,
|
||
url: thumbnail.videoUrl,
|
||
autoSize: true,
|
||
poster: thumbnail.thumbnailUrl,
|
||
thumbnails: {
|
||
url: thumbnail.thumbnailUrl,
|
||
number: thumbnail.option.number,
|
||
column: thumbnail.option.column,
|
||
},
|
||
});
|
||
|
||
console.log('Build player complete');
|
||
});
|
||
|
||
|
||
===== docs/assets/example/vast.js =====
|
||
|
||
// Depends on:
|
||
// https://glomex.github.io/vast-ima-player/
|
||
// https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side
|
||
|
||
// Google's IMA SDK are blocked by your Ad blocker.
|
||
// Please Turn Off Your Ad Blocker.
|
||
|
||
// npm i artplayer-plugin-vast
|
||
// import artplayerPluginVast from 'artplayer-plugin-vast';
|
||
|
||
var art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/video.mp4',
|
||
fullscreen: true,
|
||
fullscreenWeb: true,
|
||
plugins: [
|
||
artplayerPluginVast(({ playUrl, imaPlayer, ima }) => {
|
||
// Play the ad when the video is played
|
||
art.once('play', () => {
|
||
playUrl('https://artplayer.org/assets/vast/linear-ad.xml')
|
||
})
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/vtt.thumbnail.js =====
|
||
|
||
// npm i artplayer-plugin-vtt-thumbnail
|
||
// import artplayerPluginVttThumbnail from 'artplayer-plugin-vtt-thumbnail';
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: '/assets/sample/bbb-video.mp4',
|
||
plugins: [
|
||
artplayerPluginVttThumbnail({
|
||
vtt: '/assets/sample/bbb-thumbnails.vtt',
|
||
}),
|
||
],
|
||
})
|
||
|
||
|
||
===== docs/assets/example/webtorrent.js =====
|
||
|
||
// npm i webtorrent
|
||
// import WebTorrent from 'webtorrent';
|
||
|
||
async function playTorrent(video, url, art) {
|
||
if (WebTorrent.WEBRTC_SUPPORT) {
|
||
if (art.torrent)
|
||
art.torrent.destroy()
|
||
art.torrent = new WebTorrent()
|
||
|
||
await navigator.serviceWorker.register('/webtorrent.sw.min.js')
|
||
art.torrent.loadWorker(navigator.serviceWorker.controller)
|
||
|
||
art.torrent.add(url, (torrent) => {
|
||
const file = torrent.files.find((file) => {
|
||
return file.name.endsWith('.mp4')
|
||
})
|
||
file.streamTo(video)
|
||
})
|
||
|
||
art.on('destroy', () => art.torrent.destroy())
|
||
}
|
||
else {
|
||
art.notice.show = 'Unsupported playback format: torrent'
|
||
}
|
||
}
|
||
|
||
const art = new Artplayer({
|
||
container: '.artplayer-app',
|
||
url: 'magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=Sintel&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fsintel.torrent',
|
||
type: 'torrent',
|
||
customType: {
|
||
torrent: playTorrent,
|
||
},
|
||
})
|
||
|
||
art.on('ready', () => {
|
||
console.info(art.torrent)
|
||
})
|
||
|
||
|
||
===== Third-party Type Notices =====
|
||
|
||
===== docs/assets/ts/artplayer-plugin-vast.LICENSE.txt =====
|
||
|
||
@glomex/vast-ima-player
|
||
Apache License
|
||
Version 2.0, January 2004
|
||
http://www.apache.org/licenses/
|
||
|
||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||
|
||
1. Definitions.
|
||
|
||
"License" shall mean the terms and conditions for use, reproduction,
|
||
and distribution as defined by Sections 1 through 9 of this document.
|
||
|
||
"Licensor" shall mean the copyright owner or entity authorized by
|
||
the copyright owner that is granting the License.
|
||
|
||
"Legal Entity" shall mean the union of the acting entity and all
|
||
other entities that control, are controlled by, or are under common
|
||
control with that entity. For the purposes of this definition,
|
||
"control" means (i) the power, direct or indirect, to cause the
|
||
direction or management of such entity, whether by contract or
|
||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||
|
||
"You" (or "Your") shall mean an individual or Legal Entity
|
||
exercising permissions granted by this License.
|
||
|
||
"Source" form shall mean the preferred form for making modifications,
|
||
including but not limited to software source code, documentation
|
||
source, and configuration files.
|
||
|
||
"Object" form shall mean any form resulting from mechanical
|
||
transformation or translation of a Source form, including but
|
||
not limited to compiled object code, generated documentation,
|
||
and conversions to other media types.
|
||
|
||
"Work" shall mean the work of authorship, whether in Source or
|
||
Object form, made available under the License, as indicated by a
|
||
copyright notice that is included in or attached to the work
|
||
(an example is provided in the Appendix below).
|
||
|
||
"Derivative Works" shall mean any work, whether in Source or Object
|
||
form, that is based on (or derived from) the Work and for which the
|
||
editorial revisions, annotations, elaborations, or other modifications
|
||
represent, as a whole, an original work of authorship. For the purposes
|
||
of this License, Derivative Works shall not include works that remain
|
||
separable from, or merely link (or bind by name) to the interfaces of,
|
||
the Work and Derivative Works thereof.
|
||
|
||
"Contribution" shall mean any work of authorship, including
|
||
the original version of the Work and any modifications or additions
|
||
to that Work or Derivative Works thereof, that is intentionally
|
||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||
or by an individual or Legal Entity authorized to submit on behalf of
|
||
the copyright owner. For the purposes of this definition, "submitted"
|
||
means any form of electronic, verbal, or written communication sent
|
||
to the Licensor or its representatives, including but not limited to
|
||
communication on electronic mailing lists, source code control systems,
|
||
and issue tracking systems that are managed by, or on behalf of, the
|
||
Licensor for the purpose of discussing and improving the Work, but
|
||
excluding communication that is conspicuously marked or otherwise
|
||
designated in writing by the copyright owner as "Not a Contribution."
|
||
|
||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||
on behalf of whom a Contribution has been received by Licensor and
|
||
subsequently incorporated within the Work.
|
||
|
||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||
this License, each Contributor hereby grants to You a perpetual,
|
||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||
copyright license to reproduce, prepare Derivative Works of,
|
||
publicly display, publicly perform, sublicense, and distribute the
|
||
Work and such Derivative Works in Source or Object form.
|
||
|
||
3. Grant of Patent License. Subject to the terms and conditions of
|
||
this License, each Contributor hereby grants to You a perpetual,
|
||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||
(except as stated in this section) patent license to make, have made,
|
||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||
where such license applies only to those patent claims licensable
|
||
by such Contributor that are necessarily infringed by their
|
||
Contribution(s) alone or by combination of their Contribution(s)
|
||
with the Work to which such Contribution(s) was submitted. If You
|
||
institute patent litigation against any entity (including a
|
||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||
or a Contribution incorporated within the Work constitutes direct
|
||
or contributory patent infringement, then any patent licenses
|
||
granted to You under this License for that Work shall terminate
|
||
as of the date such litigation is filed.
|
||
|
||
4. Redistribution. You may reproduce and distribute copies of the
|
||
Work or Derivative Works thereof in any medium, with or without
|
||
modifications, and in Source or Object form, provided that You
|
||
meet the following conditions:
|
||
|
||
(a) You must give any other recipients of the Work or
|
||
Derivative Works a copy of this License; and
|
||
|
||
(b) You must cause any modified files to carry prominent notices
|
||
stating that You changed the files; and
|
||
|
||
(c) You must retain, in the Source form of any Derivative Works
|
||
that You distribute, all copyright, patent, trademark, and
|
||
attribution notices from the Source form of the Work,
|
||
excluding those notices that do not pertain to any part of
|
||
the Derivative Works; and
|
||
|
||
(d) If the Work includes a "NOTICE" text file as part of its
|
||
distribution, then any Derivative Works that You distribute must
|
||
include a readable copy of the attribution notices contained
|
||
within such NOTICE file, excluding those notices that do not
|
||
pertain to any part of the Derivative Works, in at least one
|
||
of the following places: within a NOTICE text file distributed
|
||
as part of the Derivative Works; within the Source form or
|
||
documentation, if provided along with the Derivative Works; or,
|
||
within a display generated by the Derivative Works, if and
|
||
wherever such third-party notices normally appear. The contents
|
||
of the NOTICE file are for informational purposes only and
|
||
do not modify the License. You may add Your own attribution
|
||
notices within Derivative Works that You distribute, alongside
|
||
or as an addendum to the NOTICE text from the Work, provided
|
||
that such additional attribution notices cannot be construed
|
||
as modifying the License.
|
||
|
||
You may add Your own copyright statement to Your modifications and
|
||
may provide additional or different license terms and conditions
|
||
for use, reproduction, or distribution of Your modifications, or
|
||
for any such Derivative Works as a whole, provided Your use,
|
||
reproduction, and distribution of the Work otherwise complies with
|
||
the conditions stated in this License.
|
||
|
||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||
any Contribution intentionally submitted for inclusion in the Work
|
||
by You to the Licensor shall be under the terms and conditions of
|
||
this License, without any additional terms or conditions.
|
||
Notwithstanding the above, nothing herein shall supersede or modify
|
||
the terms of any separate license agreement you may have executed
|
||
with Licensor regarding such Contributions.
|
||
|
||
6. Trademarks. This License does not grant permission to use the trade
|
||
names, trademarks, service marks, or product names of the Licensor,
|
||
except as required for reasonable and customary use in describing the
|
||
origin of the Work and reproducing the content of the NOTICE file.
|
||
|
||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||
agreed to in writing, Licensor provides the Work (and each
|
||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||
implied, including, without limitation, any warranties or conditions
|
||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||
appropriateness of using or redistributing the Work and assume any
|
||
risks associated with Your exercise of permissions under this License.
|
||
|
||
8. Limitation of Liability. In no event and under no legal theory,
|
||
whether in tort (including negligence), contract, or otherwise,
|
||
unless required by applicable law (such as deliberate and grossly
|
||
negligent acts) or agreed to in writing, shall any Contributor be
|
||
liable to You for damages, including any direct, indirect, special,
|
||
incidental, or consequential damages of any character arising as a
|
||
result of this License or out of the use or inability to use the
|
||
Work (including but not limited to damages for loss of goodwill,
|
||
work stoppage, computer failure or malfunction, or any and all
|
||
other commercial damages or losses), even if such Contributor
|
||
has been advised of the possibility of such damages.
|
||
|
||
9. Accepting Warranty or Additional Liability. While redistributing
|
||
the Work or Derivative Works thereof, You may choose to offer,
|
||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||
or other liability obligations and/or rights consistent with this
|
||
License. However, in accepting such obligations, You may act only
|
||
on Your own behalf and on Your sole responsibility, not on behalf
|
||
of any other Contributor, and only if You agree to indemnify,
|
||
defend, and hold each Contributor harmless for any liability
|
||
incurred by, or claims asserted against, such Contributor by reason
|
||
of your accepting any such warranty or additional liability.
|
||
|
||
END OF TERMS AND CONDITIONS
|
||
|
||
APPENDIX: How to apply the Apache License to your work.
|
||
|
||
To apply the Apache License to your work, attach the following
|
||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||
replaced with your own identifying information. (Don't include
|
||
the brackets!) The text should be enclosed in the appropriate
|
||
comment syntax for the file format. We also recommend that a
|
||
file or class name and description of purpose be included on the
|
||
same "printed page" as the copyright notice for easier
|
||
identification within third-party archives.
|
||
|
||
Copyright 2020 glomex GmbH
|
||
|
||
Licensed under the Apache License, Version 2.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing, software
|
||
distributed under the License is distributed on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
|
||
@alugha/ima
|
||
# The MIT License (MIT)
|
||
|
||
**Copyright 2020 Alugha GmbH**
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||
this software and associated documentation files (the "Software"), to deal in
|
||
the Software without restriction, including without limitation the rights to
|
||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||
subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|