HyperFrames v0.7.111 解析:内容寻址 Plan v2 分布式渲染、pretext 文本测量钩子与 Catalog 搜索排序
2026/9/10 11:57:53 网站建设 项目流程

HyperFrames v0.7.111 解析:内容寻址 Plan v2 分布式渲染、pretext 文本测量钩子与 Catalog 搜索排序

【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes

本文基于releases/v0.7.111.md(2026-08-17 发布)展开。该版本的核心变更集中在三处:分布式云渲染默认切换到内容寻址(Content-Addressed)的 Plan v2 传输协议,同时为 v1 保留显式兼容路径;window.__hyperframes运行时新增 pretext 文本测量钩子,让自定义工具获得更精确的排版布局数据;Catalog 搜索排序改为按词出现位置与稀有度加权。下文结合仓库源码逐一拆解这些能力的实现原理与实战用法。

版本概览

v0.7.111 是一次典型的"能力与工程并重"的版本:

  • Cloud:分布式计划(distributed plans)默认切换为 v2(PR #3311);
  • Core:在window.__hyperframes上暴露 pretext 文本测量接口(PR #3302);
  • Catalog:搜索按词出现位置与稀有度进行排名(PR #3312);
  • Internal:Studio 中将两个超过 600 行的文件拆分为多个(PR #3313)。

其中前两项是面向开发者与 Agent 的公共能力变更,后两项分别影响目录检索体验与代码可维护性。下面从最核心的分布式渲染传输协议讲起。

一、分布式渲染计划:从 v1 整体目录到 v2 内容寻址传输

1.1 背景:v1 的"整体 planDir"模型

在介绍 v2 之前,需要先理解两个传输协议共享的底层表示——本地执行计划(Local Execution Plan)。

在 packages/producer/src/services/distributed/plan.ts 的模块文档中明确给出了 planDir 的目录布局:

<planDir>/ ├── plan.json ├── compiled/ # compileForRender 输出(自包含) ├── video-frames/ # 每段视频的 JPEG 帧序列(解除符号链接) ├── audio.m4a # 仅当组合包含音频时存在 └── meta/ ├── composition.json ├── encoder.json # LockedRenderConfig └── chunks.json

buildLocalExecutionPlan(projectDir, config, executionPlanDir)把既有渲染阶段(编译 → 探测 → 抽帧 → 音频 → 冻结)组合成一个自包含的本地执行目录,供下游分块 worker 消费。它是对本地路径的纯函数:无网络调用,相同输入两次调用产生相同的执行计划哈希(planHash)。v1 的plan()包装器与 v2 的 manifest/CAS 发布器都基于这一表示。

v1 传输模型(plan.ts 中的plan(),现已标记@deprecated)的典型特征是"整体搬运":整个 planDir(可能包含多 GiB 的视频帧序列)被打包传输,且受PLAN_DIR_SIZE_LIMIT_BYTES(2 GiB,见 plan.ts)硬性上限约束。超限会抛出带PLAN_TOO_LARGE非重试错误码的PlanTooLargeError——因为同样的 planDir 每次重试都会超限,工作流适配器会依据code字段决定不自动重试。

1.2 v2 协议描述符:内容寻址布局

v0.7.111 的默认切换意味着分布式云渲染(AWS Lambda、GCP Cloud Run 等)默认产出 v2 计划。协议描述符定义在 packages/producer/src/services/distributed/planProtocol.ts:

字段v1v2
schemaVersion12
artifactLayoutplan-dir-v1content-addressed-plan-v2
hashSchemahyperframes-plan-hash-v1hyperframes-plan-manifest-hash-v2

plan.json中的protocol描述符是兼容性契约:缺失描述符即视为最原始的 v1 布局(acceptsLegacyV1WithoutDescriptor: true保留了对旧 planDir 的重放兼容);一旦存在描述符,就必须完整且被识别,否则抛出PlanProtocolUnsupportedErrorPLAN_PROTOCOL_UNSUPPORTED,非确定性失败,重试无法自愈)。readPlanProtocol还会校验 worker 的能力集(DISTRIBUTED_RENDER_CAPABILITIES:planner 同时产出 v1/v2,chunk 与 assembler 同时接受 v1/v2),从而支持不锁步的集群滚动升级。

1.3 v2 传输:小型 manifest + sha256 寻址 blob

v2 的核心设计是将传输与执行分离(见 packages/producer/src/services/distributed/planV2.ts 模块文档):

传输根是一个小型不可变plan.jsonmanifest,加上按 sha256 寻址的 blob。worker 只选择并物化(materialize)自己角色所需的依赖,然后在校验过的本地布局上调用共享执行函数。

PlanV2Manifest的关键字段包括:

  • protocol:v2 描述符;
  • planHash:manifest 自身的摘要(hyperframes-plan-manifest-hash-v2\x00前缀 + 规范 JSON 的 SHA-256);
  • sourcePlanV1Hash:保留的本地执行计划哈希(兼容线缆名称,新代码请用getPlanV2ExecutionPlanHash);
  • chunkCount/totalFrames/fps/width/height/format/ffmpegVersion/producerVersion:与 v1 结果对齐的执行元数据;
  • limitations.videoDependencyMode"exact-rendered-frames""full-source-pack"
  • artifacts:每个工件记录pathsha256sizeByteschunks"all"或 chunk 索引数组)与assembler布尔标记。

工件寻址路径由 packages/producer/src/services/distributed/planV2Layout.ts 的planV2BlobPath提供,S3 上对应<prefix>/v2/artifacts/sha256/<前两位>/<完整摘要>的布局(见下文发布器)。

1.4 角色化依赖:chunk 只拿自己需要的帧

v2 相比 v1 最实质的收益是按角色裁剪传输体积artifactTargets(planV2.ts)维护了一张"fail-safe 策略表":

  • plan.jsonmeta/chunks.jsonmeta/encoder.json→ 所有 chunk + assembler;
  • meta/composition.jsonmeta/videos.jsoncompiled/*→ 所有 chunk(assembler 不需要);
  • audio.m4a等音频工件 → 仅 assembler;
  • video-frames/*→ 依据videoDependencies精确到帧;
  • 未知的未来执行文件 → 默认发给所有角色("过度包含是安全的,静默遗漏新依赖则不是")。

视频帧依赖通过buildVideoChunkDependencies计算:调用引擎的createFrameLookupTable,对每个 chunk 覆盖的每个全局帧求globalTime = (frame * fpsDen) / fpsNum,再查表得到该帧实际激活的帧路径,从而生成"哪个 chunk 需要哪一帧"的映射。若旧版视频元数据缺失,则显式回退到"full-source-pack"(整段源帧打包),保证 fail-closed。

物化侧(materializePlanV2Target)先完整校验所有选中 blob(大小 + SHA-256),再在临时目录原子性地rename到目标目录,并写入.hyperframes-plan-v2.json物化标记;validatePlanV2MaterializedTarget会在执行前再次复核子集完整性。meta/videos.json保证分块渲染与进程内渲染对含视频源的组合做到像素级可比——chunk worker 依据它重建BeforeCaptureHook,避免页面原生<video>元素相对预抽取图像偏离约 1 帧。

1.5 发布器:manifest-last 的 S3 与 GCS 实现

v2 的发布走"manifest-last"流程,确保 manifest 不会在全部引用 blob 持久化之前可见。

AWS 侧实现在 packages/aws-lambda/src/s3PlanV2Publisher.ts(S3PlanV2ArtifactPublisher):

  • putBlob:校验 sha256 格式与源文件字节数后,流式上传到<prefix>/v2/artifacts/sha256/<digest前2位>/<digest>,并登记已发布摘要;
  • commitManifest:遍历 manifest 中所有工件摘要,任一摘要未持久化即抛出PlanV2IntegrityError;随后在临时目录写 manifest.json 并上传到<prefix>/v2/manifest.json,状态置为committed
  • abort:未提交时状态置为aborted,远程 CAS blob 不可变,可被重试复用,未提交则不可达,由 bucket 的中间对象生命周期策略过期清理。

GCP 侧有对称实现 packages/gcp-cloud-run/src/gcsPlanV2Publisher.ts。两组发布器各自配套测试(s3PlanV2Publisher.test.ts、gcsPlanV2Publisher.test.ts)覆盖"manifest 先于 blob 可见"的竞态路径。

1.6 迁移与兼容:v0.7.111 下的升级路径

  • 新集成请使用planV2()planV2WithPublisher()(planV2.ts),后者接受任意实现PlanV2ArtifactPublisher接口的发布器(本地目录、S3、GCS 或其他持久化 CAS);
  • planV2()直接产出一个本地 v2 目录:先构建共享本地执行表示作为"planner 私有暂存",发布时把 2 GiB 传输上限禁用(executionPlanSizeLimitBytes: Number.MAX_SAFE_INTEGER),因为不再产出整体归档;
  • v1 的plan()createPlanV2FromV1/publishPlanV2FromV1兼容别名仍受支持,sourcePlanV1Hash线缆字段保留以便输出/重放关联(planV2.ts);
  • 显式升级期间(混合舰队),DISTRIBUTED_RENDER_CAPABILITIES保证 chunk/assembler 同时接受 v1 与 v2;目标路径层面,worker 在消费前通过readPlanProtocol判别协议,v2 必须先物化才能以 v1 布局访问(readPlanProtocolV1会拒绝未物化的 v2)。

二、pretext:window.__hyperframes上的文本测量钩子

2.1 为什么需要它:避开 DOM reflow 与不确定性的双刃剑

把文本写进 DOM 再读回来测宽,会强制触发 reflow——逐帧做既慢,又是不确定性来源(测量结果依赖读取时机)。v0.7.111 把基于 canvas 的测量面挂到运行时上,组合可以在任意帧测量字符串来决定容器尺寸、字号或断行位置,而无需扰动布局。

实现位于 packages/core/src/text/pretext.ts,围绕@chenglou/pretext封装,并在 packages/core/src/runtime/entry.ts 中随window.__hyperframes一起在脚本求值期立即挂载(早于DOMContentLoaded,因为字体适配常在脚本求值阶段就要跑)。

2.2 暴露的 API 面

方法用途
prepare(font)为某个 CSS 字体(如"700 48px Inter")测量字符串,返回 prepared 对象
layout(prepared, width)计算 prepared 字符串在给定宽度下的行数与总高度
prepareWithSegments(font)prepare,但保留分段以便测量各段宽度
measureLineStats(prepared, width)行数 +maxLineWidth(最宽的一行)
measureNaturalWidth(prepared)字符串在单行不换行时占据的宽度

2.3 调用位置的注意点(源码中的关键注释)

  • prepare/prepareWithSegments需要 canvas,只能在浏览器中调用,Node 中不可用;而 prepared 字符串下游的一切都是纯算术,足够便宜,可以逐帧执行。
  • 刻意不暴露clearCachesetLocale:二者会改变进程级全局状态,影响"同一文件每次渲染同一视频"的确定性保证。缓存按(segment, font)键控,segment 来自Intl.Segmenter的词语粒度切分,因此缓存随组合的词汇量增长而非随帧数增长——计数器或打字机逐帧重测会复用同一批条目,只有真正的新词才会分配内存,内存上界即组合的词汇表。
  • 增量游标 API(layoutNextLinewalkLineRanges等)尚无调用方,故暂不暴露。

2.4 与既有排版工具的关系

引擎的fitTextFontSize本身就是基于prepare+layout构建的(见 packages/core/src/text/pretext.ts 注释)。因此自定义工具获得这一测量钩子后,可以复刻引擎级排版决策(如精确字号缩放),并在浏览器端测试契约 packages/core/src/text/pretext.test.ts 与脚本 packages/engine/scripts/test-fitTextFontSize-browser.ts 中验证同样的测量语义。

三、Catalog 搜索:按词出现位置与稀有度排序

3.1 从子串匹配到词汇打分

v0.7.111 的 Catalog 搜索排序变更,实现在 packages/cli/src/registry/localSearch.ts。该模块文档开门见山:此前的子串测试description.includes(query)无法回答"让节奏突然变快"这类语义查询——因为没有任何描述包含该短语,诚实的结果是零匹配。新的打分器在离线、无模型、无网络的前提下用共享词汇作答。

打分管线(tokenize+rankByWords):

  1. 小写化,按[a-z]+切词;
  2. 丢弃停用词(STOP集合:the/a/an/and/or…);
  3. 丢弃长度 ≤ 3 的词;
  4. 复数折叠到单数PLURAL_RULESstories→storymatches→match,并保护press/status/axis这类非复数的尾部 s);
  5. 共享词计数除以条目词数的平方根——这个除数至关重要,否则最啰嗦的条目会凭表面积赢下所有查询。

rankByWords返回全部条目(零分排最后),由调用方决定截断点。

3.2 两个承重的加权设计

  • 强字段权重:命中条目名称/标题的词按STRONG_FIELD_WEIGHT = 3计分,远高于描述命中。没有它,搜 "typewriter effect on a title" 时字面叫typewriter的条目会排到第七名,落后于只是顺带提到打字效果的条目。作者敲出某个效果的名字是最强信号,不能被平均掉。
  • 稀有词加权(IDF 语义):每个词按其稀有度加权——这就是发布说明中"rarer words rank more accurately"所指的机制。常见词(如count)权重低,罕见复合词(如countdown)保留高逆文档频率权重。

3.3 复合词双向展开:只增信号、不发明匹配

expandCompounds处理"一个想法两种拼法"的问题:countdown是一个 token,count down是两个,两者永远无法互中。规则是:

  • 查询 token 长度 ≥ 6 时,若从中间切开的两个部分都是目录词汇表里的词,则把两部分以推断权重INFERRED_TOKEN_WEIGHT = 0.35加入(复合词本身始终保留);
  • 相邻查询 token 拼接后若在词汇表中,也以推断权重加入;
  • 两部分都不是目录词(如timer从未出现在任何条目中)则保持原样——这是拓宽措辞,不是编造匹配

推断权重 0.35 的存在是为了防止"半个词"喧宾夺主:以全强度让type去命中type-match-cut的名称,会压过typewriter命中typewriter名称的真信号。配套的 packages/cli/src/registry/localSearch.test.ts 固定了这些排序行为,另有hasNoSearchableTokens帮助调用方区分"查询无可用 token"与"目录确实没有匹配"(例如非英文脚本查询不会再被误报为缺失)。

四、内部工程:Studio 600 行上限拆分

v0.7.111 的最后一项是纯内部重构(PR #3313):将 Studio 中两个超过 600 行上限的文件拆分为多个。这是仓库既有行数纪律的延续——相关的被拆分文件(如属性面板、图层面板等模块)可在 packages/studio/src/components/editor/ 下看到拆分后的形态。该变更不改变任何对外行为,属于可维护性基建。

小结

v0.7.111 的三项公共能力分别解决一个问题:

  1. Plan v2 内容寻址传输让分布式云渲染摆脱 2 GiB 整体归档上限,通过 sha256 寻址 + 角色化物化让 chunk worker 只下载自己实际渲染的帧,manifest-last 发布保证引用完整性,同时以协议描述符 + 能力集为混合舰队升级留出显式兼容通道;
  2. pretext 文本测量钩子把引擎内部的 canvas 测量能力开放给组合脚本与自定义工具,以"prepare 一次、算术逐帧"的模式兼顾性能与渲染确定性;
  3. Catalog 搜索排序用"名称 3 倍加权 + 稀有词加权 + 复数折叠 + 复合词推断展开"的轻量打分器,离线显著改善目录检索的语义命中率。

对需要升级分布式渲染管线的开发者,建议优先核对 worker 的协议能力集声明(planProtocol.ts)与发布器实现(s3PlanV2Publisher.ts / gcsPlanV2Publisher.ts),并参考 planV2.test.ts 与 planProtocol.test.ts 中的边界用例完成迁移验证。

【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询