首页
/ OpenMontage 动效技能实战:用 `webpage` 分类模块把真实网页做成无旁白动效短片

OpenMontage 动效技能实战:用 `webpage` 分类模块把真实网页做成无旁白动效短片

2026-09-08 19:48:10作者:明树来

导读

在 OpenMontage 的 motion-graphics 技能体系里,webpage 是一个 search-driven(搜索驱动) 的分类模块,用于解决"把一个真实网页 / 链接做成一段动效短片"这一需求:用户给出或说出一个 URL → 抓取 / 捕获页面 → 用滚动浏览、UI 逐个浮现、光标演示、区域标注等手段把页面"演"出来。它的定位与给已有视频加字幕(embedded-captions)不同,也与"对网站做带旁白的解说视频"(website-to-video)不同——本模块的源素材是一张网页,产出是一段简短、无旁白的高光短片(highlight shot)。读完本文,你将掌握网页捕获、滚动 + 聚光 / 光标点击 / 缩放定位 / 标注图钉等动效原语的编排方法,以及两条贯穿始终的硬性规则(标注"扫"上去而不是预先贴上、一切锚定真实 DOM 元素的坐标)。

一、模块在技能树中的位置:先回答"要不要搜索"

webpage 分类模块定义在 .agents/skills/motion-graphics/categories/webpage/module.md,属于 motion-graphics(设计驱动的短动效编排技能)。该技能把全流程拆成 init → plan → source ◇ → design → build → render → verify 七个阶段;其中 plan 阶段的第一个决策就是:这个需求需不需要搜索?

根据这个分叉,分类被切成两组:

  • Form categories(无搜索,用户自带内容)kinetic-typestatchartslogo-reveallower-thirdsasset_needs 为空,plan 后直接进入 design;
  • Search-driven categories(先搜索再按返回内容类型动画):返回网页/链接 → webpage;返回新闻文章 → news;返回推文 → tweet;返回图片/实体 → asset-fusion

webpagenewstweetasset-fusion 一起构成了技能的 RWA(Real Web Asset)路径:先分析需求、搜索真实素材、评审取舍,再围绕素材设计镜头、最后用 catalog 复用组件来合成。webpage分类表格 中对应的动画描述是:"webpage / UI animation (scroll, reveal, cursor, callouts)"。

二、Source(Step 2):如何捕获真实网页

2.1 两种取源方式

模块规定网页素材来自两条途径,取其一即可:

  1. hyperframes capture 抓取页面,得到 DOM + 截图
  2. 用户直接提供一个现成截图。

抓下来的页面会被冻结(frozen)为项目本地的图片 / DOM,后续动画全部基于这份冻结素材,杜绝渲染期对网络的依赖。在 shot-plan IR 中,这一步的声明方式是向 asset_needs[] 写入一条资源需求:

{ "kind": "web", "source": "<url>", "treatment": "none" }

其中 kind: web 表示要捕获网页,source 是目标 URL,treatment: none 表示捕获后无需裁切、重着色或矢量化处理(对比 news 模块里人物照片要跑 hyperframes remove-background 得到透明抠像,网页素材通常直接整页冻存)。

source 阶段只在 asset_needs 非空时运行(详见 phases/source/guide.md),对每一条需求执行 analyze → search → review → freeze,并把最终结果写入 assets/ 与台账 assets/index.md。若搜索/捕获能力不可用,则在 context.log 中标记需求未满足,类别降级为无素材版本——但 webpage 类别的核心前提就是拿到可量测的页面 DOM,所以捕获是它的"灵魂步骤"。

2.2 hyperframes capture 的真实 CLI 形态

hyperframes capture 是 HyperFrames CLI 的脚手架命令,完整用法记录在 hyperframes-cli/references/init-and-scaffold.md。在 OpenMontage 技能库中可以看到它支持以下常用形态:

npx hyperframes capture https://stripe.com                  # 从网站抓取并脚手架化
npx hyperframes capture https://linear.app -o linear-video  # 自定义输出目录
npx hyperframes capture https://example.com --json          # 给 Agent 用的 JSON 输出
npx hyperframes capture https://example.com --skip-assets   # 跳过图片 / SVG 下载
npx hyperframes capture https://example.com --max-screenshots 12   # 限制截图张数
npx hyperframes capture https://example.com --timeout 60000 # 页面加载超时(毫秒)

这些参数的价值在 webpage 动画里非常直接:--json 让 Director / 自动化流程能结构化地读取捕获结果;捕获出的 HTML/DOM 正是后面"锚定真实元素位置"的技术前提(见第五节);--max-screenshots 控制整页采样密度,配合滚动浏览的分段镜头使用。

三、动效词汇与依赖规则:webpage 用到的原语

webpage 模块明确列出了它"借力"的规则和原语。规则侧指向 hyperframes-animation 的规则库({3d-page-scroll, demo-page-scroll-spotlight, cursor-click-ripple, coordinate-target-zoom, viewport-change}),其中实际存在的文件与作用如下:

规则 / 参考 文件 作用
3d-page-scroll rules/3d-page-scroll.md 整页做成有 3D 倾角的卡片,内部内容滚动以逐段揭示页面区块
demo-page-scroll-spotlight examples/demo-page-scroll-spotlight.html 滚动 + 聚光演示示例:页面滚动后高亮目标区(真实可渲染参考)
cursor-click-ripple rules/cursor-click-ripple.md 光标移到目标、按下(压扁回弹)、从点击点放射涟漪
coordinate-target-zoom rules/coordinate-target-zoom.md 缩放进入某个非居中元素(双层嵌套 + 反向平移)
viewport-change rules/viewport-change.md 单包装层模拟虚拟相机 zoom / pan / focus-lock

原语侧(共享词汇表见 references/motion-vocabulary.md)归结为五类:

  • scroll pan——滚动平移,对应整页滚动浏览;
  • spotlight/dim——聚光 / 压暗,突出关键区域;
  • cursor move + click-ripple——光标移动 + 点击涟漪,演示交互;
  • zoom-to-region——缩放到某个坐标区域;
  • callout pin + label——锚定在页面区域上的标注图钉与文字标签。

四、Build(reuse-first):把五个原语串成一段网页高光

模块对 build 阶段给出的是复用优先的组装指令,而不是从零写代码:

把捕获到的页面作为 base layer;做一个 scroll-through(沿页面高度做 translateY)、给关键区域打 spotlight(压暗 + 高亮)、让一个 cursor 移动并点击(涟漪)、zoom 到某个坐标,并在页面区域上锚定 callout 图钉 / 标签。全程遵守 builder-contract.md

结合 catalog-map.mdbuilder-contract.md,reuse-first 的实际含义是:优先执行 npx hyperframes add <block> 把 catalog 里现成组件的源码拉进 compositions/,然后在原位改数据 / 文案 / 配色 / 时间轴,只有 catalog 覆盖不到的缺口才手写。模块要求 Builder 在 shot-plan.json 的 IR 里把这些变成可执行指令。

4.1 webpage 在 shot-plan IR 中的 content 形态

shot-plan-ir.md 为每个分类定义了专属 content 结构,webpage 对应:

"webpage": {
  "url": "<源 URL>",
  "capture": "<冻结的捕获路径>",
  "highlights": [
    { "selector": "<CSS selector|region>", "label": "<标注文案>" }
  ]
}

注意 highlights 数组元素是 selector | region + label 的组合——这正是"高亮真实元素"这一技术路线的产物:Director 用 CSS selector 指名要讲解的真实 DOM 节点(或区域),Builder 再去测量它并做精确高亮,而不是凭感觉给坐标。

4.2 五段式的标准编排节奏

把模块描述的动画意图和规则库的参考实现合起来看,一条典型的 webpage 高光镜头大致是这种节奏:

  1. 入场:捕获页(base layer)落定,可以是 3D 倾角卡片或平面整页;
  2. scroll-through:把内容容器沿 translateY 从页首滚动到目标区块(见 3d-page-scroll 的实现);
  3. spotlight:滚动落定后,一个径向渐变聚光罩淡入,压暗四周、突出焦点区(同一规则里的 spotlight overlay);
  4. cursor + click / zoom-to-region:光标移动到页面某个可交互元素上,压下并释放涟漪(cursor-click-ripple),或相机缩放进入某个非居中区域(coordinate-target-zoom / viewport-change);
  5. callout:缩放或点击落定后,图钉 + 标签浮现,给出说明性文案,然后停留足够让观众阅读的"高潮驻留"时长。

examples/demo-page-scroll-spotlight.html 就是这个能力的可渲染参照:它的时间轴注释清楚写了 9 秒四阶段的编排——3D 倾角卡片入场(0.00–0.80s)、导航/标题/CTA 逐个淡入(0.12–2.80s)、页面内容向上滚 280px(3.08–4.08s)、主视频以 translateZ 前冲 + 径向聚光压暗四周(3.58–8.84s)。其中滚动是通过 tl.to("#scroll-content", { y: -280, ease: "power2.inOut" }) 这类 y 平移完成的"程序化滚动感",聚光则是独立的 opacity 叠加层——两者都不会和 GSAP 抢同一个 transform。

五、两条不可违背的规则(与 news 模块共用的设计铁律)

模块花最大篇幅强调的两条规则,和同目录的新闻文章高亮模块(news/module.md)是同源设计:

规则一:标注是"扫"上去 / "动"上去的,绝不预先贴好(Highlights are swept ON, never pre-applied)

页面的任何讲解性标注都不允许在镜头开始时就已经存在。模块给出的禁止/允许对照如下:

  • 聚光框应当擦入scaleX 0→1),而不是开画就有;
  • marker 应当扫过某个区域;
  • callout 应当在 zoom 落定之后才弹出。

这样做的动效原因是观众的眼睛需要被引导:页面永远从"干净未标注"的状态开始,讲解信息在节奏点被表演出来,而不是一开始就铺满批注让观众无从看起。这与 news 模块 中"关键词高亮带在文字安定后才 L→R 扫出"(用 background-size 生长而不是 transform:scaleX 的 bar)是同一个原则的两种实现,也都指向"先呈现内容,再高亮局部"。

规则二:锚定真实元素位置,别靠肉眼估坐标(Anchor to REAL element positions)

因为 hyperframes capture 给的是页面真实的 HTML/DOM,所以:

  1. 用 DOM 拿到目标元素的真实量测结果;
  2. 把页面坐标换算成舞台局部坐标(getBoundingClientRect → stage-local);
  3. 用这个精确值去 zoom / 高亮,做到"step-by-step 高亮真实元素"。

模块明确禁止"Don't eyeball coords"。这条规则在 coordinate-target-zoom 规则里有完整的工程化落地方案:缩放的目标偏移要在 setup 时量一次真实 DOM,而不是手推公式。该规则文件给出的测量模板是:

await document.fonts.ready; // 等字体就绪,fallback 字体测量会偏 10–30px,放大 3× 后会被放大成几十像素
const W = 1920, H = 1080;
const r = document.getElementById("target-card").getBoundingClientRect();
const TARGET_OFFSET_X = r.left + r.width / 2 - W / 2;
const TARGET_OFFSET_Y = r.top + r.height / 2 - H / 2;
// 把 -TARGET_OFFSET_X / -TARGET_OFFSET_Y 作为 counter 平移喂给内层 tween

并且明确两个边界:

  • 缩放封顶:目标在峰值时不要超过画布的 ~88%——maxScale = Math.min((0.88*W)/r.width, (0.88*H)/r.height)。填满画面意味着中心一偏就被裁切。
  • 只在"等宽对称卡片行"里才允许跳过测量,其余一律 getBoundingClientRect 实测,因为手推 offset 最容易犯的就是符号错误,而缩放会把错误放大到画面之外。

六、zoom 的两种实现:coordinate-target-zoom vs viewport-change

webpage 的"zoom to region / coordinate"有两种等价但数学不同的实现,规则库刻意对比,避免混用:

维度 coordinate-target-zoom viewport-change
结构 两层嵌套:外层缩放 scale、内层反向平移 translate 单层包装:一个 .world 上写 translate(x,y) scale(S)
反推公式 T = -offset(与 S 无关) T = -offset × S(与缩放相关)
适用 缩放和平移可以各自独立 tween、共享 duration/ease 需要单一相机状态源 cam{scale,x,y}、用 onUpdate 统一写 transform
陷阱 变换顺序不能放同一元素上,会与直觉相反 CSS 先应用 scale 再应用 translate(矩阵从右往左),混用两层公式会漂移离靶

两者共享的关键纪律是一致的:transform-origin: 50% 50%、场景必须 overflow: hidden、不要给包装元素写 CSS transition(会和 GSAP 打架)、will-change: transform、缩放落定后至少驻留 ≥1s 让人看清目标(Climax dwell)。对网页动效而言,一般做法是:需要把焦点"安放在画面中央"用嵌套双层;而想让光标移动 / 页面滚动与相机联动、需要逐帧换算世界坐标的 focus-lock,用单层 viewport 形式。

七、光标演示:cursor-click-ripple 的实现细节

网页动效里"演示点击某个按钮 / 表单"是高频镜头。规则 cursor-click-ripple 给出三阶段时间轴:Move → Click(压下+回弹)→ Ripple(涟漪)

  • Move:光标从入场角平移到目标中心,时长建议 0.4–1.0s;移动必须在 CLICK_AT 前结束,否则"边移动边点击"会读成误触。缓动可选 power2.inOut(沉稳)、back.out(1.2–1.4)(轻微过冲"落座"感)、power3.out(果断)。
  • Click:光标和目标一起压扁再弹回(yoyo:true, repeat:1),半程 PRESS_DUR 建议 0.06–0.12s;光标压缩幅度(0.80–0.90)应大于目标(0.92–0.97),因为光标是施动者。
  • Ripple:从点击点(目标的视觉中心,不是包围盒原点)向外扩散 1–3 圈涟漪,建议 RIPPLE_DUR 0.5–1.0s、scale 3–6、stagger 0.06–0.12s、缓动 power2.out;必须用 immediateRender: false 让涟漪在 t=0 保持不可见,否则会在错误尺寸下预渲染出来。

光标与涟漪元素全程 pointer-events: none、高 z-index、无 CSS transition/动画,保证 seek 时确定性成立。

八、builder-contract:所有编排都必须守住的底层契约

webpage 模块要求 build 全程遵守 references/builder-contract.md。结合网页动效场景,要点如下:

  • 舞台根节点必须有确定尺寸#stage 需要 position: relative; width/height 显式设好,否则 flex 子元素高度塌陷、内容堆到左上角,而 lint/inspect 并不会发现;
  • 先静态 CSS 后动画:先找"hero frame"(大多数元素同框的那一帧)用纯 CSS 摆好,再上 GSAP;入场一律 gsap.from(),CSS 里摆好的位置是"终点真值",tween 只是到达它的路径;
  • 时间轴契约:全局只有一条 gsap.timeline({ paused: true }) 挂到 window.__timelines["<id>"],以 data-composition-id 为注册键;tl.seek(0) 定位,永不 tl.play();带时间的元素用 class="clip" + data-start/data-duration/data-track-index + 稳定 id
  • 确定性:禁用 Date.now() / Math.random() / 网络;数字动画 tween 代理对象走 onUpdate(seek 安全),不做墙钟计数;
  • seek-safe 揭示:延迟元素用 gsap.set(el,{autoAlpha:0}) 一次性藏起,再在入场时 gsap.to(...,{autoAlpha:1}) 揭示;禁止用 set(opacity:1) + from(opacity:0) 的组合——在暂停/seek 渲染下元素会永远隐形;
  • 允许的缓动power1–4backbouncecircelasticexposine.in/.out/.inOut
  • 调色板纪律:颜色统一收敛到一个 palette 对象 / CSS 自定义属性里,不散落内联 hex。

九、把整段流程跑起来:从 URL 到成品 MP4

webpage 模块放进 motion-graphics 主流程 看,一次完整的"网页动效"交付包含以下动作(工作目录按技能约定统一在 PROJECT_DIR = videos/<project-name>/ 下,所有 Bash 用 (cd "$PROJECT_DIR" && ...) 子 shell,绝不裸 cd):

Step 0 · init:仅在 $PROJECT_DIR/hyperframes.json 缺失时执行:

PROJECT_DIR="${MOTION_GRAPHICS_DIR:-videos/<project-name>}"
mkdir -p "$(dirname "$PROJECT_DIR")"
npx hyperframes init "$PROJECT_DIR" --non-interactive --example=blank

Step 1 · plan(Director Part 1):决策是否搜索 → 属于 search-driven → 按"返回内容类型"确认走 webpage 分类 → 写 draft shot-plan.json(envelope + asset_needs + 一段 shot brief)。

Step 2 · source ◇asset_needs 非空则执行,hyperframes capture 冻结页面 DOM/截图到 assets/,写 assets/index.md 台账。

Step 3 · design(Director Part 2):围绕冻结素材设计镜头,把 content.webpageurl/capture/highlightsblockcustomize 写入最终 shot-plan.json

Step 4 · build(Builder):复用优先合成 compositions/index.html——npx hyperframes add <block> + 原位定制,遵守第五节与第八节全部约束。

Step 5 · render

(cd "$PROJECT_DIR" && npx hyperframes render . --skill=motion-graphics -q draft -o ./renders/video.mp4)
# 透明叠加变体:--format webm(或 mov)

Step 6 · verify

(cd "$PROJECT_DIR" && npx hyperframes lint . && npx hyperframes inspect .)

出错则由 finalize 子代理做一版快照 QA + 单次原地修复 + 重渲染,期间不得改动已固定的时长。成功后报告 renders/video.mp4(或 webm/mov 叠加变体)与时长,渲染结束后如用户要求再提供 npx hyperframes preview / play 预览。

十、与相邻类别的边界与协同

webpage 放回分类全景更能看清它的边界:

  • vs news(文章高亮):news 是把文章文本以可读字号(不放大)铺开、用 marker 带原位扫过高亮关键词,主版式是"居中强调(9:16 纯文字)"或"整篇文章卡(16:9 带 logo/人物)";webpage 高亮的是捕获页面上的真实 DOM 区域,手段是滚动 + 聚光 + 光标 + 缩放,二者共用"高亮扫入不预置"与"锚真实元素"两条铁律;
  • vs tweet / asset-fusion:都属于 search-driven 分支,只是返回内容类型不同;
  • vs website-to-video.agents/skills/website-to-video/ 技能):那是带解说、更长叙事的"网站解说视频",而 webpage 是"动效即信息"的无旁白短片,时长通常在 10s 上下;路由上不确定时先读 /hyperframes

十一、给自动化与手工调度的提示

  • resume 表(见 SKILL.md):无 shot-plan.json 从 plan 继续;有 asset_needs 但无 assets/ 从 source 继续;shot-plan.json 定稿但无 compositions/index.html 从 design+build 继续;有 index.html 无 render 从 render+verify 继续;MP4 已存在即收尾。这让网页动效任务天然支持断点续跑。
  • 环境前提:macOS Apple Silicon 或 Linux x64;brew install node ffmpeg;跑一次 npx hyperframes doctor。macOS GPU 渲染加 export PRODUCER_BROWSER_GPU_MODE=hardware
  • 素材冻结是底线:网页在 build/render 阶段是纯本地资产,不依赖网络;若页面后续变化,需要重新 capture 以保持证据与视觉一致。

结语

webpage 分类模块的价值在于把"真实网页"这种高信息密度、高真实感的素材安全地引入短动效流水线:capture 冻结 DOM 让你拥有可以精确量测与定位的真实页面,scroll / spotlight / cursor / zoom / callout 五个原语构成叙事语言,"标注扫入、锚真实坐标"两条铁律保证成品既清晰又可信。它不是一个孤立小工具,而是 OpenMontage 搜索驱动动效路径(webpage / news / tweet / asset-fusion)中的一环,其产出可直接落到 compositions/index.html,经 hyperframes lint/inspect/render 变成一段可在社交平台上直接投放的无旁白高光短片。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395