0. Краткое введение
Что это за редактор?
Редактор Event Flow — слой расширенной автоматизации Social Stream Ninja. Он дополняет простые переключатели popup и позволяет задать собственную логику маршрутизации. Используйте его, когда нужно:
- Передавайте чат между сервисами с фильтрами: например, из Twitch в Discord, исключая команды.
- Создавайте команды на основе лояльности, игры с ключевыми словами и допуск к розыгрышам с логикой AND/OR/NOT.
- Запускайте пользовательские оверлеи, аудио, сцены OBS или webhooks на основе данных, дополненных в потоке.
- Объединяйте несколько платформ в одной автоматизации: Kick, Twitch и YouTube через один поток.
Popup предлагает быстрые предустановки, а Event Flow — набор инструментов для собственных сценариев.
Запуск и основы
- Откройте редактор Event Flow из меню основной панели в приложении или расширении.
- Каждый проект хранится локально до экспорта. Используйте
Exportдля резервного копирования или обмена. - Работайте на рабочих полях, называемых потоками. Каждый поток может подписываться на несколько платформ одновременно.
Обзор узлов
- Входы (левые разъёмы) ожидают контекст сообщения.
- Выходы (правые разъёмы) выдают тот же контекст с внесёнными изменениями.
- Логические узлы могут передавать сигналы как в канал
trueтак и в необязательный каналfalse.
Структура payload
Каждое сообщение содержит объект JSON. Обязательные ключи соответствуют docs/event-reference.html (platform, type, chatname, chatmessage и т. д.). Добавляйте собственные данные в meta.
Каждый поток начинается с триггера
Узлы действий (зелёные) никогда не запускаются сами: они срабатывают, только когда расположенный выше узел триггера (синий) возвращает true. Поток из одних последовательно соединённых действий выглядит корректно, но всегда бездействует: ничто не запускает цепочку. Имена узлов описывают, что узел делает, а не когда это происходит: Выделить сообщение выделяет сообщение, когда поток доходит до него, а не срабатывает при выделении сообщения в другом месте.
Оверлей Flow Actions (вывод действий)
Выберите Пожертвование: празднование + голос для готовой анимации и синтетического клипа благодарности либо расширенный Пожертвование: анимация + звук + фильтр OBS шаблон. Новые шаблоны оповещений изначально выключены, чтобы вы сначала настроили и проверили их. Для шаблона OBS выберите источник и один и тот же обычно выключенный фильтр в обоих действиях фильтра.
Воспроизвести аудиоклип и Multi-Alerts теперь используют общую библиотеку из 17 звуков: аплодисменты, барабанная дробь, свист, кассовый аппарат и другие эффекты, четыре подписанные синтетические английские фразы и простые звуки. Слушать / Остановить воспроизводит локально с видимым статусом. Можно также загрузить запись или выбрать локальный файл приложения. Для меняющихся имён и сообщений используйте существующее Озвучить текст действие.
Event Flow воспроизводит звук через источник браузера Flow Actions ; Multi-Alerts воспроизводит через свой источник. Включайте звук только в одном для одного события, чтобы избежать дублирования. Перейдите к узлу клавишей Tab и нажмите Enter или пробел для редактирования свойств.
Таким узлам, как Воспроизвести аудиоклип, Показать медиаоверлей, и управлению OBS нужна страница для выполнения и отображения. Этой страницей служит оверлей Flow Actions, доступный по адресу actions.html. Держите её открытой в программе вещания (OBS, браузерных док-панелях Streamer.bot и т. п.), чтобы действиям Event Flow было где отображаться.
- Откройте основной popup Social Stream Ninja (окно, загруженное из popup.html или значка расширения).
- Прокрутите до карточки Flow Actions. Используйте кнопку [скопировать ссылку] или нажмите URL в карточке.
- Ссылка выглядит как
https://socialstream.ninja/actions.html?session=YOURSESSION. Вставьте ссылку в источник браузера OBS (рекомендуется 1920×1080) либо откройте в любом браузере для оверлеев.
- В действии воспроизведения аудиоклипа или отображения медиаоверлея нажмите Выбрать локальный файл.
- Нажмите Скопировать локальный URL Flow Actions для OBS и используйте созданный localhost URL вместо размещённого URL Flow Actions.
- Держите SSApp запущенным. Если выбранный файл перемещён, вернитесь к действию и нажмите Указать файл заново.
Расширение Chrome не может само предоставлять файлы с диска. Если нет настольного вспомогательного приложения, используйте загрузку или размещённый URL. См. руководство по медиафайлам для Event Flow для полной настройки.
После загрузки этот оверлей может:
- Показывать GIPHY или прямые URL медиа, текст и конфетти, запускаемые потоками.
- Воспроизводить звуки — TTS и аудиоклипы — локально, чтобы зрители их слышали.
- Управляйте OBS через настройки WebSocket в разделе Flow Actions popup: смена сцен, переключение источников, обновление текста GDI+/FreeType, буфер повтора и т. д.
- API источника браузера: доступно только когда
actions.htmlзапущен внутри источника браузера OBS с включённым режимом Расширенный уровень доступа. Здесь работает смена сцен; действия записи, трансляции и буфера повтора могут использовать этот запасной путь. - OBS WebSocket: рекомендуется для стабильного управления. Flow Actions Social Stream Ninja использует API OBS WebSocket v5 из OBS 28+ и ожидает современный набор запросов на порту
4455. - Пароль: необязательно. Добавляйте только
&obspw=...к URL Flow Actions, если сервер OBS настроен на обязательную авторизацию. - Диагностика оверлея: добавьте
&obsdebug=1к URL страницыactions.htmlесли при устранении неполадок нужен небольшой индикатор подключения OBS на оверлее. - Задать текст источника: напрямую обновляет входы «Текст (GDI+)» и «Текст (FreeType 2)» OBS и поддерживает переменные шаблонов Event Flow, например
{counterValue}и{counterTarget}. - Старые установки 4.x: если вы всё ещё используете obs-websocket 4.x / порт
4444, действия с источниками, фильтрами, отключением звука и текстом не заработают до обновления OBS / obs-websocket.
См. отдельное Руководство по управлению OBS для всех триггеров, действий, шагов настройки и проверенных примеров.
- Открыть obs-websocket-test.html.
- Убедитесь, что
GetVersion,GetCurrentProgramScene, иGetSceneListвыполняются успешно. - Сначала выполните там проверку нужного действия, затем тестируйте всю автоматизацию Event Flow.
1. Что проходит через узел?
Среда Event Flow передаёт по каждой связи две вещи:
- Payload – объект данных события или сообщения.
- Сигнал шлюза – это true/false бит, сообщающий следующему узлу, нужно ли выполняться.
false разъём узла условия). Это позволяет создать запасную логику без дублирования целых потоков.
Ожидания от входа
- Источники событий (сообщение Twitch, таймеры, ручной триггер и т. п.) игнорируют вход сверху: они создают собственный payload и всегда выдают
trueесли только сам узел не выдаёт ошибку. - Узлы преобразования и логики читают payload и могут менять поля, задавать состояние или менять сигнал шлюза на
false. - Узлы действий срабатывают, только пока шлюз остаётся
true. При необходимости они также могут выдать обновлённый payload для продолжения цепочки действий.
Варианты выхода
Один выход
У большинства узлов один выход. Входящий payload и сигнал шлюза выходят без изменений, если узел их не редактирует.
Выходы true/false
Узлы условий, сравнения, регулярных выражений и логики имеют два выхода. Истина продолжает путь через зелёный выход; false становится доступным на сером/красном выходе.
Передача без изменений и переопределение
Некоторые узлы — задание переменной, математика, замена текста — меняют payload, но всё равно передают true/false состояние входа. Другие узлы, например NOT, AND, OR, сами пересчитывают логическое значение.
2. Краткая справка по логическим узлам
Эти блоки отвечают на частые вопросы о значениях true/false.
NOT (НЕ)
- Входы: 1 логическое значение true/false из предыдущего узла.
- Выходы: инвертированное логическое значение и неизменённый payload.
- Поведение по умолчанию: Если ко входу NOT ничего не подключено, он вычисляется как
false, поэтому выход равенtrue.
AND (И)
- Входы: два или более логических сигнала (A, B, ...). Лишние порты можно оставить пустыми.
- Выходы:
trueтолько если все подключённые входы равныtrue. - Используйте AND, когда несколько условий должны выполняться одновременно («подписчик» и «сообщение чата содержит !raffle»).
OR
- Отправляет
trueесли любой подключённый вход равен true. - Удобно для триггеров разных платформ: соедините узлы сообщений Twitch и YouTube с одним OR, затем используйте общее действие.
Нет. Во многих узлах уже есть комбинированные фильтры, например «Уровень пользователя» и «Содержит текст». Используйте AND, если встроенные параметры не покрывают нужное сочетание или нужен общий логический узел для нескольких веток.
true. Подключите его к значимому условию или отключите узел, чтобы случайно не разрешить выполнение потока.
3. Примеры небольших потоков
A. Автоответ, если сообщение не является командой
Здесь узел регулярного выражения выдаёт true когда сообщение является командой. Мы направляем false выход к ответу, поэтому обычные участники получают подтверждение, а команды проходят дальше.
B. Несколько обязательных проверок через AND
Узел AND гарантирует, что в Discord попадут только участники с правильным ключевым словом. Обе ветки отправляют свой логический результат в AND; payload из первой ветки передаётся дальше.
C. Узел NOT для блокировки повторных оповещений
State Check выдаёт значение true когда оповещение отключено. Инвертируя результат, NOT гарантирует, что празднование запускается только при значении флага false.
D. Случайное воспроизведение одного из двух звуков
Узел AND обязателен. Одинокий NOT выдавал бы true каждый раз, когда RANDOM бездействует, поэтому звук B звучал бы на каждом сообщении, которое не соответствует триггеру. Подключение триггера вторым входом AND ограничивает звук B только подходящими сообщениями. Такой подход работает с любой парой альтернативных действий, не только со звуком.
4. Защита от эха, циклов и обратной ретрансляции
Ретрансляция чата между средами полезна, но может создать бесконечное эхо, если захватывать собственный вывод. Соблюдайте следующие меры:
Триггеры входящих сообщений и получатели исходящих сообщений Relay Chat различают
youtube и youtubeshorts. Используйте два действия ретрансляции, если сообщение должно попасть в оба варианта. См. YouTube Shorts и Event Flow.
Отражение — исходящее сообщение, повторно захваченное из целевого чата. Текущие действия ретрансляции чата пропускают распознанные отражения; отдельной опции No Reflections нет. Чтобы скрыть или ограничить их показ в док-панели и оверлеях, используйте Reflection Filter («Фильтр отражений») действие с Block All («Блокировать все»), Allow First («Разрешить первое»), или Allow All («Разрешить все»). Это управляет показом при повторном захвате, а не отправкой. Следуйте пошаговой инструкции по настройке ретрансляции Twitch и YouTube для полной настройки.
- Избегайте дублирования систем ретрансляции. Отключите глобальную ретрансляцию всех сообщений при использовании аналогичных маршрутов Event Flow и проверьте другие сервисы, связывающие те же чаты. Пользовательские метаданные не гарантированно переживут передачу через чат платформы.
- Используйте узлы Debounce или Cooldown для оповещений не чаще одного раза в X секунд.
- Разрывайте циклы намеренно. Если две ветки подают данные друг другу, добавьте логический узел, проверяющий переменную состояния «currentlyRelaying», чтобы поток завершался раньше при установленном флаге.
5. Входы, выходы и практические вопросы
Что поступает в узел?
- Полный payload сообщения.
- Бит шлюза (
true/false). - Дополнительный контекст, например переменные состояния и таймеры, который узел явно запрашивает.
Что выходит из узла?
- Тот же payload, если узел его не меняет.
- Пересчитанный логический бит (логические узлы) или переданный без изменений бит (действия).
- Большинство побочных действий, например отправка чата, не меняют payload, но действия с баллами могут добавлять поля статуса, например
pointsTotalилиpointsSpendErrorдля последующей логики.
Когда делать ветвление?
Когда нужно по-разному реагировать на true и false. Протяните связь от нужного цветного выхода (зелёный = true, серый/красный = false) к следующему узлу.
false , поток просто заканчивается здесь. Это удобно для фильтров «блокировать всё, что не прошло проверку», но не забудьте подключить false путь, если нужны запасные варианты.
Частые вопросы и ответы
- Нужно ли ставить AND для каждой пары фильтров? Нет. Многие узлы включают несколько проверок: например, основной фильтр сообщений поддерживает ключевое слово и роль. AND нужен для сложных сочетаний или объединения сигналов разных узлов.
- Как значения true/false попадают в узел NOT? Любой узел с зелёным выходом выдаёт
trueпо умолчанию. Когда условие не выполнено, выдаётсяfalse. Подключите эту связь к NOT, чтобы инвертировать результат. - Может ли узел выдать payload, если возвращает false? Да. Payload всё равно передаётся через выход false; вы решаете, куда направить эту ветку.
- Как определить участников команды TikTok? Выберите Участник команды TikTok в узле роли пользователя. Он распознаёт уровни и значки фан-клуба/команды TikTok во входящем сообщении и не зависит от настроек основного оверлея чата.
- Может ли каждый узел озвучивания использовать отдельный голос? Да. Введите поддерживаемое провайдером имя или ID голоса в Переопределение голоса, либо оставьте поле пустым, чтобы использовать голос TTS по умолчанию в Flow Actions.
6. Справочник переменных шаблонов
Несколько действий — показ текста, задание текста источника, отправка и ретрансляция сообщений, озвучивание, вызов webhook и печать термоэтикетки — поддерживают переменные шаблонов которые заменяются данными события во время выполнения. Заключайте имена переменных в фигурные скобки, например {username}.
Основные переменные (обратная совместимость)
| Переменная | Псевдоним | Описание | Пример |
|---|---|---|---|
{username} | {chatname} | Отображаемое имя пользователя | CoolViewer123 |
{message} | {chatmessage} | Текст сообщения чата | Всем привет! |
{source} | - | Имя платформы с заглавной буквы | Twitch, YouTube |
{type} | - | Исходное имя платформы | twitch, youtube |
{donation} | {hasDonation} | Строка отображения пожертвования/чаевых | $5.00, 500 bits |
Дополнительные переменные
| Переменная | Описание | Пример |
|---|---|---|
{displayname} | Отображаемое имя (альтернативное поле) | CoolViewer123 |
{donoValue} | Эквивалент пожертвования в USD, предоставленный или рассчитанный; Event Flow получает пороговые значения из нормализованных строк hasDonation вида: значение, $значение, значение + единица или компактная запись единицы/значения. Для неизвестных именованных виртуальных единиц применяется 100 единиц = $0.01 USD; подарки TikTok без цены считаются как одна монета за подарок ($0.01 каждый). {donationAmount} — устаревший псевдоним | 5.00 |
{event} | Идентификатор типа события | cheer, raid, new_follower |
{membership} | Статус участия | MEMBERSHIP, new_sponsor |
{subtitle} | Дополнительный контекст | Участник 3 месяца |
{userid} | ID пользователя на платформе | 12345678 |
{chatimg} | URL аватара пользователя | https://... |
{contentimg} | URL вложенного изображения | https://... |
{rewardTitle} | Название награды, если источник предоставляет поле её заголовка на верхнем уровне | Выделить моё сообщение |
{meta} | Структурированные данные события (JSON) | {"viewers":100} |
{counterValue} | Текущее значение после шага счётчика или его проверки | 12 |
{counterTarget} | Целевое значение счётчика | 30 |
{counterRemaining} | Цель счётчика минус текущее значение, не ниже 0 | 18 |
{USERNAME}, {Username}, и {username} работают одинаково.
Check Counter предоставляет {counterValue}, {counterTarget}, и {counterRemaining}.
Примеры шаблонов
- Показать текст:
{username} just cheered {hasDonation}! - Задать текстовый источник OBS:
{username}: now {counterValue}, need {counterTarget} - Ретрансляция чата:
[{source}] {username}: {message} - TTS:
{username} says {message} - Оповещение о пожертвовании:
{username} donated {donation} - {subtitle} - Термоэтикетка:
{username}, новую строку, затем{donation}. См. Руководство по термопринтеру для настройки принтера, этикеток фиксированного размера и полного потока. - Вызов webhook Discord:
{"content":"{message}","username":"{username}","avatar_url":"{chatimg}"}
{donation} в обычном сообщении чата), вместо буквального текста {donation} подставляется пустая строка.
7. Рекомендации по работе
- Назовите и раскрасьте узлы, чтобы в будущем было понятно назначение каждой ветки.
- Тестируйте встроенным симулятором («Отправить тестовое событие») перед запуском потока в эфире.
- Группируйте логику рядом с источником. Фильтруйте как можно раньше, чтобы избежать лишней обработки дальше по цепочке.
- Храните повторы в узлах состояния. Используйте счётчики, переключатели и отметки времени, чтобы избежать двойных оповещений.
- Документируйте поля meta. Когда добавляете пользовательские
metaключи, описывайте их, чтобы оверлеи и удалённые клиенты оставались согласованными.
8. Дополнительные возможности
Запускайте пользовательские потоки из Stream Deck или API: именованные триггеры, начальный шаблон, поиск потоков, дополнительные данные, примеры HTTP/WebSocket/P2P и жесты поворотных регуляторов.
Хотите узнать больше?
- Используйте Узлы состояния (счётчики, переключатели, таймеры) для сохранения контекста между событиями.
- Объедините Переменные + логика для создания очередей, розыгрышей или систем подсчёта очков.
- Подключитесь к системе Баллы и награды , чтобы зрители могли намеренно запускать потоки.
- Используете настольное приложение SSApp? Разблокировать Узлы пользовательского JavaScript для произвольной логики, не покрываемой встроенными узлами.
- Проверьте Справочник событий для подробной документации payload всех платформ.
Руководство намеренно автономно: скопируйте его локально, адаптируйте для команды и продолжайте экспериментировать в редакторе.
9. Пользовательский JavaScript Только SSApp / настольное приложение
Два узла редактора Event Flow позволяют писать произвольный JavaScript, выполняемый в цепочке потока: Пользовательский код (триггер) и Выполнить пользовательский код (действие). Это способ реализовать всё, что нельзя выразить встроенными узлами.
new Function() / eval(). Откройте редактор через Настольное приложение SSApp для их включения. В режиме расширения узлы недоступны и помечены «Только настольное приложение».
Ctrl+S или Cmd+S делает то же самое. Отмена оставляет узел без изменений.
Пользовательский код — узел триггера
Перетащите Пользовательский код из группы Дополнительно на панели Триггеры на рабочее поле. Он действует как шлюз: поток продолжается, только если ваш код возвращает true.
true или false.function(message) { ... }Должен возвращать: логическое значение —
true чтобы поток продолжился, false для его остановки.Доступно: объект
message (см. API сообщений ниже), а также convertCurrency(value, targetCurrency, source) и convertToUSD(value, source).
Выполнить пользовательский код — узел действия
Перетащите Выполнить пользовательский код из группы Интеграции на панели Действия . Может изменить сообщение, заблокировать его или добавить метаданные для следующих узлов.
function(message, result) { ... }Должен возвращать: объект или Promise, объединяемый с
result— см. API результатов.Доступно:
message (payload события), result (текущее состояние результата потока), printThermal(html, options), а также convertCurrency(value, targetCurrency, source) и convertToUSD(value, source).
printThermal('<strong>' + message.chatname + '</strong>'). SSApp без диалогов ставит задание в очередь через нативный API печати Windows и использует сохранённые настройки. Поток может переопределить их параметрами, например { width: '58mm', marginLeft: '3mm', marginRight: '3mm', marginTop: '2mm', marginBottom: '2mm', feed: '3mm', marginType: 'printableArea' }. Возврат Promise позволяет Event Flow дождаться отправки и сообщить об ошибках.
Объект message
Оба узла получают полный payload события как message. Поля ниже доступны всегда; события отдельных платформ могут содержать дополнительные поля.
| Поле | Тип данных | Описание | Пример |
|---|---|---|---|
message.chatmessage | строка | Текст сообщения чата, может содержать HTML | "Hello stream!" |
message.chatname | строка | Отображаемое имя отправителя | "CoolViewer" |
message.userid | строка | ID пользователя на платформе | "12345678" |
message.type | строка | Платформа источника в нижнем регистре | "twitch", "youtube", "kick" |
message.hasDonation | строка | Форматированная строка пожертвования, если есть | "$5.00", "500 bits" |
message.donoValue | число / строка | Эквивалент пожертвования в USD, если его предоставляет источник; корректный ноль учитывается. Иначе Event Flow использует currency.js для пересчёта нормализованных строк hasDonation для сравнения с порогами, включая 100 неизвестных именованных единиц = $0.01 USD. Он не извлекает суммы пожертвований из обычного текста поля chatmessage . | 5 |
message.event | строка | Идентификатор типа события | "new_follower", "cheer", "raid" |
message.membership | строка | Статус участия, если применимо | "MEMBERSHIP" |
message.subtitle | строка | Дополнительная строка контекста | "Member for 3 months" |
message.mod | логическое значение | Отправитель — модератор | true |
message.subscriber | логическое значение | Отправитель — подписчик | true |
message.vip | логическое значение | У отправителя статус VIP | true |
message.chatimg | строка | URL аватара пользователя | "https://..." |
message.meta | объект | Произвольные структурированные данные события | { viewers: 120 } |
convertCurrency(message.hasDonation, 'EUR', message.type) для преобразования форматированной строки пожертвования в EUR. Возвращает число либо null если запрошенная целевая валюта не поддерживается. Конвертер использует приблизительные внутренние курсы Social Stream Ninja и не обращается к внешним обменным сервисам.
Что возвращает действие
Верните обычный объект из кода действия. Включённые поля объединяются с объектом result ; пропущенные поля сохраняют текущие значения.
| Поле возврата | Тип данных | Действие |
|---|---|---|
modified | логическое значение | Установите true если изменили message поля. Сообщает следующим узлам, что payload изменён. |
message | объект | Верните сообщение с возможными изменениями, чтобы следующие узлы получили их. |
blocked | логическое значение | Установите true чтобы сообщение не отображалось и не ретранслировалось. |
return { modified: false, message };Даже если вы ничего не изменили, возврат
message сохраняет передачу следующему узлу.
Примеры кода
Скопируйте любой пример в поле JavaScript Code соответствующего типа узла.
Примеры триггеров — возвращайте true для продолжения потока
!queue, !raffle, !enter).Примеры действий — возвращайте { modified, message }
{meta}).Полный пример: бот предложений новых функций для VIP
Этот поток ожидает !feature <text> от подписчиков, VIP или модераторов, переформатирует как предложение новой функции и передаёт другому получателю, например в Discord.
Шаг 1 — триггер пользовательского кода (вставьте в поле JavaScript Code триггера):
Шаг 2 — действие выполнения пользовательского кода (вставьте в поле JavaScript Code действия):
Шаг 3 — действие ретрансляции чата: добавьте обычный узел ретрансляции чата после действия и укажите Discord или другой получатель. Пользовательский код здесь не нужен — переформатированное message.chatmessage проходит автоматически.
!feature dark mode support, и убедитесь, что получатель ретрансляции чата получает переформатированную строку.
Вопросы безопасности
window и любым API, предоставленным скриптом preload (например, window.ninjafy). Считайте импортируемые файлы потоков исполняемым кодом: импортируйте только из доверенных источников.
- Нет сетевой песочницы. Код действия может вызвать
fetch(). Если вы получаете потоки от других людей, проверяйте JS перед активацией. - Ошибки перехватываются. Ошибка выполнения в вашем коде возвращает
false(триггер) или ничего не делает (действие) и записывает ошибку в консоль DevTools — поток не падает. - Ошибки синтаксиса тоже. Ошибка типа
SyntaxErrorна этапе компиляции перехватывается так же. Если узел ничего не делает, проверьте DevTools (F12).