mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-22 05:11:20 -08:00
docs(site): [SITE-04] complete bilingual guides for JASSUB Mask and Cast
This commit is contained in:
1 parent
558e946ae5
commit
3aad294aa5
106 files changed
+5268
-2065
No files matched your search
@@ -23,6 +23,9 @@ not a VitePress page. Keep both URL surfaces compatible.
|
||||
| `docs/plugin/multiple-subtitles.md`, `docs/en/plugin/multiple-subtitles.md` | Track loading, selection, shared subtitle configuration and compatible type views | `/document/plugin/multiple-subtitles.html`, `/document/en/plugin/multiple-subtitles.html` |
|
||||
| `docs/plugin/ads.md`, `docs/en/plugin/ads.md` | Preroll options, countdown-only controls, events and approved type-inference migration | `/document/plugin/ads.html`, `/document/en/plugin/ads.html` |
|
||||
| `docs/plugin/vast.md`, `docs/en/plugin/vast.md` | Published/workspace initialization, request contexts, SDK ownership and accurate runtime types | `/document/plugin/vast.html`, `/document/en/plugin/vast.html` |
|
||||
| `docs/plugin/jassub.md`, `docs/en/plugin/jassub.md` | Worker resources, ASS queries, actual method signatures, ownership and compatible declarations | `/document/plugin/jassub.html`, `/document/en/plugin/jassub.html` |
|
||||
| `docs/plugin/danmuku-mask.md`, `docs/en/plugin/danmuku-mask.md` | Segmentation configuration, start/stop, mask ownership and preserved type shape | `/document/plugin/danmuku-mask.html`, `/document/en/plugin/danmuku-mask.html` |
|
||||
| `docs/plugin/chromecast.md`, `docs/en/plugin/chromecast.md` | SDK loading, callbacks, shared sessions, receiver limitations and runtime types | `/document/plugin/chromecast.html`, `/document/en/plugin/chromecast.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 |
|
||||
@@ -36,11 +39,19 @@ 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 52 Markdown pages: 26 Chinese
|
||||
and 26 English. Danmuku, HLS, DASH, Audio Track, VTT Thumbnail, Chapter, Ambilight, Document PiP, ASR, Auto Thumbnail, Multiple Subtitles, Ads and VAST have dedicated guides and navigation in both languages. Other plugins currently
|
||||
use their package README, architecture notes and linked editor examples;
|
||||
The generated site lives in `docs/document/`. The current inventory contains 58 Markdown pages: 29 Chinese
|
||||
and 29 English. All 16 plugins have dedicated guides and navigation in both languages.
|
||||
The two proxies and two tools still need dedicated bilingual guides. Core member
|
||||
mapping and the current cross-check of earlier guides remain in SITE-04;
|
||||
navigation links alone are not complete API documentation.
|
||||
|
||||
JASSUB documents actual resize argument order, query callbacks and resource
|
||||
ownership separately from preserved historical declarations. Danmuku Mask keeps
|
||||
both plugin dependencies in its Run Code link and explains initialization versus
|
||||
first-mask completion. Chromecast distinguishes retained sessions from receiver
|
||||
playback, and player destruction from ending a shared Cast session. These guide
|
||||
checks do not validate actual ASS pixels, segmentation inference or Cast hardware.
|
||||
|
||||
Ads and VAST keep their original demos and approved compatibility decisions.
|
||||
Ads play/pause affect its countdown, and its programmatic skip does not enforce
|
||||
the close button's delay. VAST distinguishes default pre-callback allocation from
|
||||
|
||||
@@ -67,7 +67,7 @@ const config = {
|
||||
collapsible: true,
|
||||
items: [
|
||||
{ text: '🎉 弹幕库', link: '/plugin/danmuku' },
|
||||
{ text: '弹幕遮罩', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-plugin-danmuku/index.js%0A./uncompiled/artplayer-plugin-danmuku-mask/index.js&example=danmuku.mask' },
|
||||
{ text: '弹幕遮罩', link: '/plugin/danmuku-mask' },
|
||||
{ text: '视频广告', link: '/plugin/ads' },
|
||||
{ text: 'Iframe 控制', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe' },
|
||||
{ text: 'HLS 控制', link: '/plugin/hls-control' },
|
||||
@@ -75,8 +75,8 @@ const config = {
|
||||
{ text: 'VTT 缩略图', link: '/plugin/vtt-thumbnail' },
|
||||
{ text: '自动缩略图', link: '/plugin/auto-thumbnail' },
|
||||
{ text: '多重字幕', link: '/plugin/multiple-subtitles' },
|
||||
{ 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: 'ASS 字幕 - JASSUB', link: '/plugin/jassub' },
|
||||
{ text: 'Chromecast', link: '/plugin/chromecast' },
|
||||
{ text: 'VAST 广告', link: '/plugin/vast' },
|
||||
{ text: '视频章节', link: '/plugin/chapter' },
|
||||
{ text: '视频背光', link: '/plugin/ambilight' },
|
||||
@@ -142,6 +142,7 @@ const config = {
|
||||
collapsible: true,
|
||||
items: [
|
||||
{ text: 'Danmuku', link: '/en/plugin/danmuku' },
|
||||
{ text: 'Danmuku Mask', link: '/en/plugin/danmuku-mask' },
|
||||
{ text: 'Advertise', link: '/en/plugin/ads' },
|
||||
{ text: 'Iframe Control', link: 'https://artplayer.org/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe' },
|
||||
{ text: 'HLS Control', link: '/en/plugin/hls-control' },
|
||||
@@ -149,8 +150,8 @@ const config = {
|
||||
{ text: 'VTT Thumbnail', link: '/en/plugin/vtt-thumbnail' },
|
||||
{ text: 'Automatic Thumbnails', link: '/en/plugin/auto-thumbnail' },
|
||||
{ text: 'Multiple Subtitles', link: '/en/plugin/multiple-subtitles' },
|
||||
{ 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: 'ASS Subtitle - JASSUB', link: '/en/plugin/jassub' },
|
||||
{ text: 'Chromecast', link: '/en/plugin/chromecast' },
|
||||
{ text: 'VAST', link: '/en/plugin/vast' },
|
||||
{ text: 'Video Chapters', link: '/en/plugin/chapter' },
|
||||
{ text: 'Video Ambilight', link: '/en/plugin/ambilight' },
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# Chromecast
|
||||
|
||||
[简体中文](../../plugin/chromecast.md)
|
||||
|
||||
Add a right-side Cast control that selects a Cast session and loads media. Use a supported Chrome sender, HTTPS, a real receiver and receiver-accessible media. This page describes the unreleased branch. A local page, mocked SDK or successful session does not prove playback on a television.
|
||||
|
||||
## Installation and example
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-chromecast
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginChromecast from 'artplayer-plugin-chromecast';
|
||||
```
|
||||
|
||||
For scripts, load ArtPlayer before `dist/artplayer-plugin-chromecast.js`; the global is `artplayerPluginChromecast`. This preserves the [original example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast). Supply an absolute media URL reachable by your receiver; sender localhost, relative URLs and Blob URLs are not rewritten automatically.
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-chromecast/index.js">▶ Run Code</div>
|
||||
|
||||
```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
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## Options and callbacks
|
||||
|
||||
An options object is required; `{}` uses defaults. The icon is captured at registration; other options and callbacks are read from the original object at the relevant operation.
|
||||
|
||||
| Field | Type | Behavior |
|
||||
| --- | --- | --- |
|
||||
| `url` | `string` | Nonempty override, otherwise current art.option.url |
|
||||
| `sdk` | `string` | Override the Cast SDK script URL |
|
||||
| `icon` | `string` | Trusted control HTML inside the retained art-icon/art-icon-cast wrapper |
|
||||
| `mimeType` | `string` | Nonempty override, otherwise inferred from the URL extension |
|
||||
| `onStateChange` | `(state) => void` | Normalized disconnected/connecting/connected/disconnecting state |
|
||||
| `onCastAvailable` | `(available: boolean) => void` | SDK availability event, not playback success |
|
||||
| `onCastStart` | `() => void` | Called after the current loadMedia completes |
|
||||
| `onError` | `(error: unknown) => void` | SDK, connection or loading failure; not necessarily an Error instance |
|
||||
|
||||
Callback this is the original options object. The default SDK URL is `https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1`. Concurrent loads in the same module/window share the first pending URL; a later retry can read another URL.
|
||||
|
||||
MIME inference strips query/hash and lowercases the extension. mp4/webm/ogg/ogv/mp3/wav/flv/mov/avi/wmv/mpd/m3u8 map respectively to video/mp4, video/webm, video/ogg, video/ogg, audio/mp3, audio/wav, video/x-flv, video/quicktime, video/x-msvideo, video/x-ms-wmv, application/dash+xml and application/x-mpegURL. Unknown extensions use application/octet-stream. This mapping is not receiver codec support; provide mimeType explicitly when needed.
|
||||
|
||||
## Registration and session state
|
||||
|
||||
Registration returns a Promise but adds the `chromecast` control immediately. SDK loading starts on first click, so registration is not SDK readiness. The loader has a 30-second readiness limit; script load alone is insufficient without the Framework. It configures the default media receiver and ORIGIN_SCOPED auto-join policy, with no custom receiver-application option.
|
||||
|
||||
A click initializes the SDK and checks the current session. If absent, it requests a session, reads it again, then awaits loadMedia. Pending clicks for one controller share the operation. A successful session request without a current session is a connection error. The media URL is read when sending; later player source changes do not automatically cast again. Use the control to send the new media.
|
||||
|
||||
The result is at `art.plugins.artplayerPluginChromecast`:
|
||||
|
||||
| Member | Meaning |
|
||||
| --- | --- |
|
||||
| `name` | Always artplayerPluginChromecast |
|
||||
| `getCastState()` | Last raw SDK SessionState, initially null; not the normalized callback state |
|
||||
| `isCasting()` | Whether a session reference is retained, not proof of receiver playback |
|
||||
|
||||
The icon uses white for disconnected, orange for transitional and red for connected states. Session termination, failure or replacement invalidates pending work; late results cannot start stale media or show obsolete notices. SDK failures display a stage-specific notice and call onError. User callback exceptions can still propagate.
|
||||
|
||||
## Cleanup and shared sessions
|
||||
|
||||
Player destruction releases this controller's loader subscription, SDK listeners and pending operation. It does not interrupt another player waiting for the SDK or end the page-shared receiver session. Successful scripts remain; failed or last-owner-cancelled pending scripts are removed. The core owns control DOM removal.
|
||||
|
||||
There is no public start, stop, disconnect or destroy method, and no continuous synchronization of local pause, time or volume. Callbacks and icons describe observed controller state. Receiver playback, network reachability, source changes and disconnection require real hardware validation; local tests cannot substitute for it.
|
||||
|
||||
## TypeScript
|
||||
|
||||
Root and `/legacy` preserve npm1.1.0's required options and synchronous name-only declaration. For precise callbacks, Promise registration and state methods, use `/runtime`, with the same implementation:
|
||||
|
||||
```ts
|
||||
import cast from 'artplayer-plugin-chromecast/runtime';
|
||||
import type { RuntimeOption, RuntimeResult } from 'artplayer-plugin-chromecast/runtime';
|
||||
|
||||
const options: RuntimeOption = {
|
||||
onStateChange(state) { console.log(state, this.url); },
|
||||
onError(error) { console.error(error); },
|
||||
};
|
||||
const registerCast = cast(options);
|
||||
function readSession(plugin: RuntimeResult): boolean {
|
||||
return plugin.isCasting(); // Session presence, not receiver playback.
|
||||
}
|
||||
```
|
||||
|
||||
Root/runtime named types are Option, Chromecast, Result, Factory, ConnectionState, RuntimeOption, RuntimeResult and RuntimeFactory. Historical root NodeNext namespace behavior remains. Use runtime for accurate ESM default calls or older `import = require` syntax. JavaScript supports direct and `.default(...)` factory calls; type compatibility does not establish device capabilities.
|
||||
@@ -0,0 +1,108 @@
|
||||
# Danmuku Mask
|
||||
|
||||
[简体中文](../../plugin/danmuku-mask.md)
|
||||
|
||||
Generate a CSS mask from person segmentation so danmuku avoids people in the video. The plugin masks the core `.art-danmuku` layer without changing its queue, individual items or video pixels. This describes the unreleased branch; the online example and navigation checks are not model-quality acceptance.
|
||||
|
||||
## Installation and example
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-danmuku artplayer-plugin-danmuku-mask
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginDanmuku from 'artplayer-plugin-danmuku';
|
||||
import artplayerPluginDanmukuMask from 'artplayer-plugin-danmuku-mask';
|
||||
```
|
||||
|
||||
For scripts, load the core and both plugin dist files. Their globals are `artplayerPluginDanmuku` and `artplayerPluginDanmukuMask`. The [original example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-danmuku/index.js%0A./uncompiled/artplayer-plugin-danmuku-mask/index.js&example=danmuku.mask) registers them in that order and loads MediaPipe assets from the site's own directory:
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-danmuku/index.js ./uncompiled/artplayer-plugin-danmuku-mask/index.js">▶ Run Code</div>
|
||||
|
||||
```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',
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
Host matching MediaPipe assets under solutionPath. Copying a directory alone does not establish script, model, WASM, network-policy or browser support.
|
||||
|
||||
## Options
|
||||
|
||||
Options may be omitted; values are captured at registration:
|
||||
|
||||
| Field | Type / default | Runtime use |
|
||||
| --- | --- | --- |
|
||||
| `solutionPath` | `string` | SDK asset root; default CDN URL is unversioned |
|
||||
| `modelSelection` | `number` / `1` | Historical forwarded field, not proof that the current model changes |
|
||||
| `smoothSegmentation` | `boolean` / `true` | Historical forwarded field; explicit false is retained |
|
||||
| `minDetectionConfidence` | `number` / `0.5` | Historical forwarded field |
|
||||
| `minTrackingConfidence` | `number` / `0.5` | Historical forwarded field |
|
||||
| `selfieMode` | `boolean` / `false` | Historical forwarded field |
|
||||
| `drawContour` | `boolean` / `false` | Passed to binary-mask conversion |
|
||||
| `foregroundThreshold` | `number` / `0.5` | Passed to foreground threshold conversion |
|
||||
| `opacity` | `number` / `1` | Passed to SDK drawMask, not directly applied as danmuku-layer opacity |
|
||||
| `maskBlurAmount` | `number` / `3` | Blur argument passed to SDK drawMask |
|
||||
|
||||
The default solutionPath is the unversioned [MediaPipe asset root on jsDelivr](https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation).
|
||||
|
||||
Except for smoothSegmentation's undefined check, defaults retain `value || default`. Zero modelSelection, opacity, threshold or blur uses its default rather than disabling the effect. Use stop to disable masking.
|
||||
|
||||
The current selection is fixed to `runtime: 'mediapipe'` and `modelType: 'general'`. The installed adapter maps general to modelSelection 0 and ignores some extra forwarded fields. Their presence does not promise an inference change. TensorFlow first attempts webgl and tries cpu only on rejection; that does not establish MediaPipe's actual inference backend.
|
||||
|
||||
## Start, stop and failures
|
||||
|
||||
Registration synchronously returns `{ name: 'artplayerPluginDanmukuMask', start, stop }`, available at `art.plugins.artplayerPluginDanmukuMask`. The ready event starts it automatically; call start yourself if installed after ready.
|
||||
|
||||
| Method | Behavior |
|
||||
| --- | --- |
|
||||
| `start()` | Returns `Promise<void>` after initialization/scheduling, not after a complete first mask |
|
||||
| `stop()` | Returns undefined synchronously; cancels scheduling and immediately sets layer maskImage to none |
|
||||
|
||||
Repeated start does not overlap inference loops. Stop during initialization settles public start promptly while uncancellable SDK work remains observed. Late results cannot update the mask. A subsequent start waits for old work and disposal before creating another model.
|
||||
|
||||
Model creation failure logs an error and can resolve start without a usable model; explicit start can retry. Backend or required DOM/Canvas initialization can still reject start. Automatic ready startup logs rejection. Inference/pixel errors log and continue scheduling while retaining the previous usable mask.
|
||||
|
||||
Inference runs only while video is playing, not ended, and has valid dimensions. Binary-mask conversion, drawMask and Canvas pixel processing produce a PNG data URL assigned to the whole layer. No-person results retain the preceding mask. Accuracy, performance and cross-origin pixel access need actual media checks.
|
||||
|
||||
## Lifecycle and types
|
||||
|
||||
Player destruction stops work and removes ready/destroy subscriptions. The plugin owns its private canvas; after SDK work settles it resets dimensions and disposes the model. Stop is not a GPU-release completion Promise. Private SDK disposal completion still needs separate evidence. There is no public destroy, update or new event, and no takeover of application-wide TensorFlow lifetime.
|
||||
|
||||
Root and `/legacy` retain optional options, synchronous registration, async start and sync stop. There is no `/runtime` subpath. Option/Result are private declaration types, extractable from the factory. This example is type-only extraction for NodeNext ESM; it does not call `.default` at runtime:
|
||||
|
||||
```ts
|
||||
import type MaskModule from 'artplayer-plugin-danmuku-mask';
|
||||
|
||||
type MaskFactory = typeof MaskModule.default;
|
||||
type MaskOptions = Parameters<MaskFactory>[0];
|
||||
type MaskResult = ReturnType<ReturnType<MaskFactory>>;
|
||||
|
||||
const options: MaskOptions = { solutionPath: '/assets/@mediapipe/selfie_segmentation' };
|
||||
async function restartMask(mask: MaskResult): Promise<void> {
|
||||
mask.stop();
|
||||
await mask.start();
|
||||
}
|
||||
```
|
||||
|
||||
The preserved NodeNext root declaration has namespace behavior; it does not give the current runtime factory a `.default` property. Current CommonJS calls the function directly, and ESM runtime uses its default export. Do not infer runtime aliases from the type namespace. Historical export forms, actual segmentation and device performance remain separate checks.
|
||||
@@ -0,0 +1,137 @@
|
||||
# ASS Subtitles with JASSUB
|
||||
|
||||
[简体中文](../../plugin/jassub.md)
|
||||
|
||||
Render ASS subtitles on Canvas using the JASSUB Worker and WASM. The plugin returns the actual JASSUB instance with its methods/events rather than converting ASS to plain VTT. This describes the unreleased branch; Worker, WASM, fonts and actual playback require deployment-specific validation.
|
||||
|
||||
## Installation and example
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-jassub
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginJassub from 'artplayer-plugin-jassub';
|
||||
```
|
||||
|
||||
For scripts, load ArtPlayer before `dist/artplayer-plugin-jassub.js`; the global is `artplayerPluginJassub`. This preserves the [original example](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub). Its Worker/WASM/font URLs are site assets, not paths automatically created in your application by installing the plugin.
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-jassub/index.js">▶ Run Code</div>
|
||||
|
||||
```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
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
Host matching Worker, WASM and fonts with correct paths, access policies and font usage rights. Missing fonts affect layout. Default relative URLs do not establish that files are deployed.
|
||||
|
||||
## Resource and rendering options
|
||||
|
||||
Runtime options are optional and default to art.video. They are read at registration; an explicit video overrides the host video. These are current local implementation defaults, including differences from old upstream comments.
|
||||
|
||||
| Field | Actual default or meaning |
|
||||
| --- | --- |
|
||||
| `video` / `canvas` | Video defaults to art.video; caller canvas allows manual DOM handling; a usable rendering target is required |
|
||||
| `workerUrl` | `'jassub-worker.js'` |
|
||||
| `wasmUrl` | `'jassub-worker.wasm'` |
|
||||
| `legacyWasmUrl` | `'jassub-worker.wasm.js'` |
|
||||
| `modernWasmUrl` | Used when supplied and SIMD is detected; otherwise wasmUrl |
|
||||
| `subUrl` / `subContent` | Subtitle URL or ASS text sent to the Worker |
|
||||
| `fonts` | Empty array by default; entries can be URLs or Uint8Array |
|
||||
| `availableFonts` | Defaults to `{ 'liberation sans': './default.woff2' }`; font-name-to-URL/bytes map |
|
||||
| `fallbackFont` | `'liberation sans'` |
|
||||
| `useLocalFonts` | Enabled only when queryLocalFonts exists; current code defaults to true when available, with explicit false supported; permissions still apply |
|
||||
| `blendMode` | `'js'`, with `'wasm'` also accepted |
|
||||
| `asyncRender` | Defaults true, subject to createImageBitmap availability |
|
||||
| `offscreenRender` | Defaults true, requiring transferControlToOffscreen and no caller canvas |
|
||||
| `onDemandRender` | Defaults true, subject to requestVideoFrameCallback availability |
|
||||
| `targetFps` | Defaults 24; not a fixed update guarantee in on-demand mode |
|
||||
| `timeOffset` | Defaults 0 seconds |
|
||||
| `debug` | Defaults false |
|
||||
| `prescaleFactor` / `prescaleHeightLimit` / `maxRenderHeight` | Defaults 1 / 1080 / 0; rendering size controls, with no maximum imposed by a zero maxRenderHeight |
|
||||
| `dropAllAnimations` / `dropAllBlur` | Simplification options forwarded to the Worker; not set to true by the wrapper when omitted |
|
||||
| `libassMemoryLimit` / `libassGlyphLimit` | Defaults 0; libass cache limits in MiB, not a total browser-memory cap |
|
||||
|
||||
Capabilities can change the chosen rendering path. Async/offscreen/backend options are not universal performance guarantees. Do not mix incompatible Worker and wrapper versions.
|
||||
|
||||
## Instance and methods
|
||||
|
||||
Registration synchronously returns `{ name: 'artplayerPluginJassub', instance }`, not a Worker-ready Promise. Access it at `art.plugins.artplayerPluginJassub.instance`. It is an EventTarget: query after ready, and observe its error event rather than assuming a same-named player event.
|
||||
|
||||
| Method | Behavior and units |
|
||||
| --- | --- |
|
||||
| `resize(width?, height?, top?, left?, force?)` | Synchronous void; force is last, with omitted dimensions derived from video |
|
||||
| `setVideo(video)` | Rebind video, observation and the owned container position synchronously |
|
||||
| `setTrackByUrl(url)` / `setTrack(content)` / `freeTrack()` | Set subtitle URL/text or release the track |
|
||||
| `setIsPaused(boolean)` / `setRate(number)` | Manually update Worker playback state/rate |
|
||||
| `setCurrentTime(isPaused?, currentTime?, rate?)` | currentTime uses seconds |
|
||||
| `createEvent(event)` / `setEvent(event, index)` / `removeEvent(index)` | Mutate ASS events, accepting partial fields |
|
||||
| `getEvents(callback)` | Callback-based event query, not a Promise |
|
||||
| `createStyle(style)` / `setStyle(style, index)` / `removeStyle(index)` | Mutate styles, accepting partial fields |
|
||||
| `getStyles(callback)` | Callback-based style query, not a Promise |
|
||||
| `styleOverride(style)` / `disableStyleOverride()` | Enable/disable style override |
|
||||
| `setDefaultFont(font)` / `addFont(font)` | Set the default font or add a URL/byte font |
|
||||
| `runBenchmark()` | Request the Worker benchmark; not an end-to-end performance conclusion |
|
||||
| `sendMessage(target, data?, transferable?)` | Promise resolves after posting, or without posting after destroy; not a Worker acknowledgement |
|
||||
| `destroy()` | Synchronous, idempotent cleanup; no resource-reclamation Promise |
|
||||
|
||||
Except sendMessage, ordinary control methods above return void; queries supply callback data. The historical destroy(error) overload returns an original Error, converts a nonempty string to Error, or retains an empty string. Normal cleanup uses no-argument destroy.
|
||||
|
||||
AssEvent Start/Duration use milliseconds and Style is a numeric style index. Other fields are Name, MarginL/MarginR/MarginV, Effect, Text, ReadOrder and Layer. AssStyle includes Name/FontName/FontSize, PrimaryColour/SecondaryColour/OutlineColour/BackColour, Bold/Italic/Underline/StrikeOut, ScaleX/ScaleY/Spacing/Angle, BorderStyle/Outline/Shadow/Alignment, MarginL/MarginR/MarginV, Encoding, treat_fontname_as_pattern, Blur and Justify. Query results have no `_index`; the ASS text-format style name is not the runtime numeric Style.
|
||||
|
||||
Successful queries call `(null, array)`; failures supply an Error or native Event without data. Destroy fails pending queries after releasing their listeners/timers. The protocol matches by response target, without a new request ID; do not assume simultaneous same-target queries have independently correlated responses.
|
||||
|
||||
## Lifecycle and types
|
||||
|
||||
The plugin-owned `.JASSUB` container uses z-index20 and is removed on destruction; caller canvas/video nodes remain. Player destruction calls the instance's current destroy method; direct destruction is also idempotent. setVideo/destroy invalidate old frame callbacks and clean Worker/observer ownership. Late bitmaps must not restart rendering. Actual offscreen stalls, browser differences and physical devices retain separate acceptance requirements.
|
||||
|
||||
Root and `/legacy` retain historical JassubOption/JassubInstance: three required URLs, force-first resize, inaccurate Promise method returns and open extension indexes. Use `/runtime` for accurate types with the same implementation:
|
||||
|
||||
```ts
|
||||
import type Artplayer from 'artplayer';
|
||||
import jassub from 'artplayer-plugin-jassub/runtime';
|
||||
|
||||
function attachSubtitles(art: Artplayer) {
|
||||
const { instance } = jassub({
|
||||
workerUrl: '/assets/jassub/jassub-worker.js',
|
||||
wasmUrl: '/assets/jassub/jassub-worker.wasm',
|
||||
subUrl: '/subtitles.ass',
|
||||
})(art);
|
||||
instance.addEventListener('ready', () => {
|
||||
instance.getEvents((error, events) => {
|
||||
if (error) console.error(error);
|
||||
else console.log(events);
|
||||
});
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
```
|
||||
|
||||
Runtime exports FontSource, RuntimeOption, AssEvent, AssStyle, AssEventInput, AssStyleInput, WorkerRequestError, EventsCallback, StylesCallback, RuntimeEventMap, RuntimeInstance, RuntimeResult and RuntimeFactory. Precise instance fields include timeOffset, debug, the three sizing settings, optional busy and historical public `_canvas/_ctx`; `_ctx` may be false/null. There is no runtime factory `.default` self-alias. The old root's NodeNext namespace does not create one. Runtime supports an accurate ESM default and CommonJS `import = require`.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Chromecast
|
||||
|
||||
[English](../en/plugin/chromecast.md)
|
||||
|
||||
在播放器右侧添加 Chromecast 按钮,通过 Cast SDK 选择会话并加载媒体。需要受支持的 Chrome 发送端、HTTPS 页面、实际接收设备和接收端能访问的媒体地址。本页描述未发布分支;本地页面、模拟 SDK 或成功建立会话均不证明电视已播放。
|
||||
|
||||
## 安装和示例
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-chromecast
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginChromecast from 'artplayer-plugin-chromecast';
|
||||
```
|
||||
|
||||
script 先加载 ArtPlayer,再加载 `dist/artplayer-plugin-chromecast.js`,全局名为 `artplayerPluginChromecast`。以下保留[原在线示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast)。部署到接收设备时请提供它实际能够访问的绝对媒体 URL;发送端的 localhost、相对地址或 Blob 地址不会被插件自动转换。
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-chromecast/index.js">▶ Run Code</div>
|
||||
|
||||
```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
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## 配置与回调
|
||||
|
||||
配置对象必填,`{}` 使用默认值。除了注册时捕获的 icon,其余选项和回调在对应操作时读取原对象。
|
||||
|
||||
| 字段 | 类型 | 行为 |
|
||||
| --- | --- | --- |
|
||||
| `url` | `string` | 优先使用非空值,否则读取当前 art.option.url |
|
||||
| `sdk` | `string` | 可覆盖 Cast SDK 脚本地址 |
|
||||
| `icon` | `string` | 替换按钮内部 HTML;使用可信内容,保留 art-icon/art-icon-cast 包装 |
|
||||
| `mimeType` | `string` | 优先使用非空值,否则按 URL 扩展名推断 |
|
||||
| `onStateChange` | `(state) => void` | normalized state:disconnected/connecting/connected/disconnecting |
|
||||
| `onCastAvailable` | `(available: boolean) => void` | SDK 设备可用性事件,不是接收端播放成功 |
|
||||
| `onCastStart` | `() => void` | 当前媒体 loadMedia 完成后调用 |
|
||||
| `onError` | `(error: unknown) => void` | SDK 初始化、连接或加载失败;错误不一定是 Error 实例 |
|
||||
|
||||
回调中的 this 是原配置对象。默认 SDK 地址为 `https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1`。同一模块、同一 window 的并发 SDK 加载共享任务,以首个请求地址为准;失败后重试可读取新地址。
|
||||
|
||||
MIME 推断忽略 query/hash 并将扩展名转小写:mp4/webm/ogg/ogv/mp3/wav/flv/mov/avi/wmv/mpd/m3u8 分别使用 video/mp4、video/webm、video/ogg、video/ogg、audio/mp3、audio/wav、video/x-flv、video/quicktime、video/x-msvideo、video/x-ms-wmv、application/dash+xml、application/x-mpegURL;未知扩展名使用 application/octet-stream。映射不是接收设备对所有格式的支持承诺,必要时显式提供 mimeType。
|
||||
|
||||
## 注册和连接状态
|
||||
|
||||
注册实际返回 Promise,但添加 `chromecast` 控件发生在等待之前;SDK 在首次点击时才加载。注册完成不是 SDK ready。加载器有 30 秒就绪期限,单纯 script load 但 Framework 未准备好不算成功。使用默认媒体接收应用及 ORIGIN_SCOPED 自动加入策略,不提供自定义接收应用配置选项。
|
||||
|
||||
一次控件点击初始化 SDK、读取当前会话;没有会话则请求会话,再重新读取当前会话,然后等待 loadMedia。同一播放器的重复待处理点击共享操作。请求成功但仍无会话会报告连接错误。源地址在发送时读取;播放器之后切源不会自动再次投屏,应通过控件重新发送需要的媒体。
|
||||
|
||||
结果位于 `art.plugins.artplayerPluginChromecast`:
|
||||
|
||||
| 成员 | 含义 |
|
||||
| --- | --- |
|
||||
| `name` | 固定 artplayerPluginChromecast |
|
||||
| `getCastState()` | 最近一次原始 SDK SessionState,初始 null;不是回调里的标准化状态 |
|
||||
| `isCasting()` | 是否保留会话引用,不证明接收端媒体正在播放 |
|
||||
|
||||
控件图标以白色、橙色、红色表达断开、过渡、连接状态。会话结束、启动失败或被替换会使旧请求失效,迟到结果不启动旧媒体或显示陈旧通知。SDK 错误显示阶段对应 notice 并传给 onError;用户回调抛错仍可传播。
|
||||
|
||||
## 清理和共享会话
|
||||
|
||||
播放器销毁释放该实例的加载订阅、SDK 监听器和待处理操作,不中断其他播放器的 SDK 加载,也不结束页面共享的接收会话。成功加载的 SDK 脚本留在页面,失败或最后一个等待者取消时移除待加载脚本。控件 DOM 由核心管理。
|
||||
|
||||
插件没有公开的 start、stop、disconnect 或 destroy 方法,不负责持续同步本地暂停、进度和音量。回调与图标只描述该控制器观察到的状态。真实设备播放、网络可达性、切源与断连需用接收端验证,现有本地测试不能替代。
|
||||
|
||||
## TypeScript
|
||||
|
||||
根入口和 `/legacy` 保留 npm1.1.0 的必填配置、同步且仅含 name 的声明。准确回调、Promise 和状态方法使用同一实现的 `/runtime`:
|
||||
|
||||
```ts
|
||||
import cast from 'artplayer-plugin-chromecast/runtime';
|
||||
import type { RuntimeOption, RuntimeResult } from 'artplayer-plugin-chromecast/runtime';
|
||||
|
||||
const options: RuntimeOption = {
|
||||
onStateChange(state) { console.log(state, this.url); },
|
||||
onError(error) { console.error(error); },
|
||||
};
|
||||
const registerCast = cast(options);
|
||||
function readSession(plugin: RuntimeResult): boolean {
|
||||
return plugin.isCasting(); // Session presence, not receiver playback.
|
||||
}
|
||||
```
|
||||
|
||||
根和 runtime 可导出的类型为 Option、Chromecast、Result、Factory、ConnectionState、RuntimeOption、RuntimeResult、RuntimeFactory。旧根 NodeNext 命名空间形状保持不变;准确 ESM 默认调用和较早的 `import = require` 用法使用 runtime。JavaScript 支持直接工厂及 `.default(...)`;这些兼容类型不扩展实际设备能力。
|
||||
@@ -0,0 +1,108 @@
|
||||
# 弹幕遮罩
|
||||
|
||||
[English](../en/plugin/danmuku-mask.md)
|
||||
|
||||
通过人体分割结果生成 CSS 遮罩,让弹幕避开视频中的人物区域。插件处理核心的 `.art-danmuku` 层,不修改弹幕队列、条目或视频画面。本页描述未发布重构分支,不将在线示例或导航验证视为模型效果验收。
|
||||
|
||||
## 安装和示例
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-danmuku artplayer-plugin-danmuku-mask
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginDanmuku from 'artplayer-plugin-danmuku';
|
||||
import artplayerPluginDanmukuMask from 'artplayer-plugin-danmuku-mask';
|
||||
```
|
||||
|
||||
script 用法先加载核心及两个插件的 dist 文件,全局名分别为 `artplayerPluginDanmuku`、`artplayerPluginDanmukuMask`。[原在线示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-danmuku/index.js%0A./uncompiled/artplayer-plugin-danmuku-mask/index.js&example=danmuku.mask)按此顺序注册,并从站点自己的路径加载 MediaPipe 资源:
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-danmuku/index.js ./uncompiled/artplayer-plugin-danmuku-mask/index.js">▶ Run Code</div>
|
||||
|
||||
```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',
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
部署时确保 solutionPath 下有匹配的 MediaPipe 资源。复制目录本身不证明所有脚本、模型、WASM、网络策略和浏览器能力都可用。
|
||||
|
||||
## 配置
|
||||
|
||||
配置可省略,注册时读取并保存这些值:
|
||||
|
||||
| 字段 | 类型 / 默认值 | 实际用途 |
|
||||
| --- | --- | --- |
|
||||
| `solutionPath` | `string` | SDK 资源根路径;默认 CDN 未固定版本 |
|
||||
| `modelSelection` | `number` / `1` | 历史转发字段,不能据此认为当前模型已切换 |
|
||||
| `smoothSegmentation` | `boolean` / `true` | 历史转发字段,显式 false 保留 |
|
||||
| `minDetectionConfidence` | `number` / `0.5` | 历史转发字段 |
|
||||
| `minTrackingConfidence` | `number` / `0.5` | 历史转发字段 |
|
||||
| `selfieMode` | `boolean` / `false` | 历史转发字段 |
|
||||
| `drawContour` | `boolean` / `false` | 传给二值遮罩转换 |
|
||||
| `foregroundThreshold` | `number` / `0.5` | 传给前景阈值转换 |
|
||||
| `opacity` | `number` / `1` | 传给 SDK drawMask,不是直接设置弹幕层 opacity |
|
||||
| `maskBlurAmount` | `number` / `3` | 传给 SDK drawMask 的模糊量 |
|
||||
|
||||
solutionPath 默认指向未固定版本的 [jsDelivr MediaPipe 资源根目录](https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation)。
|
||||
|
||||
除 smoothSegmentation 的 undefined 判断外,默认值沿用 `value || default`。例如 modelSelection、opacity、threshold、blur 的 0 会回退默认值,不能用于关闭功能;停止遮罩使用 stop。
|
||||
|
||||
当前固定选择 `runtime: 'mediapipe'` 和 `modelType: 'general'`。已安装的 adapter 把 general 映射为 modelSelection 0,并忽略部分额外转发字段;保留参数不是承诺这些字段都会改变推理。TensorFlow 后端先尝试 webgl,只有拒绝时才尝试 cpu;这也不能证明 MediaPipe 实际使用哪种推理后端。
|
||||
|
||||
## start、stop 与失败
|
||||
|
||||
注册同步返回 `{ name: 'artplayerPluginDanmukuMask', start, stop }`,可从 `art.plugins.artplayerPluginDanmukuMask` 访问。ready 自动启动;如果在 ready 之后安装,需要自行调用 start。
|
||||
|
||||
| 方法 | 行为 |
|
||||
| --- | --- |
|
||||
| `start()` | 返回 `Promise<void>`;初始化并启动调度,不等待第一张完整遮罩 |
|
||||
| `stop()` | 同步返回 undefined;取消当前调度并立刻将层的 maskImage 设为 none |
|
||||
|
||||
重复 start 不创建重叠推理循环。stop 可在初始化过程中调用,使公共 start 及时结算;不可取消的 SDK 工作仍被观察,迟到结果不再写入遮罩。之后 start 等待旧任务和释放过程结束再重新初始化,不以多个模型并行掩盖停止问题。
|
||||
|
||||
模型创建失败会记录错误且 start 可正常结算,但没有可用模型;可显式再次 start 重试。后端或必要 DOM/Canvas 初始化失败仍可能拒绝 start。自动 ready 启动会记录拒绝。推理或像素读取失败记录错误并继续下一次调度,保留上一张可用遮罩。
|
||||
|
||||
只在视频播放、未结束且有有效尺寸时执行分割。结果经二值遮罩、drawMask 和 Canvas 像素转换生成 PNG data URL,写入整层 maskImage。没有人物结果时保留之前的遮罩;遮罩精度、性能和跨域像素访问需要实际视频验证。
|
||||
|
||||
## 生命周期和类型
|
||||
|
||||
播放器销毁停止运行并移除 ready/destroy 监听器。私有画布归插件所有,SDK 工作完成后重置其尺寸并释放模型。stop 不是 GPU 内存回收完成的 Promise;SDK 的私有资源实际释放完成仍需独立证据。插件不提供公开 destroy、update 或新事件,也不接管其他应用的全局 TensorFlow 生命周期。
|
||||
|
||||
根和 `/legacy` 保留历史声明:可选配置、同步注册、异步 start 和同步 stop;没有 `/runtime` 子路径。Option/Result 是声明内部类型,可通过工厂提取。下面仅展示 NodeNext ESM 下的类型提取,不执行 `.default` 调用:
|
||||
|
||||
```ts
|
||||
import type MaskModule from 'artplayer-plugin-danmuku-mask';
|
||||
|
||||
type MaskFactory = typeof MaskModule.default;
|
||||
type MaskOptions = Parameters<MaskFactory>[0];
|
||||
type MaskResult = ReturnType<ReturnType<MaskFactory>>;
|
||||
|
||||
const options: MaskOptions = { solutionPath: '/assets/@mediapipe/selfie_segmentation' };
|
||||
async function restartMask(mask: MaskResult): Promise<void> {
|
||||
mask.stop();
|
||||
await mask.start();
|
||||
}
|
||||
```
|
||||
|
||||
保留的 NodeNext 根类型有模块命名空间行为;这不代表当前运行时工厂有 `.default` 属性。当前 CommonJS 工厂直接调用,ESM 运行时使用默认导出;不要从类型命名空间推断运行时别名。旧版导出形状、模型真实运行和真机性能各自独立验证。
|
||||
@@ -0,0 +1,137 @@
|
||||
# ASS 字幕:JASSUB
|
||||
|
||||
[English](../en/plugin/jassub.md)
|
||||
|
||||
使用 JASSUB Worker/WASM 在 Canvas 上渲染 ASS 字幕。插件返回真实 JASSUB 实例,保留其方法与事件,不将字幕转换成普通 VTT。本页描述当前未发布分支;Worker、WASM、字体和实际视频效果仍需按部署环境验证。
|
||||
|
||||
## 安装和示例
|
||||
|
||||
```sh
|
||||
yarn add artplayer artplayer-plugin-jassub
|
||||
```
|
||||
|
||||
```js
|
||||
import Artplayer from 'artplayer';
|
||||
import artplayerPluginJassub from 'artplayer-plugin-jassub';
|
||||
```
|
||||
|
||||
script 先加载 ArtPlayer,再加载 `dist/artplayer-plugin-jassub.js`,全局名为 `artplayerPluginJassub`。下面保留[原在线示例](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub);其中的 Worker/WASM 和字体地址属于站点资产,不会因为安装插件而自动出现在应用中。
|
||||
|
||||
<div className="run-code" data-libs="./uncompiled/artplayer-plugin-jassub/index.js">▶ Run Code</div>
|
||||
|
||||
```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
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
自行托管相互匹配的 Worker、WASM 和字体,确认路径、访问策略及字体使用许可。缺失字体会影响排版;相对默认路径存在不等于文件已部署。
|
||||
|
||||
## 资源和渲染选项
|
||||
|
||||
实际配置可省略,默认绑定 art.video;配置在注册时读取,显式 video 可覆盖它。以下按当前本地实现描述,不照搬上游注释中的旧默认值。
|
||||
|
||||
| 字段 | 实际默认或含义 |
|
||||
| --- | --- |
|
||||
| `video` / `canvas` | 默认 video 为 art.video;提供自己的 canvas 可手动管理节点,至少需要可用的渲染目标 |
|
||||
| `workerUrl` | `'jassub-worker.js'` |
|
||||
| `wasmUrl` | `'jassub-worker.wasm'` |
|
||||
| `legacyWasmUrl` | `'jassub-worker.wasm.js'` |
|
||||
| `modernWasmUrl` | 检测到 SIMD 且提供此地址时优先使用,否则使用 wasmUrl |
|
||||
| `subUrl` / `subContent` | 字幕地址或 ASS 文本,传给 Worker |
|
||||
| `fonts` | 默认空数组,元素可为 URL 或 Uint8Array |
|
||||
| `availableFonts` | 默认 `{ 'liberation sans': './default.woff2' }`,字体名到 URL/字节映射 |
|
||||
| `fallbackFont` | `'liberation sans'` |
|
||||
| `useLocalFonts` | 只有存在 queryLocalFonts 时启用;未指定时当前实现为 true,可显式 false;仍受权限限制 |
|
||||
| `blendMode` | `'js'`,也可选 `'wasm'` |
|
||||
| `asyncRender` | 默认 true,但需 createImageBitmap 能力 |
|
||||
| `offscreenRender` | 默认 true,但需 transferControlToOffscreen 且没有传入自有 canvas |
|
||||
| `onDemandRender` | 默认 true,但需 requestVideoFrameCallback 能力 |
|
||||
| `targetFps` | 默认 24,按需渲染时不作为固定更新承诺 |
|
||||
| `timeOffset` | 默认 0,单位秒 |
|
||||
| `debug` | 默认 false |
|
||||
| `prescaleFactor` / `prescaleHeightLimit` / `maxRenderHeight` | 默认 1 / 1080 / 0,控制渲染尺寸;0 的最大高度表示不设置此上限 |
|
||||
| `dropAllAnimations` / `dropAllBlur` | 转发给 Worker 的简化渲染选项,未指定时不在包装层设置为 true |
|
||||
| `libassMemoryLimit` / `libassGlyphLimit` | 默认 0,libass 缓存限制参数,单位 MiB;不是浏览器总内存上限 |
|
||||
|
||||
若平台缺少能力,渲染路径会与配置意图不同。不要把异步、离屏或后端选项视为所有设备的速度保证,也不要在不同版本 Worker 与包装层之间混用资源。
|
||||
|
||||
## 实例和方法
|
||||
|
||||
注册同步返回 `{ name: 'artplayerPluginJassub', instance }`,不是 Worker ready Promise。通过 `art.plugins.artplayerPluginJassub.instance` 取得实例。实例是 EventTarget,监听 ready 后再进行查询;error 事件属于该实例,不是播放器的同名事件。
|
||||
|
||||
| 方法 | 行为与单位 |
|
||||
| --- | --- |
|
||||
| `resize(width?, height?, top?, left?, force?)` | 同步返回 void;实际 force 在最后,省略尺寸时依据视频计算 |
|
||||
| `setVideo(video)` | 同步切换绑定视频、观察器和自有容器位置 |
|
||||
| `setTrackByUrl(url)` / `setTrack(content)` / `freeTrack()` | 切换地址、ASS 文本或释放字幕轨道 |
|
||||
| `setIsPaused(boolean)` / `setRate(number)` | 手动更新 Worker 的播放状态/倍率 |
|
||||
| `setCurrentTime(isPaused?, currentTime?, rate?)` | currentTime 使用秒 |
|
||||
| `createEvent(event)` / `setEvent(event, index)` / `removeEvent(index)` | 增删改 ASS event,修改对象为部分字段 |
|
||||
| `getEvents(callback)` | 回调返回 event 数组,非 Promise |
|
||||
| `createStyle(style)` / `setStyle(style, index)` / `removeStyle(index)` | 增删改样式,修改对象为部分字段 |
|
||||
| `getStyles(callback)` | 回调返回样式数组,非 Promise |
|
||||
| `styleOverride(style)` / `disableStyleOverride()` | 设置/取消样式覆盖 |
|
||||
| `setDefaultFont(font)` / `addFont(font)` | 设置默认字体或添加 URL/字节字体 |
|
||||
| `runBenchmark()` | 请求 Worker 基准操作,不代表端到端性能结论 |
|
||||
| `sendMessage(target, data?, transferable?)` | Promise 仅表示已发送,或销毁后无需发送,不等待 Worker 确认 |
|
||||
| `destroy()` | 同步清理并可重复调用,没有资源回收完成 Promise |
|
||||
|
||||
除 sendMessage 外,上表普通控制方法返回 void;查询通过回调提供数据。`destroy(error)` 保留历史返回行为:原 Error 原样返回,非空字符串转为 Error,空字符串原样返回。正常调用使用无参 destroy。
|
||||
|
||||
AssEvent 的 Start/Duration 为毫秒,Style 是数字样式索引;其余字段为 Name、MarginL/MarginR/MarginV、Effect、Text、ReadOrder、Layer。AssStyle 包含 Name/FontName/FontSize、PrimaryColour/SecondaryColour/OutlineColour/BackColour、Bold/Italic/Underline/StrikeOut、ScaleX/ScaleY/Spacing/Angle、BorderStyle/Outline/Shadow/Alignment、MarginL/MarginR/MarginV、Encoding、treat_fontname_as_pattern、Blur、Justify。查询结果没有 `_index`,不要混淆 ASS 文本格式的样式名称与运行时 Style 数字。
|
||||
|
||||
查询回调成功为 `(null, array)`;失败为 Error 或原生 Event 且没有数据。销毁会在清理监听器/定时器后使待处理查询失败。协议按响应 target 匹配,没有新的请求 ID;避免把同时发出的同类查询当作独立关联响应。
|
||||
|
||||
## 生命周期和类型
|
||||
|
||||
插件创建的 `.JASSUB` 容器设为 z-index 20,销毁时移除;调用方传入的 canvas/video 保留。播放器销毁调用实例当前的 destroy,直接销毁也保持幂等。setVideo 和销毁会使旧帧回调失效,Worker 和自有观察器会清理;晚到的异步位图不应重新启动渲染。真实离屏停顿、浏览器差异和物理设备仍有独立验收要求。
|
||||
|
||||
根和 `/legacy` 保留旧 JassubOption/JassubInstance 类型:三个资源 URL 必填、force-first resize,以及错误的 Promise 方法返回和任意扩展索引。准确类型使用同一实现的 `/runtime`:
|
||||
|
||||
```ts
|
||||
import type Artplayer from 'artplayer';
|
||||
import jassub from 'artplayer-plugin-jassub/runtime';
|
||||
|
||||
function attachSubtitles(art: Artplayer) {
|
||||
const { instance } = jassub({
|
||||
workerUrl: '/assets/jassub/jassub-worker.js',
|
||||
wasmUrl: '/assets/jassub/jassub-worker.wasm',
|
||||
subUrl: '/subtitles.ass',
|
||||
})(art);
|
||||
instance.addEventListener('ready', () => {
|
||||
instance.getEvents((error, events) => {
|
||||
if (error) console.error(error);
|
||||
else console.log(events);
|
||||
});
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
```
|
||||
|
||||
runtime 导出 FontSource、RuntimeOption、AssEvent、AssStyle、AssEventInput、AssStyleInput、WorkerRequestError、EventsCallback、StylesCallback、RuntimeEventMap、RuntimeInstance、RuntimeResult、RuntimeFactory。精确实例字段包括 timeOffset、debug、三项尺寸设置、可选 busy,以及历史公开 `_canvas/_ctx`;`_ctx` 可能为 false/null。没有运行时工厂 `.default` 自引用;NodeNext 根类型的命名空间不能当作这种别名。runtime 支持准确 ESM 默认导入和 CommonJS `import = require`。
|
||||
@@ -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/ads.html", "plugin/ads", "plugin/ambilight.html", "plugin/ambilight", "plugin/asr.html", "plugin/asr", "plugin/audio-track.html", "plugin/audio-track", "plugin/auto-thumbnail.html", "plugin/auto-thumbnail", "plugin/chapter.html", "plugin/chapter", "plugin/danmuku.html", "plugin/danmuku", "plugin/dash-control.html", "plugin/dash-control", "plugin/document-pip.html", "plugin/document-pip", "plugin/hls-control.html", "plugin/hls-control", "plugin/multiple-subtitles.html", "plugin/multiple-subtitles", "plugin/vast.html", "plugin/vast", "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/ads.html", "plugin/ads", "plugin/ambilight.html", "plugin/ambilight", "plugin/asr.html", "plugin/asr", "plugin/audio-track.html", "plugin/audio-track", "plugin/auto-thumbnail.html", "plugin/auto-thumbnail", "plugin/chapter.html", "plugin/chapter", "plugin/chromecast.html", "plugin/chromecast", "plugin/danmuku-mask.html", "plugin/danmuku-mask", "plugin/danmuku.html", "plugin/danmuku", "plugin/dash-control.html", "plugin/dash-control", "plugin/document-pip.html", "plugin/document-pip", "plugin/hls-control.html", "plugin/hls-control", "plugin/jassub.html", "plugin/jassub", "plugin/multiple-subtitles.html", "plugin/multiple-subtitles", "plugin/vast.html", "plugin/vast", "plugin/vtt-thumbnail.html", "plugin/vtt-thumbnail", "start/i18n.html", "start/i18n", "start/option.html", "start/option"]);
|
||||
})();
|
||||
Reference in new issue
Block a user