关于 scroll-video-website
用于构建或优化视频滚动控制网站的 Skill,面向编码 Agent,涵盖帧提取、Canvas 渲染、响应式适配、无障碍和验证。
主要功能
- 01构建滚动控制的视频体验
- 02提取编号 WebP 帧
- 03在 Canvas 上渲染并交叉淡化帧
- 04渐进式加载帧
- 05支持减少动态效果设置
适用场景
- 01将产品视频转为滚动揭示动画
- 02创建视频驱动的滚动叙事页面
- 03优化现有动画帧序列
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ musoyangrigor/ scroll-video-website-skill --skill scroll-video-website安装后在 Claude Code 中输入/scroll-video-website确认已加载。
附带文件agents/openai.yamlreferences/optimize.md
详细介绍
滚动视频网站
适用场景
当用户希望:
- 根据视频构建 Apple 风格的滚动动画;
- 创建由滚动控制或逐帧播放的视频网站;
- 将产品视频制作成电影感的落地页;
- 构建由视频驱动的滚动叙事体验;
- 将视频转换为经过优化的图像序列,用于滚动动画;
- 创建由滚动控制的 Canvas 产品展示动画;
- 优化现有生成的滚动视频帧序列。
不要将此技能用于普通的自动播放视频背景或无关的滚动效果。
创建一个精简的全页面体验,类似产品动画查看器:页面本身提供滚动距离,固定的 Canvas 填满视口,并根据用户的视频生成的帧序列逐帧播放。动画就是界面,而不是传统落地页背后的背景。
调用方式
此技能有两种模式:根据视频构建滚动视频网站,或优化现有帧序列。如果第一个参数是 optimize,请遵循 references/optimize.md,不要执行下面的构建流程。
将以下简洁形式视为完整的构建请求:
$scroll-video-website <path/to/video.mp4>
视频路径必须是技能名称后的第一个参数。路径之后的所有内容都是可选的样式、布局、文案或行为指示:
$scroll-video-website ./media/product-reveal.mp4
$scroll-video-website ./media/product-reveal.mp4 use a black background and condensed typography
第一个示例表示:生成帧序列,并构建下文所述的完整默认滚动动画网站。第二个示例中,保留相同的视频驱动动画架构,同时遵循新增的视觉指示。由使用此技能的 Agent 解读并实现提示中的其余内容;此技能不会为样式选项定义单独的命令语法。
除非视频路径是绝对路径,否则将其视为相对于当前工作目录的路径。如果路径中包含空格,用户应使用引号括起。首先检查给定的确切路径。如果该路径下没有此文件名,请在当前项目中搜索完全匹配的文件名,同时排除依赖项、构建、缓存和 VCS 目录。如果恰好找到一个匹配项,则自动继续。如果没有匹配项或存在多个匹配项,请询问用户提供准确路径。<path/to/video.mp4> 或 {video_path} 中的花括号表示占位符,不属于实际路径。不要要求或解读 use 关键字。
通过以下命令优化现有序列:
$scroll-video-website optimize
优化命令不接受路径或其他参数。检查当前项目中的生成帧序列。如果恰好能识别出一个序列,则继续。如果能识别出多个序列,请列出并询问用户要优化哪一个。如果找不到序列或无法可靠识别,请告知用户未找到 frames 文件夹,然后停止。
确认项目和源视频
开始编辑前:
- 检查项目结构、脚本、框架、样式、路由、资源约定和本地说明。
- 按照上述调用规则定位用户提供的视频。如果用户未提供视频或路径,且无法可靠识别,则在实现前询问用户。
- 复用现有可用技术栈。如果已有可用项目,不要另行搭建替代项目。
- 如果可以使用
ffprobe,则检查视频的尺寸、时长、帧率、帧数和文件大小。 - 保留无关行为,只进行所需的最小且协调一致的更改。
不要创建替代图稿,也不要替换用户提供的素材。除非构建确有需要,否则避免复制源视频。
将视频转换为帧序列
默认渲染路径是带编号的 WebP 帧序列,而不是 video.currentTime。将帧提取到项目的 public/static 资源目录中,并使用零填充的文件名,例如 frames/frame_0001.webp。
- 保留源视频的帧率,最高为 30 fps。对于较长的视频片段,将其采样为大约 240–300 帧,确保负载保持实用。
- 保留源视频的宽高比。使用约为 78–82 的合理 WebP 质量,并检查结果,不要想当然地认为设置合适。
- 在实现中记录实际提取的帧数;不要留下猜测的常量。
- 提取时优先使用
ffmpeg。典型命令为ffmpeg -i input.mp4 -vf fps=30 -c:v libwebp -quality 80 frames/frame_%04d.webp;根据输入、帧率、输出路径和现有项目工具进行调整。 - 不要删除或覆盖无关资源。如果目标目录中已有帧序列,请在替换前确认它属于此动画。
仅在无法提取帧或生成的帧负载明显不合适时,才直接逐帧暂停视频并跳转。如果采用回退方案,请说明其中的取舍,并保留相同的固定舞台、双向播放和平滑滚动行为。
匹配参考体验
如果用户没有提出其他布局或文案要求,请制作纯画布页面:
- 白色页面,以及覆盖
100vw×100vh、溢出隐藏的固定舞台; - 文档高度足以实现有意设计的滚动播放效果;对于 8 秒或约 240 帧的源视频,高度约为
400vh; - 不添加导航栏、卡片、标题、行动号召、渐变或臆造的营销文案;
- 画布填满舞台,并使用
cover几何方式绘制每一帧,沿两个轴居中; - 仅在首帧就绪后进行简短的透明度渐显,避免闪现空白帧;
- 仅在符合视频素材时使用克制的图像处理,例如白色背景、轻微调整对比度,或为白底产品渲染图使用
mix-blend-mode: multiply。
如果用户要求添加内容,请保持精简,并将内容放在动画中刻意安排的时刻之上或之间,不要削弱画布的视觉主导地位。原生画布和浏览器 API 已足够时,不要引入动画依赖。
实现画布滚动播放
使用包含 aria-hidden 画布的固定或粘性舞台。根据设备像素比设置画布的后备缓冲区,最高约为 2,同时使用 CSS 像素进行绘制测量。调整大小时,先重置画布变换,再应用新的 DPR 缩放,避免缩放累积。
将页面总进度限制在有效范围内,并映射到完整帧序列:
const range = document.documentElement.scrollHeight - innerHeight
const progress = range > 0 ? Math.min(1, Math.max(0, scrollY / range)) : 0
targetFrame = progress * (frameCount - 1)
向前滚动必须推进动画,反向滚动必须倒放动画。滚动和调整大小的处理程序只应更新开销低的测量值或目标位置。运行单个 requestAnimationFrame 循环,并使用与帧率无关的指数插值平滑浮点播放头:
const dt = Math.min((now - lastTime) / 1000, 0.1)
const alpha = 1 - Math.exp(-dt * 9)
currentFrame += (targetFrame - currentFrame) * alpha
绘制播放头两侧的整数帧,并按小数余数对下一帧进行交叉淡化。先清除画布或绘制背景,绘制后重置 globalAlpha,并在调整大小时重新绘制。
渐进式加载帧
不要等待整个序列加载完毕后才进行首次绘制:
- 先加载第 1 帧,绘制后显示画布。
- 将时间线上的均匀分布帧加入队列,例如每隔 8 帧加载一帧,以便尽早为跳转提供邻近的回退帧。
- 将其余帧加入队列。
分别跟踪已请求的帧和已加载的帧,确保优先加载和剩余帧加载阶段不会重复请求同一张图片。请求的帧仍在加载时,绘制最近的已加载帧。处理图片加载失败时,不要让序列的其余部分停滞。
使用适用于项目基础路径和部署目标的资源 URL 方案。所属组件卸载时,清理滚动、调整大小、媒体查询监听器、观察器和动画帧。
响应式行为与无障碍
在窄屏上保持 cover 渲染,并接受有意裁切;不要扭曲图像。在桌面和移动设备尺寸下检查重要主体的位置。如果添加了可见内容,请考虑移动视口变化和安全区域。
对于 prefers-reduced-motion: reduce,停止擦动并停留在第一个合适的帧。确保页面内容可访问,不要劫持滚动。装饰性画布不应向屏幕阅读器提供冗余内容。
验证结果
运行项目的检查,并在可用时通过浏览器检查结果。确认:
- 首个和最后一个滚动位置分别到达提取帧的首帧和末帧;
- 正向和反向滚动都流畅连续,没有突然跳变、播放、闪烁或明显的空白画布;
- 帧请求没有重复,缺失或加载缓慢的帧会使用相邻的已加载帧作为回退;
cover裁切、DPR 调整尺寸和画布缩放在桌面和移动设备尺寸下均正常;- 减少动态效果时会停留在静态帧,并且组件清理完整;
- 生成的序列具有预期的数量、尺寸和顺序,且总大小可接受;
- 项目中无关的功能仍可正常运行。
最后总结体验、提取的帧数和负载大小、运行的检查,以及任何仍存在的源媒体限制。