framejam

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

FrameJam: style presets + one-click video and storyboard review

FrameJam:风格预设 + 一键式视频与分镜审阅

FrameJam runs next to your chat at http://localhost:2400. It gives you two things the chat is bad at: choosing a style (a structured
style.json
, plus a working Hyperframes template) and precise feedback (timestamped, pinned comments with a frame image of the render).
FrameJam works with whatever makes the video. The user reviews the rendered video (
videoPath
), so what they see is exactly what you rendered. Hyperframes is the default way to build a new video.
Words to use with the user: FrameJam calls each review a project (the start page is "Projects"). Say "I opened the project in FrameJam", not "I opened a review". Tool and field names (
open_review
,
reviewId
) stay as they are.
FrameJam 可在 http://localhost:2400 的聊天旁运行。它能补足聊天不擅长的两件事: 选择风格(结构化的
style.json
,以及一个可正常工作的 Hyperframes 模板)和精准反馈 (带时间戳的固定评论,并附有渲染画面的帧图像)。
FrameJam 可配合任何用于制作视频的工具。由用户审阅渲染后的视频(
videoPath
),因此他们看到的 正是你渲染出来的内容。Hyperframes 是制作新视频的默认方式。
与用户沟通时使用的措辞: FrameJam 将每次审阅称为一个 project(起始页为“Projects”)。应说 “我在 FrameJam 中打开了 project”,而不是“我打开了一次 review”。工具名和字段名(
open_review
、
reviewId
)保持 不变。

0. Open FrameJam in the built-in browser (always do this first)

0. 在内置浏览器中打开 FrameJam(始终先执行此步)

As soon as this skill is used, open FrameJam where the user can see it, without being asked:
  • Cursor: use the built-in browser tool (
    cursor-ide-browser
    →
    browser_navigate
    ) with
    position: "side"
    so it opens beside the chat.
  • Other harnesses: use their browser/preview tool if there is one. Otherwise give the user the link.
  • Which page: the project's
    url
    when step 1 finds one,
    http://localhost:2400/styles
    for a new video, and
    http://localhost:2400
    (Projects) until you know.
  • If the page doesn't load, nothing is hosting the UI. Run
    npx -y framejam start
    (it starts the UI in the background, or reuses a running one, and prints the URL), then open that URL. Never ask the user to start it.
  • If the framejam tools themselves aren't available, run
    npx -y framejam install <app>
    with the app you're running in (
    cursor
    ,
    claude
    or
    codex
    ). It adds the MCP server and the skill (or confirms them) and starts the UI. Open the link it prints, then tell the user the last step it prints (restarting the app once so the tools load).
使用此 skill 后,立即在用户可见的位置打开 FrameJam,无需询问:
  • Cursor: 使用内置浏览器工具(
    cursor-ide-browser
    →
    browser_navigate
    ),并设置
    position: "side"
    ,使其在聊天旁打开。
  • 其他 harness: 如果有浏览器或预览工具,则使用对应工具;否则向用户提供链接。
  • 要打开的页面: 第 1 步找到项目时使用项目的
    url
    ;新视频使用
    http://localhost:2400/styles
    ;尚未确定时使用
    http://localhost:2400
    (Projects),直到确定具体页面。
  • 如果页面无法加载,说明没有进程在托管 UI。运行
    npx -y framejam start
    (它会在后台启动 UI, 或复用一个正在运行的实例,并打印 URL),然后打开该 URL。绝不能让用户自行启动。
  • 如果 FrameJam 工具本身不可用,根据当前使用的应用运行
    npx -y framejam install <app>
    (
    cursor
    、
    claude
    或
    codex
    )。它会添加 MCP server 和 skill(或确认二者已安装)并启动 UI。 打开它打印的链接,然后告知用户打印出的最后一步(重启应用一次,以便加载工具)。

1. Work out what the user is doing (before asking anything)

1. 弄清用户想做什么(提问前先执行)

The user may type nothing but
/framejam
. Check these in order and act on the first that applies. Don't ask "what do you want to make?" if any of them answers it.
  1. What they typed. "/framejam make a 10s teaser for X" → do that. A style check is only needed for a new video.
  2. This conversation. If you've been making or editing a video in this chat, keep going with it: render the current state to the next
    renders/vN.mp4
    , then add it to the same project (
    add_version
    with its
    reviewId
    , or
    open_review
    with the same
    title
    ), and wait for feedback.
  3. Feedback waiting. Call
    list_reviews()
    . If a project is
    sent_not_delivered
    or
    user_commenting
    , call
    get_feedback({ reviewId })
    and apply it.
  4. A FrameJam project for this folder: one whose
    videoPath
    or
    panelsDir
    is inside the current workspace.
    • awaiting_user
      : open its
      url
      and call
      wait_for_feedback
      .
    • delivered_to_agent
      : an earlier chat got the comments but never shipped the next version. Call
      get_feedback
      to get them again, apply them, and ship the next version.
    • A storyboard the user approved, and no video yet: build the video from the panels.
  5. A video project here, but no FrameJam project. A Hyperframes
    index.html
    with
    data-composition-id
    , a Remotion or Motion Canvas project, a
    renders/
    folder or a loose video file: use the newest render if it's newer than the source, otherwise render. Open it as v1 and wait for feedback. Use the project's own tool; for a plain video file, pass
    videoPath
    only.
  6. Nothing relevant (empty folder, unrelated code repo): open the Styles page and ask what video to make: what it's about, roughly how long, the format (16:9, 9:16, 1:1), and any copy, footage or brand assets. Mention they can pick a look on the Styles page. Don't start building from a style alone. New videos default to Hyperframes.
If several projects could match, ask one short question that lists them.
用户可能只输入
/framejam
。请按以下顺序检查,并执行第一个适用的项目。如果其中任何一项已经说明了 用户的需求,就不要询问“你想制作什么?”。
  1. 用户输入的内容。 “/framejam make a 10s teaser for X”(为 X 制作一个 10 秒预告片)→ 照此执行。只有新建视频时才需要检查风格。
  2. 当前对话。 如果你一直在当前聊天中制作或编辑视频,请继续处理:将当前状态渲染到下一个
    renders/vN.mp4
    ,然后将其添加到同一个 project(使用
    add_version
    并传入其
    reviewId
    , 或使用
    open_review
    并保持相同的
    title
    ),随后等待反馈。
  3. 有反馈正在等待。 调用
    list_reviews()
    。如果某个 project 的状态为
    sent_not_delivered
    或
    user_commenting
    ,调用
    get_feedback({ reviewId })
    并应用反馈。
  4. 当前文件夹中的 FrameJam project: 其
    videoPath
    或
    panelsDir
    位于 当前工作区内。
    • awaiting_user
      :打开其
      url
      并调用
      wait_for_feedback
      。
    • delivered_to_agent
      :之前的对话已收到评论,但从未交付下一版本。调用
      get_feedback
      再次获取评论,应用修改并交付下一版本。
    • 用户已批准某个分镜,但尚无视频:根据这些面板构建视频。
  5. 此处有视频项目,但没有 FrameJam project。 例如:包含
    data-composition-id
    的 Hyperframes
    index.html
    、Remotion 或 Motion Canvas 项目、
    renders/
    文件夹,或者一个单独的動画文件:如果最新渲染比源文件更新,则使用最新渲染;否则重新渲染。以 v1 打开并等待反馈。使用项目自身的工具;对于普通视频文件,只传入
    videoPath
    。
  6. 没有相关内容(空文件夹、无关代码仓库):打开 Styles 页面,并询问用户想制作什么视频:主题是什么、大致时长、格式(16:9、9:16、1:1),以及是否有文案、素材或品牌资产。 提醒用户可以在 Styles 页面选择视觉风格。不要仅凭风格就开始制作。新视频默认使用 Hyperframes。
如果可能匹配多个 project,请提出一个简短问题,并列出这些候选项。

The loop

工作循环

  1. Style. Call
    get_selected_preset
    . If it returns
    selected: null
    , ask the user to pick one on the Styles page you just opened (then call it again), or pick one yourself with
    list_presets({ mood, pacing, format })
    and
    get_preset(id)
    .
    • Follow
      style.guide
      literally, whatever the tool. Use the exact
      palette
      hex values,
      fonts
      ,
      easing
      names,
      transitions
      ,
      textAnimations
      and
      rhythm.averageShotSeconds
      .
    • templateFiles
      is a working Hyperframes composition. In a Hyperframes project, copy it in and replace the copy rather than starting from a blank file. With any other tool, don't copy it; read it as a reference for the look.
  2. Build the video with the project's tool (Hyperframes details below, other tools further down).
  3. Render to a new file per version, e.g.
    renders/v1.mp4
    ,
    renders/v2.mp4
    , so earlier versions stay comparable.
  4. Open the review:
    open_review({ title, videoPath: "<abs>/renders/v1.mp4" })
    . Use an absolute path, and the same
    title
    every time so later renders become new versions of this project. Open the returned
    url
    in the built-in browser (step 0) and tell the user in one line: "Click the video to point at something (or pause and type), then press Finish review."
  5. Wait, in the same turn: call
    wait_for_feedback({ reviewId })
    right after opening the review. Don't end your turn first — the review page shows "Agent listening" only while you're in this loop.
    • status: "pending"
      means nothing arrived in the last ~50s. Call it again right away, without asking the user.
    • Stop after 12
      pending
      results in a row (about 10 minutes).
      Don't wait forever. End your turn with one short message: the project's
      url
      , "Press Finish review when you're done, then paste the line the page shows (or say
      apply my FrameJam feedback
      ) and I'll pick it up." The comments are saved, so nothing is lost. When the user comes back, call
      get_feedback
      (step 1.3). Stop earlier if the user tells you to in chat.
    • status: "feedback"
      returns
      comments[]
      , a markdown summary, and frame images.
    • revised: true
      means the user reopened their review after you got it and changed the comments. The new list replaces the old one: drop changes from the old list that aren't in the new one.
    • Done? If the comments only say the video is done, approved or good to go, with nothing to change, don't make another version. Tell the user where the final file is and stop waiting.
  6. Apply every comment.
    • at
      /
      time
      /
      endTime
      is where in the video.
      position
      is where in the frame.
    • The frame image for a pinned comment has the pin drawn on it: look at what's under the pin, then find that element in your source at that time.
    • wholeVideo: true
      means a global note (pacing, colour, music, and so on).
  7. Ship the next version. Re-render to
    renders/v2.mp4
    , then call
    add_version({ reviewId, videoPath, note })
    (or
    open_review
    again with the same
    title
    ). The
    note
    is a one-line summary of what you changed; the user sees it when the new version arrives and in the version menu. Each version is one round: the user's "Finish review" locked the previous version, and the new one starts with no comments. If you couldn't address a comment, say why in chat and in the note.
  8. Go back to step 5.
  1. 风格。 调用
    get_selected_preset
    。如果返回
    selected: null
    ,请用户在刚打开的 Styles 页面 选择一个风格(然后再次调用),或者自行调用
    list_presets({ mood, pacing, format })
    和
    get_preset(id)
    选择一个。
    • 无论使用哪种工具,都必须严格遵循
      style.guide
      。准确使用
      palette
      十六进制值、
      fonts
      、
      easing
      名称、
      transitions
      、
      textAnimations
      和
      rhythm.averageShotSeconds
      。
    • templateFiles
      是一个可正常工作的 Hyperframes 合成项目。在 Hyperframes 项目中,应将其复制进来并替换该副本, 而不是从空白文件开始。使用其他工具时不要复制它;应将其作为视觉风格参考。
  2. 使用项目的工具构建视频。
  3. 每个版本都渲染为新文件,例如
    renders/v1.mp4
    、
    renders/v2.mp4
    ,以便比较早期版本。
  4. 打开审阅:
    open_review({ title, videoPath: "<abs>/renders/v1.mp4" })
    。使用绝对路径,并且始终使用相同的
    title
    ,让后续渲染成为同一 project 的新版本。 在内置浏览器中打开返回的
    url
    (第 0 步),并用一行告诉用户: “点击视频以标注某个位置(或暂停后输入),然后按 Finish review。”
  5. 在同一轮中等待: 打开审阅后立即调用
    wait_for_feedback({ reviewId })
    。不要先结束当前轮次—— 只有你处于此循环中时,审阅页面才会显示“Agent listening”。
    • status: "pending"
      表示最近约 50 秒内没有收到任何内容。立即再次调用,不要询问用户。
    • 连续收到 12 次
      pending
      结果后停止
      (约 10 分钟)。不要无限等待。用一条简短消息结束当前轮次:提供项目的
      url
      ,并说明“完成后按 Finish review,然后粘贴页面显示的那一行(或说
      apply my FrameJam feedback
      ),我会继续处理。”评论会被保存,因此不会丢失任何内容。当用户返回时,调用
      get_feedback
      (第 1.3 步)。如果用户在聊天中要求停止,则提前停止。
    • status: "feedback"
      会返回
      comments[]
      、Markdown 摘要和帧图像。
    • revised: true
      表示用户在你获取反馈后重新打开了审阅并修改了评论。新列表 替换旧列表:丢弃旧列表中未出现在新列表里的修改。
    • 完成了吗? 如果评论只表示视频已完成、已批准或可以使用,并且没有任何需要修改的内容,就不要制作另一个版本。告知用户最终文件的位置,然后停止等待。
  6. 应用每一条评论。
    • at
      /
      time
      /
      endTime
      表示视频中的位置。
      position
      表示画面中的位置。
    • 固定评论的帧图像上会画出图钉:查看图钉下方的内容,然后在对应时间的源文件中找到该元素。
    • wholeVideo: true
      表示全局备注(节奏、颜色、音乐等)。
  7. 交付下一版本。 重新渲染为
    renders/v2.mp4
    ,然后调用
    add_version({ reviewId, videoPath, note })
    (或再次使用相同
    title
    调用
    open_review
    )。
    note
    是一行修改摘要;用户会在新版本到达时以及版本菜单中看到它。 每个版本对应一轮:用户点击“Finish review”会锁定上一版本,新版本开始时没有评论。如果某条评论无法处理,请在聊天和
    note
    中说明原因。
  8. 返回第 5 步。

Hyperframes (the default)

Hyperframes(默认方式)

  • First run on this machine: run
    npx hyperframes doctor
    once. It checks Node, ffmpeg and Chrome, which rendering needs. If something is missing, tell the user how to install it before you build.
  • Build the composition:
    index.html
    with a root
    data-composition-id
    +
    data-width
    /
    data-height
    ,
    .clip
    elements with
    data-start
    /
    data-duration
    /
    data-track-index
    , and a paused GSAP timeline registered in
    window.__timelines["<id>"]
    . Run
    npx hyperframes lint
    and fix errors.
  • Render:
    npx hyperframes render -o renders/v1.mp4
    .
  • Open: pass
    videoPath
    , like any other tool. The user reviews the render.
  • 本机首次运行: 运行一次
    npx hyperframes doctor
    。它会检查渲染所需的 Node、ffmpeg 和 Chrome。如果缺少某项内容,请先告知用户如何安装,再开始构建。
  • 构建合成项目:
    index.html
    的根元素需要包含
    data-composition-id
    和
    data-width
    /
    data-height
    ;
    .clip
    元素需要包含
    data-start
    /
    data-duration
    /
    data-track-index
    ;并需将一个处于暂停状态的 GSAP 时间线注册到
    window.__timelines["<id>"]
    中。运行
    npx hyperframes lint
    并修复错误。
  • 渲染:
    npx hyperframes render -o renders/v1.mp4
    。
  • 打开: 像使用其他工具一样传入
    videoPath
    。由用户审阅渲染结果。

Other tools (Remotion, Motion Canvas, ffmpeg, recordings, …)

其他工具(Remotion、Motion Canvas、ffmpeg、屏幕录制等)

  • Keep the project's own tool and render command (
    npx remotion render
    , the Motion Canvas exporter, an ffmpeg script, a screen recording). Don't convert the project to Hyperframes.
  • Render each version to a new mp4/webm/mov file and call
    open_review({ title, videoPath })
    .
  • Use the preset's
    style.guide
    ,
    palette
    ,
    fonts
    ,
    easing
    and pacing in the tool's own terms.
  • 保留项目自身的工具和渲染命令(
    npx remotion render
    、Motion Canvas 导出器、ffmpeg 脚本、 屏幕录制)。不要将项目转换为 Hyperframes。
  • 每个版本都渲染为新的 mp4/webm/mov 文件,并调用
    open_review({ title, videoPath })
    。
  • 使用预设中的
    style.guide
    、
    palette
    、
    fonts
    、
    easing
    和节奏,并以所用工具自身的术语来表达。

Storyboards (before there's a video)

分镜(尚无视频时)

Use a storyboard review when the user wants to agree on the shots first, or asks for a storyboard, shot list, or "frames before we animate". Same loop, but each version is a set of still panels instead of a render.
  1. Make the panels. One image per shot (png, jpg, webp, gif or svg), all the same aspect as the final video, in one folder, named so they sort in order:
    storyboard/01.png
    ,
    02.png
    , … Good sources, in order of preference:
    • Hyperframes snapshots of a rough composition (
      npx hyperframes snapshot --at 0.5,2.5,4.5 -o storyboard
      ), or stills from the project's own tool.
    • Images you generate, one per shot.
    • Quick HTML mockups you screenshot.
  2. Open it:
    open_review({ title, panelsDir: "<abs>/storyboard", panels: [{ path: "01.png", title: "Cold open", caption: "Slow push in. VO: 'Every team ships faster now.' 2s" }, …] })
    .
    panels
    is optional; without it every image in the folder is used in file-name order. Titles and captions are what the user reads under each panel, so put the shot name, the action or camera move, the voiceover line and the duration there.
  3. Wait with
    wait_for_feedback
    , exactly as for videos (open the URL in the built-in browser first, and stop after 12
    pending
    results in a row).
  4. Read the comments by panel.
    at
    is
    "panel 3 (Cold open)"
    ,
    panel
    has the number, title, caption and the panel's
    imagePath
    , and
    position
    is where on the panel the user clicked. The attached image shows the panel with the pin drawn on it.
    wholeVideo: true
    means the whole storyboard (order, pacing, adding or cutting shots).
  5. Next version: update or regenerate the images, then
    add_version({ reviewId, note })
    . With no media it re-reads the same
    panelsDir
    and keeps titles and captions for files that are still there; pass
    panels
    again to change the order, titles or captions. Earlier versions keep their own copies of the images.
  6. When the user approves the storyboard, build the video shot by shot from the panels and captions, and open it as a normal video review (a new
    open_review
    with the render as
    videoPath
    ).
当用户希望先就镜头达成一致,或要求分镜(storyboard)、镜头清单(shot list)或“先看画面再动画 (frames before we animate)”时,使用分镜审阅。流程与视频相同,但每个版本使用一组静态面板,而不是渲染结果。
  1. 制作面板。 每个镜头使用一张图片(png、jpg、webp、gif 或 svg),所有图片的宽高比均与最终视频一致, 并放在同一个文件夹中。文件命名应确保按正确顺序排序:
    storyboard/01.png
    、
    02.png
    ……。可用来源按优先级排序如下:
    • 粗略合成项目的 Hyperframes 快照(
      npx hyperframes snapshot --at 0.5,2.5,4.5 -o storyboard
      ), 或项目自身工具生成的静态帧。
    • 生成的图片,每个镜头一张。
    • 快速制作的 HTML 模型,然后截取屏幕图像。
  2. 打开它:
    open_review({ title, panelsDir: "<abs>/storyboard", panels: [{ path: "01.png", title: "Cold open", caption: "Slow push in. VO: 'Every team ships faster now.' 2s" }, …] })
    。
    panels
    是可选参数;如果不传,则按文件名顺序使用文件夹中的每张图片。标题和说明是用户在各面板下方看到的内容,因此应写明镜头名称、动作或运镜、旁白台词和时长。
  3. 使用
    wait_for_feedback
    等待,流程与视频完全相同(先在内置浏览器中打开 URL,并在连续收到 12 次
    pending
    结果后停止)。
  4. 按面板读取评论。
    at
    的值为
    "panel 3 (Cold open)"
    ;
    panel
    包含编号、标题、说明和面板的
    imagePath
    ;
    position
    是用户在面板上点击的位置。附加图像会显示已画出图钉的面板。
    wholeVideo: true
    表示针对整个分镜的反馈(顺序、节奏、增加或删除镜头)。
  5. 下一版本: 更新或重新生成图片,然后调用
    add_version({ reviewId, note })
    。没有媒体变更时,它会重新读取 同一
    panelsDir
    ,并为仍然存在的文件保留标题和说明;如需更改顺序、标题或说明,请再次传入
    panels
    。早期版本会保留各自独立的图片副本。
  6. 用户批准分镜后,根据面板和说明逐镜头构建视频,并将其作为普通视频审阅打开(使用新的
    open_review
    ,并将渲染文件作为
    videoPath
    )。

Other ways in

其他进入方式

  • If the user says "apply my FrameJam feedback" (with or without a review id), call
    get_feedback()
    . Without a
    reviewId
    it picks the review whose comments haven't reached you yet. If the user typed comments but never pressed Finish review, they're handed over now.
    list_reviews()
    shows every project and where its round stands.
  • If MCP isn't connected, the user can use Copy comments as text in the review page's version menu and paste the result into chat.
  • 如果用户说“apply my FrameJam feedback”(无论是否提供 review id),调用
    get_feedback()
    。如果没有
    reviewId
    ,它会选择评论尚未传给你的 review。如果用户输入了评论但从未按下 Finish review, 这些评论现在就会移交给你。
    list_reviews()
    会显示每个 project 及其当前轮次状态。
  • 如果 MCP 尚未连接,用户可以在审阅页面的版本菜单中使用 Copy comments as text,并将结果粘贴到聊天中。

Updating FrameJam

更新 FrameJam

If the user asks to update FrameJam, run
npx -y framejam@latest install <app>
with the app you're running in (
cursor
,
claude
or
codex
; without it, every app found on the computer is set up). It updates the skill, the MCP server entry and the FrameJam page that's running. Then tell the user to restart the app once: your FrameJam tools load the new version only after a restart.
如果用户要求更新 FrameJam,请根据当前使用的应用运行
npx -y framejam@latest install <app>
(
cursor
、
claude
或
codex
;如果不传,则为电脑上找到的每个应用完成设置)。它会更新 skill、MCP server 条目以及正在运行的 FrameJam 页面。然后请用户重启应用一次:只有重启后,FrameJam 工具才会加载新版本。

Rules

规则

  • Don't ask the user to describe timestamps in chat. Send them to the review page.
  • Never fake a render. If a render fails, fix it before opening the review.
  • Keep the review URL stable: one project per video, with a new version for each render.
  • Call it a "project" when you talk to the user.
  • 不要让用户在聊天中描述时间戳。引导他们到审阅页面操作。
  • 绝不能伪造渲染结果。如果渲染失败,先修复再打开审阅。
  • 保持审阅 URL 稳定:一个视频对应一个 project,每次渲染都创建新版本。
  • 与用户沟通时,要称其为“project”。