---
id: v4-1827-ndi-into-ipsource
title: NDI merged into IP Source page (Config-T)
doc_type: design-record
status: in-dev
target_release: "8.4"
last_updated: 2026-07-27
sources:
  - { type: jira, ref: "V4-1827", url: "https://tvunetworks.atlassian.net/browse/V4-1827" }
  - { type: jira, ref: "FB-7860", url: "https://tvunetworks.atlassian.net/browse/FB-7860" }
  - { type: jira, ref: "V4-2261", url: "https://tvunetworks.atlassian.net/browse/V4-2261" }
  - { type: jira, ref: "V4-1676", url: "https://tvunetworks.atlassian.net/browse/V4-1676" }
  - { type: doc, ref: "WebR-20220107 reference (combobox dual-mode)", url: "https://www.figma.com/design/ET5crxAZsdcYGR513p4ON7/WebR-20220107?node-id=7854-11352" }
figma:
  file: rJJjWWs51n2iFOlCIC7aYG
  nodes:
    - { id: "7452:4", label: "PRD (Round-3, rewritten)", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7452-4" }
    - { id: "7884:653", label: "AFTER Section — NDI merged into IP Source (3 states)", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7884-653" }
    - { id: "7884:652", label: "BEFORE Section — current IP Source (2 source types)", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7884-652" }
    - { id: "7909:839", label: "Interaction flow note (in AFTER section)", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7909-839" }
    - { id: "7838:2", label: "UX Delivery Section (UX card + Journey card, moved onto work page)", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7838-2" }
    - { id: "7917:839", label: "AFTER (states) Section — NDI discovery & apply feedback (7 states ④-⑩, Round 3.1)", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7917-839" }
    - { id: "7839:2", label: "UX Delivery card", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7839-2" }
    - { id: "7840:2", label: "User Journey Map card", url: "https://www.figma.com/design/rJJjWWs51n2iFOlCIC7aYG/?node-id=7840-2" }
---

# Feature Design Record — NDI merged into IP Source page (V4-1827)

- **JIRA**: [V4-1827](https://tvunetworks.atlassian.net/browse/V4-1827)　**Scope**: Config-T (RPS One Local UI). LCD side = [V4-2261](https://tvunetworks.atlassian.net/browse/V4-2261) (separate, related).
- **Owner(dev)**: Dave Hu (current assignee) · Config-T module = Bonnie Zhou　**PM**: Trevor Yao　**Designer**: Nancy
- **Status**: 待 review (UX design updated)　**日期**: 2026-07-21

## 1. 问题与根因
RPS One 目前只支持 SDI/HDMI + IP Source 两种直播输入源。客户（Red Bull）现场需求 + PM 定位为 NAB26 卖点，要求**新增** NDI（经 ETH 模块）作为直播输入源，含 NDI discovery server 自动发现。这是**新增能力**，不是修 bug。

设计方向经三轮演进：Round 1（6 列 Source List 表 + Add External Source 弹窗）、Round 2（每 Transmitter 单源表单 + 独立 NDI 导航 tab + per-Tx toggle）均被 owner 判定不满足；Round 3（本记录）= **NDI 归入现有 IP Source 页，用 `Type of source` radio 三选一互斥**，对齐 Config-T 既有 IP Source 页的管理范式。

## 2. Scope & Non-goals
**做**：在 Config-T IP Source 页新增 NDI 源类型（radio 第 3 项）+ 三态内容区（HDMI 提示 / IP 6 卡 / NDI 单源表单）+ per-Transmitter 作用域 + 分隔线 + NDI combobox 双模式（Discovery + Manual）。

**不做（Non-goals / backlog）**：
- ~~NDI 源状态反馈补充态~~ → **已于 2026-07-22 补充交付（Round 3.1，见 §7.5 状态态补充）**：发现源空态 / 扫描中 / 发现失败 / 连接中 / Apply 成功 / Apply 失败 / 超长源名 7 态。**4-Tx 绑定总览**仍拎出本轮（不属状态态，是新视图 + 涉与单路配置流的权衡；待 owner 确认诉求再评估形态）。
- NDI combobox 下拉的**真实源名清单**（owner/域知识；mockup 用示例名 STUDIO-CAM-01/02、GFX-SERVER (NDI)、STUDIO-CAM-ARENA-NORTH-UPPER-DECK-CAM-07）。**仍 backlog**。
- LCD 侧（V4-2261，独立单）。
- 产品 UI 遗留 Helvetica → DS Roboto 统一（不可移植系统字体，非本轮）。

## 3. Baseline 参考
- 现状 IP Source 页原稿：`1011:7877`（Default）/ `1011:8187`（Single），page `2:12`（"More than one IP Stream"）—— M21 sibling 视觉契约来源，不改。
- 工作页现状参考帧（BEFORE）：`7862:1721`（2 选 radio + 6 卡内容），现收进 BEFORE Section `7884:652`。
- 源类型 radio 组件：`WebUI/Form/Item/Radio`（第 3 项为预留 hidden group，本轮启用）；radio dot 组件 `WebUI/Form/Radio/Selected`（key `74f7335f…`）/`Unselect`（key `de850a00…`）。
- NDI 表单字段来源：Round-2 草稿 `7504:41261`（Source Name Input + URL combobox `select box/filled` + Apply Button）——沿用字段，去掉 toggle。
- WebR-20220107 node 7854-11352：combobox 双模式交互参考。

## 4. 设计 — 状态与指示模型
**源类型互斥（per-Transmitter）**：`Type of source` radio 三选一 —— HDMI/SDI/USB · IP Source · NDI。同一 Tx 只能激活一个（一路一信号）。选中项 label = 绿 `{0.2,0.671,0.31}`（产品基线 raw），未选 = 白。radio dot swap Selected/Unselect 组件。每个 Tx（1-4 分页）各自记忆，切 Tx 刷新 radio + 内容区。

**三态内容区**：
| 选中 | 内容 |
|---|---|
| HDMI/SDI/USB | 无预览无设置，居中提示 `Local input active — no configuration required.`（避免"页面坏了"观感）|
| IP Source | 现有 6 卡源网格 + `Merge All IP Source`（原样保留，Merge 仅此态）|
| NDI | 单源表单：`Source Name` 输入 + `URL: ndi://` combobox + `Apply`。**无 per-Tx enable toggle**（选中 radio NDI 即启用，toggle 语义重复）|

**分隔线**：radio 行与内容区间加一条水平分隔线（`--line-light` #434343 dark），明确"下方是所选类型的配置区"。

**NDI combobox 双模式**：下拉选网络发现的 NDI 源 = Discovery 模式；手输 `ndi://` 地址 = Manual 模式；关键字搜索过滤列表（三合一）。沿用 WebR 交互。

## 5. UX 交付
- **产品 UI 文案（设备语言单语，M33）**：`Type of source` · `HDMI/SDI/USB` · `IP Source` · `NDI` · `Source Name` · `URL: ndi://` · `Apply` · `Merge All IP Source` · 提示 `Local input active — no configuration required.`
- **注释层（双语，M23）**：PRD 卡 `7452:4`（6 段）+ UX Delivery 卡 `7839:2`（Why/Changes/Data Contract/Interaction/Acceptance）+ User Journey Map 卡 `7840:2`（5-stage × 5-lens，Ops persona）+ AFTER 三帧 cyan 状态 caption。
- **组件来源**：radio/dot/Input/select box/Button 均库组件 instance；分隔线 = raw rect（匹配 `--line-light` token，与产品 raw 基线一致）；NDI 表单字段 clone 自 Round-2 草稿。

## 6. 决策记录
| # | 决策 | 理由 |
|---|---|---|
| 1 | NDI 归入 IP Source 页，不新增独立导航 tab | 所有源类型集中一处，贴合操作员既有管理习惯；owner 三轮拍板 |
| 2 | 切换控件回归 radio 单选（否掉分段/二级 tab/下拉/分栏/方块按钮）| "框架 OK，控件回归最传统单选"；三源互斥语义最直观 |
| 3 | NDI 表单不设 enable toggle | 选中 radio NDI 即等于该路启用，toggle 语义重复（owner 确认删）|
| 4 | radio 行与内容区间加分隔线 | 明确从属关系，缓解"整块内容突变"观感 |
| 5 | PRD/交付措辞去"移除"改"新增" | 产品当前无 NDI、无 NDI tab；"移除 tab" 只相对作废的 Round-2 草稿成立，对外 PRD 描述现状基线（owner 纠正）|
| 6 | combobox 保留 Discovery + Manual 双模式 | Trevor 明确问"manual only? no discovery?"，确认双模式（Jira 2026-07-20）|
| 7 | Priority Medium → High | owner 本轮要求（较急）|

## 7. 依赖 / 待办
- **真实 NDI 源名清单**：combobox 下拉当前用示例名；真实源来自 NDI discovery server（owner/域知识），拿到后可程序化批量替换。
- **固件/接口**：NDI discovery server 扫描结果 → combobox 选项的实时数据接口（dev 侧）。
- **字体**：radio label 产品原为 Helvetica（use_figma 不可 load）；AFTER 帧内 radio label 已统一为 Roboto（可迁移），产品其余 Helvetica 未触（非本轮）。
- **Jira 字段**：parent=V4-1676（8.4）已确认；fixVersion 当前空（待 owner 决定是否锁版本）；priority 待改 Medium→High（收尾 propose）。

## 7.5 状态态补充（Round 3.1，2026-07-22）

对 AFTER 交付补齐 NDI 数据流的 7 个 edge/feedback 态（此前 §2 backlog）。新建独立 Section `V4-1827 · AFTER (states) — NDI discovery & apply feedback`（`7917:839`，AFTER Section 正下方 x=3620 y=2100，probe 防叠加通过），内含 7 个局部态帧（均 clone 自 NDI 帧② `7892:790`，950 宽 mirror，各配 cyan caption ④–⑩，EN 单语对齐现有 ①②③）。

| # | 态 | node | 呈现 | 组件 |
|---|---|---|---|---|
| ④ | 发现源空态 | `7918:839` | combobox 展开：`No NDI sources found on the network` + `Type an ndi:// address manually`（Item 去高亮承载提示，Item2 副行灰、Item3 隐藏）| Drop down List/Item override |
| ⑤ | 扫描中 | `7918:879` | combobox 展开：`Scanning for NDI sources…`（纯文案，dev 侧加 spinner 动效）| Drop down List/Item |
| ⑥ | 发现失败 | `7918:919` | combobox 展开：`NDI Discovery unavailable — check the network`（dev 侧加 warning icon）| Drop down List/Item |
| ⑦ | 连接中 | `7918:959` | 表单填妥（STUDIO-CAM-01）+ Apply=`Connecting…`（disabled，dev 侧 loading spinner）| Button（clickable=no）|
| ⑧ | Apply 成功 | `7918:1359` | 顶部居中 `Message status=success`：`NDI source applied to Transmitter 1` | `Message` set（node `1408:17153`）|
| ⑨ | Apply 失败 | `7918:1399` | 顶部居中 `Message status=error`：`Failed to apply — source unreachable. Check the source and try again.` | `Message` set |
| ⑩ | 超长源名 | `7918:1439` | combobox Item1 尾部截断 `STUDIO-CAM-ARENA-NORTH-UPPER-DECK-C…` + `Tooltips`(pointing=Center down) 悬浮全名；Item2 正常长度对比 | Drop down List + `Tooltips` set |

**M49 §3 Feedback UI Inventory（同源锁定）**：④⑤⑥ = Drop down 展开浮层内联态（同宽同位，no-action）；⑧⑨ = `Message` 瞬时状态行（success/error 只换 status+文案，同宽同位顶部居中，no-action）；⑦ = 按钮 loading 态（归属 Apply，非独立反馈面）。不混用 toast/alert/Message 多套反馈面。

**设计取舍**：扫描/失败/连接中的**动效**（spinner）与 icon 属实现细节，mockup 用文案 + 状态色（Message 自带 success 绿/error 红）传达语义，动效交 dev（handoff 注明）。`Message` 用 `size=M`（@320 换行，容纳长短文案）、`Show close icon=false`（auto-dismiss）。

**字体**：新增提示文本 = Roboto Regular；改既有帧文本碰 Helvetica（Source Name/URL/Apply label）走 `fontName` 覆盖 Roboto 绕墙（不 load 旧 Helvetica）。

**交付层同步**：Journey 卡 `7840:2` stage3/5 的 🟡🔴 Opportunities → ✅（指向帧 ④–⑥ / ⑦–⑨）；UX Delivery 卡 `7839:2` Acceptance 增补状态态验收项。overlap 复检 = 0（Section 14 直接子两两不叠）。

## 7.6 Source Name 字段移除（Round 3.2，2026-07-27）

**owner 决策**：NDI 表单去掉 `Source Name` 输入字段——**产品里没有任何位置展示这个名称**，让用户为源命名却无处体现，是无回报的录入负担。NDI 源改为**仅以 `ndi://` URL 标识**。

**改动**：
| 层 | 内容 |
|---|---|
| 产品 UI（8 帧） | 删 `Frame 38`（`Source Name:` label + Input instance）：AFTER 帧② `7892:790` + 7 个状态态帧 `7918:839/879/919/959/1359/1399/1439`。表单收敛为 `URL: ndi://` combobox + `Apply` 两件 |
| 布局回收 | form 高 170→114、帧高 367→311（auto-layout hug 自动收缩）；各帧内 ABSOLUTE 定位的 combobox 展开浮层 + Tooltip 同步上移 56px；AFTER 帧③ 与 caption ③ 上移 56；states Section 7 组按 k×56 级联上移，Section 高 3367→2975 |
| PRD `7452:4` | 功能需求 / 验收标准两段的「单源表单」描述去掉 Source Name；各**新增一条**显式条目：源仅以 ndi:// URL 标识、不设用户自定义源名称字段 / NDI 表单无 Source Name 字段 |
| UX 卡 `7839:2` | Changes（`NDI form = URL ndi:// combobox + Apply only; no Source Name field…`）· Data Contract（`NDI Source Name: string, user-entered` → `No user-entered source name is stored — the ndi:// URL is the source identifier`）· Acceptance（单源表单验收补「仅 URL + Apply、无名称字段」）|
| Journey 卡 `7840:2` | stage 3 Pairing 的 Actions / Touchpoints 去掉 Source Name 步骤与触点 |
| 流程卡 `7909:839` · caption | `NDI → URL ndi:// combobox … + Apply`；caption ② 补 `no name field`；caption ⑩ 改 `Long discovered source name`（明确指发现列表里的源名，与已删的输入字段区分）|

**顺带修正的 Round 3.1 遗留**（同一交付物、低风险）：① UX 卡 Acceptance 末条原为 EN+ZH 挤同一行且字号 11 → 拆成 EN 13/lh20 + ZH 11/lh15 两行，与 sibling 一致；② Journey 卡 stage 5 Opportunities 正文误继承 label 的 cyan → 恢复白色。

**技术坑（新增，复用价值高）**：`deleteCharacters` + `insertCharacters(i, s, 'BEFORE')` 继承的是**前一个字符**的样式；当替换目标是**行首**时，前一个字符是上一行的换行符，会把上一行（另一语言）的 font / size / lineHeight / fill 整套带过来——本轮 Journey 卡 Actions/Touchpoints 行因此整行变成 Noto Sans SC 13 cyan。**对策**：行级替换后必须逐行复检字体，并用**同节点内未被触碰的同类行**作样式基准回灌（`getRangeFontName/FontSize/LineHeight/Fills` → `setRange*`），不要硬编码字号。

**机检（in-file，REST 无 token）**：overlap（Section 间 + 5 个 Section 内）= 0 · I3 overflow = 0 · 产品区 glyph = 0 · 产品区 `Source Name` 残留 = 0 · 注释区字体违例 = 0（1 条告警为误报：ZH 行仅含中文标点）· library-origin remote 116 / local 0 · M23.14 EN 1.69 / ZH 1.27 差异化保持。证据：`docs/handoffs/.conformance/rJJjWWs51n2iFOlCIC7aYG-round3.2-2026-07-27.json`。

**未动**：`_backup` Section `7485:1144`（Round-2 作废草稿）内仍有 Source Name 字样，属已归档 out-of-scope，刻意不改。

## 8. 交付链接
- Figma page `< V4-1827 > NDI Source … Config-T 20260623`（canvas `7452:2`）：
  - Context Section `7452:3`（PRD `7452:4` + Jira 卡 `7455:1416`）
  - BEFORE Section `7884:652`（现状参考 `7862:1721`）
  - AFTER Section `7884:653`（交互流程卡 `7909:839` + 3 状态帧 `7885:652` IP / `7892:790` NDI + combobox 展开 / `7892:1066` HDMI + 3 caption）
  - **AFTER (states) Section `7917:839`（Round 3.1，2026-07-22）**：7 态帧 ④空 `7918:839` / ⑤扫描 `7918:879` / ⑥失败 `7918:919` / ⑦连接中 `7918:959` / ⑧成功 `7918:1359` / ⑨失败 `7918:1399` / ⑩超长名 `7918:1439` + 7 条 cyan caption `7938:1047`–`7938:1053`
  - UX Delivery Section `7838:2`（**已从 page 3078 移到本工作页 x4900**）：UX 交付卡 `7839:2`（Acceptance 已补状态态验收项）+ User Journey Map 卡 `7840:2`（stage3/5 Opportunities 已升 ✅）
  - `_backup` Section `7485:1144`（Round-2 单源草稿，已归档改名）
- Spec: `docs/superpowers/specs/2026-07-21-v4-1827-ndi-into-ipsource-design.md`
- Kickoff packet: `tvu-design-system/docs/internal/_design-kickoffs/v4-1827-ndi-into-ipsource.md`

## 9. 路由与评审
- **Assignee**（按 scope）：Config-T dev（当前 Dave Hu；模块 Bonnie Zhou）
- **Reviewer（PM）**：Trevor Yao
- **FYI**：Dave Hu · fujianfang · Bonnie Zhou（此前在该单评论过的相关方）
- **JIRA 回复**：草稿先给 owner 过目再发（slack-jira-write-confirm）；格式 = `UX Design updated.` + Figma Section 短锚链接 + @Trevor review + cc 上述 FYI（ADF + accountId 真 mention）。
