📄 文档管理系统

← 返回列表

不用学AE!3步用AI把网页变成视频,GitHub一周涨2k⭐的工具这么用

article #AI工具 #视频制作 #HyperFrames #pi #自动化 📅 创建:2026-05-30 01:10:57 🔄 更新:2026-05-29 17:12:38
👁️ 预览 & 复制到公众号 ✏️ 编辑

最近在 GitHub 上看到了一个挺有意思的项目——HyperFrames(heygen-com/hyperframes,Apache-2.0 协议,21,219 Stars)。

简单说,它就是一个 HTML → 视频的渲染器。你用网页技术写动画,它给你输出 MP4。

为什么值得写?最近 AI 视频赛道挺热闹的,Runway、Pika、Minimax 都在卷。但我更感兴趣的是生产级工具——能流水线跑的那种。HyperFrames 解决了这个问题:不管你有多少条视频要出,只要模板固定,AI 帮你批量生成。

正好最近在研究 pi(earendil-works/pi,56,679 Stars,MIT 协议),它和 HyperFrames 配合起来很有意思——pi 写代码,HyperFrames 出视频,整个链路都是 AI 驱动。

今天分享一下这个组合怎么用。


一、这两个工具是怎么配合的?

先说清楚它们的定位:

pi 是终端编程 harness,写 HTML/CSS/JS 能力的,但本身不输出视频。

HyperFrames 是渲染器,接收 HTML 文件,输出 MP4/WebM。

这两者之间没有原生集成——pi 写完 HTML,人把文件复制到 HyperFrames 项目目录里,跑 CLI 命令。所以流程是这样的:

用户(描述需求) → pi(写 HTML,含 HyperFrames 标记)
                        ↓
                HyperFrames CLI(lint → inspect → render)
                        ↓
                MP4 视频输出

核心连接点就是剪贴板——pi 输出代码,你复制进 HyperFrames 项目目录。


二、实战:生成一条 Pi Agent 介绍视频

2.1 初始化项目

npx hyperframes init pi-agent-video --example product-promo --non-interactive

这条命令做了几件事:
- 创建项目目录结构(index.html + compositions/ 文件夹)
- 复制示例资源到 assets/
- 安装依赖

项目长这样:

pi-agent-video/
├── index.html           # 主时间线场景调度
├── compositions/        # 各场景组件
├── assets/              # 资源文件
├── package.json
└── meta.json

2.2 写主时间线 index.html

主时间线文件负责把各个场景组件按时间顺序拼起来,类似视频编辑器里的序列轨道。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <title>Pi Agent - AI 编程助手</title>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      html, body {
        margin: 0;
        width: 1920px;
        height: 1080px;
        overflow: hidden;
        background: #0a0a0f;
        font-family: "Inter", sans-serif;
      }
      .scene { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
    </style>
  </head>
  <body>
    <div id="root" data-composition-id="main" data-start="0" data-duration="20" data-width="1920" data-height="1080">

      <!-- 背景音乐 -->
      <audio id="bg-music" src="E:/hermes-agent/share-video/static/music.mp3" data-start="0" data-volume="0.3" data-media-start="0"></audio>

      <!-- 场景 1: Logo 开场 (0-2秒) -->
      <div data-composition-id="scene1-logo-intro" data-composition-src="compositions/scene1-logo-intro.html" data-start="0" data-duration="2" data-track-index="1" data-width="1920" data-height="1080"></div>

      <!-- 场景 2: 什么是 Pi (2-6秒) -->
      <div data-composition-id="scene2-what-is-pi" data-composition-src="compositions/scene2-what-is-pi.html" data-start="2" data-duration="4" data-track-index="1" data-width="1920" data-height="1080"></div>

      <!-- 场景 3: 核心能力 (6-11秒) -->
      <div data-composition-id="scene3-core-features" data-composition-src="compositions/scene3-core-features.html" data-start="6" data-duration="5" data-track-index="1" data-width="1920" data-height="1080"></div>

      <!-- 场景 4: 技能展示 (11-16秒) -->
      <div data-composition-id="scene4-skills-tools" data-composition-src="compositions/scene4-skills-tools.html" data-start="11" data-duration="5" data-track-index="1" data-width="1920" data-height="1080"></div>

      <!-- 场景 5: 结尾 (16-20秒) -->
      <div data-composition-id="scene5-outro" data-composition-src="compositions/scene5-outro.html" data-start="16" data-duration="4" data-track-index="1" data-width="1920" data-height="1080"></div>
    </div>

    <script>
      window.__timelines = window.__timelines || {};
      const mainTl = gsap.timeline({ paused: true });
      window.__timelines["main"] = mainTl;
    </script>
  </body>
</html>

关键参数:
- data-composition-id — 每个场景的唯一标识(必须是有效 UUID 或字符串,不能留空)
- data-start — 在主时间线上的起始时间(秒)
- data-duration — 持续时长(秒)

2.3 写场景组件

场景组件是独立的 HTML 文件,放在 compositions/ 目录下。每个场景有自己的动画时间线。

场景 1:Logo 开场

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <title>Pi Logo 开场</title>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body {
        margin: 0;
        width: 1920px;
        height: 1080px;
        overflow: hidden;
        background: linear-gradient(135deg, #0a0a0f 0%, #1a1a2e 50%, #16213e 100%);
        font-family: "Inter", sans-serif;
      }
      #scene1-logo-intro {
        width: 1920px;
        height: 1080px;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
      }
      .logo-container { display: flex; flex-direction: column; align-items: center; gap: 20px; }
      .glow-ring {
        position: absolute;
        width: 400px;
        height: 400px;
        border: 2px solid rgba(108, 99, 255, 0.3);
        border-radius: 50%;
      }
      .pi-symbol {
        font-size: 180px;
        font-weight: 700;
        color: #fff;
        text-shadow: 0 0 80px rgba(108, 99, 255, 0.6);
      }
      .pi-wordmark { font-size: 72px; font-weight: 700; color: #fff; letter-spacing: 4px; }
      .tagline {
        font-size: 28px;
        font-weight: 400;
        color: rgba(255, 255, 255, 0.7);
        letter-spacing: 8px;
        margin-top: 20px;
      }
    </style>
  </head>
  <body>
    <div id="scene1-logo-intro" data-composition-id="scene1-logo-intro" data-width="1920" data-height="1080">
      <div class="glow-ring"></div>
      <div class="logo-container">
        <div class="pi-symbol">π</div>
        <div class="pi-wordmark">Pi Agent</div>
        <div class="tagline">你的 AI 编程助手</div>
      </div>
    </div>
    <script>
      (function () {
        const tl = gsap.timeline({ paused: true });

        // 光环动画:从小到大淡出
        tl.fromTo(".glow-ring", { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.8, ease: "power2.out" }, 0.2);
        tl.to(".glow-ring", { scale: 1.8, opacity: 0, duration: 0.6, ease: "power2.in" }, 1.0);

        // Pi 符号弹入
        tl.fromTo(".pi-symbol", { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.6, ease: "back.out(1.7)" }, 0.4);

        // 文字滑入
        tl.fromTo(".pi-wordmark", { y: 30, opacity: 0 }, { y: 0, opacity: 1, duration: 0.5, ease: "power2.out" }, 0.8);
        tl.fromTo(".tagline", { y: 20, opacity: 0 }, { y: 0, opacity: 1, duration: 0.5, ease: "power2.out" }, 1.1);

        // 淡出结束
        tl.to(".logo-container", { opacity: 0, duration: 0.4, ease: "power2.in" }, 1.6);

        window.__timelines = window.__timelines || {};
        window.__timelines["scene1-logo-intro"] = tl;
      })();
    </script>
  </body>
</html>

场景 2:产品定位

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <title>什么是 Pi</title>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body {
        margin: 0;
        width: 1920px;
        height: 1080px;
        overflow: hidden;
        background: linear-gradient(135deg, #0a0a0f 0%, #1a1a2e 50%, #16213e 100%);
        font-family: "Inter", sans-serif;
      }
      #scene2-what-is-pi {
        width: 1920px;
        height: 1080px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        position: relative;
      }
      .content { text-align: center; max-width: 1200px; }
      .headline {
        font-size: 80px;
        font-weight: 700;
        color: #fff;
        line-height: 1.2;
        margin-bottom: 40px;
      }
      .highlight { color: #6c63ff; }
      .description {
        font-size: 32px;
        font-weight: 400;
        color: rgba(255, 255, 255, 0.7);
        line-height: 1.6;
        max-width: 900px;
        margin: 0 auto;
      }
      .particles { position: absolute; width: 100%; height: 100%; pointer-events: none; }
      .particle {
        position: absolute;
        width: 6px;
        height: 6px;
        background: rgba(108, 99, 255, 0.5);
        border-radius: 50%;
      }
    </style>
  </head>
  <body>
    <div id="scene2-what-is-pi" data-composition-id="scene2-what-is-pi" data-width="1920" data-height="1080">
      <div class="particles">
        <div class="particle" style="top: 15%; left: 20%;"></div>
        <div class="particle" style="top: 25%; left: 75%;"></div>
        <div class="particle" style="top: 60%; left: 15%;"></div>
        <div class="particle" style="top: 70%; left: 85%;"></div>
        <div class="particle" style="top: 40%; left: 30%;"></div>
        <div class="particle" style="top: 80%; left: 60%;"></div>
        <div class="particle" style="top: 35%; left: 50%;"></div>
        <div class="particle" style="top: 55%; left: 70%;"></div>
      </div>
      <div class="content">
        <h1 class="headline">AI 协作的<br/><span class="highlight">新时代</span></h1>
        <p class="description">Pi 是你的私人 AI 编程助手,实时理解上下文、执行任务,<br/>从你的工作流程中不断学习进化。</p>
      </div>
    </div>
    <script>
      (function () {
        const tl = gsap.timeline({ paused: true });

        // 标题滑入
        tl.fromTo(".headline", { y: 50, opacity: 0 }, { y: 0, opacity: 1, duration: 0.8, ease: "power3.out" }, 0);

        // 描述文字滑入
        tl.fromTo(".description", { y: 30, opacity: 0 }, { y: 0, opacity: 1, duration: 0.6, ease: "power3.out" }, 0.5);

        // 粒子渐入 + 漂浮动画
        tl.to(".particle", { opacity: 1, duration: 0.4, stagger: 0.1 }, 0.2);
        tl.to(".particle", { y: -15, duration: 2.5, ease: "sine.inOut", stagger: 0.4 }, 0.5);

        // 场景结束淡出
        tl.to(".content", { opacity: 0, duration: 0.4 }, 3.6);

        window.__timelines = window.__timelines || {};
        window.__timelines["scene2-what-is-pi"] = tl;
      })();
    </script>
  </body>
</html>

其他三个场景(核心能力、技能展示、结尾 CTA)用类似结构编写,完整代码就不在这里展开了。

2.4 验证与渲染

写完组件之后,跑两条命令检查有没有问题:

# 语法和结构检查
npx hyperframes lint

# 布局溢出检查(文字有没有跑到框外)
npx hyperframes inspect

lint 会告诉你缺少什么属性、语法错误在哪;inspect 会渲染一遍时间线,报告布局问题。

都没问题的话,预览一下:

npx hyperframes preview --port 3002

这条命令会启动本地服务,给你一个 Studio URL,在浏览器里可以看到视频预览效果,带时间轴和播放控制。

最后,渲染输出 MP4:

npx hyperframes render --output "E:/pi-agent/hyperframes-video/pi-agent-intro.mp4" --quality high

输出参数说明:

参数 选项 默认值
--output 文件路径 renders/name_timestamp.mp4
--quality draft / standard / high standard
--fps 24 / 30 / 60 30
--format mp4 / webm mp4

三、跑通这条链路的关键细节

坑 1:data-composition-id 必须有效

如果属性值不合法(空字符串、格式错误的 UUID),lint 会报错但不说清楚原因。

修复方法:用标准 UUID 格式,比如 scene1-logo-intro(字符串也行,关键是不能为空)。

坑 2:CSS transform 和 GSAP 混用会冲突

/* 错误:GSAP 会覆盖 CSS transform */
.pi-symbol { transform: scale(0); }

/* 正确:用 fromTo 从初始状态开始动画 */
tl.fromTo(".pi-symbol", { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.6 }, 0.4);

记住规则:动画元素的初始状态交给 GSAP 管理,不要写在 CSS 里

坑 3:音频文件路径

背景音乐要用 <audio src="..." data-start="0"> 的形式,直接把 src 写在元素上,不要用子元素 <source>。否则 lint 会报 media_missing_src 错误。


四、这套组合适合什么场景?

适合 不适合
批量视频生产(相同模板,不同内容) 单条需要逐帧精修的视频
AI 驱动的自动化流水线 一次性的创意视频(用 AE/Pr 更顺手)
有明确时间线的结构化内容 复杂嵌套时间线、互相依赖的动画

总结一下:如果你有大量同类型的视频要出(产品介绍、教程合集、品牌宣传片),这条链路值得跑通。pi 负责写代码,HyperFrames 负责渲染,人只需要描述需求和最终质检,中间环节全自动化。


写在最后

AI 工具的价值不在于单个有多强,而在于能不能串成一条高效的工作流。pi + HyperFrames 这个组合,恰好说明了这一点。

工具本身没有壁垒——会用的人多了,壁垒就变成了用得熟练的程度

你平时有跑通过什么 AI 工作流?是怎么串起来的?评论区聊聊。


评论区预置内容

Pi + HyperFrames 这个组合上手真的快
原来还能这样用 AI 做视频
我之前用 Remotion,比这个麻烦多了
pi 写 HTML + HyperFrames 出视频,这条链路确实顺

💬 评论区

加载中...