0. 快速入门
这个编辑器是什么?
Event Flow 编辑器是 Social Stream Ninja 的“高级自动化”层。它位于简单弹出窗口开关之上,让您编写自己的路由逻辑。在需要以下功能时使用它:
- 在服务之间筛选并转发聊天(例如将 Twitch 镜像到 Discord,但阻止命令)。
- 通过 AND/OR/NOT 逻辑构建基于忠诚度的命令、关键词游戏或抽奖资格限制。
- 根据在流程中补充的数据,触发自定义叠加层、音频、OBS 场景或 webhook。
- 在单个自动化中混合多个平台(Kick + Twitch + YouTube 通过一个流程路由)。
可以将弹出窗口视为“快速预设”,将 Event Flow 视为定制工作流的工具集。
启动和基础知识
- 从主仪表板菜单(桌面应用或扩展)打开 Event Flow 编辑器。
- 每个项目在导出前都保存在本地。使用
Export以备份或分享。 - 在称为以下名称的画布中工作: 流程。每个流程都可以同时订阅多个平台。
节点速览
- 输入 (左侧端口)接收消息上下文。
- 输出 (右侧端口)发出相同上下文以及所有编辑。
- 逻辑节点可能同时发出
true频道和可选的false频道。
载荷结构
每条消息都携带 JSON 对象。必需键遵循 docs/event-reference.html (platform、type、chatname、chatmessage 等)。将自定义数据附加到 meta.
每个流程都从触发器开始
操作节点(绿色)从不自行运行,只有上方的触发器节点(蓝色)求值为以下结果时才触发: true。仅将操作串联起来的流程看似有效,但会一直闲置,因为没有任何东西启动该链。节点名称描述的是节点 做什么,而不是它何时发生: 精选消息(Feature Message) 在流程到达它时精选消息,而不会在您于其他位置精选消息时触发。
Flow Actions 叠加层(操作输出)
选择 打赏:庆祝 + 语音 以使用现成的动画和合成感谢语音片段,或使用高级的 打赏:动画 + 声音 + OBS 滤镜 模板。新提醒模板初始为禁用状态,让您可以先配置并测试。对于 OBS 模板,在两个滤镜操作中选择同一个来源和同一个通常关闭的滤镜。
播放音频片段 和 Multi-Alerts 现在共享一个包含 17 种声音的音效库:掌声、击鼓、呼啸、收银机及其他效果,四个带标签的合成英语短语,以及简单声音。 试听 / 停止(Listen / Stop) 在本地预览并显示播放状态。您仍可以上传录音或选择应用本地文件。对于变化的姓名或消息,使用现有的 朗读文本(Speak Text) 操作。
Event Flow 通过以下页面播放: Flow Actions 浏览器源;Multi-Alerts 通过自己的浏览器源播放。对于同一事件,只在其中一个来源启用声音,以免重复播放。使用 Tab 移动到流程节点,按 Enter 或空格编辑其属性。
例如以下节点: 播放音频片段, 显示媒体叠加层,以及 OBS 控件都需要一个渲染界面。该界面就是由以下地址提供的 Flow Actions 叠加层页面: actions.html。让它在直播软件(OBS/Streamer.bot 浏览器停靠面板等)中保持运行,让 Event Flow 操作有地方显示。
- 打开 Social Stream Ninja 主弹出窗口(从以下位置加载的窗口: popup.html 或扩展图标)。
- 滚动到“Flow Actions”卡片。使用 [复制链接] 按钮,或点击卡片内的 URL。
- 链接类似于
https://socialstream.ninja/actions.html?session=YOURSESSION。将其粘贴到 OBS 浏览器源(建议 1920×1080),或在任意叠加层浏览器中打开。
- 在 Play Audio Clip 或 Display Media Overlay 操作中,点击 选择本地文件.
- 点击 复制用于 OBS 的本地 Flow Actions URL 并使用生成的 localhost URL 代替托管的 Flow Actions URL。
- 保持 SSApp 运行。如果所选文件移动了,请回到操作并点击 重新关联.
Chrome 扩展本身无法提供磁盘文件。没有桌面辅助应用时,请使用 Upload 或托管 URL。请参阅 Event Flow 媒体文件指南 了解完整设置。
加载后,该叠加层可以:
- 显示由流程触发的 GIPHY 或直接媒体 URL、文本和彩纸。
- 在本地播放声音(TTS、音频片段),让观众听到。
- 通过弹出窗口 Flow Actions 部分中的 WebSocket 设置与 OBS 通信(场景切换、来源开关、GDI+/FreeType 文本更新、回放缓冲区等)。
- 浏览器源 API: 仅在以下情况下可用:
actions.html在 OBS 浏览器源内运行,带有 高级访问级别(Advanced Access Level)。此处支持场景切换,录制 / 直播 / 回放缓冲区操作也可以将它用作回退方式。 - OBS WebSocket: 建议使用,以实现一致的控制。Social Stream Ninja Flow Actions 使用 OBS 28+ 的 OBS WebSocket v5 API,并要求端口上提供现代请求集:
4455. - 密码: 可选。仅在 OBS 服务器要求身份验证时,才将
&obspw=...添加到 Flow Actions URL。 - 叠加层诊断: 附加
&obsdebug=1到以下页面的 URL:actions.html如果希望在排查问题时,在叠加层上显示一个小型实时 OBS 连接徽章。 - 设置文本源(Set Text Source): 直接更新 OBS Text (GDI+) 和 Text (FreeType 2) 输入,并支持 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 运行时通过每条连线传递两种内容:
- 载荷 — 事件或消息数据对象。
- 门控信号 — 一个 true/false 位,告知下一个节点是否运行。
false 端口,位于 Condition 节点上)。这样就能轻松构建回退逻辑,无需复制整个流程。
输入要求
- 事件来源 (Twitch Message、Timers、Manual Trigger 等)忽略上游输入,它们生成自己的载荷,并始终发出
true除非节点本身出错。 - 转换和逻辑节点 读取载荷,并可重写字段、设置状态,或将门控信号翻转为
false. - 操作节点 仅在门控保持以下值时触发:
true。如果您希望继续串联操作,它们仍可输出更新后的载荷。
输出模式
单个输出
大多数节点提供一个输出。进入的内容(载荷 + 门控)会原样输出,除非节点对其进行编辑。
True/False 输出
Condition、Compare、Regex 和 Logic 节点提供两个输出端口。 真(True) 通过绿色端口继续; false 会在灰色/红色端口提供。
透传与覆盖
一些节点(Set Variable、Math、Text Replace)会修改载荷,但仍转发 true/false 来自输入的状态。其他节点(NOT、AND、OR)自行重新计算布尔值。
2. 逻辑节点速查
这些模块解答最常见的“true/false 是什么意思?”问题。
非(NOT)
- 输入:来自前一节点的 1 个布尔值(true/false)。
- 输出:反转后的布尔值,以及未改动的载荷。
- 默认行为: 如果 NOT 输入没有连接任何内容,它会求值为
false,因此输出为true.
与(AND)
- 输入:两个或更多布尔信号(A、B 等)。可让额外端口留空。
- 输出:
true仅当所有连接输入都等于true. - 当多个条件必须同时满足时使用 AND(“是订阅者” 和 “聊天消息包含 !raffle”)。
OR
- 发出
true如果 任意 连接的输入为 true。 - 适合多平台触发器:将 Twitch 和 YouTube 消息节点接入单个 OR,然后统一下游操作。
不需要。许多节点已经提供一体化筛选器(例如“Filter User Level” + “Contains Text”)。仅当内置选项无法涵盖您的组合,或需要供其他分支共用的可复用逻辑连接点时,才使用 AND。
true。保持它连接到有意义的节点,或禁用该节点,以免意外放行流程。
3. 微型流程示例
A. 除命令消息外自动回复
此处 Regex 节点发出 true ,条件是消息为命令。我们将 false 端口接到回复,因此普通聊天者会收到确认,而命令直接通过。
B. 使用 AND 要求多项检查
AND 节点确保只有使用正确关键词的会员才会转发到 Discord。两个分支都将布尔结果发送到 AND 节点;载荷来自 第一个分支 ,并继续向下游传递。
C. 使用 NOT 节点阻止重复提醒
State Check 在提醒被静音时输出 true 。通过反转该结果,NOT 节点确保仅在标志为以下值时播放庆祝效果: false.
D. 随机播放两种声音之一
AND 门不可省略。 独立的 NOT 会输出 true 每当 RANDOM 门闲置时,因此声音 B 会在每条以下聊天消息时播放: 不匹配触发条件的消息。 将触发器连接到 AND 的第二个输入,可将声音 B 限制为仅在消息匹配时播放。同一模式适用于任何二选一的动作组合,不限于音频。
4. 防止回显、循环和转发反馈
跨界面转发聊天很有用,但如果监听自己的输出,就可能产生无限回显。请遵循以下防护措施:
传入触发器和传出 Relay Chat 的目标都会区分
youtube 和 youtubeshorts。当消息应到达两个变体时,使用两个转发操作。请参阅 YouTube Shorts 与 Event Flow.
回流是指发送到目标聊天后又被捕获的消息。当前 Relay Chat 操作会跳过这些已识别的回流;没有单独的 No Reflections 复选框。如需隐藏或限制它们在停靠面板和叠加层中的显示,请使用 回流过滤器(Reflection Filter) 操作,带有 全部阻止, 允许第一条,或 全部允许。这控制重新接收时的显示,而不是发送。请遵循 Twitch 和 YouTube 转发教程 了解完整设置。
- 避免重复转发系统。 使用等效的 Event Flow 路由时,请禁用全局 Relay all,并检查是否有其他服务桥接相同聊天。自定义元数据不能保证在经过平台聊天后仍保留。
- 使用 Debounce 或 Cooldown 节点 用于每 X 秒只应触发一次的提醒。
- 有意识地打断循环。 如果两个分支相互输入,请添加逻辑节点检查状态变量(“currentlyRelaying”),以便在标志已设置时提前退出流程。
5. 输入、输出和实用问题
节点接收什么?
- 完整消息载荷。
- 门控位(
true/false). - 节点明确请求的可选上下文(状态变量、计时器)。
什么内容离开节点?
- 相同载荷,除非节点对其进行编辑。
- 重新计算的门控位(逻辑节点)或透传位(操作)。
- 大多数副作用(如发送聊天)不会改变载荷,但积分操作可以附加状态字段,例如
pointsTotal或pointsSpendError用于下游逻辑。
何时分支?
每当希望针对以下内容作出不同反应时: true 与 false。从所需的彩色输出(绿色 = true,灰色/红色 = false)拖动连线到下一个节点。
false 输出,流程就会在此结束。这非常适合筛选器(“阻止所有未通过检查的内容”),但别忘了连接 false 路径,如果需要回退处理。
常见问答
- 每一对筛选器都必须使用 AND 吗? 不需要。许多节点包含多项检查(例如,基本 Message Filter 支持关键词 + 角色)。仅对高级组合,或合并来自不同节点的信号时使用 AND。
- true/false 值如何到达 NOT 节点? 任何具有绿色输出的节点都会发出
true作为默认值。条件失败时,它发出false。将该连线接入 NOT 以反转结果。 - 节点返回 false 时,仍能发出载荷吗? 可以。载荷仍会通过 false 输出传递;由您决定该分支应通向何处。
- 如何匹配 TikTok Team 成员? 选择 TikTok Team 成员(TikTok Team Member) 在 User Role 节点中。它识别传入消息中的 TikTok Fan Club/team 等级和徽章,不依赖 Main Chat Overlay 设置。
- 每个 Speak Text 节点可以使用不同的语音吗? 可以。在以下字段中输入提供商支持的语音名称或 ID: 语音覆盖(Voice Override),或留空以使用 Flow Actions TTS 默认值。
6. 模板变量参考
多个操作节点(Show Text、Set Text Source、Send Message、Relay Chat、TTS Speak、Call Webhook、Print Thermal Label)支持 模板变量 在运行时会被事件数据替换。用花括号包裹变量名,例如 {username}.
核心变量(向后兼容)
| 变量 | 别名 | 说明 | 示例 |
|---|---|---|---|
{username} | {chatname} | 用户的显示名称 | CoolViewer123 |
{message} | {chatmessage} | 聊天消息文本 | 大家好! |
{source} | - | 平台名称(首字母大写) | Twitch, YouTube |
{type} | - | 平台名称(原始值) | twitch, youtube |
{donation} | {hasDonation} | 打赏显示标签 | $5.00, 500 bits |
扩展变量
| 变量 | 说明 | 示例 |
|---|---|---|
{displayname} | 显示名称(备用字段) | CoolViewer123 |
{donoValue} | 提供或估算的等值美元打赏金额;Event Flow 从标准化的以下字段推导阈值: hasDonation 标签,例如数值, $数值、数值 + 单位,或紧凑的单位/数值格式。未知命名虚拟单位按 100 单位 = 0.01 美元换算;未定价的 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} | 来源提供顶层奖励标题字段时的奖励名称 | 高亮我的消息(Highlight My Message) |
{meta} | 结构化事件数据(JSON) | {"viewers":100} |
{counterValue} | 经过 Counter 或 Check Counter 步骤后的当前计数器值 | 12 |
{counterTarget} | 计数器目标值 | 30 |
{counterRemaining} | 计数器目标减去当前值,最小为 0 | 18 |
{USERNAME}, {Username},以及 {username} 都以相同方式工作。
Check Counter 提供 {counterValue}, {counterTarget},以及 {counterRemaining}.
示例模板
- 显示文本(Show Text):
{username} just cheered {hasDonation}! - 设置 OBS 文本源(Set OBS Text Source):
{username}: now {counterValue}, need {counterTarget} - 转发聊天(Relay Chat):
[{source}] {username}: {message} - TTS:
{username} says {message} - 打赏提醒:
{username} donated {donation} - {subtitle} - 热敏标签:
{username},换行,然后{donation}。请参阅 热敏打印机指南 了解打印机设置、固定尺寸标签和完整流程。 - Discord 调用 Webhook:
{"content":"{message}","username":"{username}","avatar_url":"{chatimg}"}
{donation} 在普通聊天消息中),占位符会替换为空字符串,而不是显示字面的 {donation} 文本。
7. 最佳实践检查表
- 命名并设置颜色: 为节点设置名称和颜色,以便以后分辨各个分支。
- 使用内置模拟器测试 (Send Test Event),然后再将流程投入直播。
- 在来源附近集中逻辑。 尽早筛选,避免后续额外处理。
- 将重复记录存入状态节点。 使用计数器、开关和时间戳避免重复提醒。
- 记录 meta 字段。 当您添加自定义的
meta键时,请记录它们,让叠加层和远程客户端保持一致。
8. 进一步探索
从 Stream Deck 或 API 运行自定义工作流:命名触发器、入门模板、工作流发现、额外数据、HTTP/WebSocket/P2P 示例和旋钮手势。
准备深入了解?
- 使用 状态节点 (计数器、开关、计时器)来跟踪事件之间的上下文。
- 组合 变量和逻辑 以构建队列系统、抽奖或评分引擎。
- 接入 积分和奖励 系统,让观众可以主动触发流程。
- 运行 SSApp 桌面应用? 解锁 自定义 JavaScript 节点 用于内置节点未涵盖的任意逻辑。
- 检查 事件参考 了解所有平台的详细载荷文档。
本指南有意设计为独立文档,您可以复制到本地、为团队调整,并继续在编辑器中尝试。
9. 自定义 JavaScript 仅限 SSApp / 桌面应用
Event Flow 编辑器中的两个节点让您编写在流程处理管线内运行的任意 JavaScript: 自定义代码(Custom Code) (触发器)和 执行自定义代码(Execute Custom Code) (操作)。当内置节点无法表达某种需求时,它们提供自定义途径。
new Function() / eval()。通过以下入口打开编辑器: SSApp 桌面应用 以启用它们。在扩展模式中,节点显示为灰色,并带有标签 “仅限桌面应用”.
Ctrl+S 或 Cmd+S 执行相同操作。Cancel 不会更改节点。
Custom Code — 触发器节点
拖动 自定义代码(Custom Code) 来自 高级 分组,位于 触发器 面板拖到画布上。它充当门控:仅当代码返回以下值时流程才继续: true.
true 或 false.function(message) { ... }必须返回: 布尔值 —
true 让流程继续, false 以停止它。可用: 对象
message (参见 消息 API 如下),加上 convertCurrency(value, targetCurrency, source) 和 convertToUSD(value, source).
Execute Custom Code — 操作节点
拖动 执行自定义代码(Execute Custom Code) 来自 集成 分组,位于 操作 面板。它可以修改消息、阻止消息或附加供下游节点读取的元数据。
function(message, result) { ... }应返回: 对象或 Promise,合并到
result— 请参阅 结果 API.可用:
message (事件载荷), result (当前流程结果状态), printThermal(html, options),加上 convertCurrency(value, targetCurrency, source) 和 convertToUSD(value, source).
printThermal('<strong>' + message.chatname + '</strong>')。SSApp 通过原生 Windows 打印机 API 静默排队作业,并使用这些已保存设置。流程可以通过以下选项覆盖它们: { width: '58mm', marginLeft: '3mm', marginRight: '3mm', marginTop: '2mm', marginBottom: '2mm', feed: '3mm', marginType: 'printableArea' }。返回 Promise 使 Event Flow 能够等待提交并报告错误。
对象 message
两个节点都以以下形式接收完整事件载荷: 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 | 数值 / 字符串 | 来源提供时的等值美元打赏金额;有效的零值会被采用。Event Flow 回退到 currency.js 转换标准化的 hasDonation 标签用于阈值比较,包括 100 个未知命名单位 = 0.01 美元。它不会解析 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 字段。告知下游节点载荷已编辑。 |
message | 对象 | 将消息(可能已修改)传回,让下游节点收到您的更改。 |
blocked | 布尔值 | 设置 true 以防止消息被显示或转发。 |
return { modified: false, message };即使没有更改任何内容,返回
message 使它继续流向下一个节点。
代码片段示例
将任意一项复制到相应节点类型的 JavaScript Code 文本区域。
触发器代码片段 — 返回 true 以继续流程
!queue, !raffle, !enter).操作代码片段 — 返回 { modified, message }
{meta}).完整示例 — VIP 功能请求机器人
该流程监听 !feature <text> 来自订阅者、VIP 或版主的内容,将其重新格式化为功能请求,并转发到第二个目标(例如 Discord)。
步骤 1 — Custom Code 触发器 (粘贴到触发器的 JavaScript Code 字段):
步骤 2 — Execute Custom Code 操作 (粘贴到操作的 JavaScript Code 字段):
步骤 3 — Relay Chat 操作:在操作后添加标准 Relay Chat 节点,并配置为指向 Discord(或其他)目标。此处无需自定义代码,重新格式化的 message.chatmessage 会自动流经。
!feature dark mode support,并确认 Relay Chat 目标收到重新格式化的字符串。
安全注意事项
window 对象,以及 preload 脚本提供的任何 API(例如 window.ninjafy)。请将导入的流程文件视为可执行代码,只导入可信来源的流程。
- 没有网络沙盒。 操作代码可以调用
fetch()。如果接受他人分享的流程,请在启用前审核 JS。 - 错误会被捕获。 代码中的运行时错误会返回
false(触发器)或不执行操作(操作),并记录到 DevTools 控制台,流程不会崩溃。 - 语法错误也一样。 类型为
SyntaxError的编译错误也会以相同方式捕获。如果节点似乎没有反应,请检查 DevTools(F12)。