@effing/annie

中文文档
0.48.0发布于 2026/11/12MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 2227

安妮动画框架生成器公用事业

中文使用文档
文档目录14 节
  1. 安装
  2. 概念
  3. 安妮格式
  4. 生成模式
  5. 快速启动
  6. API 概览
  7. 职能
  8. 实例
  9. 有快车/节点.js
  10. 使用回放路由器/ 重混
  11. 保存到文件
  12. 读安妮
  13. FFmpeg 整合
  14. 相关软件包

@ effing/annie (英语)

为动画地层生成并读取PNG,JPEG或QOI框架的TR档案.

部分 财源 家庭——用TypeScript制作节目视频.

Annie是一个简单的动画格式:一个包含相继命名的PNG,JPEG或 问 题 边框。 生成帧服务器侧,将其流到浏览器或FFmpeg上,并用同一套包回读.

安装

npm install @effing/annie

概念

安妮格式

Annie是一个TR档案,每个条目都是PNG,JPEG或QOI框架:

frame_00000
frame_00001
frame_00002
...

框架在像素格式,通道(有或没有α)和大小上可能有所不同,但一个阴极的所有框架必须是一个格式:所有PNG,所有JPEG或所有QOI. FFS和FFmpeg用解码器解码了它的第一帧.

该格式为:

  • 可流性 ——帧在生成时可以被写入
  • 通用 - 在所有地方都支持第三次评估报告
  • FFmpeg 兼容 —— 可作为图像输入直接管道到FFmpeg

生成模式

安妮支持两代模式:

缓冲 ——收集所有帧,返回完整归档:

const archive = await annieBuffer(frames);

流线 作为帧的 Yield 块生成:

const stream = annieStream(frames);

快速启动

import { annieStream, annieBuffer } from "@effing/annie";
import { createCanvas, renderReactElement } from "@effing/canvas";
import { tween, easeOutQuad } from "@effing/tween";

// Define a frame generator
async function* generateFrames() {
  yield* tween(90, async ({ lower: progress }) => {
    const scale = 1 + 0.3 * easeOutQuad(progress);
    const canvas = createCanvas(1080, 1920);
    const ctx = canvas.getContext("2d");
    await renderReactElement(
      ctx,
      <div style={{
        width: 1080,
        height: 1920,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        fontSize: 72,
        transform: `scale(${scale})`
      }}>
        Hello World!
      </div>,
      { fonts: myFonts }
    );
    return canvas.encode("png");
  });
}

// Stream response
const stream = annieStream(generateFrames(), { signal: request.signal });
return new Response(stream, {
  headers: { "Content-Type": "application/x-tar" }
});

API 概览

职能

annieStream(frames, options?)

创建一个 ReadableStream 当框架生成时产生 TAR 块.

function annieStream(
  frames: AsyncIterable<Buffer>,
  options?: AnnieStreamOptions,
): ReadableStream<Buffer>;

选项 :

  • signal - 中止取消的签名

annieBuffer(frames)

收集所有帧并返回完整的TRA缓冲.

function annieBuffer(frames: AsyncIterable<Buffer>): Promise<Buffer>;

annieFrames(source)

Async-e透出一个现存安妮的相框,按上升指数顺序排列.

function annieFrames(source: AnnieSource): AsyncGenerator<AnnieFrame>;

源头可以是 Uint8Array编号 :ArrayBuffer,一个可移动的字节块(例如节点.js) Readable),或网络 ReadableStream。每个框架带有 index条目 name粗线 data 字节和 a contentType 从帧的魔法字节中嗅出(存档本身没有记录图像格式): "image/png", (中文(简体) ), "image/jpeg", (中文(简体) ), "image/qoi",或 "application/octet-stream" 为了其他一切.

sniffImageContentType(bytes)

从它的主字节中检测出一个 PNG、 JPEG 或 QOI 图像, 相同的方式 annieFrames 有: 完整的八字节PNG签名, FF D8 FF 用于 JPEG,或 qoif 为QOI(在有14字节标题时,有3或4个频道和色相空间0或1). 回返 "image/png", (中文(简体) ), "image/jpeg", (中文(简体) ), "image/qoi" 或者说 undefined。 。 。 .

function sniffImageContentType(bytes: Uint8Array): ImageContentType | undefined;

实例

有快车/节点.js

import { Readable } from "stream";
import { annieStream } from "@effing/annie";

app.get("/animation.tar", async (req, res) => {
  const stream = annieStream(generateFrames());
  res.setHeader("Content-Type", "application/x-tar");
  Readable.fromWeb(stream).pipe(res);
});

使用回放路由器/ 重混

import { annieStream } from "@effing/annie";

export async function loader({ request }: LoaderFunctionArgs) {
  const stream = annieStream(generateFrames(), { signal: request.signal });
  return new Response(stream, {
    headers: { "Content-Type": "application/x-tar" },
  });
}

保存到文件

import { writeFile } from "fs/promises";
import { annieBuffer } from "@effing/annie";

const buffer = await annieBuffer(generateFrames());
await writeFile("animation.tar", buffer);

读安妮

import { readFile } from "fs/promises";
import { annieFrames } from "@effing/annie";

for await (const frame of annieFrames(await readFile("animation.tar"))) {
  console.log(frame.name, frame.contentType, frame.data.length);
}

FFmpeg 整合

注意Annie TAR档案可以直接被管道到FFmpeg. 提取帧用 tar -xO 和管道到FFmpeg的图像2pipe输入. 当每个帧都有相同的格式时,这个功能就起作用了;QOI帧需要FFmpeg 5.1或更新.

# Create animated PNG (loops forever)
tar -xO < animation.tar | ffmpeg -f image2pipe -framerate 30 -i - -plays 0 -c:v apng -f apng output.png

# Create MP4 video
tar -xO < animation.tar | ffmpeg -f image2pipe -framerate 30 -i - -c:v libx264 -pix_fmt yuv420p output.mp4

# Create GIF
tar -xO < animation.tar | ffmpeg -f image2pipe -framerate 30 -i - output.gif

版本与发布记录

@effing/annie 共发布 119 个版本,首次发布于 2026/01/21;过去 12 个月发布了 119 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.48.0latest2026/11/121 天前
0.47.32026/11/112 天前
0.47.22026/11/104 天前
0.47.12026/10/2915 天前
0.47.02026/10/2717 天前
0.46.22026/10/2222 天前

关于 @effing/annie 的常见问题

@effing/annie 是什么?

安妮动画框架生成器公用事业

如何安装 @effing/annie?

在项目目录运行 npm install @effing/annie,或使用 pnpm add / yarn add / bun add。

@effing/annie 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@effing/annie 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@effing/annie 可以商用吗?

@effing/annie 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@effing/annie 的下载量有多少?

根据 npm 官方下载统计,@effing/annie 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,227 次,日均约 74 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@effing/annie 还在维护吗?

最新版本 0.48.0 发布于 2026/11/12(1 天前);至今共发布 119 个版本,其中过去 12 个月发布了 119 个;首次发布于 2026/01/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。