Permalink to ScriptScript
<script> 元素承载旁白或讲者说出的每一个字。Script 以散文为先:它不包含时间码、不引用媒体、不设定样式、不携带生成参数。管线中的其他组件都会读取 Script;Script 本身不读取任何内容。
<import from="@hypit/script@1"/>
<script id="story">
<opening>
<HOST> Hello world.
</opening>
</script>引入 @hypit/script@1 会激活 Script Surface。id 属性让其他组件可以引用该 Script 及其各部分。
Permalink to segmentSegment
Segment 是按顺序排列的语音内容块。标签名即其 id——在同一个 Script 内必须唯一。
<script id="story">
<opening>
Hello world.
</opening>
<pause/>
<middle>
This is the second part.
</middle>
<close>
Goodbye.
</close>
</script>- Segment 可以是自闭合标签(
<pause/>)。空的 Segment 拥有结构但没有语音词元;它并不意味着静音或任何默认时长。 - Segment 不能嵌套——每个 Segment 都是
<script>的顶层子元素。 - Segment 名称遵循 XML 命名规则:字母、数字、连字符、下划线。
其他组件通过 {story.segment.opening} 引用单个 Segment,通过 {story.segment.opening.dialogue} 或 {story.segment.opening.speech} 引用其文本投影。
Permalink to role-cueRole Cue
Role Cue 标识 Segment 内部谁说了什么。它们不是讲者实体,不选择语音,也不创建角色。
<dialogue>
<ALICE> What time is it?
<BOB> It's 8:30.
</dialogue>- Role Cue 没有关闭标签。一段话从当前 Role Cue 开始,延续到下一个 Role Cue 或 Segment 结尾为止。
- 一个 Segment 必须全部使用或全部不使用 Role Cue——混用会导致错误。
- 标签长度为 1–32 个字符。
Role Cue 会产生不同的文本投影:
| 投影 | 上例的输出 |
|---|---|
| dialogue | ALICE: What time is it?BOB: It's 8:30. |
| speech | What time is it?It's 8:30. |
| caption | What time is it?It's 8:30. |
dialogue Text 包含 Role Cue 前缀,speech Text 和 CaptionDocument 会去除前缀。给
seedance:ReferenceVideo 提供输入的 Prompt Program 可以使用 {story.segment.dialogue.dialogue}
(带标签)。Script 输出一份 {story.caption} CaptionDocument,里面有显示词、N:M 对齐单元
和作者写出的 Cue 分界;里面没有秒数或帧数。
Permalink to dual-textDual Text
当屏幕上显示的文字与实际说出的文字不同时:
<explanation>
<HOST> We call it <SVML | semantic video markup language>.
</explanation>左侧进入 caption 投影;右侧进入 dialogue 和 speech 投影。
| 投影 | 输出 |
|---|---|
| caption | We call it SVML. |
| speech | We call it semantic video markup language. |
左侧为空是合法的:
<HOST> I was < | um> saying that this works.这意味着 "um" 会被说出但永远不会显示为字幕。两侧可以有不同的单词数量——这是一种 N:M 对齐单元,而非 1:1 替换;Selection 不能切开这个单元。
标记只能出现在 Dual Text 的 spoken side。display side 是字面文本,未转义的 @ 会报错;
如果确实要显示 at-sign,请写成 \@。
|| 是 Caption Cue Break 语法,只能位于完整对齐单元之间,不能写进 Dual Text 或切开
N:M 单元。字幕稍后才把 CaptionDocument 与 SemanticTrack 汇合得到帧时间。
Permalink to 扁平词属性扁平词属性
显示词可以带一个扁平的属性块。属性写在词后面,不嵌套,也不表达时间:
<HOST> This is really{emphasis,keyword} important{brand}.</HOST>不写 = 的属性值默认为 true,也可以写成 name=value。Caption 包负责把属性名映射为
局部词样式;Selection 仍然负责整段 Alignment Unit 的基础样式。属性不能切开或包住 Dual
对齐单元。
Permalink to captiondocument-的组成CaptionDocument 的组成
CaptionDocument 是 Script 拥有的字幕真相,包含三种明确的语法对象:
- Display Word(显示词):一个用于渲染的词面,包含应该显示的标点;
- Alignment Unit(对齐单元):最小的显示-口播对应关系,Dual Text 的 N:M 映射也保持为一个单元;
- Cue Break(Cue 分界):作者写出的
||,只能放在完整对齐单元之后。
标点不是口播 token,也不会获得独立时间窗。Dual Text 后面的句号会吸附到前一个显示词:
<test | now>. here 显示为 test. here,口播投影仍是 now. here。英文按词拆分;汉字、
平假名和片假名按字符级 lexical unit 拆分,因此中文不会被当成一个巨大的词。
Permalink to selectionSelection
Selection 是内联声明的具名语义范围。每个名字只能有一对打开/关闭标记;它的值是两个 语义锚点,而不是帧区间:
<script id="story">
@whole
<opening>
<HOST> @problem Current tools make agents operate a timeline. @/problem
</opening>
<answer>
<HOST> @solution SVML removes that editing loop. @/solution
</answer>
@/whole~
</script>Permalink to 语法语法
| 标记 | 含义 |
|---|---|
@id | 打开,右吸附(从下一个单词开始) |
~@id | 打开,左吸附(从前一个单词的末尾开始) |
@/id | 关闭,左吸附(在前一个单词的末尾结束) |
@/id~ | 关闭,右吸附(在下一个单词的起始处结束) |
~ 后缀/前缀控制边界是吸附到左边还是右边。默认的打开标记为右吸附;默认的关闭标记为左吸附。
完整 Script 严格拥有 2M + 2N + 2 个有序语义锚点:每个 Token 两个、每个 Segment 两个,
再加 Program 自己的首尾。最外侧切口仍用 affinity 区分语义:第一个 Segment 前的 ~@id
选择 Program start,@id 选择首 Segment start;末 Segment 后的 @/id 选择末 Segment end,
@/id~ 选择 Program end。对齐后它们可能落在同一帧,但作者身份并不相同。
Permalink to 多个具名-selection多个具名 Selection
不同名字可以重叠或交叉,但每个名字仍然只有一个区间:
Selection 不要求像 XML 标签那样嵌套,它们可以互相交叉:
<demo>
<HOST> @a One @b two @/a three @/b.
</demo>Selection 标记是零宽度的,不会出现在任何文本投影中。它们编译为带有
startAnchorId/endAnchorId 的 NarrativeSelection。Script 本身不包含秒数或帧号——时间
信息来自 SemanticTrack 对齐。
其他组件通过 {story.selection.problem} 引用 Selection,将视觉内容绑定到叙事中的语义时刻。
Permalink to momentMoment
Moment 是具名的时间点(不是范围):
<ecosystem>
<HOST> @ranking! Image generation, video generation, captions and B-roll
all become reusable components.
</ecosystem>| 标记 | 含义 |
|---|---|
@id! | 右吸附(时间点位于下一个单词的起始处) |
~@id! | 左吸附(时间点位于前一个单词的末尾) |
每个 Moment 名字只出现一次,编译为带有 anchorId 的 NarrativeMoment。Selection 和 Moment
共享同一命名空间——同一个 id 不能同时用于两者。
其他组件通过 {story.moment.ranking} 引用 Moment。
Permalink to 注释与转义注释与转义
<!-- This is a comment. Comments never enter any projection. -->
<demo>
<HOST> Follow us \@svml on social media.
</demo>保留语法起始符必须转义:
| 转义 | 产生 |
|---|---|
\@ | 字面量 @ |
\< | 字面量 < |
\\ | 字面量 \ |
| | 字面量 ` |
普通文本中的单个 | 本身就是字面量;未转义的 || 才是 Caption Cue Break。
在 Dual Text 内部,第一个未转义的 | 分隔 display 和 spoken 两侧;display 侧的竖线必须
写成 \|,需要字面量右尖括号时写成 \>。
Permalink to 综合示例综合示例
一个使用所有语法构造的完整 Script:
<script id="story">
@whole
<hook>
<HOST> @problem Girls, you need to hear this. Never let anyone take credit
for your work. @/problem
</hook>
<meeting>
<HOST> @solution I started sending <BCC | B C C> recaps after every
meeting: timestamps, decisions, who said what. @ranking! After
the first recap, everything changed. @/solution
</meeting>
<evidence>
<HOST> That gave me @emphasis the courage I was missing @/emphasis.
</evidence>
<payoff>
<HOST> And guess what? I'm sitting in my old boss's chair now.
</payoff>
@/whole~
</script>此 Script 声明了:
- 四个 Segment:
hook、meeting、evidence、payoff - 一个 Role Cue:
HOST(在所有 Segment 中保持一致) - 一个 Dual Text:
<BCC | B C C>(显示为 "BCC",说出为 "B C C") - 三个 Selection:
whole(整个 Script)、problem、solution、emphasis - 一个 Moment:
ranking(标记 "After the first recap" 这一瞬间)
下游组件通过名称引用这些内容:{story.segment.hook.dialogue} 用于生成,{story.selection.problem} 用于 B-roll 时间绑定,{story.moment.ranking} 用于视觉卡片揭示。