SDK пакетов · apiVersion 1

Свои виджеты и темы — без сборки приложения

OSE подхватывает пакеты из папки: виджет — это widget.json, JS-класс и CSS, тема — токены и CSS. SDK собирает рабочую заготовку, проверяет её теми же правилами, что загрузчик приложения, и даёт типы window.OSE для автодополнения.

  • Ничего не пересобирать — папка в данных пользователя
  • JavaScript и CSS, как на обычной веб-странице
  • Проверка манифеста до установки
npx ose-plugin create hello
npx ose-plugin check .

Быстрый старт

Нужен Node 18+. SDK лежит в npm (ose-plugin) — репозиторий клонировать не обязательно.

npx ose-plugin create hello                  # пакет виджета в ./hello
npx ose-plugin create plain --theme --name Plain
npx ose-plugin check .                       # проверка до установки
npx ose-plugin check config/plugins --json   # все пакеты, вывод для CI
npx ose-plugin pack hello                    # hello.zip для «Установить из ZIP»

В самом репозитории OSE те же действия без npm: node sdk/create.mjs, node sdk/validate.mjs и node sdk/pack.mjs.

  1. 1

    Создайте пакет

    Заготовка уже рабочая: манифест, класс виджета, стили и README с инструкцией. Дальше остаётся переписать содержимое под себя.

  2. 2

    Положите в каталог пакетов

    Разработка — config/plugins/<id>/; установленное приложение — %APPDATA%\com.openstreamenvironment.app\plugins\ (на других системах — каталог данных приложения). Можно и без ручной папки: соберите архив через ose-plugin pack и нажмите «Установить из ZIP» в «Настройки → Пакеты».

  3. 3

    Обновите страницу

    Перезапуск не нужен: манифесты перечитываются при загрузке страницы. Панель сама перезагрузится, когда вернёте ей фокус, а источник в OBS обновите вручную. Код и CSS сервер отдаёт с диска — правки видны сразу.

  4. 4

    Добавьте виджет из библиотеки

    Карточка появится в колонке виджетов; тема — в «Настройки → Оформление» с пометкой пакета.

Что внутри пакета

Один каталог — один пакет. Манифест выбирает тип: widget.json для виджета, theme.json для темы.

Виджет

Класс наследуется от OSE.BaseWidget: движок сам создаёт элемент, выставляет геометрию и зовёт render() при монтировании и изменении настроек.

widget.json · widget.js · widget.css · README.md

Тема

Токены --md-*, --font-* и --panel-* плюс необязательный CSS под своим data-theme. Тема применяется на оверлее, сценах и заставке.

theme.json · theme.css · README.md

Виджет

Схема настроек рисует инспектор сама, вручную верстать поля не нужно. В this.config приходят значения из настроек.

widget.json

{
  "apiVersion": 1,
  "kind": "widget",
  "id": "hello",
  "name": "Привет",
  "entry": "widget.js",
  "styles": ["widget.css"],
  "defaultGeometry": { "x": 40, "y": 42, "w": 20, "h": 10 },
  "settings": {
    "text": {
      "type": "string",
      "label": "Текст",
      "default": "Привет, эфир!"
    }
  }
}

widget.js

(function () {
  const OSE = window.OSE;
  if (!OSE) return;

  class HelloWidget extends OSE.BaseWidget {
    render() {
      if (!this.element) return;
      this.element.textContent =
        String(this.config.text || "Привет");
    }
  }

  OSE.defineWidget("hello", HelloWidget);
})();

Настройки

Инспектор понимает семь типов полей; значение по умолчанию берётся из default, а у select должно быть одним из options — иначе приложение молча возьмёт первый вариант.

  • string — однострочный текст;
  • text — многострочный текст;
  • number — число;
  • range — ползунок с min, max и step;
  • color — цвет;
  • boolean — переключатель;
  • select — список вариантов { "value", "label" }.

Жизненный цикл и события

Движок сам снимает подписки и таймеры при удалении виджета. События — те же кадры, что летят в оверлей: ALERT, CHAT_MESSAGE, RECENT_EVENT, GOAL_UPDATE, STAT_UPDATE, SESSION_STATS, THEME_UPDATE.

onMount() {
  this.subscribe(OSE.EVENT_TYPES.ALERT, (alert) => {
    this.element.textContent = `${alert.kind}: ${alert.user}`;
  });
  this.every(() => this.render(), 1000);
}

Кроме того, доступны this.geometry, this.element, this.canvas и this.ctx, this.startRenderLoop(fps), this.context.readCssVar("--md-primary") и OSE.asset(id, файл) для файлов пакета.

Тема

Тема появляется в списке как plugin:<id>. Править её из панели нельзя — источник правды в пакете.

theme.json

{
  "apiVersion": 1,
  "kind": "theme",
  "id": "plain",
  "name": "Plain",
  "tokens": {
    "--md-primary": "#7aa2f7",
    "--md-surface": "#0b1020",
    "--md-on-surface": "#e6edf7"
  },
  "css": "theme.css"
}

theme.css

Правила пишите под своим data-theme, иначе они протекут в другие темы и в панель управления.

[data-theme="plugin:plain"] .widget-instance {
  border-radius: 4px;
}

Шрифт попадает в эфир, поэтому берите только свободные лицензии, разрешающие коммерческое использование (SIL OFL и подобные), и кладите текст лицензии рядом с файлом.

Проверка и типы

Ошибку в манифесте лучше увидеть в терминале, чем после перезапуска приложения с пустой карточкой.

ose-plugin check повторяет правила загрузчика: id совпадает с именем папки, entry и styles существуют и не выходят за пакет, у настроек известные типы, у темы есть токены с --. Предупреждения (например, default не из options) установку не блокируют, но обычно это опечатка.

npx ose-plugin check .
npx ose-plugin check config/plugins
npx ose-plugin check . --json   # для скриптов и CI

В пакете SDK есть index.d.ts — глобальные типы window.OSE, BaseWidget и событий. Добавьте в начало своего JS:

/// <reference path="node_modules/ose-plugin/index.d.ts" />
// @ts-check

Редактор начнёт подсказывать this.config, хуки и нагрузку событий. Манифесты описаны и JSON-схемами в sdk/schema/ — при добавлении ссылки $schema редактор проверит и widget.json.