npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fourier-video/sdk

v4.0.1

Published

Typed TSX project, React, Motion, and Shader authoring SDK for Fourier

Downloads

460

Readme

@fourier-video/sdk

English | 简体中文

把前端视觉能力变成 Agent 可理解、可配置、可复用的视频组件。

Fourier SDK 是 Fourier 宿主与开发者生态之间的类型化创作接口。它既用于声明 Project、Scene 和 Template,也用于开发 React、Motion、Shader、Text Motion、Three.js 与程序化视觉 artifact。SDK ABI v1.2 使用真实 DOM/CSS/WAAPI/WebGL,由 Fourier Core 在宿主给定的绝对有理时间采样;Core/render 继续兼容读取 ABI v1/v1.1。

为什么选择 Fourier SDK

  • 复用 Web 开发生态:继续使用 TypeScript、TSX、React、CSS、Motion 和 Three.js,而不是学习封闭的动画描述格式。
  • 为确定性渲染而设计:绝对时间、稳定随机数、受控媒体和宿主时间轴让预览、seek、测试与导出保持一致。
  • 类型与 schema 同时服务人和 Agent:开发者获得类型检查,Agent 获得可发现的参数、默认值、边界与用途描述。
  • 能力开发一次、跨项目复用:组件、Scene、Template 和品牌视觉系统可以独立预览、测试,并发布到 Fourier World。
  • 运行环境由 SDK 持有:artifact 不必自行管理 React、Three.js 和 JSX runtime 版本,减少组件与宿主版本漂移。

Fourier SDK 的分工是让开发者创造高质量视觉能力,让 Agent 选择参数并组织视频;SDK 的 preview/testing/World 使用 Fourier Core,完整工程执行由 Render Engine 完成,组件可通过 Fourier World 发布和发现。

安装

要求 Bun >=1.3。安装 SDK 会传递安装 @fourier-video/core,无需显式安装 Core。React、JSX runtime 与 React 类型由 SDK 持有,视频工程不需要安装或声明 React。DOM Timeline 还需要安装与 Playwright 1.62.0 对应的 Chromium:

bun add @fourier-video/sdk
bunx playwright install chromium

macOS 使用 headed Chromium + CDP viewport capture;Linux 使用 headless shell + HeadlessExperimental.beginFrame。两者都暂停虚拟时间,不使用墙钟 sleep 或普通 Playwright screenshot 作为降级路径。

TSX 工程声明

@fourier-video/sdk/project 提供 defineProject、defineTemplate 和类型化 JSX 节点。工程、Scene 与 Template 都以 main.tsx 为唯一入口:

import { Canvas, defineProject, Project, Text, Timeline } from "@fourier-video/sdk/project";

export default defineProject(
  <Project id="hello" version="1.0" audioSampleRate={48_000}>
    <Canvas width={1920} height={1080} fps={30} background="#000000" colorSpace="sRGB" />
    <Timeline>
      <Text id="title" duration="2s" role="title" content="Hello"
        x={960} y={540} width={1200} height={180} layer={1}
        font="fonts/Inter.ttf" fontSize={96} lineHeight={1.1}
        color="#FFF" align="center" />
    </Timeline>
  </Project>,
);

作者属性使用原生 boolean、对象 props、content、tts 和 keyframes;after/with 使用裸 ID;裁切和导出字段分别是 sourceIn/sourceOut、exportName。声明会编译为引擎 IR,最终仍由 FFmpeg 渲染。

ABI v1.2 React

Artifact 使用 component,marker 固定为 ABI v1。component 只能读取 props;稳定的 width、height、seed 通过 hook 获取,逐帧 frame/fps/progress/time 不进入组件接口。

import {
  defineReact,
  field,
  useRef,
  useFourierContext,
  useFourierLifecycle,
  useFourierTimeline,
} from "@fourier-video/sdk";

export default defineReact({
  name: "MetricPanel",
  schema: { value: field.number({ min: 0, default: 42 }) },
  component({ props }) {
    const root = useRef<HTMLDivElement>(null);
    const { width, height } = useFourierContext();
    const timeline = useFourierTimeline();
    useFourierLifecycle({
      fourierStart() {
        if (root.current === null) throw new Error("missing root");
        timeline.animate(root.current, [
          { opacity: 0, transform: "translateY(20px)" },
          { opacity: 1, transform: "translateY(0px)" },
        ]);
      },
      fourierEnd() {},
    });
    return <div ref={root} style={{ width, height }}>{props.value}</div>;
  },
  designPreview() {
    return {
      props: {},
      composition: { width: 640, height: 360, durationSeconds: 3 },
    };
  },
});

没有 lifecycle、animation、media、SMIL 和 render driver 的 React artifact 是静态 artifact,只采样一次并复用 PNG。React 可注册零或一个 lifecycle;Motion 必须恰好注册一个。

Artifact 源码中的 React hook、ReactNode、CSSProperties、RefObject 等必须从 @fourier-video/sdk 或对应的 /react、/motion、/three 入口导入,不直接导入 react、react/jsx-runtime。3D 组件同样只能从 @fourier-video/sdk/three 导入 Three.js class、loader 和类型,不直接依赖 three。Core host 会把隐式 JSX runtime 和 SDK alias 到 SDK/render adapter 解析出的版本,因此 artifact 所在视频目录可以完全没有 package.json 和 node_modules。

ABI v1.2 Motion

Motion 必须通过 supportsTextMotion 显式声明是否支持文本。image/video/react 仍以当前时刻 subject 进入 component;文本不会混入该接口:支持文本的 Motion 必须另外实现接收原始字符串的 textComponent。结果仍按 Motion PNG → TSX Transform → FFmpeg layer/blend/opacity 合成。

export default defineMotion({
  name: "Reveal",
  schema: {},
  supportsTextMotion: false,
  component({ subject }) {
    const root = useRef<HTMLDivElement>(null);
    const timeline = useFourierTimeline();
    useFourierLifecycle({
      fourierStart() {
        if (root.current === null) throw new Error("missing root");
        timeline.animate(root.current, [
          { opacity: 0, transform: "scale(.9)" },
          { opacity: 1, transform: "scale(1)" },
        ]);
      },
      fourierEnd() {},
    });
    return <div ref={root}>{subject}</div>;
  },
  designPreview() {
    return {
      props: {},
      subject: <img src={imageDataUri} width={640} height={360} />,
      composition: { width: 640, height: 360, durationSeconds: 3 },
    };
  },
});

支持 Text Motion 时必须同时提供普通 subject 和文本两个实现:

export default defineMotion({
  name: "TextReveal",
  schema: {},
  supportsTextMotion: true,
  component({ subject }) {
    return <div>{subject}</div>;
  },
  textComponent({ text }) {
    return <span>{text}</span>;
  },
  designPreview() {
    return {
      props: {},
      subject: "Fourier",
      composition: { width: 640, height: 120, durationSeconds: 3 },
    };
  },
});

声明 supportsTextMotion: true 却缺少 textComponent 会在定义时失败;声明为 false 的组件用于 text/subtitle 宿主时会被引擎拒绝。

对于支持文本的 Motion,designPreview().subject 返回 string 时会自动走文本入口;作者不需要为 preview 编写分支或 renderer。

fill="none" 的非 active 区间直接返回原 subject;backwards、forwards、both 分别使用局部 0、连续 active 时间和完整 duration 边界。

ABI v1.2 Shader 修饰

defineShader() 把 SDK 持有的 WebGL2 shader 定义为可复用修饰器。当前宿主画面由 uFourierSource 提供;时间、进度、尺寸、时长和 seed 沿用现有 Fourier uniform。designPreview().subject 必须是已打包图片 URL 或 data URI。

Shader artifact 放在工程 shaders/ 下,可在 Image、Video、Text、Subtitle、ReactLayer 中声明多个 <Shader>:

<Image {...imageProps}>
  <Motion id="reveal" at="0f" duration="30f" fill="both" component="Reveal.tsx" />
  <Shader id="grade" at="0f" duration="30f" fill="both"
    component="ChannelShader.tsx" props={{ amount: 0.8 }} layer={10} />
  <Shader id="grain" at="0f" duration="30f" fill="both"
    component="Grain.tsx" layer={20} />
  <Transform {...transformProps} />
</Image>

执行顺序固定为 Motion → Shader → Transform。Shader 按 layer 升序,同层按声明顺序;每个 pass 保持宿主尺寸,fill="none" 的非活动区直接透传输入画面。完整 artifact 写法见 ChannelShader.tsx。

Timeline 与确定性随机数

useFourierTimeline().animate() 不返回原生 Animation,播放权始终属于宿主。省略 duration 时使用宿主时长;只支持有限的 duration/delay/iterations、固定 playback rate 1 和 replace composite。直接调用 element.animate() 会以 UNREGISTERED_WAAPI_ANIMATION 拒绝。

DOM timeline 也自动接管原生 <audio>/<video> 与 SVG SMIL animation。media 与 SMIL 会保持暂停并按宿主绝对时间 seek;普通 media 在结尾停住,loop media 按素材时长循环。素材使用本地相对 import 或 data URI,不要在组件中自行调用 play()、设置 currentTime 或推进 SVG timeline。

随机关键帧必须只由稳定 seed 生成:

const { seed } = useFourierContext();
const random = createFourierPrng(`${seed}:noise`);
const x = random() * 20 - 10;

声明式 Fourier Motion

常规 CSS 动画可以直接使用 SDK 内置的 motion.* interface,不安装 motion/framer-motion,也不复制它们的源码。FourierMotion 隐藏一次 lifecycle 注册,任意数量的 motion.div、motion.span 或 motion.create(tag) 都会进入同一条宿主控制时间轴:

import { FourierMotion, motion } from "@fourier-video/sdk/motion";

function Reveal({ children }) {
  return (
    <FourierMotion>
      <motion.div
        animate={[
          { opacity: 0, y: 48, filter: "blur(14px)", offset: 0 },
          { opacity: 1, y: 0, filter: "blur(0px)", offset: 0.42 },
          { opacity: 1, y: 0, filter: "blur(0px)", offset: 1 },
        ]}
        transition={{ ease: [0.16, 1, 0.3, 1] }}
      >
        {children}
      </motion.div>
    </FourierMotion>
  );
}

x/y/z 的数字单位为 px,rotate/skew 的数字单位为 deg;transition.duration/delay 使用秒。省略 duration 时仍铺满 Motion 宿主时长。接口不返回原生 Animation,因此预览、测试和正式导出保持相同的绝对时间定位语义。

Fourier Three.js

3D React artifact 使用 SDK 持有的 @fourier-video/sdk/three。该入口同时导出 React authoring API、Three.js、GLTFLoader 与 FourierCanvas,组件不安装或直接导入 react/three:

import modelUrl from "./assets/model.glb";
import {
  FourierCanvas,
  GLTFLoader,
  Group,
  defineReact,
  useRef,
} from "@fourier-video/sdk/three";

export default defineReact({
  name: "RotatingModel",
  schema: {},
  component() {
    const model = useRef<Group | null>(null);
    return (
      <FourierCanvas
        onCreate={async ({ scene }) => {
          const gltf = await new GLTFLoader().loadAsync(modelUrl);
          model.current = gltf.scene;
          scene.add(gltf.scene);
        }}
        onFrame={({ progress }) => {
          if (model.current) model.current.rotation.y = progress * Math.PI * 2;
        }}
      />
    );
  },
  designPreview() {
    return { props: {}, composition: { width: 960, height: 540, durationSeconds: 6 } };
  },
});

onCreate 可以异步加载工程内打包的 GLB;Fourier 会等待资源完成。onFrame 必须同步,并根据 timeMilliseconds、timeSeconds 或 progress 直接求出当前状态,不能累加状态或启动 requestAnimationFrame。宿主在预览拖动、测试和正式导出时都会先定位绝对时间,再同步渲染 WebGL。

图片纹理同样直接从 /three 导入 TextureLoader。SDK 导出的版本兼容 Three.js loader,并支持本地图片 import、URL、{ src }、loadManyAsync() 和可读的解码错误;可通过第二个 constructor 参数统一设置 colorSpace 或 flipY。

浏览器不能直接读取 .blend。请从 Blender 导出 GLB/GLTF 后使用相对 import;示例 Example3D.tsx 加载由 Low+Poly+Earth.blend 导出的 GLB,并完成一圈确定性旋转。

Universe 世界投影

@fourier-video/sdk/universe 在 React artifact 内把普通 React、Canvas 或 FourierCanvas 的既有渲染结果放入无限二维世界;它不创建新的渲染后端:

import { Universe, World, defineCamera } from "@fourier-video/sdk/universe";

const camera = defineCamera({
  width: 1920,
  height: 1080,
  moves: [{
    at: "0f",
    duration: "60f",
    to: { kind: "fit", target: "diagram", fit: "contain", padding: 80 },
    path: { kind: "linear" },
    ease: "ease-in-out",
  }],
});

function SpatialDiagram() {
  return (
    <Universe camera={camera}>
      <World id="diagram" x={4000} y={-1200} width={1200} height={800}>
        <ArchitectureDiagram />
      </World>
    </Universe>
  );
}

Camera 使用中心坐标、逻辑 width/height、zoom 和顺时针 rotation。World 默认中心 anchor;其显式 bounds 同时用于 Camera Fit 与安全裁剪。Camera Motion 支持 pose/fit target、TimeExpression、linear/bezier/arc/curve/custom path;custom path 对相同输入必须返回相同坐标。

多镜头使用 defineCameraProgram({ cameras, initialCamera, cuts })。Cut 是 Active Camera 切换,不等同于零时长 Move。多个 Universe 可直接组合为 split screen 或 picture-in-picture。Camera 与输出 viewport 必须保持相同宽高比;同一逻辑 Camera 可以等比例输出到更高分辨率。

Placeholder 示例资源

组件作者在开发 designPreview()、Motion subject 和素材插槽时,推荐先使用 SDK placeholder 目录中的占位资源,而不是连接网络或在组件里维护一份临时 data URI。目录提供:

  • pic:普通图片与透明人物图。
  • video:本地 MP4。
  • fonts:用于验证自带字体加载的字体文件。
  • 3d_model:浏览器可加载的 GLB 和对应 Blender 源文件。

在 SDK 仓库内可以直接相对导入;组件发布到 Fourier World 前,将需要的占位资源复制到组件自己的 assets/ 或 fonts/ 目录,并写入 package files:

import placeholderImageUrl from "./assets/placeholder.png";

designPreview() {
  return {
    props: {},
    subject: <img src={placeholderImageUrl} width={960} height={540} />,
    composition: { width: 960, height: 540, durationSeconds: 3 },
  };
}

OTF、TTF、WOFF、WOFF2 等浏览器字体通过本地 import 交给 loadFont();它会生成稳定的内部 family 并返回可直接用于 fontFamily 的字符串,不需要维护 FONT_FAMILY、@font-face 或 designPreview().fonts:

import { defineReact, loadFont } from "@fourier-video/sdk";
import titleFontUrl from "./fonts/Title.otf";

const titleFont = loadFont(titleFontUrl);

// component 内:
<div style={{ fontFamily: titleFont }}>Fourier</div>

Placeholder 只负责让预览可运行、可复现;生产素材仍应通过 schema props、Motion subject 或工程资源传入。runtime 默认拒绝网络,因此不要把远程图片、视频或字体 URL 当作占位方案。

预览、测试与检查

bunx fourier-sdk preview
# 默认以卡片列表加载 SDK example 下的全部组件

bunx fourier-sdk preview ./components
# 也可以加载一个目录或单个 artifact

# CLI 还会在 0.0.0.0:3212 暴露允许 CORS 的监听端口
bunx fourier-sdk preview ./components --public-port 4321

fourier check ./components/MetricPanel.tsx

作者入口只需要默认导出一个 defineReact()、defineMotion() 或 defineShader() definition;不编写 preview renderer、逐帧 render handler 或单独的 preview config。ABI v1.2 preview server 只负责编译 definition 和热更新,播放器直接加载同一份 DOM/CSS/WAAPI/WebGL runtime,并通过时间轴设置时间,不从服务端拉取逐帧 PNG。目录模式会按视口惰性挂载卡片 runtime、复用版本化 UI 资源,并在热更新时只重编受影响的 artifact;离开视口或切到后台的预览暂停采样。designPreview() 只声明 props、画布、时长和 Motion/Shader subject,不参与具体渲染。

发布到 Fourier World

一个可发布 npm 包可以包含 1—50 个组件目录。根 package.json 的 fourier.components 列出各组件的 package.json;每个组件继续使用既有入口、分类、Agent instruction、适用场景、标签与视觉风格字段。

fourier-sdk login --email [email protected]
fourier-sdk publish https://www.npmjs.com/package/@studio/fourier-components/v/1.2.3 --dry-run
fourier-sdk publish https://www.npmjs.com/package/@studio/fourier-components/v/1.2.3

--dry-run 会下载 npm 精确版本,校验 registry SHA-512 integrity,编译每个组件,并渲染浏览器兼容的 H.264 预览。真实发布只上传预览与 npm 派生元数据;World 不保存源码归档。审核通过后,可以整包安装,也可以用 #ComponentName 安装或移除单个组件:

fourier-sdk search "产品发布的电影感标题动画" --type motion --style cinematic --json
fourier-sdk add https://www.npmjs.com/package/@studio/fourier-components/v/1.2.3
fourier-sdk del https://www.npmjs.com/package/@studio/fourier-components/v/1.2.3#MetricPanel

search 无需登录,调用 Fourier World 的关键词 + 语义混合检索;结果保留既有组件字段,并增加精确的 npmPackageUrl / npmComponentUrl。add 仍写入 components/@studio/MetricPanel,并在项目级 .fourier-world.json v2 记录已校验来源;del 默认移动到可恢复的 .fourier-trash。完整 manifest 与命令见 Fourier World 发布规范。

生产画面不随宿主时间变化的 ABI v1 React 应显式声明 static: true。runtime 会验证该组件没有注册 lifecycle、animation、media、SMIL 或 render driver;正式渲染只生成一张 PNG,再按工程节点时长复用。未声明 static 时由 runtime 挂载后自动推断。

ABI v1 的标准 testing 入口是文件路径:

import { openArtifact } from "@fourier-video/sdk/testing";

const fixture = await openArtifact("/absolute/path/MetricPanel.tsx");
try {
  const frame = await fixture.renderFrame({ frame: 20 });
  const exact = await fixture.renderTime({
    time: { numerator: 1n, denominator: 3n },
  });
  await fixture.assertDeterministic({ times: [
    { numerator: 0n, denominator: 1n },
    { numerator: 1n, denominator: 3n },
  ] });
  console.log(frame.sha256, exact.sha256);
} finally {
  await fixture.close();
}

assertDeterministic 必须且只能传非空 frames 或 times。

文档与示例

维护命令

bun run typecheck
bun test
bun run test:dom
bun run build
bun run prepack