docs(site): [SITE-04] document chapter and ambilight contracts in both languages

This commit is contained in:
Harvey Zhao committed 2026-09-16 02:30:01 +08:00
1 parent dba354f8cd
commit 3138812610
86 files changed
+3857 -1748

No files matched your search

+11 -2
View File
@@ -15,6 +15,8 @@ not a VitePress page. Keep both URL surfaces compatible.
| `docs/plugin/dash-control.md`, `docs/en/plugin/dash-control.md` | DASH SDK generations, menus, lifecycle and types | `/document/plugin/dash-control.html`, `/document/en/plugin/dash-control.html` |
| `docs/plugin/audio-track.md`, `docs/en/plugin/audio-track.md` | Separate audio synchronization, ownership and update types | `/document/plugin/audio-track.html`, `/document/en/plugin/audio-track.html` |
| `docs/plugin/vtt-thumbnail.md`, `docs/en/plugin/vtt-thumbnail.md` | Sprite index format, timing boundaries, asynchronous registration and types | `/document/plugin/vtt-thumbnail.html`, `/document/en/plugin/vtt-thumbnail.html` |
| `docs/plugin/chapter.md`, `docs/en/plugin/chapter.md` | Chapter ranges, caller-data mutation, replacement updates, cleanup and types | `/document/plugin/chapter.html`, `/document/en/plugin/chapter.html` |
| `docs/plugin/ambilight.md`, `docs/en/plugin/ambilight.md` | Sampling options, start/stop ownership, pixel access and compatible type entries | `/document/plugin/ambilight.html`, `/document/en/plugin/ambilight.html` |
| `docs/.vitepress/config.js` | Navigation, base URL, output path, page head | Repository `docs/document/` |
| `docs/vite.config.ts` | Search plugin configuration | VitePress/Vite integration; real search acceptance remains pending |
| `docs/public/main.js` | Run Code links and first-visit language redirect | Copied into the built site |
@@ -28,11 +30,18 @@ and run `node refactor/scripts/demos.mjs --check`. Preserve the frozen BASE-04
inventory. Also refresh and check the current site inventory; the two inventories
serve different purposes. Neither path check replaces browser navigation tests.
The generated site lives in `docs/document/`. The current inventory contains 36 Markdown pages: 18 Chinese
and 18 English. Danmuku, HLS, DASH, Audio Track and VTT Thumbnail have dedicated guides and navigation in both languages. Other plugins currently
The generated site lives in `docs/document/`. The current inventory contains 40 Markdown pages: 20 Chinese
and 20 English. Danmuku, HLS, DASH, Audio Track, VTT Thumbnail, Chapter and Ambilight have dedicated guides and navigation in both languages. Other plugins currently
use their package README, architecture notes and linked editor examples;
navigation links alone are not complete API documentation.
Chapter and Ambilight guides preserve their original demo code and explicitly
document the mutation, lifecycle and historical type boundaries. Keep their
language pairs together; the content mapping is in `refactor/site-content-review.md`.
Run Code markers need visible text as well as the existing className/data-libs
hooks. Navigation checks verify exact code forwarding, not playback in the editor.
The documented core version in the shared navigation is 6.0.0, marked unreleased.
VTT Thumbnail guides preserve the original vtt.thumbnail demo. The document-vtt
suite checks actual screenshot crop pixels, a shared time boundary, a gap and
cleanup using the original video, controlled VTT/SVG resources and real progress
@@ -19,7 +19,7 @@ const config = {
{ text: 'Online Editor', link: 'https://artplayer.org' },
{ text: '🤖LLMs', link: 'https://artplayer.org/llms.txt' },
{
text: '5.3.x',
text: '6.0.0 (unreleased)',
items: [
{ text: 'Changelog', link: 'https://github.com/zhw2590582/ArtPlayer/blob/master/CHANGELOG.md' },
{ text: 'Donation', link: 'https://github.com/zhw2590582/ArtPlayer#donations' },
@@ -77,8 +77,8 @@ const config = {
{ text: 'ASS 字幕 - JASSUB', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub' },
{ text: 'Chromecast', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast' },
{ text: 'VAST 广告', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast' },
{ text: '视频章节', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chapter/index.js&example=chapter' },
{ text: '视频背光', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight' },
{ text: '视频章节', link: '/plugin/chapter' },
{ text: '视频背光', link: '/plugin/ambilight' },
{ text: '文档画中画', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-document-pip/index.js&example=document.pip' },
{ text: '独立音轨', link: '/plugin/audio-track' },
],
@@ -149,8 +149,8 @@ const config = {
{ text: 'ASS Subtitle - JASSUB', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub' },
{ text: 'Chromecast', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast' },
{ text: 'VAST', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast' },
{ text: 'Video Chapters', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chapter/index.js&example=chapter' },
{ text: 'Video Ambilight', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight' },
{ text: 'Video Chapters', link: '/en/plugin/chapter' },
{ text: 'Video Ambilight', link: '/en/plugin/ambilight' },
{ text: 'Document PIP', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-document-pip/index.js&example=document.pip' },
{ text: 'Audio Track', link: '/en/plugin/audio-track' },
],
@@ -0,0 +1,88 @@
# Video ambilight
[简体中文](../../plugin/ambilight.md)
Sample colors from the video to display a blurred glow around the player. The plugin reads pixels with Canvas, needs no additional SDK, and does not change video playback or audio output.
This page describes the refactor branch. Its lifecycle fixes and accurate type entry are not published yet. The online example and unpinned npm/CDN packages are not the current candidate.
## Installation and example
```sh
yarn add artplayer artplayer-plugin-ambilight
```
```js
import Artplayer from 'artplayer';
import artplayerPluginAmbilight from 'artplayer-plugin-ambilight';
```
For script usage, load ArtPlayer before `dist/artplayer-plugin-ambilight.js`. The global is `artplayerPluginAmbilight`. The following code is unchanged from the [online ambilight example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight). Your application must provide its own container and accessible video.
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-ambilight/index.js">▶ Run Code</div>
```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,
}),
],
})
```
## Options
| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `blur` | `string` | `'50px'` | CSS blur radius |
| `opacity` | `number` | `0.5` | Glow grid opacity; the example explicitly uses `1` |
| `frequency` | `number` | `10` | Maximum samples per second; use a positive value; playback and frame scheduling limit the actual rate |
| `duration` | `number` | `0.3` | Color transition duration in seconds |
| `zIndex` | `number` | Actual value fixed at `9` | Historical accepted input that does not change the grid's stacking order |
The plugin samples a 3×3 grid. Colors update only while the player is playing and the sampling interval has elapsed. `frequency` does not set the video's frame rate. Masks, clipping and an ancestor's `overflow` styles can also affect how much of the glow is visible.
## start and stop
The result has the fixed `name` of `artplayerPluginAmbilight`. When installed through the constructor options, it starts scheduling after the player's `ready` event:
```js
const light = art.plugins.artplayerPluginAmbilight;
light.stop(); // Stop sampling and retain the last colors.
light.start(); // Resume sampling while the player is playing.
```
Both methods return `undefined` synchronously and do not play or pause the video. `stop()` retains the last colors. `start()` is not a Promise that captures a frame immediately. Repeated calls do not create multiple sampling loops. If you install the plugin with `art.plugins.add(...)` after `ready` has already fired, call `start()` on the returned result yourself.
There is no plugin `update` or separate `destroy` method. Destroying the player stops frame scheduling, removes the grid and plugin subscriptions, and releases the sampling canvas. Retained `start/stop` methods do no work after destruction.
## Media access and proxies
The browser must be able to decode the video and read its pixels into Canvas. Cross-origin video needs the appropriate media CORS configuration and server response headers; successful playback alone does not grant pixel access. A failed pixel read skips that update and retains existing colors. A later readable source can recover. The plugin does not bypass browser origin restrictions.
Canvas proxy sampling uses the actual dimensions of its output canvas. Other proxies must be checked for a drawable output; a passing desktop combination does not establish support for every browser or proxy. The effect does not control a physical monitor's backlight.
## TypeScript compatibility entries
The root and `/legacy` entries retain the published 1.1.0 factory type: the options object is required, while its fields are optional. Pass `{}` for defaults with those types. JavaScript calls can still omit the argument.
For accurate optional calls, the CommonJS `.default` self-alias, or callable NodeNext ESM default types, use `/runtime`, which shares the same implementation:
```ts
import ambilight from 'artplayer-plugin-ambilight/runtime';
const installLight = ambilight();
const installDefaultLight = ambilight.default({ opacity: 0.5 });
```
The root declarations export the named types `Option`, `Result`, `Callable`, `Factory` and `RuntimeFactory`. Version 1.0.0 used `export =` and required option fields, unlike 1.1.0. Earlier `import = require` callers can move to `/runtime`; reads of optional fields need a fallback. Node10 TypeScript default imports of `/runtime` require `esModuleInterop`; `import = require` works without it.
@@ -23,7 +23,7 @@ For script tags, load ArtPlayer before the plugin's `dist/artplayer-plugin-audio
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>
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-audio-track/index.js">▶ Run Code</div>
```js
// npm i artplayer-plugin-audio-track
@@ -0,0 +1,104 @@
# Video chapters
[简体中文](../../plugin/chapter.md)
Divide the progress bar into chapters and display a title on hover while retaining the player's seeking and thumbnail controls. The plugin does not extract chapter metadata from the media file; your application supplies the times.
This page describes the refactor branch. Its candidates and fixes are not published yet. The online example and unpinned npm/CDN packages may use different code.
## Installation and example
```sh
yarn add artplayer artplayer-plugin-chapter
```
```js
import Artplayer from 'artplayer';
import artplayerPluginChapter from 'artplayer-plugin-chapter';
```
For script usage, load ArtPlayer before `dist/artplayer-plugin-chapter.js`. The plugin global is `artplayerPluginChapter`. The following code is unchanged from the [online chapter example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chapter/index.js&example=chapter). The site provides its container, video and thumbnail image; replace those resources when integrating it into your application.
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-chapter/index.js">▶ Run Code</div>
```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: '终わり' },
],
}),
],
})
```
## chapters
The factory accepts an optional options object containing `chapters`. Each entry has these fields:
| Field | Type | Meaning |
| --- | --- | --- |
| `start` | `number` | Start time in seconds; a finite, nonnegative number |
| `end` | `number` | End time in seconds; `Infinity` means the current video's end |
| `title` | `string` | Hover title; an empty string retains an untitled interval |
Every interval must satisfy `start < end <= video duration`, without overlapping the next chapter. The plugin sorts chapters by start time and fills uncovered intervals at the beginning, end and between chapters. It **mutates the supplied array** by sorting it, inserting untitled entries and replacing `Infinity` with the current duration. Pass a fresh array and fresh entry objects whenever you need to preserve the original configuration.
Chapters are created only when the media duration is finite and positive. Missing, empty or non-array input clears the view; TypeScript still accepts only the declared array type. Invalid field types throw `TypeError`; invalid times and overlapping intervals throw `Error`. Titles are plain text, not HTML. Displayed titles are trimmed without changing the original object's `title`.
## update
The result has the fixed `name` of `artplayerPluginChapter`. `update(option)` replaces the chapters synchronously and returns `undefined`. Its options object is required; `update({})` clears the chapters:
```js
art.plugins.artplayerPluginChapter.update({
chapters: [{ start: 0, end: Infinity, title: 'Introduction' }],
});
// Clear all chapter segments and the hover title.
art.plugins.artplayerPluginChapter.update({});
```
An update clears the previous view before validating the replacement. If validation throws, the previous chapters are not retained. A successful update synchronously emits the existing `setBar('loaded', ...)` event; progress interactions continue to use the core controls.
The initial configuration is applied only on the first `video:loadedmetadata`. Switching media does not calculate new chapters automatically. After the new media loads, call `update` with fresh data for its duration. Do not reuse an object whose `Infinity` end was already replaced by the previous duration.
## Lifecycle and styling
Destroying the player removes this plugin's listeners, chapter nodes, title and `artplayer-plugin-chapter` class, including when `art.destroy(false)` retains the player HTML. Calling `update` on a retained result after destruction does not recreate the view. There is no separate plugin `destroy()` method.
The existing `.art-chapter`, `.art-chapter-title` and chapter `data-start/end/duration/title` hooks remain. Long titles are clipped to the progress bar width, while their full text remains in the text content and data attributes. The stylesheet is shared by the page and is retained when one player is destroyed.
## TypeScript
The root and `/legacy` entries share the public API and export the `Chapters`, `Option` and `Result` types. This package does not require a separate `/runtime` entry:
```ts
import artplayerPluginChapter from 'artplayer-plugin-chapter';
import type { Chapters } from 'artplayer-plugin-chapter';
const chapters: Chapters = [{ start: 0, end: Infinity, title: 'Introduction' }];
const installChapters = artplayerPluginChapter({ chapters });
```
Desktop tests cover chapters with quality selection, thumbnails and fullscreen. They do not establish support on every mobile device. The current Windows WebKit quality-switch tests still encounter stalls while reading browser state, so this page does not promise timing reliability on every platform.
@@ -23,7 +23,7 @@ For script loading, load ArtPlayer first, followed by `dist/artplayer-plugin-vtt
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>
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-vtt-thumbnail/index.js">▶ Run Code</div>
```js
// npm i artplayer-plugin-vtt-thumbnail
@@ -0,0 +1,88 @@
# 视频背光
[English](../en/plugin/ambilight.md)
从视频画面采样颜色,在播放器周围显示模糊背光。插件使用 Canvas 读取像素,不需要额外 SDK,也不改变视频的播放或音频输出。
本页描述当前重构分支。生命周期修复及精确类型入口尚未发布;在线示例和未固定版本的 npm/CDN 包不等于当前候选。
## 安装和示例
```sh
yarn add artplayer artplayer-plugin-ambilight
```
```js
import Artplayer from 'artplayer';
import artplayerPluginAmbilight from 'artplayer-plugin-ambilight';
```
使用 script 时先加载 ArtPlayer,再加载 `dist/artplayer-plugin-ambilight.js`,全局名为 `artplayerPluginAmbilight`。下面保留[在线背光示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight)的原始代码;应用需要提供自己的容器和可访问的视频。
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-ambilight/index.js">▶ Run Code</div>
```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,
}),
],
})
```
## 配置
| 字段 | 类型 | 默认值 | 含义 |
| --- | --- | --- | --- |
| `blur` | `string` | `'50px'` | CSS 模糊半径 |
| `opacity` | `number` | `0.5` | 背光网格透明度;示例显式设置为 `1` |
| `frequency` | `number` | `10` | 每秒采样次数上限,建议使用正数;实际频率受播放和帧调度限制 |
| `duration` | `number` | `0.3` | 背光颜色过渡时长,单位秒 |
| `zIndex` | `number` | 实际固定为 `9` | 保留的历史参数,不改变实际层级 |
插件按 3×3 网格采样颜色。它只在播放器处于播放状态且采样间隔满足条件时更新颜色;`frequency` 不是视频帧率设置。遮罩、裁剪或父容器的 `overflow` 样式也可能影响背光可见范围。
## start 和 stop
结果的 `name` 固定为 `artplayerPluginAmbilight`。在构造选项中安装时,插件收到播放器 `ready` 后开始调度:
```js
const light = art.plugins.artplayerPluginAmbilight;
light.stop(); // Stop sampling and retain the last colors.
light.start(); // Resume sampling while the player is playing.
```
两个方法都同步返回 `undefined`,不会播放或暂停视频。`stop()` 保留最后一次颜色;`start()` 不是“立即采一帧”的 Promise。重复调用不会创建多条采样循环。如果在播放器已经触发 `ready` 后才调用 `art.plugins.add(...)` 安装插件,需要自行调用返回结果的 `start()`。
插件没有 `update` 方法或独立的 `destroy` 方法。销毁播放器会停止帧调度、移除网格和插件订阅、释放采样画布。销毁后保留的 `start/stop` 不再启动工作。
## 媒体访问和代理
视频必须能被浏览器解码并允许 Canvas 读取像素。跨域视频需要正确的媒体跨域配置和服务端 CORS 响应;仅能播放不代表允许取色。像素读取失败时跳过该次更新并保留现有颜色,后续可读取的来源仍可恢复,插件不会绕过浏览器的跨域限制。
Canvas proxy 使用它实际输出的画布尺寸取样。其他代理能否提供可绘制画面需要分别验证;不要把一个桌面组合通过解释为所有浏览器或代理都支持。颜色采样也不代表物理显示器背光控制。
## TypeScript 兼容入口
根入口和 `/legacy` 保留已发布 1.1.0 的工厂类型:参数对象必填,字段可选。使用这些类型时传入 `{}` 选择默认值。JavaScript 运行时仍接受省略参数。
需要准确的可选调用、CommonJS `.default` 自引用或 NodeNext ESM 默认调用类型时,使用同一实现的 `/runtime`:
```ts
import ambilight from 'artplayer-plugin-ambilight/runtime';
const installLight = ambilight();
const installDefaultLight = ambilight.default({ opacity: 0.5 });
```
根声明可导入的类型包括 `Option`、`Result`、`Callable`、`Factory` 和 `RuntimeFactory`。1.0.0 的 `export =` 及必填配置字段与 1.1.0 不同;旧 `import = require` 代码可迁到 `/runtime`,读取可选字段时提供默认值。Node10 TypeScript 默认导入 `/runtime` 需要启用 `esModuleInterop`,不启用时可用 `import = require`。
@@ -23,7 +23,7 @@ import artplayerPluginAudioTrack from 'artplayer-plugin-audio-track';
下面与[在线音轨示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-audio-track/index.js&example=audio.track)使用同一份代码。站点提供示例媒体和 `.artplayer-app` 容器;接入自己的应用时替换这些地址和容器。
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-audio-track/index.js"></div>
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-audio-track/index.js">▶ Run Code</div>
```js
// npm i artplayer-plugin-audio-track
@@ -0,0 +1,104 @@
# 视频章节
[English](../en/plugin/chapter.md)
将进度条划分为章节,悬停时显示标题,并保留播放器原有的进度拖动和缩略图。插件不解析媒体文件中的章节元数据;章节时间由应用提供。
本页描述当前重构分支。候选版本和修复尚未发布,在线示例与未固定版本的 npm/CDN 包不一定包含本页所述修复。
## 安装和示例
```sh
yarn add artplayer artplayer-plugin-chapter
```
```js
import Artplayer from 'artplayer';
import artplayerPluginChapter from 'artplayer-plugin-chapter';
```
使用 script 时先加载 ArtPlayer,再加载 `dist/artplayer-plugin-chapter.js`;插件全局名为 `artplayerPluginChapter`。下面保留[在线章节示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chapter/index.js&example=chapter)的原始代码。站点提供示例容器、视频和缩略图,接入应用时替换为自己的资源。
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-chapter/index.js">▶ Run Code</div>
```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: '终わり' },
],
}),
],
})
```
## chapters
工厂参数可以省略,也可以传入 `{ chapters }`。每个章节包含:
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `start` | `number` | 开始时间,单位秒,必须是非负有限数 |
| `end` | `number` | 结束时间,单位秒;允许 `Infinity` 表示当前视频结束 |
| `title` | `string` | 悬停标题;空字符串保留没有标题的区间 |
区间必须满足 `start < end <= 视频时长`,相邻章节不能重叠。插件会按开始时间排序,补齐头尾及章节之间的空白区间。它会**直接修改传入的数组**,包括排序、插入空标题章节和把 `Infinity` 替换为当前时长;需要保留原始配置时,每次传入新的数组及章节对象。
只有媒体时长为正的有限数时才生成章节。缺省、空或非数组的章节输入会清空视图;TypeScript 参数仍只接受声明的数组类型。字段类型错误会抛出 `TypeError`,非法时间或重叠区间会抛出 `Error`。标题按文本显示,不解析 HTML;显示时去除首尾空白,原对象的 `title` 不变。
## update
插件返回结果的 `name` 固定为 `artplayerPluginChapter`。`update(option)` 同步替换章节并返回 `undefined`,参数对象必填;`update({})` 清空章节:
```js
art.plugins.artplayerPluginChapter.update({
chapters: [{ start: 0, end: Infinity, title: 'Introduction' }],
});
// Clear all chapter segments and the hover title.
art.plugins.artplayerPluginChapter.update({});
```
更新先清除旧视图再校验新数据;无效更新抛错后不会保留旧章节。成功更新会同步触发原有 `setBar('loaded', ...)`,进度交互继续使用核心控制器。
初始配置只在首次 `video:loadedmetadata` 时应用。切换媒体不会自动计算新章节;在新媒体加载后,调用 `update` 并传入适合新时长的全新数据。不要复用已经把 `Infinity` 改成旧时长的对象。
## 生命周期与样式
销毁播放器会移除插件自己的监听器、章节节点、标题及 `artplayer-plugin-chapter` 类,包括 `art.destroy(false)` 保留播放器 HTML 的情况。销毁后保留的结果对象调用 `update` 不会重建视图;没有单独的插件 `destroy()` 方法。
原有 `.art-chapter`、`.art-chapter-title` 和章节 `data-start/end/duration/title` 钩子保留。长标题在进度条宽度内截断,完整文字仍保存在文本和数据属性中。样式表由页面共享,销毁一个实例不会移除它。
## TypeScript
根入口及 `/legacy` 使用同一公开 API,可以导入 `Chapters`、`Option` 和 `Result` 类型;本包不需要另外切换到 `/runtime`:
```ts
import artplayerPluginChapter from 'artplayer-plugin-chapter';
import type { Chapters } from 'artplayer-plugin-chapter';
const chapters: Chapters = [{ start: 0, end: Infinity, title: 'Introduction' }];
const installChapters = artplayerPluginChapter({ chapters });
```
章节、清晰度、缩略图和全屏的桌面组合有独立测试;这不代表全部移动设备已通过。当前 Windows WebKit 的清晰度切换测试仍存在浏览器读取停顿,不能据此承诺所有平台均无时序问题。
@@ -23,7 +23,7 @@ import artplayerPluginVttThumbnail from 'artplayer-plugin-vtt-thumbnail';
下面与[在线缩略图示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-vtt-thumbnail/index.js&example=vtt.thumbnail)使用同一份代码。站点提供媒体和 `.artplayer-app` 容器,自己的应用需要替换对应地址。
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-vtt-thumbnail/index.js"></div>
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-vtt-thumbnail/index.js">▶ Run Code</div>
```js
// npm i artplayer-plugin-vtt-thumbnail
@@ -50,5 +50,5 @@
}
// <stdin>
installNavigation(window, ["advanced/built-in.html", "advanced/built-in", "advanced/class.html", "advanced/class", "advanced/event.html", "advanced/event", "advanced/global.html", "advanced/global", "advanced/plugin.html", "advanced/plugin", "advanced/property.html", "advanced/property", "component/contextmenu.html", "component/contextmenu", "component/controls.html", "component/controls", "component/layers.html", "component/layers", "component/setting.html", "component/setting", "", "index.html", "plugin/audio-track.html", "plugin/audio-track", "plugin/danmuku.html", "plugin/danmuku", "plugin/dash-control.html", "plugin/dash-control", "plugin/hls-control.html", "plugin/hls-control", "plugin/vtt-thumbnail.html", "plugin/vtt-thumbnail", "start/i18n.html", "start/i18n", "start/option.html", "start/option"]);
installNavigation(window, ["advanced/built-in.html", "advanced/built-in", "advanced/class.html", "advanced/class", "advanced/event.html", "advanced/event", "advanced/global.html", "advanced/global", "advanced/plugin.html", "advanced/plugin", "advanced/property.html", "advanced/property", "component/contextmenu.html", "component/contextmenu", "component/controls.html", "component/controls", "component/layers.html", "component/layers", "component/setting.html", "component/setting", "", "index.html", "plugin/ambilight.html", "plugin/ambilight", "plugin/audio-track.html", "plugin/audio-track", "plugin/chapter.html", "plugin/chapter", "plugin/danmuku.html", "plugin/danmuku", "plugin/dash-control.html", "plugin/dash-control", "plugin/hls-control.html", "plugin/hls-control", "plugin/vtt-thumbnail.html", "plugin/vtt-thumbnail", "start/i18n.html", "start/i18n", "start/option.html", "start/option"]);
})();