@vestra-player/sdk 1.5.38 → 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 +10 -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/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/testing.d.ts +64 -3
- package/dist/plugin/testing.js +199 -6
- package/dist/plugin/types.d.ts +202 -22
- package/dist/processing.d.ts +118 -4
- package/dist/processing.js +139 -0
- package/dist/wire.d.ts +7 -0
- package/dist/wire.js +5 -0
- package/llms-full.txt +297 -22
- package/llms.txt +20 -20
- 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
|
|
|
@@ -2709,6 +2709,7 @@ The table lists the API whose documentation names a player version, newest last:
|
|
|
2709
2709
|
| 0.5.12 | SystemInfo.rendering |
|
|
2710
2710
|
| 0.5.13 | SystemInfo.renderingReason, RenderingMode, RenderingPreference, RenderingReasonCode, RenderingReason, RenderingState, Rendering |
|
|
2711
2711
|
| 0.5.16 | UpscalingReasonCode, UpscalingReason, UpscalingState, VideoUpscaling |
|
|
2712
|
+
| 0.5.20 | VideoShaders |
|
|
2712
2713
|
|
|
2713
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).
|
|
2714
2715
|
|
|
@@ -2730,7 +2731,7 @@ A plugin lists what it may do in the manifest's `capabilities` (Manifest). A cal
|
|
|
2730
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 | |
|
|
2731
2732
|
| `ui.dialog` | Dialogs.confirm, Dialogs.openFile, Dialogs.openFiles, Dialogs.openDirectory, Dialogs.saveFile | — | Show file pickers and confirmations | |
|
|
2732
2733
|
| `plugins.manage` | Packages.validate, Packages.validateArchive, Packages.setEnabled, Packages.reload, Packages.uninstall | — | Install, uninstall and disable other plugins | yes |
|
|
2733
|
-
| `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) | |
|
|
2734
2735
|
| `processing.audio` | Plugin.audio.filter | `playback.read`, `events` | Process the sound | |
|
|
2735
2736
|
| `subtitles.read` | Subtitles.state, Subtitles.onChange, Subtitles.refresh | — | Read subtitles | |
|
|
2736
2737
|
| `subtitles.control` | Subtitles.select, Subtitles.load, Subtitles.remove, Subtitles.setStyle | — | Load and change subtitles | |
|
|
@@ -2897,7 +2898,23 @@ RenderSettings; more shaders fail with `invalid`.
|
|
|
2897
2898
|
|
|
2898
2899
|
| Limit | Value | Meaning |
|
|
2899
2900
|
| --- | --- | --- |
|
|
2900
|
-
| 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`. |
|
|
2901
2918
|
|
|
2902
2919
|
#### Limits documented at their API
|
|
2903
2920
|
|
|
@@ -3889,7 +3906,7 @@ interface Scope extends Disposable {
|
|
|
3889
3906
|
/** Playback state and controls (`playback.read`, `events`, `playback.control`). */
|
|
3890
3907
|
readonly player: Player;
|
|
3891
3908
|
/**
|
|
3892
|
-
* 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.
|
|
3893
3910
|
*/
|
|
3894
3911
|
readonly video: {
|
|
3895
3912
|
/**
|
|
@@ -3910,6 +3927,15 @@ interface Scope extends Disposable {
|
|
|
3910
3927
|
* @throws Error without a code (throws) A second call in the same plugin while the first handle is not disposed.
|
|
3911
3928
|
*/
|
|
3912
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;
|
|
3913
3939
|
/**
|
|
3914
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.
|
|
3915
3941
|
*/
|
|
@@ -7455,8 +7481,10 @@ interface SystemInfo {
|
|
|
7455
7481
|
* Absent (`undefined`) on players before 0.5.12, which do not report it:
|
|
7456
7482
|
* the renderer is then unknown, not software.
|
|
7457
7483
|
*
|
|
7458
|
-
* Today the player renders on the GPU on macOS
|
|
7459
|
-
*
|
|
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
|
|
7460
7488
|
* Platforms); test this field
|
|
7461
7489
|
* rather than SystemInfo.os.
|
|
7462
7490
|
* @player 0.5.12; older players leave it out (declare `"minPlayerVersion": "0.5.12"` when the plugin relies on it).
|
|
@@ -8223,7 +8251,7 @@ What Player.stats reports. Every field is the backend's own value
|
|
|
8223
8251
|
```ts
|
|
8224
8252
|
interface PlaybackStats {
|
|
8225
8253
|
/**
|
|
8226
|
-
* 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).
|
|
8227
8255
|
*/
|
|
8228
8256
|
backend: string;
|
|
8229
8257
|
/** The playback session number. */
|
|
@@ -9352,7 +9380,7 @@ interface RenderSettings {
|
|
|
9352
9380
|
targetPeak: number;
|
|
9353
9381
|
/** Per-scene peak estimation (where the GPU supports it). */
|
|
9354
9382
|
peakDetect: boolean;
|
|
9355
|
-
/** 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. */
|
|
9356
9384
|
shaders: string[];
|
|
9357
9385
|
/** Motion interpolation, resampled to the display's refresh rate. */
|
|
9358
9386
|
interpolation: boolean;
|
|
@@ -9365,19 +9393,23 @@ The GPU renderer's options, from `plugin.video.render()`
|
|
|
9365
9393
|
(`processing.video`). Single owner, like VideoView; the two are
|
|
9366
9394
|
independent handles.
|
|
9367
9395
|
|
|
9368
|
-
Platforms:
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
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
|
|
9372
9402
|
compute shaders, so `peakDetect` is accepted but has no effect; output
|
|
9373
9403
|
is always SDR.
|
|
9374
9404
|
|
|
9375
9405
|
GPU renderer options (tone mapping, peak detection, shaders,
|
|
9376
|
-
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);
|
|
9377
9408
|
under software rendering the handle is `failed` with `unsupported` after
|
|
9378
9409
|
the player's first answer to `render()` (reported to `onError` too), and so is
|
|
9379
9410
|
every `set`. Single owner, like VideoView. `set` never throws; the
|
|
9380
|
-
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).
|
|
9381
9413
|
|
|
9382
9414
|
- @capability processing.video, playback.read and events (like VideoFilter)
|
|
9383
9415
|
|
|
@@ -9395,7 +9427,9 @@ interface RenderOptions extends Disposable {
|
|
|
9395
9427
|
* ```
|
|
9396
9428
|
*/
|
|
9397
9429
|
set(value: Partial<RenderSettings>): void;
|
|
9398
|
-
/**
|
|
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
|
+
*/
|
|
9399
9433
|
readonly status: FilterStatus;
|
|
9400
9434
|
/**
|
|
9401
9435
|
* The status changed (including later pushes such as shader compile errors).
|
|
@@ -9421,7 +9455,8 @@ On a GPU-rendering player HDR video is tone-mapped with BT.2390 for a
|
|
|
9421
9455
|
250-nit display; under software rendering the plugin hides its HDR menu.
|
|
9422
9456
|
`set` merges the values into the plugin's render options and the
|
|
9423
9457
|
player reports the result through `onStatus`: `failed` with
|
|
9424
|
-
`unsupported` means the player renders in software (
|
|
9458
|
+
`unsupported` means the player renders in software (Linux, or Windows
|
|
9459
|
+
while GPU rendering is off).
|
|
9425
9460
|
```ts
|
|
9426
9461
|
const render = plugin.video.render();
|
|
9427
9462
|
render.onStatus((s) => {
|
|
@@ -9430,6 +9465,127 @@ render.onStatus((s) => {
|
|
|
9430
9465
|
render.set({ toneMapping: "bt.2390", targetPeak: 250 }); // nits
|
|
9431
9466
|
```
|
|
9432
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
|
+
|
|
9433
9589
|
### UpscalingReasonCode
|
|
9434
9590
|
|
|
9435
9591
|
Why the GPU's video upscaler does not work, as a stable kebab-case code.
|
|
@@ -11849,10 +12005,10 @@ RenderingReason.message for the rest. The codes of player 0.5.13:
|
|
|
11849
12005
|
|
|
11850
12006
|
| Code | Meaning |
|
|
11851
12007
|
| --- | --- |
|
|
11852
|
-
| `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). |
|
|
11853
12009
|
| `pending` | GPU rendering is starting. |
|
|
11854
12010
|
| `headless` | The player runs without a user interface. |
|
|
11855
|
-
| `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`). |
|
|
11856
12012
|
| `env` | The environment chose it (`VESTRA_RENDER`, `VESTRA_SOFTWARE_RENDER`). |
|
|
11857
12013
|
| `preference` | The user chose software rendering (Rendering.setPreference); GPU chosen and available reports `default`. |
|
|
11858
12014
|
| `denylist` | The graphics driver is on the player's denylist. |
|
|
@@ -12217,6 +12373,28 @@ type VideoNode =
|
|
|
12217
12373
|
kind: "frameBlend";
|
|
12218
12374
|
/** Output frame rate, integer 24–120. */
|
|
12219
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";
|
|
12220
12398
|
};
|
|
12221
12399
|
```
|
|
12222
12400
|
|
|
@@ -12238,6 +12416,27 @@ const chain: VideoNode[] = [
|
|
|
12238
12416
|
plugin.video.filter("picture").set(chain);
|
|
12239
12417
|
```
|
|
12240
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
|
+
|
|
12241
12440
|
### AudioNode
|
|
12242
12441
|
|
|
12243
12442
|
One node of an AudioFilter chain, by `kind`. Values outside the
|
|
@@ -13394,6 +13593,39 @@ class TestHost implements Transport {
|
|
|
13394
13593
|
* ```
|
|
13395
13594
|
*/
|
|
13396
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;
|
|
13397
13629
|
/**
|
|
13398
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.
|
|
13399
13631
|
* @example Check the filter chain the plugin applied
|
|
@@ -13655,9 +13887,9 @@ class TestHost implements Transport {
|
|
|
13655
13887
|
* import activate from "../main.ts";
|
|
13656
13888
|
*
|
|
13657
13889
|
* const host = new TestHost();
|
|
13658
|
-
* host.videoRender.gpu = false; // software draws now (
|
|
13890
|
+
* host.videoRender.gpu = false; // software draws now (Linux)
|
|
13659
13891
|
* host.rendering.startedWith = "software";
|
|
13660
|
-
* 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" };
|
|
13661
13893
|
* host.rendering.gpu = { available: false, reason: host.rendering.reason };
|
|
13662
13894
|
* const { stop } = await startPlugin(activate, {
|
|
13663
13895
|
* directory: new URL("..", import.meta.url),
|
|
@@ -13665,7 +13897,7 @@ class TestHost implements Transport {
|
|
|
13665
13897
|
* });
|
|
13666
13898
|
* const item = host.command("gpu-rendering");
|
|
13667
13899
|
* assert.equal(item.state.enabled, false);
|
|
13668
|
-
* assert.equal(item.state.reason, "
|
|
13900
|
+
* assert.equal(item.state.reason, "this player has no GPU renderer on Linux yet");
|
|
13669
13901
|
* await stop();
|
|
13670
13902
|
* ```
|
|
13671
13903
|
*/
|
|
@@ -15100,6 +15332,49 @@ const IMAGE_LIMITS: Readonly<{
|
|
|
15100
15332
|
}>;
|
|
15101
15333
|
```
|
|
15102
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
|
+
|
|
15103
15378
|
### HostError
|
|
15104
15379
|
|
|
15105
15380
|
A definite refusal from the player (or the plugin runner), with a stable
|
|
@@ -15359,7 +15634,7 @@ What Player.stats reports. Every field is the backend's own value
|
|
|
15359
15634
|
```ts
|
|
15360
15635
|
interface PlaybackStats {
|
|
15361
15636
|
/**
|
|
15362
|
-
* 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).
|
|
15363
15638
|
*/
|
|
15364
15639
|
backend: string;
|
|
15365
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: L2646–
|
|
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: L2087–2275; TestHost:
|
|
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,7 +108,7 @@ 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
|
|
|
@@ -117,30 +117,30 @@ export default async function activate(plugin: Plugin) {
|
|
|
117
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
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
119
|
- Guidelines: Interface guidelines L2441–2548; Menu guidelines L2549–2645
|
|
120
|
-
- Reference: Manifest L2646–
|
|
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):
|
|
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
|
|