mcpField
K
kinetograph

kinetograph

github.com/0xs4n4tg其他29637 次安装今天更新
代码仓库

关于 kinetograph

kinetograph 是一项技能,用于通过 Remotion 风格的 TypeScript 在无浏览器环境中制作和渲染视频。它介绍了借助 Kinetograph 命令行逐帧检查、校验和渲染项目的流程。

主要功能

  1. 01使用 Remotion API 制作视频
  2. 02预览静帧和帧条
  3. 03检查场景并检查帧问题
  4. 04对项目进行类型检查
  5. 05使用导出选项渲染视频

适用场景

  1. 01从 TypeScript 项目制作视频
  2. 02渲染前检查动画帧
  3. 03查找布局、资源或字体问题
  4. 04渲染指定帧范围

MCP 相关

Kinetograph 为除 studio 外的每个命令提供一个 MCP 工具;图像命令直接返回图像。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/0xs4n4tg/kinetograph --skill kinetograph

安装后在 Claude Code 中输入/kinetograph确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
AUTHORING.md
ENGINE.md
INTERNALS.md
SCENE.md

详细介绍

使用 Kinetograph

Kinetograph 无需浏览器即可渲染视频。你使用 Remotion API 和少量原生元素编写 TypeScript;Node 负责运行;GPU 合成器负责绘制。你无法观看视频,因此要查看单帧并读取场景图。

要将现有 Remotion 项目迁移到 Kinetograph,请使用 kinetograph-migrate skill。

所有命令都以 npx kinetograph <command> 的形式运行。添加 --json 可获取一个可解析的 JSON 对象;失败时会返回 { "error": { "code", "message" } },退出代码为 1。(通过 MCP(kinetograph mcp)使用时,除 studio 外,每条命令对应一个工具,工具名称与命令相同(audio analyze 对应 audio_analyze),参数也相同;still、strip 和 onion 会直接返回图像本身,对这些命令来说 output 是可选的。)

工作流程

  1. 编写项目文件,例如 src/index.tsx,调用 registerRoot(见下文)。
  2. 查看。 使用 kinetograph still src/index.tsx 45 -o out/f45.png 获取单帧;使用 kinetograph strip src/index.tsx -n 12 -o out/strip.png 一次获取 12 帧带标签的画面(先做这个,它会展示整个动画);使用 kinetograph onion src/index.tsx 0..60 -n 6 -o out/path.png 查看运动路径。打开 PNG 查看图像。
  3. 检查。 无需查看像素:kinetograph inspect src/index.tsx --frame 45 会显示每个图层解析后的坐标、尺寸、边界、效果和文本行。kinetograph lint src/index.tsx(--frames 0,45,89 用于指定帧;默认抽取 8 帧)会报告文本溢出文本框或画布、图层位于画布外、文本重叠、缺少字体和资源等问题,并注明帧和图层 ID。按报告修复。它只检查帧中可见的内容:在某一帧中,不透明度为 0 的图层(或不透明度为 0 的组内图层)以及被裁剪区域完全遮住的图层都会跳过,因此画布外淡入的 toast 在隐藏时不会被报告。渲染不会进行类型检查,所以拼错属性名(opactiy={0.5})会导致图像以完全不透明的状态绘制,且不会报错;kinetograph check src/index.tsx 会对项目运行 tsc --noEmit(使用最近的 tsconfig.json),而 lint 会将相同错误报告为 type-error。
  4. 修复并从第 2 步开始重复操作。生成单帧用时不到一秒。
  5. 渲染。 使用 kinetograph render src/index.tsx -o out/video.mp4。添加 --draft 可快速查看半尺寸效果;添加 --range 0..90 可指定片段(a..b 表示从 a 到 b-1,a..=b 则包含 b);长片可添加 --concurrency 4 同时绘制多帧(输出文件相同)。导出选项与 Remotion 相同:--scale 2 可从 1080p 输出 4K(按该尺寸绘制,不会放大);--codec h265|prores|vp9|gif(输出扩展名必须匹配:prores 用 .mov,vp9 用 .webm,gif 用 .gif);--crf 20 或 --video-bitrate 8M(不能同时使用);--prores-profile 4444、--pixel-format yuv444p、--audio-codec opus、--audio-bitrate 320k,GIF 还可使用 --every-nth-frame 2。遇到不兼容的组合时,系统会拒绝并说明需要更改的内容。React 会在生产模式下运行(速度更快);如需 React 的警告,可使用 --dev-react 保留开发构建。

此外:compositions <entry> 会列出合成(使用 --comp <id> 选择一个;通过 --props '{"title":"Hi"}' 传递属性);audio analyze <entry> 会测量声音;snapshot <entry> --update 会批准帧,之后运行 snapshot <entry> 会与这些帧进行比较;bench <entry> 会统计各阶段耗时;effects 会列出效果;doctor <entry> 会指出引擎无法绘制的内容及其所在帧(参见“兼容模式和 doctor”;单独运行 doctor 会说明此安装版本支持的功能)。studio <entry> 会在 http://127.0.0.1:3000 启动本地工作室(预览、时间轴、场景树、属性、渲染队列)并打开浏览器;它面向屏幕前的操作者,会持续运行直至停止,并非 MCP 工具。自行启动时请使用 --no-open。

入口可以是项目文件(.tsx、.ts、.jsx、.js)或 .json 场景(参见 references/SCENE.md);所有命令都接受这两种入口。

一个项目

import { AbsoluteFill, Composition, Layer, Rect, Text, interpolate, registerRoot, spring,
         useCurrentFrame, useVideoConfig, dropShadow, linearGradient, registerFont, staticFile } from 'remotion';

registerFont({ family: 'DM Sans', path: staticFile('DMSans-Medium.ttf') }); // fonts BEFORE any text is measured

const Card = () => {
  const frame = useCurrentFrame();
  const { fps, width, height } = useVideoConfig();
  const s = spring({ frame, fps, config: { damping: 14 } });
  return (
    <AbsoluteFill style={{ backgroundColor: '#10131a' }}>
      <Layer x={width / 2} y={height / 2} scale={s} origin="center" effects={[dropShadow({ y: 12, blur: 24 })]}>
        <Rect width={600} height={300} radius={32} fill={linearGradient(['#f9a', '#fc6'])} />
        <Text font="DM Sans" size={72} color="#fff" x={60} y={100}>gets better</Text>
      </Layer>
    </AbsoluteFill>
  );
};

registerRoot(() => <Composition id="Main" component={Card} durationInFrames={90} fps={30} width={1080} height={1920} />);
  • Remotion 的 API 按照文档运行:useCurrentFrame、useVideoConfig、interpolate、interpolateColors、spring、 Easing、random、Sequence、Series、Loop、Freeze、AbsoluteFill、Img、staticFile、delayRender。 staticFile('x.png') 指向入口文件旁的 public/x.png。
  • @remotion/transitions、motion-blur、noise、paths、shapes、layout-utils、animation-utils、captions、 fonts、lottie 和 @remotion/google-fonts/<Family> 均可照常导入。@remotion/rive 的 <RemotionRiveCanvas src={staticFile('a.riv')}> 会使用 Rive 自带的运行时播放 Rive 文件(逐帧精确;新增了 stateMachine 和 stateMachineInputs 属性;引用的资源需放在 .riv 文件旁,或通过 assetLoader 提供)。可选的 @kinetographdev/skia 插件(npm install @kinetographdev/skia;如果未安装,第一个 Skia 画布会提示)会让 @remotion/skia 和 @shopify/react-native-skia(<SkiaCanvas>、RN-Skia 组件、SkSL 着色器)基于真正的 Skia 运行(包括 Reanimated 共享值、FitBox、surface、Skia.Data/Image/Typeface、动画图像、段落测量、paint 着色器和 SVG 文本)。其他 @remotion/* 包目前尚不存在。 新工作请使用下方的元素。<div>、className、样式表(.css 导入、<style>、Tailwind)和 SVG 也能使用(兼容模式,参见“兼容模式与 doctor”):引擎自带的 CSS 引擎会为其设置样式、布局并绘制;如果某一帧包含尚无法绘制的内容,则会在不绘制该内容的情况下(或以近似方式)绘制,并由命令发出警告。
  • @remotion/sfx 的音效(whip、ding 等)可通过 <Audio src={whip} /> 播放。首次渲染时,每种音效都会下载到 ~/.cache/kinetograph/sfx;之后即可离线使用。
  • @remotion/zod-types(zColor、zMatrix、zTextarea)会为 <Composition schema> 打包;Kinetograph 不会根据 schema 检查属性。
  • @remotion/timeline-utils(波形峰值和绘制、循环及帧条带计算)支持本地文件;需要将视频图像作为 WebCodecs 帧的功能(extractFrames)会抛出 UnsupportedApiError 并说明原因。
  • @remotion/media-parser 的 parseMedia 会通过 FFmpeg 读取本地文件(staticFile('clip.mp4')),获取时长、尺寸、fps、编解码器、轨道、旋转角度、采样率、元数据及慢速字段。不支持 box 树(slowStructure)或采样回调(onVideoTrack);与其他地方一样,URL 会失败(离线)。
  • @remotion/webcodecs 可以打包;convertMedia 可将文件的音频写入 WAV,列表和轨道检查也可使用,其余功能(视频编码和解码、extractFrames)会抛出 UnsupportedApiError。@remotion/canvas 是 Remotion Studio 的编辑器画布:它可以打包,但每次调用都会抛出相同的错误。
  • 渲染是帧编号的纯函数。Math.random()、Date.now() 和计时器均由帧驱动;抖动请使用 random(seed)。切勿读取真实时钟。
  • 请在排版文本之前注册字体。使用未注册字体的文本会触发 lint 错误。

元素和效果

每个元素都接受 id、x、y、scale、rotation、origin="center"、opacity、blendMode、effects、clip、 mask、matte、motionBlur,以及 3D 属性 z、rotateX、rotateY。数值可以是普通数值,也可以是关键帧列表。

元素用途
<Layer>组;layout(flexbox)和 preserve3d
<Rect>、<Ellipse>、<Path>、<Shape>矢量图形,带有 fill(颜色或渐变)和 stroke
<Text>文本;font、size、color、maxWidth、align、逐字符设置的 chars
<Image>、<Img>PNG、JPEG、GIF、WebP、SVG 文件;fit="cover"
<Noise>、<MeshGradient>、<Lottie>生成图层和 Lottie 图层
<Camera>用于 3D 变换的透视摄像机
<Audio>音频文件:src、volume、trimBefore、playbackRate、loop

效果(同名辅助函数;kinetograph effects 会列出其字段):blur、backdropBlur、glow、 chromaticAberration、dropShadow、insetShadow、saturate、contrast、brightness、grayscale、sepia、invert、 hueRotate、gradientMap、lut、colorGrade(HyperFrames 的调色及其 18 种外观效果:{ effects: { halftone: 0.9 } })、grain、dither、halftone、dotMatrix、displace、cornerPin,以及用于编写自定义 WGSL 的 shader。 motionBlur({ samples: 8 }) 放在同一个 effects 数组中。

详情请参阅此技能的参考文档:references/AUTHORING.md(§5 辅助函数、§6 元素及其 JSON、§7 Remotion API)、references/SCENE.md(每种图层类型、效果和字段;各项的确切含义)、references/ENGINE.md(DOM 引擎)和 references/INTERNALS.md(帧的生成过程、代码索引)。

音频

Web Audio 代码会针对帧时间线离线运行。在模块级别调用 onFrame;ctx 是 OfflineAudioContext,t 是以秒为单位的起始时间。

import { onFrame } from '@kinetographdev/audio';

onFrame(42, (ctx, t) => {
  const o = ctx.createOscillator(); const g = ctx.createGain();
  o.frequency.setValueAtTime(3000, t); o.frequency.exponentialRampToValueAtTime(4500, t + 0.055);
  g.gain.setValueAtTime(0.4, t); g.gain.exponentialRampToValueAtTime(0.001, t + 0.06);
  o.connect(g).connect(ctx.destination); o.start(t); o.stop(t + 0.06);
});

<Audio src={staticFile('music.mp3')} volume={(f) => interpolate(f, [0, 30], [0, 1])} /> 会播放音频文件。render 会将二者混合到视频中。使用 kinetograph audio analyze src/index.tsx 检查音频:integratedLufs(null 表示静音)、truePeakDb(应低于 -1)、clippedSamples(应为 0)以及 silences。在线视频的响度目标约为 -14 LUFS。

兼容模式与 doctor

为 Remotion 编写的项目可能会在原生元素旁使用 DOM 元素、style、className 和样式表。引擎会用自己的 CSS 引擎(references/ENGINE.md)对其进行样式处理和布局,并绘制它能处理的内容。这里没有浏览器:即使某一帧包含暂时无法绘制的内容,仍会绘制该帧,只是缺少该项或以近似方式呈现;still、strip 和 render 会在 stderr 上输出 warning:,指出每种情况(元素、属性、值、原因、帧);使用 --json 时,同一列表会包含在结果的 compat.leftOut 中。为 still、strip 或 render 传入 --strict,可在遇到此类情况的第一帧时以 UNSUPPORTED_CONTENT 失败,而不是生成近似画面。长时间渲染前,先查明缺少哪些内容。对 DOM 元素的引用可通过同一 CSS 引擎提供 getBoundingClientRect 及相关方法;先测量再渲染的 useLayoutEffect 代码会在该帧内完成;fetch、new Image() 和 matchMedia 可用于项目文件及合成尺寸;<canvas> 配合 getContext('2d') 会原生绘制(路径、渐变、文本、阴影、滤镜、drawImage、getImageData;<Video onVideoFrame> 会将帧传给 drawImage,而 getImageData 可读取其像素);webgl/webgl2 上下文也同样受支持;但不支持网络。<Canvas width height draw={(ctx) => ...} /> 是用于相同绘制任务的原生元素。在组件中,如果某一帧有绘制到画布,画布会在该帧开始时清空;如果没有操作画布,则会保留其像素。每次都要根据帧编号绘制整帧,切勿在上一帧绘制的内容上继续绘制。

kinetograph doctor src/index.tsx 会对每一帧运行 JS 阶段(不使用 GPU),并报告:

  • 没有不受支持内容的帧数(cleanFrames、unsupportedFrames、cleanShare);
  • 按元素、属性和原因分组的每个 问题,按影响帧数从多到少排列:出现该问题时的 values、元素 paths($0.2 <div>,即宿主树中的位置),以及包含首尾帧的 ranges。

页面自身脚本引发且未能处理的错误(console.error、未捕获的异常、未处理的 Promise 拒绝)也会作为问题报告,例如 page script console.error,并将消息放入 values:如果某个库捕获了自身错误(Mermaid),就不会绘制任何内容,且只会通过这种方式说明原因。对此使用 --strict 会失败。

--range 0..90 可限制帧范围,--comp 和 --props 可选择合成及其属性。报告中的 stylesheets: 说明表示某个样式表无法使用(例如无法构建的 Tailwind、远程字体)。

如何解读:带有 property 的问题表示该元素的相应 CSS 属性;值为 null 则表示元素本身不受支持。100% clean 表示没有内容被遗漏。要提高这一比例,请移除或替换排名靠前的问题所指出的内容(将尚未绘制某个属性的绘制器替换为能够绘制该属性的绘制器),然后再次运行 doctor。lint 也会将每个问题列为 compat 警告(不会失败),但只检查它抽样的帧;doctor 会检查所有帧。

0.2.0 可绘制和使用的内容

每项一行;详情请查看指针。单独运行 kinetograph doctor 可列出渲染器及当前安装版本支持的功能。

  • 编码器。 内置 ffmpeg 负责所有解码,并使用现有编码器进行编码。它缺少的任何编码器都会通过外部 ffmpeg 程序运行:捆绑的 GPL 版本(libx264、libx265),或你自己的版本。KINETOGRAPH_FFMPEG=$(which ffmpeg) 可使用系统 ffmpeg 的编码器,包括 Linux 上 Intel 和 AMD GPU 的 h264_vaapi、hevc_vaapi、h264_qsv 和 hevc_qsv(仅限 --encoder;绝不会作为默认编码器)。macOS 硬件加速不可用时,H.264 默认使用 libx264;macOS 和 Linux 上默认使用 VP9;--crf、--video-bitrate。AUTHORING.md §9(渲染标志)、/docs/ffmpeg-license/。
  • SVG 文件作为图片。 <Img src={staticFile('a.svg')}>、<img>、background-image、data: URL;SVG 图片内部的文本不会绘制(会发出警告)。ENGINE.md“SVG 文件作为图片”。
  • 场景颜色可使用任何 CSS 颜色(white、rgb()、hsl()、oklch() 等),不局限于十六进制颜色。SCENE.md,顶部。
  • 缺失字形。 字体缺少的字符会逐个回退到捆绑的 Noto Symbols 2、Math 和 Emoji(单色)。不捆绑 CJK 字体:请加载字体。任何字体都没有的字符会由 doctor、--strict 和 inspect 报告(missingChars)。除非你加载等宽字体,否则 monospace 使用捆绑的 JetBrains Mono(Regular)。ENGINE.md“回退字体”。
  • <Series> / <TransitionSeries> 接受 Fragment 包裹的子项,因此 .map() 可以生成成对的元素。AUTHORING.md §7.1。
  • renderer: 行。 render、still 和 doctor 会打印 Skia GPU (Metal) 或 Skia CPU (...);CPU 表示运行较慢。
  • GSAP(核心、免费插件、Flip):将暂停的时间轴定位到 frame / fps,或让 gsap.to 自行播放。 AUTHORING.md §11.9、/docs/compat/#gsap。
  • 插件 @kinetographdev/gsap、p5-brush、anime、motion:将使用自身时钟的库定位到对应帧。 AUTHORING.md §11.10、/docs/libraries/。
  • 可渲染内容的库: Recharts、d3-selection、anime.js、Motion animate()、Paper.js、Bklit、rough.js、Chart.js、 Plot、Vega、Shiki(代码会回退到捆绑的 JetBrains Mono);Mermaid 使用其默认 HTML 标签(<foreignObject>)绘制。AUTHORING.md §11.10。
  • HyperFrames 项目可直接渲染:render|still|doctor|studio <index.html|dir>;运行时会先下载 CDN 脚本、ES 模块、媒体和图片,并将其固定在 kinetograph.lock.json 中(无需先运行 fetch-deps;--offline 绝不会下载;fetch-deps --update 会刷新锁定文件)。AUTHORING.md §11.11、/docs/compat/#hyperframes-projects。
  • 普通 HTML 页面(不使用 React)也能以相同方式渲染:为根元素指定 data-composition-id、data-width、 data-height 和 data-duration(秒;30 fps),否则页面会以 1920x1080、1 秒的设置渲染;缺少这些属性时,doctor、render 和 still 会发出警告。脚本的运行方式与浏览器相同; requestAnimationFrame 会获取每一帧的时间(第 45 帧为 1500 ms)。页面的 canvas 会在帧与帧之间保留像素(可实现拖影),而单帧会重放此前的调用,因此静帧与渲染结果中的对应帧一致。
  • Canvas。 <Canvas width height draw> 或 <canvas> + getContext('2d'|'webgl'|'webgl2'|'webgpu');在组件中, 每次都要重绘整帧(绝不要基于之前的帧继续绘制)。普通 HTML 页面例外(见下文)。AUTHORING.md §6.5 至 §6.7。带效果的 preserve-3d 会被扁平化(ENGINE.md)。
  • <Video datamosh> 使用视频的运动矢量,将一个镜头涂抹到下一个镜头中。AUTHORING.md §11.8、 /docs/guides/datamosh/。
  • 运动跟踪。 kinetograph track public/clip.mp4 --point x,y(首帧中的视频像素坐标,y 轴向下;在静帧中找到该点)会运行一次 Blender 跟踪器,并写入 clip.mp4.track.json;在组件中, const { x, y, rotation, scale, corners } = useTrack('clip.mp4.track.json')(来自 @kinetographdev/core)可将任何内容固定到该点。检查它打印的 lost 帧;使用 --model locrotscale 可跟踪旋转和缩放。--detect 会自动查找点(Blender 的 Detect Features);--plane p1,p2,p3,p4 会根据平坦表面上的 4 个或更多点创建平面跟踪,cornerPin(usePlaneTrack(file).pin) 则可将图片固定到该平面。AUTHORING.md §11.12、 /docs/guides/motion-tracking/。

减少迭代次数的习惯

  • 先运行 strip 再运行 render;先运行 lint 再运行 strip。修复所有 lint 错误。
  • 图层位置不对时,使用 inspect 检查,不要凭图片猜测:bounds 和 matrix 的单位是画布像素。
  • 为遮罩源以及 <Audio> 或遮罩引用的任何对象指定明确的 id。
  • 样式获批后运行一次 snapshot --update,这样之后任何导致像素变化超过 2 级的改动都会显示出来。
  • 对使用 DOM 元素或 CSS 的项目,在运行 render 之前运行 doctor:它会显示渲染时会省略或近似处理的内容。
  • 失败的任务会打印原因:进行任何更改之前,先查看 error.message 和 error.code。

评论

支持 Markdown