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 模板,在两个滤镜操作中选择同一个来源和同一个通常关闭的滤镜。
选择 播放音频剪辑 → 浏览声音 搜索英语、西班牙语和巴西葡萄牙语的原始效果和预先录制的合成短语。按类别、事件、语言、交付或持续时间进行过滤;保存收藏夹并在选择前在本地预览 使用声音。 声音库 也可以自行打开并为自定义覆盖提供声音 URL。多重警报使用相同的浏览器。
在事件流中,使用加号按钮构建一组随机的两到二十种声音,然后选择 使用随机集。每个触发器都会播放一种选定的声音。选择单个声音或输入另一个音频 URL 会替换该组。 播放选项 控制重叠、排队和动作的冷却时间; 停止音频剪辑 停止 Flow Actions 剪辑并清除其队列。限制付费命令时,在任何花费积分操作之前放置速率限制器。音频播放不会自动退还单独的积分费用。您仍然可以上传录音或选择应用程序本地文件。要更改名称或消息,请使用 朗读文本(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 设置。
- How do I limit TikTok TTS to Team level 10 or higher? 选择 Compare Property → TikTok Team Level, Greater or equal (>=),以及 10. Connect this and a From Source → TikTok condition to an 与(AND) node, then connect AND to 朗读文本(Speak Text). This reads
meta.teamMemberLevel, which native TikTok connectors and Standard capture supply when numeric Fan Club data is available. Image-only badges cannot provide an exact level; messages without the field do not match. Use Test Flow → TikTok Team Level to try levels below and above your minimum. Disable any separate automatic TTS if this flow should be the only reader. - 每个 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)。