逐日AI
第 2 周 · D10约 6 小时

审片室:能预览、能改词、能重生成单镜的人机协作后台

生产线不可能全自动,这一天给它配一个网页审核台:按镜头看素材、改台词、重生成单个镜头,并把人的每一次修改变成可追溯的版本。

今日目标 0/3

登录后可以勾选并保存进度。

今日目标

  1. 能做出一个按镜头展示素材的审核页面,支持预览、改词与重生成单镜
  2. 能把人的修改接回工作流,让重生成只影响受影响的下游节点
  3. 能说清版本对比与回滚该存什么,以及画布式工作台的取舍

昨天把产能推到了多集并行,今天面对它带来的第一个后果:产量上去之后,人工检查成了新瓶颈。读完回到页面顶部把这三条勾掉。

小白版讲解

审片室:人在哪一步介入

正规剧组里有一个房间叫审片室。它不在拍摄现场,也不在剪辑室,它是一个专门用来「看」的地方:导演、制片、平台方坐在一起,一条一条过素材,说这条留、这条重拍、这句词改一下。

这个房间的存在本身就是一个工程判断:片子不是拍完才检查的,是边拍边检查的。等全部拍完再看,发现第三镜的演员穿错了衣服,后面所有跟它接戏的镜头都白拍了。

生成式流水线一模一样,而且更狠——它的每一步都要花钱,返工的代价直接写在账单上。所以问题不是「要不要人工介入」,而是「人该在哪一步介入」。

有三个天然的卡点,判据是这一步的下游有多贵

第一个是剧本定稿之后、生成任何素材之前。这时候什么都还没花,改一行字的成本接近零,而它决定了后面所有素材的方向。这是性价比最高的卡点,也是最容易被跳过的——因为这时候还没有画面,看起来「没什么可审的」。

第二个是首帧出来之后、视频生成之前。首帧是这条线上最便宜的一档,而视频是最贵的一档,同一个镜头差出一到两个数量级。首帧不对就去生成视频,等于拿一张废图去烧后面那笔大的。这是全线性价比最高的一道人工闸门。

第三个是成片合成之后、发布之前。这一道拦的不是质量而是风险:内容安全、版权、标识合不合规。明天会专门讲。

三个卡点里,今天做的审核台主要服务第二个:按镜头看素材,随时叫停

最小信息架构:运行、集、镜三层

审核台的页面长什么样,取决于你把信息分成几层。这条线的天然结构是三层:一次运行、一集、一个镜头。

一次运行是最外层,对应一个 runId 和一个目录。它回答的问题是「这批东西是什么时候、用什么输入跑出来的」。

一集是中间层,它是人真正关心的交付单位。运营不会问「第十七镜好了没」,他们问「第三集能不能上线」。

一个镜头是最内层,也是唯一可以被单独重做的单位。这是本课反复出现的判断:如果重做的最小单位是一集,那么改一句台词就要重烧四十个镜头的视频;如果最小单位是一个镜头,改一句台词只影响一个镜头的配音。

页面按镜头铺开,每张卡片上放五样东西:首帧图、镜头视频、台词、配音音频、以及这一镜的版本列表。页面本身不必复杂,一个手写的 HTML 加几个 JSON 接口就够了:

HTMLHTML
<section class="card">
  <h3>s02 · close · 4 秒</h3>
  <img src="/media/.../first-frame.png" alt="s02 首帧" />
  <video src="/media/.../clip.mp4" controls></video>
  <audio src="/media/.../voice-1.mp3" controls></audio>
  <textarea rows="2">五分钟后?这不可能</textarea>
  <button>算影响范围</button>
  <button class="primary">重生成受影响节点</button>
</section>

本课的实验刻意不引入任何前端框架,用 node:http 起服务、页面是一个单文件 HTML,跑起来还是那条 pnpm install --ignore-workspace && pnpm start。理由是今天要教的是接口与数据形状,不是构建工具。审核台的价值百分之九十在后端的数据设计上,前端就是把它显示出来而已。

爆炸半径:改一句台词会波及谁

人点下「重生成」的时候,系统要回答一个问题:这一次修改,哪些东西作废了?

答案不能拍脑袋,要从依赖图上算。这条线的依赖关系很清楚:画面描述决定首帧,首帧决定镜头视频;台词决定配音;所有的视频和配音一起决定时间轴。

于是改一句台词,作废的是这一镜的配音,以及整集的时间轴——因为配音时长变了,后面镜头的起止时间要重排。首帧和视频完全不受影响,一帧都不用重烧。改画面描述则相反,作废的是首帧、视频、时间轴,配音不受影响。

算法上要注意方向:是从被改的节点沿着「谁依赖我」正向传播,不是往上游找依赖。往上游找会把没受影响的上游也重跑一遍,这是最常见的写反。

affected.js
// 依赖边:首帧 → 视频;台词 → 配音;所有视频与配音 → 时间轴
const graph = [
  { id: 's02:frame', deps: [] },
  { id: 's02:clip', deps: ['s02:frame'] },
  { id: 's02:voice', deps: [] },
  { id: 'episode:timeline', deps: ['s02:clip', 's02:voice'] },
]
 
// 改 dialogue 的种子是配音,改 visual 的种子是首帧
const SEED = { dialogue: 'voice', visual: 'frame' }
 
function affectedNodes(graph, shotId, field) {
  const affected = new Set([`${shotId}:${SEED[field]}`])
  // 沿着「谁依赖我」正向传播,跑到不动点为止
  for (let changed = true; changed; ) {
    changed = false
    for (const n of graph) {
      if (affected.has(n.id)) continue
      if (n.deps.some((d) => affected.has(d))) {
        affected.add(n.id)
        changed = true
      }
    }
  }
  return graph.map((n) => n.id).filter((id) => affected.has(id))
}
// 改台词 → ['s02:voice', 'episode:timeline'],首帧与视频一帧都不用重烧

算出半径之后还有一步,很多实现会漏:没受影响的节点,产物要从上一版复制过来,而不是重新生成一遍。少了这一步,你算得再准也没省下钱。

半径算出来之后,要先摆给人看,再让人决定要不要跑。审核台上那条橙色提示写的是「待生效:dialogue → 新台词;波及 s02 的配音、整集的时间轴」。这一步看起来只是个提示,实际上是审核台最有价值的一块信息:它把「我这一改要花多少钱」提前告诉了人。改一句台词只重合成一段配音,人会毫不犹豫地点下去;如果提示说要重烧三个镜头的视频,人多半会先想想这一改值不值。把代价前置到决策之前,比事后给一张账单有用得多。

怎么证明自己真的省了?不要去比文件哈希——离线模式下同样的提示词会生成逐字节相同的占位图,哈希一样并不能说明没重跑。数接口调用次数才是硬证据:实验里的自检会打印「这次重生成调了 0 次图像、0 次视频、1 次语音」,这个证据在真实厂商下同样成立。

版本不是备份

人改了一版,觉得不如原来的,想改回去。这个需求听起来像备份,但它不是。

备份的语义是「出事了拿回来」:只保留一份最近的好状态,恢复之后旧的那份就没了。版本的语义是「两个都在」:新旧同时存在,可以并排对比,可以来回切换,最终选哪个是人的判断。

审核场景要的是后者。审片室里导演说「刚才那版是不是更好」,你得能立刻把两版并排放出来,而不是「恢复一下您再看看」。

落到数据上,区别体现在三个地方:

第一,产物按版本分目录存v1/ v2/ 各一份,一个文件都不删。磁盘比重新生成便宜太多了。

第二,当前版本是一个指针,不是一份拷贝。回滚就是把指针挪回去,不涉及任何文件搬运,因此是瞬时的、可逆的。

第三,每个版本要记住自己重跑了什么、为什么。只存产物是不够的——三天后有人问「第二版为什么比第一版好」,你得答得出来。

version.js
// 一镜的状态:一串版本 + 一个当前指针。回滚只动指针,不动文件。
const shotState = {
  current: 2,
  versions: [
    {
      version: 1,
      at: '2026-09-07T10:00:00Z',
      dialogue: '五分钟后?这不可能',
      artifacts: { 's02:frame': 'shots/s02/v1/first-frame.png', 's02:voice': 'shots/s02/v1/voice-1.mp3' },
      regenerated: ['s02:frame', 's02:clip', 's02:voice'],
      reason: '首次生成',
    },
    {
      version: 2,
      at: '2026-09-07T10:12:31Z',
      dialogue: '五分钟后?谁在跟我开玩笑',
      artifacts: { 's02:frame': 'shots/s02/v2/first-frame.png', 's02:voice': 'shots/s02/v2/voice-1.mp3' },
      regenerated: ['s02:voice', 'episode:timeline'], // 首帧是从 v1 复制过来的
      reason: '人工修改 dialogue',
    },
  ],
}
 
const rollback = (state, version) => ({ ...state, current: version })

还有一个容易忽略的连带影响:回滚一镜会改变整集的时间轴。第二版的配音比第一版长一秒,切回第一版之后,后面所有镜头的起止时间都要重排。所以回滚不是只改指针就完事,还要重算一次时间轴——它便宜,是纯本地计算。

画布还是列表

见过 AI 视频工具的人会问:为什么不做成画布?就是那种一个个节点连起来、可以拖拽、可以缩放的非线性工作台,看起来专业得多。

画布确实有它无法替代的地方:当依赖关系需要被人编辑的时候。如果用户要自己决定「这个镜头的首帧从哪张图来」「这两条支线怎么合并」,那么依赖关系就是用户在编辑的东西,画布是它唯一直观的表达。

但它换来的代价是实打实的:

交互成本高。画布上完成一次「改台词并重生成」,要先找到那个节点、点开、改、再找到运行按钮。列表上是一个输入框加一个按钮。审片这件事一天要做几百次,每次多三秒就是半小时。

移动端基本不可用。而审片恰恰是一件很适合在手机上做的事——制片在路上就能过一遍。

实现量大一个数量级。拖拽、缩放、连线、自动布局、撤销重做,每一样都要写,而且写不好就很难用。

还有一个更本质的差别:审片是一件节奏性的工作。人要的是「下一条、下一条、下一条」这种流水线式的推进感,看到不对就停下来处理,处理完继续往下。列表天然支持这个节奏,滚动就是推进。画布则要求人不断在空间里定位「我刚才看到哪儿了」,两百个节点铺开之后,光是找到下一个要看的镜头就要花几秒钟。工具的形态要顺着工作的节奏走,不是顺着数据结构走。

判据其实很简单:依赖关系是固定的,就用列表;依赖关系需要用户编辑,才上画布。这条线的依赖是固定的——首帧决定视频、台词决定配音,用户不需要也不应该改这个。所以本课选列表。

审核意见要结构化

最后一件事,也是最容易被做成摆设的一件事:人在审片时说的话,要不要存下来,怎么存。

存成一段自由文本,比如「这一镜女主的脸不太对」,对下一次自动化毫无用处——它读不懂。存成结构化字段就不一样了:

JSONJSON
{
  "shotId": "s03",
  "verdict": "redo",
  "tags": ["face-inconsistent", "subtitle-overflow"],
  "comment": "女主脸型与定妆图不一致",
  "at": "2026-09-07T10:20:00Z"
}

有了 verdicttags,你就能写出这样的规则:某一镜连续两次被打上 face-inconsistent,就不要再自动重试了,直接标记成需要人工;某个角色的 face-inconsistent 命中率显著偏高,说明它的定妆图该重做了。

还有一个附带好处:结构化之后,这些记录能反过来当作评测集。攒够一两百条带 verdict 的记录,你就有了一份「人认为什么样算合格」的标注数据——明天要用视觉模型自动打分,阈值定在几分才和人的判断一致,靠的就是拿这份数据回测,而不是拍脑袋。这也是为什么审核台该早点上:它一开工就在替你攒数据。

这就是「让人的判断被下一次自动化复用」的含义——不是让模型去读人的评语,而是让人的评语一开始就长成机器能用的形状。代价是审核台上要多几个按钮和几个预设标签,而不是一个万能的输入框。明天的自动质检会直接接着用这份记录:机器打分产出的结论和人工审核的结论,用的是同一套 verdicttags 词表。

源码导读

动手实验

🧪 D10 实验:可预览、可改词、可重生成单镜的最小审核后台

代码位置:labs/ai-drama-pipeline/day-10-review-console

验收标准:

  1. 自检打印 7 项结果,solution 全部为勾且退出码为零。
  2. 改一句台词,算出的受影响节点恰好是「该镜的配音 + 整集的时间轴」,首帧与视频不在其中。
  3. 重生成之后新版本记录的重跑节点与上一步一致,且图像与视频接口一次都没被调用。
  4. 没被波及的镜头版本号不变,被改的那一镜出现第二版。
  5. 回滚到第一版之后台词与配音都回到旧版本,第二版的产物仍在磁盘上,可以再切回去。

这是本课唯一一天要起 HTTP 服务的实验,端口 3080。常驻服务没法用管道喂输入,所以验收入口是 MOCK=1 SELFTEST=1 pnpm start:进程起来之后自己走完全流程、逐项打勾叉、按结果退出。想手动点一点就用 MOCK=1 pnpm start,然后在浏览器里打开本机的 3080 端口。

  1. 先跑 solution 的自检,看懂七项分别在验什么,再回头看 starter 的四个练习点。
  2. 实现爆炸半径计算,跑自检确认改台词只波及配音与时间轴。
  3. 实现「未受影响的产物从上一版复制」,确认这次重生成的图像与视频调用次数是零。
  4. 实现回滚,在浏览器里改一句词、重生成、再点回滚,看图片和音频真的切回去了。
  5. 实现结构化审核意见落盘,打开产物目录里的 review.json 确认字段齐全。

面试题

今天三道题在下方题库区,侧重人机协作的介入点选择、局部重生成的影响范围计算、版本与回滚的数据设计。展开后先看分析过程再看要点——照着推导练,比背要点管用。标注了国内高频与海外高频,方便按目标市场取舍。

检查清单与明日预告

  • 能做出一个按镜头展示素材的审核页面,支持预览、改词与重生成单镜
  • 能把人的修改接回工作流,让重生成只影响受影响的下游节点
  • 能说清版本对比与回滚该存什么,以及画布式工作台的取舍
  • 能说出三个人工卡点分别在哪,以及为什么首帧那一道性价比最高
  • 能解释版本与备份的语义差别,以及为什么回滚要重算时间轴
  • 实验的 5 条验收标准全部通过
  • 3 道面试题不看要点也能答出至少 2 道

明天 D11 我们把今天这套人工判断交给机器:用视觉模型逐项给成片打分,低分镜头自动打回重做,并把内容安全与生成合成内容标识落进导出环节。顺序是有意的——先有人审的流程和结构化的结论,机器审才有对齐的目标;反过来先做自动质检,你会连「多少分算合格」都定不下来。

面试题库

  • 一条自动化流水线要插入人工审核,你会把卡点放在哪几步?为什么?Where would you place human review checkpoints in an automated pipeline, and why there?
    国内高频海外高频基础#human-in-the-loop#pipeline-design#cost

    分析过程 · 先想清楚再作答

    1. 这题在考你有没有成本意识。答「每一步都让人看一眼」是没做过工程的回答——人是最贵的资源,卡点多了流水线就退化成手工作坊。
    2. 给一条可复用的判据:**卡点放在「下游最贵的那一步」之前**。判断某个位置该不该设卡,只问一句「如果这里错了,往后要白花多少钱」。
    3. 按这条判据落到生成式流水线上,会得到三个位置:剧本定稿之后(此时零成本,却决定了后面所有素材的方向)、首帧出来之后视频生成之前(首帧是最便宜的一档,视频是最贵的一档,同一个镜头差出一到两个数量级)、成片合成之后发布之前(这一道拦的不是质量而是合规风险)。
    4. 补一条生产视角:卡点不等于阻塞。第一和第二道可以做成「默认放行、超时自动继续」,只有第三道必须硬卡——合规问题不能靠超时放行。
    5. 结论里要点出一个反直觉的事实:最容易被跳过的恰恰是第一道,因为这时候还没有画面,看起来没什么可审的;但它是唯一一道改起来零成本的闸门。
    6. 可预期的追问是「人来不及审怎么办」。答案是分级:机器先打分,只把低分的推给人,人的时间花在机器拿不准的那部分上。

    How to reason about it · think before answering

    1. This one tests cost awareness. Saying a human should look at every step marks someone who has not run this in production: humans are the expensive resource, and too many gates turn a pipeline back into handwork.
    2. Offer a reusable rule: put the gate immediately before the most expensive downstream step. To decide whether a position deserves a gate, ask how much money is wasted if something is wrong here.
    3. Applied to a generative pipeline that yields three positions: after the script is locked (free to change, yet it steers every asset that follows), after the first frame but before video generation (the frame is the cheapest step and the clip is the most expensive, one to two orders of magnitude apart), and after the final cut but before publishing (this one gates risk, not quality).
    4. Add the production view: a checkpoint is not necessarily blocking. The first two can auto-continue on timeout; only the compliance gate must hard-block, because you cannot let a legal check pass by timing out.
    5. State the counterintuitive part: the first gate is the one people skip, because there are no visuals yet and it looks like there is nothing to review, while it is the only gate where changes cost nothing.
    6. Expected follow-up: what if reviewers cannot keep up. Tier it. Machines score everything, humans only see the low scores, and human attention goes where the machine is unsure.

    答题要点

    • 判据是「卡点放在下游最贵的那一步之前」,问的是这里错了往后白花多少钱。
    • 三个位置:剧本定稿后、首帧出来后视频生成前、成片合成后发布前。
    • 首帧那一道性价比最高:首帧是最便宜的一档,视频是最贵的一档,同一个镜头差出一到两个数量级。
    • 前两道可以默认放行加超时继续,只有合规那一道必须硬卡。
    • 人力不够就分级:机器先打分,人只看低分的那些。

    Key points

    • Rule: place the gate right before the most expensive downstream step, judged by wasted spend if this step is wrong.
    • Three positions: after script lock, after first frame and before video, after final cut and before publish.
    • The first-frame gate pays best: the frame is the cheapest step and the clip the most expensive, one to two orders of magnitude apart.
    • The first two gates can auto-continue on timeout; only the compliance gate hard-blocks.
    • When reviewers are the bottleneck, tier it: machines score everything, humans only see low scores.
  • 用户改了中间一步的输入,怎么算出哪些下游需要重做?A user edits an intermediate input. How do you compute which downstream steps must rerun?
    国内高频海外高频进阶#dag#incremental-recompute#cost

    分析过程 · 先想清楚再作答

    1. 这题的区分度在方向和收尾两处,很多人只答出中间那段「沿依赖图传播」,前后都丢了。
    2. 方向:从被改的节点**沿着「谁依赖我」正向传播**,不是往上游找依赖。写反的后果很隐蔽——上游会被一起重跑,结果是对的,钱多花了一倍,测试也发现不了。
    3. 落到实现:把种子节点放进集合,反复扫一遍图,只要某个节点的依赖里有一个已经在集合里就把它也加进来,跑到不动点为止;最后按拓扑序返回,调用方顺着数组跑就不会先跑下游后跑上游。
    4. 收尾这一步最容易漏:**没受影响的节点,产物要从上一版复制过来,不是重新生成**。半径算得再准,少了复制这一步就一分钱没省。
    5. 然后是怎么验证。不要比文件哈希——同样的输入很可能生成逐字节相同的结果,哈希相同证明不了没重跑。要数**接口调用次数**,这才是硬证据,而且在离线与真实两种模式下都成立。
    6. 可预期的追问是「输入没变但你想重跑怎么办」。留一个强制重跑的开关,并且把它和自动判定分开记账,否则你会分不清一次重跑是系统判的还是人手动点的。

    How to reason about it · think before answering

    1. The signal lives at the two ends. Most candidates produce the middle part, propagation over a dependency graph, and drop both the direction and the finish.
    2. Direction: propagate forward along who-depends-on-me from the edited node, not backward to its dependencies. Getting it backward is insidious, because upstream nodes rerun, the output is still correct, the bill doubles, and no test catches it.
    3. Implementation: seed a set, sweep the graph repeatedly adding any node with a dependency already in the set until it stops growing, then return in topological order so the caller can just walk the array.
    4. The finish is what people forget: unaffected nodes must have their artifacts copied from the previous version, not regenerated. A perfect radius saves nothing without that copy.
    5. Then verification. Do not compare file hashes, because identical inputs often produce byte-identical output and a matching hash proves nothing. Count API calls instead; that evidence holds both offline and against a real vendor.
    6. Expected follow-up: what about forcing a rerun when nothing changed. Keep an explicit force flag and account for it separately, or you lose the ability to tell system-decided reruns from human-triggered ones.

    答题要点

    • 从被改的节点沿着「谁依赖我」正向传播,不是反向找依赖。
    • 扫图到不动点,结果按拓扑序返回,保证执行顺序不会颠倒。
    • 没受影响的节点要从上一版复制产物,否则半径算得再准也没省钱。
    • 验证要数接口调用次数,不要比文件哈希——同样的输入可能产出逐字节相同的结果。
    • 另留一个强制重跑开关,并与自动判定分开记账。

    Key points

    • Propagate forward along who-depends-on-me from the edited node, never backward.
    • Sweep to a fixed point and return in topological order so execution never runs downstream first.
    • Copy artifacts for unaffected nodes from the previous version, or the computed radius saves nothing.
    • Verify by counting API calls, not by comparing file hashes, since identical inputs can produce byte-identical output.
    • Keep a separate force-rerun switch and account for it apart from automatic decisions.
  • 版本回滚要存什么?只存最终产物够不够?What must a version record hold for rollback? Are the final artifacts enough?
    国内高频海外高频进阶#versioning#rollback#data-modeling

    分析过程 · 先想清楚再作答

    1. 题眼在「够不够」三个字,它在提示答案是否定的。先把问题重述成一句判断:**版本不是备份**,这句话说出来这题就答对了一半。
    2. 两者的语义不一样。备份是「出事了拿回来」,只需要保留最近一份好状态;版本是「两个都在」,要能并排对比、来回切换,最终选哪个由人定。审核场景要的是后者。
    3. 所以每个版本要存三类东西:产物本身(按版本分目录,一个文件都不删)、产生它的输入(那一版的台词与画面描述,否则三天后没人说得清两版差在哪)、以及这一版重跑了哪些节点与原因。
    4. 当前版本要设计成一个指针,不是一份拷贝。回滚就是把指针挪回去,不搬文件,因此是瞬时且可逆的;这也让「再切回新版本」变成理所当然的操作。
    5. 有一个连带影响必须提到,提了就说明你真做过:**回滚一镜会改变整集的时间轴**。新版配音比旧版长一秒,切回去之后后面所有镜头的起止时间都要重排。所以回滚之后要重算一次时间轴,好在这是纯本地计算,很便宜。
    6. 可预期的追问是「版本存多久」。按产物体积和业务价值定:小文本无限存,视频这种大件设一个保留期,过期只留元数据和输入,需要时可以按同样的输入重跑出来。

    How to reason about it · think before answering

    1. The hinge is are they enough, which signals the answer is no. Restate it as a claim: a version is not a backup. Saying that sentence gets you half the credit.
    2. The semantics differ. A backup means restore after an incident and only needs the latest good state. A version means both exist, side by side, switchable, with a human choosing. Review workflows need the latter.
    3. So each version stores three things: the artifacts themselves, kept in per-version directories with nothing deleted; the inputs that produced them, the line and the visual description, or nobody can explain the difference three days later; and which nodes reran plus why.
    4. The current version should be a pointer, not a copy. Rollback moves the pointer without touching files, which makes it instant and reversible, and makes switching forward again equally natural.
    5. Mention the knock-on effect, because it shows you have actually shipped this: rolling back one shot changes the whole episode timeline. If the new take of the voice is a second longer, every later shot shifts, so rollback must recompute the timeline. That part is cheap local computation.
    6. Expected follow-up: how long to keep versions. Scale it by artifact size and business value: keep small text forever, put a retention window on video, and after expiry keep only metadata and inputs so the artifact can be regenerated on demand.

    答题要点

    • 版本不是备份:备份只要最近一份好状态,版本要求新旧同时存在、能并排对比。
    • 每版要存三类:产物(按版本分目录、不删)、产生它的输入、重跑的节点与原因。
    • 当前版本是指针不是拷贝,回滚只挪指针,瞬时且可逆。
    • 回滚一镜会改变整集时间轴,回滚后要重算一次——这是纯本地计算,很便宜。
    • 保留策略按体积分级:文本长期留,大视频设保留期,过期只留元数据与输入以便按需重跑。

    Key points

    • A version is not a backup: backups keep the latest good state, versions keep old and new side by side.
    • Store three things per version: artifacts in per-version directories, the inputs that produced them, and which nodes reran and why.
    • Make the current version a pointer, not a copy, so rollback is instant and reversible.
    • Rolling back one shot shifts the episode timeline, so recompute it after rollback; it is cheap local work.
    • Set retention by size: keep text forever, expire large video and retain metadata plus inputs for regeneration.

评论

登录后即可参与讨论

还没有评论,来说第一句。