Skip to content

Plugin Guide ​

The plugin system is modeled after mature plugin frameworks: a plugin is an npm package whose main exports apply(ctx, config); the framework calls it on load and injects routing, services, data models and an event bus via ctx.

Framework Mapping ​

Framework conceptOpenVideoAPI equivalent
ctx.plugin(plugin, config)same (nested plugins)
ctx.model.definectx.model.define (dynamic tables)
ctx.provide (services)same
inject (dependencies)openvideoPlugin.inject
ctx.on / ctx.emitsame (danmaku:send / ready / dispose / before:restart)
schemaopenvideoPlugin.schema
Console plugins (UI)client.admin.tabs + client.player
Marketplace / registryplugin-registry.json (versions + dependencies)
Plugin template / scaffoldingOpenVideoAPI-Dev npm run new
bash
git clone https://github.com/yangyang8002/OpenVideoAPI-Dev.git
cd OpenVideoAPI-Dev
npm run setup          # clone server + install deps
npm run dev            # dev server on port 1920 → http://localhost:1920/admin/
npm run new hello      # scaffold plugins/openvideo-plugin-hello/

Files under plugins/<pkg>/lib/ hot-reload automatically; data/plugin dirs are isolated from production. See Plugin Dev Env.

Plugin Structure ​

openvideo-plugin-hello/
├── package.json                 # npm manifest + openvideoPlugin declaration
└── lib/
    ├── index.js                 # apply(ctx, config) entry
    └── client/                  # optional frontend extensions
        ├── admin/panel.js
        └── player/hook.js
json
{
  "name": "openvideo-plugin-hello",
  "version": "1.0.0",
  "main": "lib/index.js",
  "openvideoPlugin": {
    "name": "hello",
    "description": "My first plugin",
    "inject": ["store", "model", "app", "logger", "http"],
    "provide": ["helloStats"],
    "schema": [ { "key": "greeting", "label": "Greeting", "type": "string", "default": "Hello" } ],
    "client": {
      "admin": { "scripts": ["lib/client/admin/panel.js"], "tabs": [{ "id": "hello", "title": "hello" }] },
      "player": { "scripts": ["lib/client/player/hook.js"], "replaces": false }
    }
  }
}

Entry Forms ​

js
// 1. function
module.exports = function (ctx, config) { ... };

// 2. class (constructor(ctx, config))
module.exports = class HelloPlugin { constructor(ctx, config) { ... } };

// 3. object with apply (recommended)
module.exports = { name: 'hello', version: '1.0.0', apply(ctx, config) { ... } };

Lifecycle ​

StageWhenNotes
Loadenable / server startapply(ctx, config) in topological order; hot reload unloads old instance first
Readyall enabled plugins loadedctx.on('ready', fn)
Run—routes / events / timers work; ctx.provide services available to others
Restartctx.app.restart()broadcasts ctx.on('before:restart', fn); new process waits for the port
Disposedisable / hot reload / uninstallctx.on('dispose', fn) cleanup; listeners & old routes removed automatically

In the Dev environment, editing any .js/.json under lib/ triggers automatic reload.

v2 Capabilities (26.10.0+) ​

Since 26.10 the plugin contract is at v2 (fully backward compatible): the manifest adds deps version constraints and hooks lifecycle hooks, and ctx gains static / pages / cron / settings / logs / i18n / bus / model.namespace. See Plugin Contract v2; the main-repo plugins/openvideo-plugin-demo 1.1.0 demonstrates every capability.

Next Steps ​

MIT License · Made with ♥ by yangyang8002