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
Создайте пакет
Заготовка уже рабочая: манифест, класс виджета, стили и README с инструкцией. Дальше остаётся переписать содержимое под себя.
-
2
Положите в каталог пакетов
Разработка —
config/plugins/<id>/; установленное приложение —%APPDATA%\com.openstreamenvironment.app\plugins\(на других системах — каталог данных приложения). Можно и без ручной папки: соберите архив черезose-plugin packи нажмите «Установить из ZIP» в «Настройки → Пакеты». -
3
Обновите страницу
Перезапуск не нужен: манифесты перечитываются при загрузке страницы. Панель сама перезагрузится, когда вернёте ей фокус, а источник в OBS обновите вручную. Код и CSS сервер отдаёт с диска — правки видны сразу.
-
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.
Документация и примеры
- Руководство по SDK — команды, манифест, настройки, события и темы.
- Формат пакетов — контракт загрузчика и структура ответа
/api/plugins. - API приложения — локальный HTTP-сервер и шина WebSocket.
- Примеры — готовые виджеты
helloиlast-donation, темаplain-theme. - ose-plugin в npm — пакет SDK.
Есть идея виджета?
Начните с npx ose-plugin create и пришлите ссылку в issues репозитория. Код пакета исполняется в отдельной рамке-песочнице: у неё нет доступа к интерфейсу приложения и его данным. Сеть внутри рамки доступна, поэтому ставить стоит только доверенный код.