Files
hms-mediaengine/_entwicklung/docs/plugin-sdk/manifest-reference.md
T

260 lines
8.6 KiB
Markdown
Raw Normal View History

# `plugin.json` Manifest-Referenz
Dieses Dokument beschreibt alle Felder des Plugin-Manifests `plugin.json`. Grundlage sind das JSON-Schema `schemas/plugin/plugin_manifest_v1.schema.json` und der Validator `packages/plugin_sdk/hms_plugin_sdk/manifest.py` (PLAN.md §14.214.3).
## Schema-Version und API-Version
| Feld | Typ | Pflicht | Wert |
| --- | --- | --- | --- |
| `schema_version` | integer | ja | `1` (konstant) |
| `api_version` | integer | ja | `1` (konstant) |
`schema_version` und `api_version` müssen exakt `1` sein. Der Validator lehnt jede andere Version ab (`manifest.py`).
## Pflichtfelder
Das Schema verlangt folgende Felder auf oberster Ebene:
```json
["schema_version", "id", "name", "version", "api_version", "kind", "vendor", "entrypoints", "capabilities", "failure_mode"]
```
### `id`
- **Typ:** string
- **Pflicht:** ja
- **Regeln:** Reverse-DNS-Notation, mindestens 5 Zeichen, mindestens zwei durch `.` getrennte Teile, nur Kleinbuchstaben `az`, Ziffern `09`, `.`, `_`, `-`. Kein `..` erlaubt.
- **Beispiel:** `com.hms.fx.vignette`
### `name`
- **Typ:** string, minLength 1
- **Pflicht:** ja
- **Beispiel:** `Vignette`
### `version`
- **Typ:** string
- **Pflicht:** ja
- **Regeln:** Semantische Version `X.Y.Z` (genau drei durch `.` getrennte Ganzzahlen).
- **Beispiel:** `1.0.0`
### `kind`
- **Typ:** enum
- **Pflicht:** ja
- **Werte:** `source`, `generator`, `filter`, `transition`, `mixer`, `output`, `control`, `automation` (PLAN.md §14.1)
- **Beispiel:** `filter`
### `vendor`
- **Typ:** string, minLength 1
- **Pflicht:** ja
- **Beispiel:** `HMS`
### `entrypoints`
- **Typ:** object, minProperties 1
- **Pflicht:** ja
- **Beschreibung:** Backend-Entrypoints mit Shader-Pässen. Erlaubte Backend-Schlüssel: `d3d11`, `gl`, `gles`.
Jeder Entrypoint ist ein Objekt mit:
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `type` | string | ja | Entrypoint-Typ, z. B. `hlsl`, `glsl`, `glsl_es`, `hlsl_multipass`, `glsl_multipass`, `glsl_es_multipass` |
| `passes` | array, minItems 1 | ja | Liste der Shader-Pässe |
Jeder Pass ist ein Objekt mit genau einem Shader-Pfad:
- **D3D11:** `pixel_shader` (z. B. `shaders/d3d11/main.hlsl`)
- **GL/GLES:** `fragment` (z. B. `shaders/gl/main.frag`)
**Beispiel (Einpass, Vignette):**
```json
"entrypoints": {
"d3d11": {
"type": "hlsl",
"passes": [{"pixel_shader": "shaders/d3d11/main.hlsl"}]
},
"gl": {
"type": "glsl",
"passes": [{"fragment": "shaders/gl/main.frag"}]
},
"gles": {
"type": "glsl_es",
"passes": [{"fragment": "shaders/gles/main.frag"}]
}
}
```
**Beispiel (Multipass, Gaussian Blur, PLAN.md §14.3):**
```json
"entrypoints": {
"d3d11": {
"type": "hlsl_multipass",
"passes": [
{"pixel_shader": "shaders/d3d11/horizontal.hlsl"},
{"pixel_shader": "shaders/d3d11/vertical.hlsl"}
]
},
"gl": {
"type": "glsl_multipass",
"passes": [
{"fragment": "shaders/gl/horizontal.frag"},
{"fragment": "shaders/gl/vertical.frag"}
]
},
"gles": {
"type": "glsl_es_multipass",
"passes": [
{"fragment": "shaders/gles/horizontal.frag"},
{"fragment": "shaders/gles/vertical.frag"}
]
}
}
```
Der Validator prüft, dass jeder deklarierte Shader-Pfad relativ und sicher ist (kein absoluter Pfad, kein `..`) und wenn ein Plugin-Root übergeben wird tatsächlich existiert (`manifest.py`).
### `capabilities`
- **Typ:** object
- **Pflicht:** ja
- **Pflichtfelder:** `minimum_tier`, `supported_backends`
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `minimum_tier` | enum | ja | `DESKTOP_FULL`, `DESKTOP_LITE`, `PI_LITE`, `HEADLESS_CONTROL` |
| `requires_input_texture` | boolean | nein | `true`, wenn der Effekt eine Eingangs-Textur braucht (Filter) |
| `supported_backends` | array, minItems 1 | ja | `d3d11`, `gl`, `gles` |
**Beispiel (Vignette):**
```json
"capabilities": {
"minimum_tier": "PI_LITE",
"requires_input_texture": true,
"supported_backends": ["d3d11", "gl", "gles"]
}
```
### `failure_mode`
- **Typ:** enum
- **Pflicht:** ja
- **Werte:** `bypass`, `hold`, `black`
- **Beschreibung:** Verhalten bei einem Pluginfehler. `bypass` überbrückt den Effekt (PLAN.md §3.5, §14.5).
- **Beispiel:** `bypass`
## Optionale Felder
### `parameters`
- **Typ:** array
- **Pflicht:** nein (im Schema), aber empfohlen
- **Beschreibung:** Liste der Plugin-Parameter. Details siehe [parameters-and-dmx.md](parameters-and-dmx.md).
Jeder Parameter ist ein Objekt mit:
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `id` | string, minLength 1 | ja | Eindeutige Parameter-ID |
| `label` | string, minLength 1 | ja | Anzeigename |
| `type` | enum | ja | `float`, `int`, `enum`, `bool`, `color` |
| `default` | beliebig | ja | Standardwert |
| `minimum` | number | nein | Untergrenze (für `float`/`int`) |
| `maximum` | number | nein | Obergrenze (für `float`/`int`) |
| `values` | array | nein | Werte für `enum` |
| `dmx_slots` | array, maxItems 8 | nein | DMX-Slot-Belegung (18) |
| `curve` | string | nein | Kurvenform, z. B. `quadratic` |
**Beispiel (Vignette):**
```json
"parameters": [
{"id": "amount", "label": "Amount", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [1]},
{"id": "radius", "label": "Radius", "type": "float", "minimum": 0, "maximum": 2, "default": 0.5, "dmx_slots": [2]},
{"id": "softness", "label": "Softness", "type": "float", "minimum": 0, "maximum": 1, "default": 0.4, "dmx_slots": [3]},
{"id": "roundness", "label": "Roundness", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [4]},
{"id": "center_x", "label": "Center X", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [5]},
{"id": "center_y", "label": "Center Y", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [6]},
{"id": "color", "label": "Color", "type": "color", "default": [0, 0, 0], "dmx_slots": [7]},
{"id": "invert", "label": "Invert", "type": "bool", "default": 0, "dmx_slots": [8]},
{"id": "mix", "label": "Mix", "type": "float", "minimum": 0, "maximum": 1, "default": 1, "dmx_slots": []}
]
```
**Validator-Regeln für Parameter (`manifest.py`):**
- `id` muss vorhanden und ein String sein; doppelte IDs sind Fehler.
- `type` muss einer von `float`, `int`, `enum`, `bool`, `color` sein.
- Für `float` müssen `minimum`, `maximum` und `default` vorhanden sein.
- `dmx_slots` muss eine Liste von Ganzzahlen sein.
- Die Summe aller `dmx_slots` über alle Parameter darf **8 nicht überschreiten** (PLAN.md §14.7).
### `adaptive_quality`
- **Typ:** object
- **Pflicht:** nein (im Schema), aber für qualitätsabhängige Effekte empfohlen
- **Pflichtfelder:** `default`, `variants`
- **Beschreibung:** Adaptive-Quality-Varianten. Details siehe [adaptive-quality.md](adaptive-quality.md).
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `default` | string | ja | Standard-Variante, z. B. `auto` |
| `variants` | array, minItems 1 | ja | Liste der Varianten |
| `transition_ms` | number, minimum 0 | nein | Übergangszeit in Millisekunden |
| `semantic_parameters_unchanged` | array of string | nein | Parameter, deren Semantik beim Wechsel unverändert bleibt |
Jede Variante ist ein Objekt mit:
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `id` | string | ja | Varianten-ID, z. B. `low`, `medium`, `high` |
| `internal_scale` | number, exclusiveMinimum 0, maximum 1 | nein | Interne Auflösungsskala |
| `samples` | integer, minimum 1 | nein | Sample-Anzahl |
**Beispiel (Vignette):**
```json
"adaptive_quality": {
"default": "auto",
"variants": [
{"id": "low", "internal_scale": 1.0, "samples": 1},
{"id": "medium", "internal_scale": 1.0, "samples": 1},
{"id": "high", "internal_scale": 1.0, "samples": 1}
],
"transition_ms": 180,
"semantic_parameters_unchanged": ["mix"]
}
```
## Validierung
Die Validierung (`manifest.py`) umfasst (PLAN.md §14.5):
- Manifest-Schema;
- eindeutige Plugin-ID und semantische Version;
- API-Kompatibilität;
- Pfad- und ZIP-Sicherheit;
- erlaubte Dateitypen und Größenlimits;
- Shader-Kompilierung;
- Capability-Prüfung;
- vollständige, vorab kompilierbare Adaptive-Quality-Varianten und unveränderte Parametersemantik;
- Lizenzmetadaten;
- Hash des Pakets.
## ZIP-Sicherheit (§27.2)
Beim Installieren als ZIP gelten zusätzlich (`manifest.py`):
- maximal 512 Dateien (`MAX_PLUGIN_FILES`);
- maximale entpackte Gesamtgröße 32 MiB (`MAX_TOTAL_UNPACKED`);
- maximale Dateigröße 8 MiB (`MAX_FILE_SIZE`);
- erlaubte Dateiendungen: `.json`, `.hlsl`, `.frag`, `.vert`, `.glsl`, `.png`, `.md`, `.txt`, `.toml`, `.csv`;
- keine absoluten Pfade, kein `..`;
- `plugin.json` muss an der Paketwurzel liegen.