kane50613/takumi

GitHub: kane50613/takumi

一款用 Rust 构建的 JSX/HTML 转图像渲染引擎,无需 headless 浏览器即可生成 OG 图片、动画和矢量 SVG,完全兼容 next/og。

Stars: 2466 | Forks: 48

Takumi # Takumi **一个将 JSX、HTML 和 node 树转换为图像的 Rust 渲染引擎。无需 headless 浏览器。** 支持从 Node.js、Cloudflare Workers、浏览器或任何 Rust 应用中渲染 OpenGraph 卡片、动态 GIF、视频帧和矢量 SVG。 与 `next/og` 完全兼容。 [![npm version](https://img.shields.io/npm/v/takumi-js?label=takumi-js)](https://www.npmjs.com/package/takumi-js) [![crates.io](https://img.shields.io/crates/v/takumi?label=takumi)](https://crates.io/crates/takumi) [![npm downloads](https://img.shields.io/npm/dm/%40takumi-rs%2Fcore?label=downloads)](https://www.npmjs.com/package/@takumi-rs/core) [![license](https://img.shields.io/badge/license-MIT%20%2F%20Apache--2.0-blue)](#license) [文档](https://takumi.kane.tw/docs/) · [演练场](https://takumi.kane.tw/playground) · [案例展示](https://takumi.kane.tw/showcase)
## 为什么选择 Takumi Takumi 是一个用 Rust 构建的渲染 pipeline,专为完成一项任务而生:**将 markup 和 CSS 转换为像素**。它在一个单独的二进制文件内解析 CSS、进行布局、文字塑形(text shaping)、合成图层并编码输出。在渲染同一张 OG 卡片时,headless-Chromium 方案需要消耗约 **300 MB 的 RAM** 以及浏览器的冷启动时间;而 Takumi 只需要**一次函数调用**。 **一套引擎,适用于所有部署目标:** - **Node.js** 加载原生 binding - **Cloudflare Workers 和浏览器** 加载 WASM 构建版本 - **Rust 应用** 直接嵌入 `takumi` crate 提供针对 macOS、Linux (glibc 和 musl) 以及 Windows 平台的预编译二进制文件,支持 x64 和 ARM64 架构。 **CSS 支持超越了常规的 OG 图片子集:** - CSS Grid、block、inline、float - `::before`、`::after`、`:is()`、`:where()` - masks、`clip-path`、`backdrop-filter`、blend modes - `background-clip: text`、conic gradients - RTL 文本 - Tailwind v4 工具类,包括任意值 ## 快速开始 ``` bun i takumi-js ``` ### 静态图像 ``` import { render } from "takumi-js"; import { writeFile } from "node:fs/promises"; const image = await render(

Hello from Takumi

, { width: 1200, height: 630 }, ); await writeFile("./output.png", image); ``` ### 字体 内置的仅仅是一款作为最后备选的 Latin 字体。其余字体请通过 `fonts` 加载:支持 URL、原始字节或 `googleFonts`。指定 weight 范围或提供 `axes` 条目即可加载 variable font,从而让 `font-variation-settings` 驱动其坐标轴: ``` import { render } from "takumi-js"; import { googleFonts } from "takumi-js/helpers"; const image = await render(
Hello from Takumi
, { width: 1200, height: 630, fonts: googleFonts([{ name: "Fraunces", weight: "100..900", axes: { opsz: "9..144" } }]), }, ); ``` 需要渲染大量图像?只需在 `Renderer` 上注册一次字体即可重复使用。详见 [排版与字体](https://takumi.kane.tw/docs/typography-and-fonts)。 ### API 路由(兼容 `next/og`) ``` import { ImageResponse } from "takumi-js/response"; export function GET() { return new ImageResponse(

Hello from Takumi

, { width: 1200, height: 630 }, ); } ``` ### 动态 WebP ``` import { renderAnimation } from "takumi-js"; import { writeFile } from "node:fs/promises"; const animation = await renderAnimation({ width: 400, height: 400, fps: 30, format: "webp", scenes: [ { durationMs: 1000, node: (
), }, ], }); await writeFile("./output.webp", animation); ``` ### 矢量 SVG ``` import { renderSvg } from "takumi-js"; import { writeFile } from "node:fs/promises"; const svg = await renderSvg(

Hello from Takumi

, { width: 1200, height: 630 }, ); await writeFile("./output.svg", svg); ``` ### Rust ``` cargo add takumi ``` 从 [Rust 示例](./example/rust) 开始。 ## 对比 | 特性 | `next/og` (Satori) | Takumi | | :--------------------------------- | :----------------: | :-----------------------------------------------------------: | | **运行时 (Runtime)** | Node / Edge | Node, Edge, CF Workers, Browser, **Rust crate** | | **模板输入** | JSX / React | JSX, HTML strings, 来自任何语言的 JSON node 树 | | **布局 (Layout)** | Flexbox | Flexbox, **CSS Grid**, block, inline, float | | **选择器 (Selectors)** | 有限支持 | 复杂选择器, `:is()`, `:where()`, `::before`, `::after` | | **`backdrop-filter`, blend modes** | ✗ | ✅ | | **动画输出 (Animated output)** | ✗ | **WebP / APNG / GIF / 视频帧** | | **矢量 SVG 输出** | ✅ 原生支持 | ✅ **外加栅格与动画输出** | | **Headless 浏览器** | ✗ | ✗ | | **`ImageResponse` API** | ✅ 原生支持 | ✅ **完全兼容** | 前往 [image-bench.kane.tw](https://image-bench.kane.tw) 对比各提供商的渲染输出结果。 ## 谁在使用 Takumi - [Dcard](https://dcard.tw) 渲染帖子分享图像 - [TanStack](https://tanstack.com) 为其文档渲染 OG 图像 - [Fumadocs](https://fumadocs.dev) 生成其文档的 OG 图像 - [Nuxt OG Image](https://nuxtseo.com/docs/og-image/renderers/takumi) 内置 Takumi 作为渲染器 - [Luma](https://lu.ma) 渲染活动分享图像 - [shiki-image](https://github.com/pi0/shiki-image) 将语法高亮代码转换为图像 更多项目请见 [案例展示](https://takumi.kane.tw/showcase)。Takumi 是 [Vercel OSS Program](https://vercel.com/oss) 的一部分。 ## 核心架构 Takumi 会将任何模板转换为包含三种节点类型的 **node 树**:`container`、`image` 和 `text`。该树会依次经过以下处理: 1. **布局** 通过 [taffy](https://github.com/DioxusLabs/taffy) 实现:支持 Flexbox、Grid、block、float、`calc()`、绝对定位、z-index 2. **文字塑形** 通过 [parley](https://github.com/linebender/parley) 和 [skrifa](https://github.com/googlefonts/fontations/tree/main/skrifa) 实现:支持 WOFF/WOFF2 字体、emoji、RTL、多重内联块(multi-span inline blocks) 3. **合成**:处理层叠上下文、blend modes、filter、transform,并通过 [resvg](https://github.com/linebender/resvg) 处理 SVG 4. **输出**:支持输出静态格式(PNG、JPEG、WebP、ICO);动画格式(GIF、APNG、WebP);以及用于视频 pipeline 的原始 RGBA 帧 由于其输入契约是一个 node 树,因此任何能序列化为 HTML 或 JSON 的模板系统都可以作为数据源:React、Svelte、Vue、纯字符串,或是任何语言编写的自定义序列化器。 一条 **时间轴** 贯穿整个 pipeline:渲染器接收一个时间戳,因此 PNG 是 `t=0` 时刻的树状态,而 GIF 是同一棵树在 `t` 上的采样集合。CSS `@keyframes`、`animation` 简写属性,以及 Tailwind 动画工具类(`animate-spin`、`animate-bounce`、任意值)均会在渲染时进行解析。 同样的布局逻辑还驱动了第二个后端:`renderSvg()`(Rust 中的 `render_svg`,隐藏在 `svg-backend` feature 之后)会生成一份由 ``、``、渐变和字形轮廓构成的真实 `` 文档,因此你可以输出可缩放的矢量图形而非像素。如果你之前使用 [satori](https://github.com/vercel/satori) 来获取 SVG,这便是直接兼容的替代方案。 ``` flowchart LR A[Templates] --> N[Node Tree] --> P[Rendering Pipeline] C[Stylesheets] --> P R[Resources] --> P D(Time Axis) -.-> P P --> F[(Raw Pixels)] P --> S[Vector SVG] F --> G[PNG / JPEG / WebP / ICO] F --> H[GIF / APNG] F --> I[Video frames] ``` ## 案例展示 | Takumi OG image [(源码)](./example/twitter-images/components/og-image.tsx) | Package OG card [(源码)](./example/twitter-images/components/package-og-image.tsx) | | :------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------: | | ![Takumi OG Image](https://static.pigsec.cn/wp-content/uploads/repos/cas/13/13851200a2434133f1213cfecb47181a3dd975d741e324150a6dec1f68135271.png) | ![Package OG Image](https://static.pigsec.cn/wp-content/uploads/repos/cas/ca/ca72ff8ed9564b38218b5b3c2e440eeb57e2550a47facbcd77184f59565b3abb.png) | | **Prisma 风格 API 卡片** [(源码)](./example/twitter-images/components/prisma-og-image.tsx) | **X 风格社交帖子** [(源码)](./example/twitter-images/components/x-post-image.tsx) | | ![Prisma OG Image](https://static.pigsec.cn/wp-content/uploads/repos/cas/d2/d29f9613bd5a0f94886b4869094e7433f6a14843f2b01e634ee54bff09126da6.png) | ![X-style Post Image](https://static.pigsec.cn/wp-content/uploads/repos/cas/e0/e0dd07b26c7a6fc1f7d3d6e3beb8866edd35d507eb2fdd802a6bc3156bd3202a.png) | | **关键帧动画** [(源码)](./example/ffmpeg-keyframe-animation/src/index.tsx) | **[shiki-image](https://github.com/pi0/shiki-image)** | | [![Keyframe Animation](https://static.pigsec.cn/wp-content/uploads/repos/cas/0d/0d3d97560ba50b58856640c473458f30d91baf83aa70cd7fc3d250a1f634531f.webp)](./example/ffmpeg-keyframe-animation/output/animation.mp4) | ![Shiki Image Example](https://static.pigsec.cn/wp-content/uploads/repos/cas/b5/b5af2313321f4239ef1fd1add3d474cf2bbffc8be3feb5c1d0502a8d571dd255.webp) | **更多示例:** [Next.js](./example/nextjs)、[Cloudflare Workers](./example/cloudflare-workers)、[TanStack Start](./example/tanstack-start)、[Svelte](./example/svelte)、[Rust](./example/rust)、[ffmpeg 关键帧动画](./example/ffmpeg-keyframe-animation) - [(非官方) Takumi 演练场](https://takumi-playground.kapadiya.net/) ## 开源协议 MIT 或 Apache-2.0
Vercel OSS Program
标签:GNU通用公共许可证, HTML转图片, MITM代理, Node.js, OpenGraph, Rust, WebAssembly, 前端开发工具, 可视化界面, 图像渲染, 程序员工具, 网络流量审计, 通知系统