@vestra-player/sdk 1.5.37 → 1.5.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +1 -0
- package/dist/api-requests.js +1 -0
- package/dist/host-capabilities.js +1 -0
- package/dist/player-runtime.d.ts +1 -0
- package/dist/player-runtime.js +1 -0
- package/dist/plugin/appearance.js +11 -2
- package/dist/plugin/packages.js +3 -0
- package/dist/plugin/player.js +6 -1
- package/dist/plugin/resolvers.js +10 -2
- package/dist/plugin/runtime.d.ts +14 -1
- package/dist/plugin/runtime.js +107 -16
- package/dist/plugin/scope.d.ts +1 -0
- package/dist/plugin/scope.js +2 -0
- package/dist/plugin/shaders.d.ts +9 -0
- package/dist/plugin/shaders.js +160 -0
- package/dist/plugin/subtitles.js +14 -2
- package/dist/plugin/testing.d.ts +74 -3
- package/dist/plugin/testing.js +221 -8
- package/dist/plugin/timeline.d.ts +1 -1
- package/dist/plugin/timeline.js +10 -2
- package/dist/plugin/types.d.ts +213 -22
- package/dist/plugin/ui.js +9 -2
- package/dist/plugin/window.d.ts +1 -1
- package/dist/plugin/window.js +10 -2
- package/dist/processing.d.ts +118 -4
- package/dist/processing.js +139 -0
- package/dist/wire.d.ts +24 -2
- package/dist/wire.js +19 -3
- package/llms-full.txt +318 -25
- package/llms.txt +23 -23
- package/package.json +1 -1
package/llms-full.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @vestra-player/sdk 1.5.
|
|
1
|
+
# @vestra-player/sdk 1.5.39: full reference
|
|
2
2
|
|
|
3
3
|
> Everything needed to write a Vestra Player plugin (plugin API `vestra/1`): the guides, every public declaration of `@vestra-player/sdk` and `@vestra-player/sdk/testing` with its documentation, and the complete source of the example plugins. Generated from the SDK's sources by scripts/llms.mjs; the short index is llms.txt.
|
|
4
4
|
|
|
@@ -329,11 +329,11 @@ The rule that follows: **state you change outside a handler, or after an `await`
|
|
|
329
329
|
|
|
330
330
|
#### Stopping
|
|
331
331
|
|
|
332
|
-
The player stops a plugin when the user disables or uninstalls it, when it is reloaded or upgraded,
|
|
332
|
+
The player stops a plugin when the user disables or uninstalls it, when it is reloaded or upgraded, when the player quits, and, with lazy activation, when nothing has used it for a while (Idle plugins).
|
|
333
333
|
|
|
334
334
|
1. The player first removes everything the plugin owns on its side: menu items, windows, panels, settings pages, filter chains, subtitle layers, snapshots, export jobs, resolvers, generated streams.
|
|
335
335
|
2. The SDK then refuses new requests, fails pending ones with `code: "disabled"` and disposes the root scope. That disposal only cleans up locally (timers, abort signals, sockets): the player-side resources are already gone.
|
|
336
|
-
3. A process that has not exited 300 ms later is killed.
|
|
336
|
+
3. A process that has not exited 300 ms later is killed (2 s later when it stops because it is idle).
|
|
337
337
|
|
|
338
338
|
So `onDispose` cleanup must be quick and must not rely on the player. Media the plugin opened with player.open **keeps playing** after it stops.
|
|
339
339
|
|
|
@@ -344,7 +344,7 @@ A plugin's process does not live as long as the player. Within one player sessio
|
|
|
344
344
|
- the plugin is **reloaded** (from the plugin manager, or a development load with `--plugin`) or **upgraded**;
|
|
345
345
|
- it **crashed**, or failed to start, and is started again.
|
|
346
346
|
|
|
347
|
-
A later player may restart a plugin in more cases: restarting plugins that share one process together when one of them faults or hangs, or stopping a plugin nobody uses and starting it on its next use. Write the plugin for those too.
|
|
347
|
+
A later player may restart a plugin in more cases: restarting plugins that share one process together when one of them faults or hangs, or stopping a plugin nobody uses and starting it on its next use (Idle plugins). Write the plugin for those too.
|
|
348
348
|
|
|
349
349
|
Everything in the process is gone after such a restart: variables, timers, caches, open sockets. The menus, windows and panels come back because `activate` creates them again. **Keep state that must survive a restart in session storage (or persistent storage):**
|
|
350
350
|
|
|
@@ -358,6 +358,16 @@ Session storage is for state that belongs to this run of the player: a queue the
|
|
|
358
358
|
|
|
359
359
|
Write `activate` so that running it twice in one session is normal: read what you kept, then build the interface from it.
|
|
360
360
|
|
|
361
|
+
#### Idle plugins are stopped
|
|
362
|
+
|
|
363
|
+
With lazy activation (player 0.5.18 and later, while the player turns it on), the player works like a browser's extension service workers (Chrome Manifest V3): a plugin that holds nothing only its process can serve is stopped after about a minute without use, and started again by its next use.
|
|
364
|
+
|
|
365
|
+
- **What stays while it is stopped**: its menu items and keys (with the last `enabled`, `checked` and `reason` it set), its settings pages, its file and link resolvers and its drop targets. Using one of them, or showing one of its settings pages, starts the plugin; it runs `activate`, registers them again, and then receives the click, the open or the drop. The player also remembers these between runs, so a plugin nobody uses is not started at launch at all.
|
|
366
|
+
- **What keeps it running**: anything the player must deliver to it or that is its running work: a listener (`player.onChange`, `window.onChange`, `bindings.onChange`, `packages.onChange` and the other `onChange`, `onEnd`), a command state, panel or window binding that reads `plugin.player.state` or another state, an open window, a mounted panel, an OSD panel, a timeline layer, a filter chain, a stream or subtitle track it added, a next/previous provider, a sleep lease, a window setting, a job or snapshot in progress. Reading `plugin.player.state` inside a handler does not: the SDK reads the state again when the plugin starts.
|
|
367
|
+
- **What does not keep it running**: work the player does not see. A `fetch`, a socket, a `setTimeout` or `setInterval`, or a promise the plugin awaits is lost when an idle plugin is stopped, as in Chrome. Set the command's `busy` while its work runs (a busy command keeps the plugin running), or keep what it needs in session storage and pick it up in `activate`.
|
|
368
|
+
|
|
369
|
+
`TestHost.listening` lists the events a plugin really listens to; empty means listeners do not keep it running.
|
|
370
|
+
|
|
361
371
|
#### The data directory
|
|
362
372
|
|
|
363
373
|
plugin.dataDirectory is a writable directory for the plugin's own files (settings, caches, remembered folders). It needs no capability; the player creates it before it starts the plugin.
|
|
@@ -2699,6 +2709,7 @@ The table lists the API whose documentation names a player version, newest last:
|
|
|
2699
2709
|
| 0.5.12 | SystemInfo.rendering |
|
|
2700
2710
|
| 0.5.13 | SystemInfo.renderingReason, RenderingMode, RenderingPreference, RenderingReasonCode, RenderingReason, RenderingState, Rendering |
|
|
2701
2711
|
| 0.5.16 | UpscalingReasonCode, UpscalingReason, UpscalingState, VideoUpscaling |
|
|
2712
|
+
| 0.5.20 | VideoShaders |
|
|
2702
2713
|
|
|
2703
2714
|
The Slint library carries no version tags: `Theme.danger` needs player 0.3.0; `@vestra/icons.slint` and the palette `vestra-light` need 0.4.0 (Theme).
|
|
2704
2715
|
|
|
@@ -2720,7 +2731,7 @@ A plugin lists what it may do in the manifest's `capabilities` (Manifest). A cal
|
|
|
2720
2731
|
| `ui.mount` | Panels.mount, Panels.bottom, Panels.sidebar, Panels.backdrop, PanelSlot.onChange, Panel.onChange, BackdropSlot.onChange | — | Show panels in the bottom bar, the sidebar or behind the video | |
|
|
2721
2732
|
| `ui.dialog` | Dialogs.confirm, Dialogs.openFile, Dialogs.openFiles, Dialogs.openDirectory, Dialogs.saveFile | — | Show file pickers and confirmations | |
|
|
2722
2733
|
| `plugins.manage` | Packages.validate, Packages.validateArchive, Packages.setEnabled, Packages.reload, Packages.uninstall | — | Install, uninstall and disable other plugins | yes |
|
|
2723
|
-
| `processing.video` | Plugin.video.filter, Plugin.video.view, Plugin.video.render | `playback.read` | Process the picture (filters, shaders) | |
|
|
2734
|
+
| `processing.video` | Plugin.video.filter, Plugin.video.view, Plugin.video.render, Plugin.video.shaders | `playback.read` | Process the picture (filters, shaders) | |
|
|
2724
2735
|
| `processing.audio` | Plugin.audio.filter | `playback.read`, `events` | Process the sound | |
|
|
2725
2736
|
| `subtitles.read` | Subtitles.state, Subtitles.onChange, Subtitles.refresh | — | Read subtitles | |
|
|
2726
2737
|
| `subtitles.control` | Subtitles.select, Subtitles.load, Subtitles.remove, Subtitles.setStyle | — | Load and change subtitles | |
|
|
@@ -2887,7 +2898,23 @@ RenderSettings; more shaders fail with `invalid`.
|
|
|
2887
2898
|
|
|
2888
2899
|
| Limit | Value | Meaning |
|
|
2889
2900
|
| --- | --- | --- |
|
|
2890
|
-
| Entries of `RenderSettings.shaders` | 16 | mpv user shaders (`.glsl`): absolute paths of existing files, at most 16, in order. |
|
|
2901
|
+
| Entries of `RenderSettings.shaders` | 16 | mpv user shaders (`.glsl`): absolute paths of existing files, at most 16, in order. They run before the shaders of every plugin's `VideoShaders` handles. |
|
|
2902
|
+
|
|
2903
|
+
#### Video primitives
|
|
2904
|
+
|
|
2905
|
+
The `convolution` and `lut3d` VideoNodes and the shader channel VideoShaders (player 0.5.20). Values beyond them fail with `invalid`; more shaders than `shaders` across all plugins fail with `limit`.
|
|
2906
|
+
|
|
2907
|
+
| Limit | Value | Meaning |
|
|
2908
|
+
| --- | --- | --- |
|
|
2909
|
+
| `VIDEO_PROCESSING_LIMITS.shaders` | 16 | Shaders across every plugin's `plugin.video.shaders()` handles. |
|
|
2910
|
+
| `VIDEO_PROCESSING_LIMITS.shaderBytes` | 16777216 (16 MiB) | Bytes of one shader file. |
|
|
2911
|
+
| `VIDEO_PROCESSING_LIMITS.shaderIdBytes` | 128 | Bytes of a shader handle's id. |
|
|
2912
|
+
| `VIDEO_PROCESSING_LIMITS.lutBytes` | 16777216 (16 MiB) | Bytes of one `lut3d` `.cube` file. |
|
|
2913
|
+
| `VIDEO_PROCESSING_LIMITS.lutSize` | 65 | Largest `LUT_3D_SIZE` of a `lut3d` file, points per axis. |
|
|
2914
|
+
| `VIDEO_PROCESSING_LIMITS.lutPathBytes` | 4096 (4 KiB) | Bytes of a `lut3d` file path. |
|
|
2915
|
+
| `VIDEO_PROCESSING_LIMITS.matrixValue` | 1024 | Largest magnitude of a `convolution` matrix entry. |
|
|
2916
|
+
| `VIDEO_PROCESSING_LIMITS.rdiv` | 256 | Largest `convolution` `rdiv`. |
|
|
2917
|
+
| `VIDEO_PROCESSING_LIMITS.bias` | 65535 | Largest `convolution` `bias`. |
|
|
2891
2918
|
|
|
2892
2919
|
#### Limits documented at their API
|
|
2893
2920
|
|
|
@@ -3879,7 +3906,7 @@ interface Scope extends Disposable {
|
|
|
3879
3906
|
/** Playback state and controls (`playback.read`, `events`, `playback.control`). */
|
|
3880
3907
|
readonly player: Player;
|
|
3881
3908
|
/**
|
|
3882
|
-
* Video processing: this plugin's filter chain, the display layer, the GPU render options and the GPU's video upscaler. The first
|
|
3909
|
+
* Video processing: this plugin's filter chain, the display layer, the GPU render options, this plugin's shaders and the GPU's video upscaler. The first four need `processing.video` and `playback.read`; the filter chain also needs `events` (without it the SDK never sees the media become ready and the chain stays `waiting`). The upscaler needs `video.upscaling` only.
|
|
3883
3910
|
*/
|
|
3884
3911
|
readonly video: {
|
|
3885
3912
|
/**
|
|
@@ -3900,6 +3927,15 @@ interface Scope extends Disposable {
|
|
|
3900
3927
|
* @throws Error without a code (throws) A second call in the same plugin while the first handle is not disposed.
|
|
3901
3928
|
*/
|
|
3902
3929
|
render(): RenderOptions;
|
|
3930
|
+
/**
|
|
3931
|
+
* This plugin's own GPU shaders named `id` (default `"shaders"`; needs `processing.video`; SDK 1.5.39, player 0.5.20). Unlike render(), every plugin may hold shader handles at the same time; the player joins their lists. Nothing is sent until the first `set()`.
|
|
3932
|
+
* @param id - Local name of the handle, 1–128 bytes, unique within the plugin.
|
|
3933
|
+
* @returns A VideoShaders owned by this scope.
|
|
3934
|
+
* @throws capability (throws) The manifest does not declare `processing.video`.
|
|
3935
|
+
* @throws invalid (throws) `id` is empty, longer than 128 bytes or has control characters.
|
|
3936
|
+
* @throws Error without a code (throws) A second handle with the same `id` while the first is not disposed.
|
|
3937
|
+
*/
|
|
3938
|
+
shaders(id?: string): VideoShaders;
|
|
3903
3939
|
/**
|
|
3904
3940
|
* The GPU's video upscaler (NVIDIA RTX Video Super Resolution on Windows; needs `video.upscaling`, player 0.5.16): whether it works here and why not, and turning it on or off for this plugin.
|
|
3905
3941
|
*/
|
|
@@ -7445,8 +7481,10 @@ interface SystemInfo {
|
|
|
7445
7481
|
* Absent (`undefined`) on players before 0.5.12, which do not report it:
|
|
7446
7482
|
* the renderer is then unknown, not software.
|
|
7447
7483
|
*
|
|
7448
|
-
* Today the player renders on the GPU on macOS
|
|
7449
|
-
*
|
|
7484
|
+
* Today the player renders on the GPU on macOS, on Windows when the
|
|
7485
|
+
* user turned on Video ▸ GPU Rendering (Experimental) (since version 0.5.14;
|
|
7486
|
+
* off by default), and in software otherwise: on Windows by default, on
|
|
7487
|
+
* Linux and without a user interface (see
|
|
7450
7488
|
* Platforms); test this field
|
|
7451
7489
|
* rather than SystemInfo.os.
|
|
7452
7490
|
* @player 0.5.12; older players leave it out (declare `"minPlayerVersion": "0.5.12"` when the plugin relies on it).
|
|
@@ -8213,7 +8251,7 @@ What Player.stats reports. Every field is the backend's own value
|
|
|
8213
8251
|
```ts
|
|
8214
8252
|
interface PlaybackStats {
|
|
8215
8253
|
/**
|
|
8216
|
-
* The rendering path: "libmpv · GPU 渲染(OpenGL)" (GPU
|
|
8254
|
+
* The rendering path: "libmpv · GPU 渲染(OpenGL)" (GPU on macOS, the default there), "libmpv · GPU 渲染(Direct3D)" (GPU on Windows, when turned on; version 0.5.14 and later) or "libmpv · 软件渲染" (software: Windows by default, Linux, headless, fallback). The strings are the player's display text in the interface language (shown here in Chinese).
|
|
8217
8255
|
*/
|
|
8218
8256
|
backend: string;
|
|
8219
8257
|
/** The playback session number. */
|
|
@@ -9342,7 +9380,7 @@ interface RenderSettings {
|
|
|
9342
9380
|
targetPeak: number;
|
|
9343
9381
|
/** Per-scene peak estimation (where the GPU supports it). */
|
|
9344
9382
|
peakDetect: boolean;
|
|
9345
|
-
/** mpv user shaders (`.glsl`): absolute paths of existing files, at most 16, in order. */
|
|
9383
|
+
/** mpv user shaders (`.glsl`): absolute paths of existing files, at most 16, in order. They run before the shaders of every plugin's VideoShaders handles. */
|
|
9346
9384
|
shaders: string[];
|
|
9347
9385
|
/** Motion interpolation, resampled to the display's refresh rate. */
|
|
9348
9386
|
interpolation: boolean;
|
|
@@ -9355,19 +9393,23 @@ The GPU renderer's options, from `plugin.video.render()`
|
|
|
9355
9393
|
(`processing.video`). Single owner, like VideoView; the two are
|
|
9356
9394
|
independent handles.
|
|
9357
9395
|
|
|
9358
|
-
Platforms:
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9396
|
+
Platforms: macOS renders on the GPU by default; Windows does since
|
|
9397
|
+
version 0.5.14 of the player when the user turns on Video ▸ GPU Rendering
|
|
9398
|
+
(Experimental) (off by default, Rendering). Under software
|
|
9399
|
+
rendering (Windows by default, Linux, headless, fallback) every `set`
|
|
9400
|
+
fails with `unsupported`; SystemInfo.rendering tells which
|
|
9401
|
+
renderer draws without creating the handle. macOS OpenGL 4.1 has no
|
|
9362
9402
|
compute shaders, so `peakDetect` is accepted but has no effect; output
|
|
9363
9403
|
is always SDR.
|
|
9364
9404
|
|
|
9365
9405
|
GPU renderer options (tone mapping, peak detection, shaders,
|
|
9366
|
-
interpolation). Only the GPU renderer has them
|
|
9406
|
+
interpolation). Only the GPU renderer has them (macOS; Windows with GPU
|
|
9407
|
+
rendering turned on, version 0.5.14 and later);
|
|
9367
9408
|
under software rendering the handle is `failed` with `unsupported` after
|
|
9368
9409
|
the player's first answer to `render()` (reported to `onError` too), and so is
|
|
9369
9410
|
every `set`. Single owner, like VideoView. `set` never throws; the
|
|
9370
|
-
result shows in `status`.
|
|
9411
|
+
result shows in `status`. For shaders that several plugins add at the
|
|
9412
|
+
same time, use VideoShaders (SDK 1.5.39).
|
|
9371
9413
|
|
|
9372
9414
|
- @capability processing.video, playback.read and events (like VideoFilter)
|
|
9373
9415
|
|
|
@@ -9385,7 +9427,9 @@ interface RenderOptions extends Disposable {
|
|
|
9385
9427
|
* ```
|
|
9386
9428
|
*/
|
|
9387
9429
|
set(value: Partial<RenderSettings>): void;
|
|
9388
|
-
/**
|
|
9430
|
+
/**
|
|
9431
|
+
* `failed` with `unsupported` while the player renders in software; `failed` with `failed` when mpv cannot compile a shader (pushed later; while other plugins' VideoShaders are on too, the player cannot tell whose shader failed and says so in the message).
|
|
9432
|
+
*/
|
|
9389
9433
|
readonly status: FilterStatus;
|
|
9390
9434
|
/**
|
|
9391
9435
|
* The status changed (including later pushes such as shader compile errors).
|
|
@@ -9411,7 +9455,8 @@ On a GPU-rendering player HDR video is tone-mapped with BT.2390 for a
|
|
|
9411
9455
|
250-nit display; under software rendering the plugin hides its HDR menu.
|
|
9412
9456
|
`set` merges the values into the plugin's render options and the
|
|
9413
9457
|
player reports the result through `onStatus`: `failed` with
|
|
9414
|
-
`unsupported` means the player renders in software (
|
|
9458
|
+
`unsupported` means the player renders in software (Linux, or Windows
|
|
9459
|
+
while GPU rendering is off).
|
|
9415
9460
|
```ts
|
|
9416
9461
|
const render = plugin.video.render();
|
|
9417
9462
|
render.onStatus((s) => {
|
|
@@ -9420,6 +9465,127 @@ render.onStatus((s) => {
|
|
|
9420
9465
|
render.set({ toneMapping: "bt.2390", targetPeak: 250 }); // nits
|
|
9421
9466
|
```
|
|
9422
9467
|
|
|
9468
|
+
### VideoShaders
|
|
9469
|
+
|
|
9470
|
+
This plugin's own GPU shaders, from `plugin.video.shaders(id)`
|
|
9471
|
+
(`processing.video`, SDK 1.5.39, player 0.5.20): mpv user shaders
|
|
9472
|
+
(`.glsl`, `//!HOOK` …) that the GPU renderer runs on every frame.
|
|
9473
|
+
|
|
9474
|
+
Any number of plugins hold shader handles at the same time (unlike
|
|
9475
|
+
RenderOptions, which has one owner). The player joins every
|
|
9476
|
+
handle's list in a stable order, after the render options' own
|
|
9477
|
+
`shaders`: built-in plugins first, then installed plugins in the order
|
|
9478
|
+
they were first installed, then development loads (`--plugin`); ties by
|
|
9479
|
+
plugin id, and a plugin's handles by `id`. At most 16 shaders across all
|
|
9480
|
+
handles (`limit` beyond, nothing changes); the render options keep their
|
|
9481
|
+
own 16.
|
|
9482
|
+
|
|
9483
|
+
Files must be this plugin's own: absolute paths inside its package
|
|
9484
|
+
directory or Plugin.dataDirectory after following links, each
|
|
9485
|
+
at most 16 MiB. Elsewhere: `invalid`; a file that does not exist:
|
|
9486
|
+
`missing`. The player reads the files when the list is set.
|
|
9487
|
+
|
|
9488
|
+
GPU rendering only (macOS; Windows with Video ▸ GPU Rendering
|
|
9489
|
+
(Experimental) turned on): under software rendering a non-empty list is
|
|
9490
|
+
`failed` with `unsupported`, and a switch to software during the run
|
|
9491
|
+
pushes `unsupported` to every handle with shaders and removes every
|
|
9492
|
+
list (they no longer count against the 16); set them again once the
|
|
9493
|
+
player draws on the GPU (after a restart). Shaders act when a
|
|
9494
|
+
frame is drawn, so processed snapshots and exports never contain them
|
|
9495
|
+
(use a VideoNode for that). When mpv cannot compile a shader the
|
|
9496
|
+
handle turns `failed` with `failed` (pushed later); mpv does not say
|
|
9497
|
+
which file failed, so while several plugins' shaders are on, each of
|
|
9498
|
+
them hears it and the message says the player cannot tell whose.
|
|
9499
|
+
|
|
9500
|
+
`set` sends the whole list (last write wins); `clear` and `dispose`
|
|
9501
|
+
withdraw it; the player removes a stopped plugin's shaders itself.
|
|
9502
|
+
Players before 0.5.20 refuse the request (the handle is `failed`): declare
|
|
9503
|
+
`"minPlayerVersion": "0.5.20"`.
|
|
9504
|
+
|
|
9505
|
+
- @capability processing.video
|
|
9506
|
+
- @player 0.5.20; older players refuse the request.
|
|
9507
|
+
|
|
9508
|
+
```ts
|
|
9509
|
+
interface VideoShaders extends Disposable {
|
|
9510
|
+
/**
|
|
9511
|
+
* Replace this handle's shader list (last write wins); `[]` withdraws it.
|
|
9512
|
+
*
|
|
9513
|
+
* Never throws: a refused list shows in `status` (`invalid`, `missing`,
|
|
9514
|
+
* `limit`, `unsupported`) and goes to Scope.onError, and what the
|
|
9515
|
+
* player held stays.
|
|
9516
|
+
* @capability processing.video
|
|
9517
|
+
* @param paths - Absolute paths of shader files in this plugin's package or data directory, in the order they run.
|
|
9518
|
+
* @example Switch between two shader presets
|
|
9519
|
+
* The plugin offers a light and a strong preset; picking one replaces
|
|
9520
|
+
* the handle's list in one request. The files were written to the
|
|
9521
|
+
* plugin's data directory when the user imported them.
|
|
9522
|
+
* ```ts
|
|
9523
|
+
* const presets: Record<string, string[]> = {
|
|
9524
|
+
* light: [join(plugin.dataDirectory, "denoise.glsl")],
|
|
9525
|
+
* strong: [join(plugin.dataDirectory, "denoise.glsl"), join(plugin.dataDirectory, "sharpen.glsl")],
|
|
9526
|
+
* };
|
|
9527
|
+
* plugin.video.shaders("presets").set(presets.strong!);
|
|
9528
|
+
* ```
|
|
9529
|
+
*/
|
|
9530
|
+
set(paths: readonly string[]): void;
|
|
9531
|
+
/**
|
|
9532
|
+
* Withdraw this handle's shaders (the same as `set([])`).
|
|
9533
|
+
* @capability processing.video
|
|
9534
|
+
* @example Turn the plugin's shaders off from a menu item
|
|
9535
|
+
* A Video menu item turns the plugin's shader on and off. Clearing
|
|
9536
|
+
* keeps the handle, so the next pick sets the list again.
|
|
9537
|
+
* ```ts
|
|
9538
|
+
* const shaders = plugin.video.shaders();
|
|
9539
|
+
* let on = false;
|
|
9540
|
+
* plugin.commands.add({
|
|
9541
|
+
* id: "toggle-shader",
|
|
9542
|
+
* path: ["@video", "Sharpen (Shader)"],
|
|
9543
|
+
* checked: () => on,
|
|
9544
|
+
* run: () => {
|
|
9545
|
+
* on = !on;
|
|
9546
|
+
* // Clearing keeps the handle; the next pick sets the list again.
|
|
9547
|
+
* if (on) shaders.set([file]);
|
|
9548
|
+
* else shaders.clear();
|
|
9549
|
+
* },
|
|
9550
|
+
* });
|
|
9551
|
+
* ```
|
|
9552
|
+
*/
|
|
9553
|
+
clear(): void;
|
|
9554
|
+
/** Current status: `waiting` before ready media, `applying`, `applied`, or `failed` with the reason (see the remarks). */
|
|
9555
|
+
readonly status: FilterStatus;
|
|
9556
|
+
/**
|
|
9557
|
+
* The status changed, including later pushes (a compile failure, a switch to software rendering).
|
|
9558
|
+
* @capability processing.video
|
|
9559
|
+
* @example Report a shader that does not compile
|
|
9560
|
+
* The OSD shows mpv's message when the plugin's shader fails to compile.
|
|
9561
|
+
* The player pushes that failure after the list was accepted, so it
|
|
9562
|
+
* arrives through `onStatus`, not as a refused `set`.
|
|
9563
|
+
* ```ts
|
|
9564
|
+
* const shaders = plugin.video.shaders();
|
|
9565
|
+
* shaders.onStatus((status) => {
|
|
9566
|
+
* if (status.state === "failed") void plugin.osd.show("Shader: {}", [status.error.message]);
|
|
9567
|
+
* });
|
|
9568
|
+
* ```
|
|
9569
|
+
*/
|
|
9570
|
+
onStatus(listener: (status: FilterStatus) => void): Disposable;
|
|
9571
|
+
}
|
|
9572
|
+
```
|
|
9573
|
+
|
|
9574
|
+
Example: Add a sharpening shader the plugin ships
|
|
9575
|
+
|
|
9576
|
+
The video looks sharper on the GPU renderer; under software rendering
|
|
9577
|
+
the OSD says why it is not. The shader file lives in the plugin's
|
|
9578
|
+
package, and the player puts it after other plugins' shaders that come
|
|
9579
|
+
earlier in its order.
|
|
9580
|
+
```ts
|
|
9581
|
+
const shaders = plugin.video.shaders("sharpen");
|
|
9582
|
+
shaders.onStatus((s) => {
|
|
9583
|
+
// `unsupported`: software rendering; `failed`: mpv could not compile it.
|
|
9584
|
+
if (s.state === "failed") void plugin.osd.show("Sharpen: {}", [s.error.message]);
|
|
9585
|
+
});
|
|
9586
|
+
shaders.set([join(packageDirectory, "shaders", "sharpen.glsl")]);
|
|
9587
|
+
```
|
|
9588
|
+
|
|
9423
9589
|
### UpscalingReasonCode
|
|
9424
9590
|
|
|
9425
9591
|
Why the GPU's video upscaler does not work, as a stable kebab-case code.
|
|
@@ -10735,6 +10901,10 @@ interface PluginInfo {
|
|
|
10735
10901
|
* The manifest's display texts in the interface language, translated with that package's catalog; absent from players before 0.4.3 (read `manifest.json` there).
|
|
10736
10902
|
*/
|
|
10737
10903
|
display?: PluginDisplay;
|
|
10904
|
+
/**
|
|
10905
|
+
* For `state: "running"`: `"running"` while its process runs, `"idle"` while the player stopped it because nothing used it (lazy activation: it starts again on its next use, its menu items, keys, settings pages, resolvers and drop targets stay). Absent in other states and from players before 0.5.18. A change between the two alone does not fire Packages.onChange.
|
|
10906
|
+
*/
|
|
10907
|
+
process?: "running" | "idle";
|
|
10738
10908
|
}
|
|
10739
10909
|
```
|
|
10740
10910
|
|
|
@@ -11835,10 +12005,10 @@ RenderingReason.message for the rest. The codes of player 0.5.13:
|
|
|
11835
12005
|
|
|
11836
12006
|
| Code | Meaning |
|
|
11837
12007
|
| --- | --- |
|
|
11838
|
-
| `default` | Nothing ruled the GPU out; the platform's default. |
|
|
12008
|
+
| `default` | Nothing ruled the GPU out; the platform's default (macOS: GPU; Windows since version 0.5.14: software until the user turns on GPU rendering). |
|
|
11839
12009
|
| `pending` | GPU rendering is starting. |
|
|
11840
12010
|
| `headless` | The player runs without a user interface. |
|
|
11841
|
-
| `no-gpu-backend` | This player has no GPU renderer on this system (Windows
|
|
12011
|
+
| `no-gpu-backend` | This player has no GPU renderer on this system (Linux today; Windows has one since version 0.5.14, off by default, which reports `default`). |
|
|
11842
12012
|
| `env` | The environment chose it (`VESTRA_RENDER`, `VESTRA_SOFTWARE_RENDER`). |
|
|
11843
12013
|
| `preference` | The user chose software rendering (Rendering.setPreference); GPU chosen and available reports `default`. |
|
|
11844
12014
|
| `denylist` | The graphics driver is on the player's denylist. |
|
|
@@ -12203,6 +12373,28 @@ type VideoNode =
|
|
|
12203
12373
|
kind: "frameBlend";
|
|
12204
12374
|
/** Output frame rate, integer 24–120. */
|
|
12205
12375
|
fps: number;
|
|
12376
|
+
}
|
|
12377
|
+
/**
|
|
12378
|
+
* A convolution matrix of your own per plane (FFmpeg `convolution`, SDK 1.5.39, player 0.5.20): sharpen, blur, emboss or detect edges with a 3×3, 5×5 or 7×7 kernel, or a row or column kernel. `planes[i]` is plane `i` of the decoded picture: for the usual YUV video 0 is luma (brightness), 1 and 2 are the colour planes, 3 is alpha. A missing entry or `null` leaves that plane as it is; at least one entry has a matrix. Players before 0.5.20 refuse the kind with `invalid`.
|
|
12379
|
+
*/
|
|
12380
|
+
| {
|
|
12381
|
+
/** The node type. */
|
|
12382
|
+
kind: "convolution";
|
|
12383
|
+
/** 1–4 entries, by plane; `null` passes the plane through. */
|
|
12384
|
+
planes: (ConvolutionPlane | null)[];
|
|
12385
|
+
}
|
|
12386
|
+
/**
|
|
12387
|
+
* Recolour the picture with a 3D look-up table (FFmpeg `lut3d`, SDK 1.5.39, player 0.5.20): a `.cube` file the plugin ships in its package or wrote to its Plugin.dataDirectory. The player reads the file when the chain is set (and again for each new source, snapshot or export), so it must stay there while the chain uses it. The table is applied to RGB; the player converts the picture to RGB and back. Players before 0.5.20 refuse the kind with `invalid`.
|
|
12388
|
+
*/
|
|
12389
|
+
| {
|
|
12390
|
+
/** The node type. */
|
|
12391
|
+
kind: "lut3d";
|
|
12392
|
+
/**
|
|
12393
|
+
* Absolute path of a `.cube` file (`LUT_3D_SIZE` 2–65, at most 16 MiB) inside the plugin's package directory or data directory after following links; a path with `[` or `]` is refused. Outside those: `invalid`; a file that does not exist: `missing`.
|
|
12394
|
+
*/
|
|
12395
|
+
file: string;
|
|
12396
|
+
/** How colours between the table's points are computed; `tetrahedral` is FFmpeg's default. */
|
|
12397
|
+
interpolation: "nearest" | "trilinear" | "tetrahedral" | "pyramid" | "prism";
|
|
12206
12398
|
};
|
|
12207
12399
|
```
|
|
12208
12400
|
|
|
@@ -12224,6 +12416,27 @@ const chain: VideoNode[] = [
|
|
|
12224
12416
|
plugin.video.filter("picture").set(chain);
|
|
12225
12417
|
```
|
|
12226
12418
|
|
|
12419
|
+
### ConvolutionPlane
|
|
12420
|
+
|
|
12421
|
+
One plane's kernel of a `convolution` VideoNode: each output
|
|
12422
|
+
sample is `(sum of matrix × neighbourhood) × rdiv + bias`, clipped to the
|
|
12423
|
+
sample range.
|
|
12424
|
+
|
|
12425
|
+
```ts
|
|
12426
|
+
type ConvolutionPlane = {
|
|
12427
|
+
/**
|
|
12428
|
+
* `square`: `matrix` is a 3×3, 5×5 or 7×7 kernel, row by row (9, 25 or 49 entries); `row` / `column`: a horizontal / vertical kernel with an odd number of entries up to 49.
|
|
12429
|
+
*/
|
|
12430
|
+
mode: "square" | "row" | "column";
|
|
12431
|
+
/** Integers −1024–1024 (FFmpeg reads whole numbers only). */
|
|
12432
|
+
matrix: number[];
|
|
12433
|
+
/** Multiplier 0–256; 0 divides by the sum of the matrix (by 1 when it sums to 0), which keeps the brightness of a blur. */
|
|
12434
|
+
rdiv: number;
|
|
12435
|
+
/** Added after the multiplication, 0–65535 in the plane's sample units (128 is mid grey for 8-bit video). */
|
|
12436
|
+
bias: number;
|
|
12437
|
+
};
|
|
12438
|
+
```
|
|
12439
|
+
|
|
12227
12440
|
### AudioNode
|
|
12228
12441
|
|
|
12229
12442
|
One node of an AudioFilter chain, by `kind`. Values outside the
|
|
@@ -12796,6 +13009,10 @@ class TestHost implements Transport {
|
|
|
12796
13009
|
readonly calls: Call[];
|
|
12797
13010
|
/** The host events the plugin subscribed to (needs `events` etc.). */
|
|
12798
13011
|
readonly subscriptions: Set<string>;
|
|
13012
|
+
/**
|
|
13013
|
+
* The subscribed events the plugin really listens to: an `onChange` and the like, or a binding that reads the state. The SDK's own copies of the state (what keeps `plugin.player.state` current) are left out. Empty means the player may stop the plugin while nothing uses it (unless it holds something else: a window, a panel, a filter…).
|
|
13014
|
+
*/
|
|
13015
|
+
readonly listening: Set<string>;
|
|
12799
13016
|
/**
|
|
12800
13017
|
* The player's source facts (phase, position, duration, paused, rate, audio tracks, loop, ...). Wire-level shape; change it with TestHost.setSource, which also broadcasts it.
|
|
12801
13018
|
*/
|
|
@@ -13376,6 +13593,39 @@ class TestHost implements Transport {
|
|
|
13376
13593
|
* ```
|
|
13377
13594
|
*/
|
|
13378
13595
|
failVideoRender(code: "failed" | "unsupported", message: string): void;
|
|
13596
|
+
/**
|
|
13597
|
+
* The shader channel (`plugin.video.shaders(id)`, SDK 1.5.39): the lists the player holds for this plugin's handles by id (the real paths, after following links), and how many shaders other plugins hold, which count against VIDEO_PROCESSING_LIMITS`.shaders` (`limit`). Files must be under TestHost.fileRoots; under software rendering (`videoRender.gpu = false`) a non-empty list fails with `unsupported`.
|
|
13598
|
+
*/
|
|
13599
|
+
readonly videoShaders: {
|
|
13600
|
+
/** This plugin's lists by handle id; a cleared handle has none. */
|
|
13601
|
+
handles: Map<string, string[]>;
|
|
13602
|
+
/** Shaders other plugins hold (0–16). */
|
|
13603
|
+
others: number;
|
|
13604
|
+
};
|
|
13605
|
+
/**
|
|
13606
|
+
* Where the plugin's own files may be: its package directory and its data directory (startPlugin sets both when the list is still empty). `lut3d` files and shader-channel files outside them fail with `invalid`, as in the player.
|
|
13607
|
+
*/
|
|
13608
|
+
fileRoots: string[];
|
|
13609
|
+
/**
|
|
13610
|
+
* What the player pushes to a shader handle when mpv cannot compile a shader (code `failed`; the player cannot tell whose shader failed, so every handle with shaders hears it) or the player switches to software rendering (`unsupported`; use TestHost.failVideoRender, which also tells the handles). Pushed only to a handle that holds shaders.
|
|
13611
|
+
* @capability None.
|
|
13612
|
+
* @example Make the plugin's shader fail to compile
|
|
13613
|
+
* The plugin's shader handle reports `failed`, as when mpv rejects a
|
|
13614
|
+
* shader. The host pushes the failure only to a handle that holds
|
|
13615
|
+
* shaders, which its accepted `set` made it; the SDK updates the
|
|
13616
|
+
* handle's `status` when the push arrives, so the test settles first.
|
|
13617
|
+
* ```ts
|
|
13618
|
+
* const file = join(plugin.dataDirectory, "sharpen.glsl");
|
|
13619
|
+
* writeFileSync(file, "//!HOOK MAIN\n");
|
|
13620
|
+
* const shaders = plugin.video.shaders("sharpen");
|
|
13621
|
+
* shaders.set([file]); // the handle now holds a shader
|
|
13622
|
+
* await host.settle();
|
|
13623
|
+
* host.failVideoShaders("sharpen", "shader compile failed: ERROR: 0:3: ...");
|
|
13624
|
+
* await host.settle();
|
|
13625
|
+
* assert.equal(shaders.status.state, "failed");
|
|
13626
|
+
* ```
|
|
13627
|
+
*/
|
|
13628
|
+
failVideoShaders(id: string, message: string): void;
|
|
13379
13629
|
/**
|
|
13380
13630
|
* The player's processing (filter) state. Wire-level; may change in minor versions. `resources` holds each `video.filter` / `audio.filter` chain the plugin applied, keyed by the SDK's resource id.
|
|
13381
13631
|
* @example Check the filter chain the plugin applied
|
|
@@ -13637,9 +13887,9 @@ class TestHost implements Transport {
|
|
|
13637
13887
|
* import activate from "../main.ts";
|
|
13638
13888
|
*
|
|
13639
13889
|
* const host = new TestHost();
|
|
13640
|
-
* host.videoRender.gpu = false; // software draws now (
|
|
13890
|
+
* host.videoRender.gpu = false; // software draws now (Linux)
|
|
13641
13891
|
* host.rendering.startedWith = "software";
|
|
13642
|
-
* host.rendering.reason = { code: "no-gpu-backend", message: "
|
|
13892
|
+
* host.rendering.reason = { code: "no-gpu-backend", message: "this player has no GPU renderer on Linux yet" };
|
|
13643
13893
|
* host.rendering.gpu = { available: false, reason: host.rendering.reason };
|
|
13644
13894
|
* const { stop } = await startPlugin(activate, {
|
|
13645
13895
|
* directory: new URL("..", import.meta.url),
|
|
@@ -13647,7 +13897,7 @@ class TestHost implements Transport {
|
|
|
13647
13897
|
* });
|
|
13648
13898
|
* const item = host.command("gpu-rendering");
|
|
13649
13899
|
* assert.equal(item.state.enabled, false);
|
|
13650
|
-
* assert.equal(item.state.reason, "
|
|
13900
|
+
* assert.equal(item.state.reason, "this player has no GPU renderer on Linux yet");
|
|
13651
13901
|
* await stop();
|
|
13652
13902
|
* ```
|
|
13653
13903
|
*/
|
|
@@ -15082,6 +15332,49 @@ const IMAGE_LIMITS: Readonly<{
|
|
|
15082
15332
|
}>;
|
|
15083
15333
|
```
|
|
15084
15334
|
|
|
15335
|
+
### VIDEO_PROCESSING_LIMITS
|
|
15336
|
+
|
|
15337
|
+
The player's bounds for the video primitives of SDK 1.5.39 (player
|
|
15338
|
+
0.5.20): `convolution` and `lut3d` VideoNodes and the shader
|
|
15339
|
+
channel (`plugin.video.shaders()`). Values beyond them fail with
|
|
15340
|
+
`invalid`; more shaders than `shaders` fail with `limit`.
|
|
15341
|
+
|
|
15342
|
+
```ts
|
|
15343
|
+
const VIDEO_PROCESSING_LIMITS: Readonly<{
|
|
15344
|
+
/** Shaders across every plugin's `plugin.video.shaders()` handles (16). */
|
|
15345
|
+
shaders: 16;
|
|
15346
|
+
/** Bytes of one shader file (16 MiB). */
|
|
15347
|
+
shaderBytes: number;
|
|
15348
|
+
/** Bytes of a shader handle's id (128). */
|
|
15349
|
+
shaderIdBytes: 128;
|
|
15350
|
+
/** Bytes of one `lut3d` `.cube` file (16 MiB). */
|
|
15351
|
+
lutBytes: number;
|
|
15352
|
+
/** Largest `LUT_3D_SIZE` of a `lut3d` file, points per axis (65). */
|
|
15353
|
+
lutSize: 65;
|
|
15354
|
+
/** Bytes of a `lut3d` file path (4096). */
|
|
15355
|
+
lutPathBytes: 4096;
|
|
15356
|
+
/** Largest magnitude of a `convolution` matrix entry (1024). */
|
|
15357
|
+
matrixValue: 1024;
|
|
15358
|
+
/** Largest `convolution` `rdiv` (256). */
|
|
15359
|
+
rdiv: 256;
|
|
15360
|
+
/** Largest `convolution` `bias` (65535). */
|
|
15361
|
+
bias: 65535;
|
|
15362
|
+
}>;
|
|
15363
|
+
```
|
|
15364
|
+
|
|
15365
|
+
Example: Refuse a shader list the player would not take
|
|
15366
|
+
|
|
15367
|
+
The plugin checks a shader list against the player's limit before it
|
|
15368
|
+
sets it, and says so on the OSD instead of waiting for a `limit` failure.
|
|
15369
|
+
The limit counts every plugin's shaders, so the player still decides.
|
|
15370
|
+
```ts
|
|
15371
|
+
import { VIDEO_PROCESSING_LIMITS } from "@vestra-player/sdk/testing";
|
|
15372
|
+
|
|
15373
|
+
if (files.length > VIDEO_PROCESSING_LIMITS.shaders)
|
|
15374
|
+
void plugin.osd.show("Too many shaders");
|
|
15375
|
+
else plugin.video.shaders().set(files);
|
|
15376
|
+
```
|
|
15377
|
+
|
|
15085
15378
|
### HostError
|
|
15086
15379
|
|
|
15087
15380
|
A definite refusal from the player (or the plugin runner), with a stable
|
|
@@ -15341,7 +15634,7 @@ What Player.stats reports. Every field is the backend's own value
|
|
|
15341
15634
|
```ts
|
|
15342
15635
|
interface PlaybackStats {
|
|
15343
15636
|
/**
|
|
15344
|
-
* The rendering path: "libmpv · GPU 渲染(OpenGL)" (GPU
|
|
15637
|
+
* The rendering path: "libmpv · GPU 渲染(OpenGL)" (GPU on macOS, the default there), "libmpv · GPU 渲染(Direct3D)" (GPU on Windows, when turned on; version 0.5.14 and later) or "libmpv · 软件渲染" (software: Windows by default, Linux, headless, fallback). The strings are the player's display text in the interface language (shown here in Chinese).
|
|
15345
15638
|
*/
|
|
15346
15639
|
backend: string;
|
|
15347
15640
|
/** The playback session number. */
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vestra Player SDK
|
|
2
2
|
|
|
3
|
-
> @vestra-player/sdk 1.5.
|
|
3
|
+
> @vestra-player/sdk 1.5.39: write plugins for Vestra Player in TypeScript (plugin API `vestra/1`). A plugin is a folder with `manifest.json` and an entry module whose default export `activate(plugin)` the player calls; it runs in its own Node.js process. Everything a plugin creates (commands, windows, panels, filters, listeners…) is a handle that is released automatically when the plugin stops. L<n>: a line of llms-full.txt (next to this file), which has every page, declaration and example.
|
|
4
4
|
|
|
5
5
|
**Rules**
|
|
6
6
|
|
|
@@ -33,7 +33,7 @@ my-plugin/
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
Fields: `id`, `version`, `apiVersion`, `entry`, `capabilities`, `name`, `author`, `punchline`, `description`, `tags`, `icon`, `readme`, `changelog`, `sourceUrl`, `license`, `minPlayerVersion`; unknown fields and capabilities are rejected. Rules and limits:
|
|
36
|
+
Fields: `id`, `version`, `apiVersion`, `entry`, `capabilities`, `name`, `author`, `punchline`, `description`, `tags`, `icon`, `readme`, `changelog`, `sourceUrl`, `license`, `minPlayerVersion`; unknown fields and capabilities are rejected. Rules and limits: L2646–2717.
|
|
37
37
|
|
|
38
38
|
**main.ts**
|
|
39
39
|
|
|
@@ -61,7 +61,7 @@ export default async function activate(plugin: Plugin) {
|
|
|
61
61
|
- `ui.mount`: Panels.mount/bottom/sidebar/backdrop, PanelSlot/Panel/BackdropSlot.onChange
|
|
62
62
|
- `ui.dialog`: Dialogs.confirm/openFile/openFiles/openDirectory/saveFile
|
|
63
63
|
- `plugins.manage`: Packages.validate/validateArchive/setEnabled/reload/uninstall
|
|
64
|
-
- `processing.video`: Plugin.video.filter/video.view/video.render (also `playback.read`)
|
|
64
|
+
- `processing.video`: Plugin.video.filter/video.view/video.render/video.shaders (also `playback.read`)
|
|
65
65
|
- `processing.audio`: Plugin.audio.filter (also `playback.read`, `events`)
|
|
66
66
|
- `subtitles.read`: Subtitles.state/onChange/refresh
|
|
67
67
|
- `subtitles.control`: Subtitles.select/load/remove/setStyle
|
|
@@ -78,9 +78,9 @@ export default async function activate(plugin: Plugin) {
|
|
|
78
78
|
- `secrets`: Secrets.get/set/delete
|
|
79
79
|
- `rendering.manage`: Rendering.setPreference/restartPlayer
|
|
80
80
|
- `video.upscaling`: VideoUpscaling.state/set
|
|
81
|
-
- No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme, packages.list and rendering.state. Details:
|
|
81
|
+
- No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme, packages.list and rendering.state. Details: L2718–2778.
|
|
82
82
|
|
|
83
|
-
**Test**: `tests/*.test.ts` with `node:test`, run by `vestra-plugin test`. `startPlugin(activate, { directory: new URL("..", import.meta.url) })` from `@vestra-player/sdk/testing` returns `{ host, stop }`, `host` an in-memory player (TestHost): act (`host.command(id).run()`, `host.press(key)`), `await host.settle()`, assert on `host.osd`, `host.window(id).props`… Guide:
|
|
83
|
+
**Test**: `tests/*.test.ts` with `node:test`, run by `vestra-plugin test`. `startPlugin(activate, { directory: new URL("..", import.meta.url) })` from `@vestra-player/sdk/testing` returns `{ host, stop }`, `host` an in-memory player (TestHost): act (`host.command(id).run()`, `host.press(key)`), `await host.settle()`, assert on `host.osd`, `host.window(id).props`… Guide: L2087–2275; TestHost: L12957.
|
|
84
84
|
|
|
85
85
|
**Command line**
|
|
86
86
|
|
|
@@ -108,39 +108,39 @@ export default async function activate(plugin: Plugin) {
|
|
|
108
108
|
- `limit`: A player-wide limit was reached, a property value is over the limits of PropValue
|
|
109
109
|
- `reserved`: The id is `vestra` or starts with `vestra.`
|
|
110
110
|
- `versionMismatch`: The package needs a newer player
|
|
111
|
-
- Others: PluginError, llms-full.txt
|
|
111
|
+
- Others: PluginError, llms-full.txt L3797.
|
|
112
112
|
|
|
113
113
|
## Reference
|
|
114
114
|
|
|
115
115
|
- [llms-full.txt](https://vestrasys.github.io/vestra-player-sdk/llms-full.txt), also node_modules/@vestra-player/sdk/llms-full.txt; pages: [site](https://vestrasys.github.io/vestra-player-sdk/).
|
|
116
116
|
- Tutorials: Getting started L9–237
|
|
117
|
-
- Concepts: How a plugin runs L238–
|
|
118
|
-
- How-to: Control playback
|
|
119
|
-
- Guidelines: Interface guidelines
|
|
120
|
-
- Reference: Manifest
|
|
121
|
-
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html):
|
|
122
|
-
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html):
|
|
117
|
+
- Concepts: How a plugin runs L238–418; Commands, menus and key bindings L419–530; Playback state, controls and sources L531–676; Video and audio processing L677–763; Windows, panels, settings pages, dialogs and the OSD L764–1052
|
|
118
|
+
- How-to: Control playback L1053–1181; Store a plugin's data L1182–1249; Load subtitles from a plugin L1250–1328; Keep a slider responsive while dragging L1329–1503; Remember a window's state between runs L1504–1633; Offer a GPU rendering switch L1634–1754; Translate a plugin L1755–1938; Migrate a plugin to English source text L1939–2086; Test a plugin L2087–2275; Publish a plugin L2276–2364; Migrating off package rollback (1.5.16, removed in 1.5.17) L2365–2440
|
|
119
|
+
- Guidelines: Interface guidelines L2441–2548; Menu guidelines L2549–2645
|
|
120
|
+
- Reference: Manifest L2646–2717; Capabilities L2718–2778; Limits L2779–2924; Commands, menus and bindings L2925–3408; Platforms L3409–3439; Theme L3440–3661; Command line L3662–3719
|
|
121
|
+
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L3720–12641
|
|
122
|
+
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L12642–15437
|
|
123
123
|
|
|
124
124
|
## API
|
|
125
125
|
|
|
126
126
|
Where each `plugin.<module>` is declared:
|
|
127
127
|
|
|
128
|
-
- Plugin
|
|
129
|
-
- Commands
|
|
128
|
+
- Plugin L4132, Scope L3872, PluginError L3797, Disposable L3735
|
|
129
|
+
- Commands L4529; Windows L5466; Panels L6912; Dialogs L7582; Player L8323; video: VideoFilter L9203, VideoView L9303, RenderOptions L9390, VideoShaders L9468, VideoUpscaling L9714; audio: AudioFilter L9248; Subtitles L9910; media: MediaCapture L10314; Resolvers L10544; Packages L10946; Osd L9068; Host L8910; Clipboard L11274; Power L11361; Tools L11420; Storage L11572; System L11771; Secrets L11851; window: MainWindow L7229; App L7409; Rendering L12114; Bindings L11174; Ui L4818; Timeline L7141; Drops L6159; Appearance L6240; I18n L6473; Settings L6756.
|
|
130
130
|
|
|
131
131
|
## Examples
|
|
132
132
|
|
|
133
133
|
Tested plugins in [examples/](https://github.com/vestrasys/vestra-player-sdk/tree/main/examples):
|
|
134
134
|
|
|
135
|
-
- hello: The README Quick start: one menu command and an on-screen message.
|
|
136
|
-
- blur: A tool window with one slider that blurs the playing video.
|
|
137
|
-
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone.
|
|
138
|
-
- bookmark: A tool window bound to the playback state: remember the position and jump back to it.
|
|
139
|
-
- panel-menu: A sidebar panel with its own right-click menu.
|
|
140
|
-
- menus: Radio menu items, separator groups and a menu item whose title changes.
|
|
141
|
-
- theme-widgets: A tool window drawn with the player's theme and widgets.
|
|
142
|
-
- markdown: A window that shows a Markdown document.
|
|
143
|
-
- i18n: A plugin in the player's language: English source text, a Chinese translation.
|
|
135
|
+
- hello: The README Quick start: one menu command and an on-screen message. L15872–15961
|
|
136
|
+
- blur: A tool window with one slider that blurs the playing video. L15962–16223
|
|
137
|
+
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L16224–16556
|
|
138
|
+
- bookmark: A tool window bound to the playback state: remember the position and jump back to it. L16557–16743
|
|
139
|
+
- panel-menu: A sidebar panel with its own right-click menu. L16744–16952
|
|
140
|
+
- menus: Radio menu items, separator groups and a menu item whose title changes. L16953–17112
|
|
141
|
+
- theme-widgets: A tool window drawn with the player's theme and widgets. L17113–17276
|
|
142
|
+
- markdown: A window that shows a Markdown document. L17277–17473
|
|
143
|
+
- i18n: A plugin in the player's language: English source text, a Chinese translation. L17474–17641
|
|
144
144
|
|
|
145
145
|
## Optional
|
|
146
146
|
|