npm.io
1.1.91 • Published 22h agoCLI

fkbuilder

Licence
MIT
Version
1.1.91
Deps
20
Size
6.5 MB
Vulns
0
Weekly
1.4K

FKbuilder - 程序化视频生成库

基于 Node.js + Paper.js 的纯 JavaScript 视频制作库,提供简洁的 API 和强大的功能。

简介

FKbuilder 是一个面向开发者的程序化视频生成库,通过“轨道-场景-元素”的层次化架构与时间线驱动的 API,帮助你用代码构建具有动画、转场、文本特效、图形与图表的高质量视频。

  • 面向工程化的工作流:用 JavaScript 组装素材与逻辑,精准控制时间与动画。
  • 丰富的元素生态:文本、图片、视频、形状、音频、字幕、SVG、JSON、代码块、ECharts 图表等。
  • 强大的动画系统:预设动画、关键帧动画、变换动画以及每帧更新的持续动画(onFrame)。
  • 高性能渲染:基于 Paper.js 的 2D 渲染,支持并行渲染与上下文变量传递。
  • 易于集成:简单的 API 设计,适用于生成教程视频、数据可视化短片、产品演示、自动化内容生产等场景。

核心特性

  • 多轨道多场景 - 灵活的轨道和场景管理系统,支持复杂的视频结构
  • 丰富的元素类型 - 文本、图片、视频、形状、音频、字幕、示波器、SVG、JSON 等
  • 强大的动画系统 - 预设动画、关键帧动画、变换动画、onFrame 持续动画
  • 精确的时间控制 - 灵活的时间线管理和元素时间控制
  • 高性能渲染 - 基于 Paper.js 的 2D 渲染引擎,支持实例化
  • 丰富的转场效果 - 支持 gl-transitions 转场库(20+ 种转场效果)
  • 文本特效 - 渐变、阴影、发光、描边、文字拆分动画
  • 视频导出 - 支持 MP4 格式导出,支持管道模式和文件模式
  • 持续动画支持 - 通过 onFrame 回调实现每帧更新的持续动画效果
  • 组件化设计 - 可复用的组件系统,支持相对坐标和时间控制
  • 并行渲染 - 支持 Worker Threads 并行渲染,大幅提升渲染性能
  • 上下文关联 - 在并行渲染中自动传递上下文变量,支持闭包变量

安装

通过 npm 安装
npm install fkbuilder
# 或
yarn add fkbuilder
# 或
pnpm add fkbuilder
本地开发安装
git clone <repository-url>
cd FKbuilder
npm install

系统要求

  • Node.js >= 16.0.0
  • FFmpeg(用于视频编码)
安装 FFmpeg

macOS:

brew install ffmpeg

Ubuntu/Debian:

sudo apt-get install ffmpeg

Windows: 下载并安装 FFmpeg,确保添加到系统 PATH。

快速开始

基础示例

ESM 模块(推荐):

import { VideoBuilder } from 'fkbuilder';

CommonJS 模块:

const { VideoBuilder } = require('fkbuilder');

完整示例:

import { VideoBuilder } from 'fkbuilder';

// 创建视频构建器
const builder = new VideoBuilder({
  width: 1920,
  height: 1080,
  fps: 30,
});

// 创建轨道
const track = builder.createTrack({ zIndex: 1 });

// 创建场景
const scene = track.createScene({ duration: 5 })
  .addBackground({ color: '#1a1a2e' })
  .addText({
    text: 'Hello, World!',
    x: '50%',
    y: '50%',
    fontSize: 80,
    color: '#ffffff',
    textAlign: 'center',
    duration: 5,
    startTime: 0,
    animations: ['fadeIn'],
  });

// 渲染视频(自动 build 和 export)
await builder.render('./output/video.mp4');

核心概念

VideoBuilder(视频构建器)

视频构建器是创建视频的入口,管理所有轨道和场景。

const builder = new VideoBuilder({
  width: 1920,        // 视频宽度
  height: 1080,       // 视频高度
  fps: 30,            // 帧率
});

主要方法:

  • createTrack(config) - 创建轨道
  • render(outputPath, options) - 渲染视频(自动 build 和 export)
  • export(outputPath, options) - 导出视频
  • build() - 构建 VideoMaker 对象
  • initialize() - 初始化(预加载资源)
Track(轨道)

轨道用于组织场景,支持多个轨道叠加。

// 创建轨道
const track = builder.createTrack({ 
  zIndex: 1,          // 层级(数字越大越在上层)
  name: '主轨道'      // 轨道名称(可选)
});

// 添加组件到轨道
track.addComponent(component);
Scene(场景)

场景是视频的基本单元,包含多个元素。

// 创建场景
const scene = track.createScene({ 
  duration: 5,        // 场景时长(秒)
  startTime: 0,       // 开始时间(可选,不指定则自动计算)
});

// 添加组件到场景
scene.addComponent(component);
Component(组件)

组件是可复用的元素容器,有自己的宽高和时间控制。组件内的元素使用相对坐标(相对于组件)。

import { Component } from 'fkbuilder';

// 创建组件
const cardComponent = new Component({
  name: 'Card',
  width: 400,         // 组件宽度
  height: 300,        // 组件高度
  x: '50%',           // 组件位置(相对于父容器)
  y: '50%',
  anchor: [0.5, 0.5], // 锚点
  startTime: 0,       // 开始时间(相对于父容器)
  duration: 5,        // 持续时间
  zIndex: 10,
});

// 在组件内添加元素(使用相对坐标)
cardComponent
  .addBackground({ color: '#2e3b3c' })
  .addRect({
    x: '50%',         // 相对于组件中心
    y: '50%',
    width: '80%',     // 相对于组件宽度
    height: '60%',    // 相对于组件高度
    fillColor: '#5acbed',
  })
  .addText({
    text: '卡片标题',
    x: '50%',
    y: '30%',
    fontSize: 36,
    color: '#ffffff',
  });

// 添加到场景或轨道
scene.addComponent(cardComponent);
// 或
track.addComponent(cardComponent);

元素类型

文本元素
scene.addText({
  text: 'Hello',
  x: '50%',           // 支持百分比和像素值
  y: '50%',
  fontSize: 72,
  fontFamily: 'Arial',
  color: '#ffffff',
  textAlign: 'center',
  duration: 5,
  startTime: 0,
  // 文本效果
  textShadow: true,
  textShadowColor: '#000000',
  textShadowBlur: 20,
  gradient: true,
  gradientColors: ['#FF6B6B', '#4ECDC4'],
  gradientDirection: 'horizontal',
  textGlow: true,
  textGlowColor: '#FFFFFF',
  textGlowBlur: 30,
  stroke: true,
  strokeColor: '#000000',
  strokeWidth: 2,
  // 文字拆分动画
  split: 'letter',    // 'letter', 'word', 'line' 或 null
  splitDelay: 0.1,
  // 动画
  animations: ['fadeIn', 'bigIn'],
  // onFrame 持续动画
  onFrame: (element, progress, time) => {
    // 每帧更新
  },
});
图片元素
scene.addImage({
  src: './path/to/image.jpg',
  x: '50%',
  y: '50%',
  width: 800,
  height: 600,
  anchor: [0.5, 0.5],
  fit: 'cover',       // 'cover', 'contain', 'fill', 'none'
  duration: 5,
  startTime: 0,
  animations: ['zoomIn'],
  borderRadius: 20,
  shadowBlur: 30,
  shadowColor: '#000000',
});
视频元素
scene.addVideo({
  src: './path/to/video.mp4',
  x: '50%',
  y: '50%',
  width: 1920,
  height: 1080,
  anchor: [0.5, 0.5],
  fit: 'cover',
  duration: 10,
  startTime: 0,
  animations: ['fadeIn'],
});
形状元素
// 矩形
scene.addRect({
  x: '50%',
  y: '50%',
  width: 400,
  height: 300,
  bgcolor: '#4a90e2',
  borderRadius: 20,
  anchor: [0.5, 0.5],
  duration: 5,
  startTime: 0,
  animations: ['fadeIn'],
});

// 圆形
scene.addCircle({
  x: '50%',
  y: '50%',
  radius: 100,
  fillColor: '#ff6b6b',
  strokeColor: '#ffffff',
  strokeWidth: 3,
  anchor: [0.5, 0.5],
  duration: 5,
  startTime: 0,
  animations: ['bounce'],
});

// 路径
scene.addPath({
  points: [[0, 0], [100, 50], [200, 0]],
  closed: true,
  fillColor: '#4ECDC4',
  strokeColor: '#ffffff',
  strokeWidth: 2,
  duration: 5,
  startTime: 0,
});
音频元素
scene.addAudio({
  src: './path/to/audio.mp3',
  startTime: 0,
  duration: 10,
  volume: 1.0,
  fadeIn: 1,          // 淡入时长(秒)
  fadeOut: 1,         // 淡出时长(秒)
});
字幕元素
scene.addSubtitle({
  text: '这是一段字幕文本,会根据时长自动分割',
  fontSize: 48,
  color: '#ffffff',
  position: 'center', // 'center', 'top', 'bottom'
  duration: 10,
  startTime: 0,
  maxLength: 20,      // 每段最大字符数
  // 支持所有文本效果
  textShadow: true,
  gradient: true,
  animations: ['fadeIn'],
});
LRC 歌词字幕
scene.addLRC({
  lrcPath: './path/to/lyrics.lrc',
  fontSize: 48,
  color: '#ffffff',
  position: 'bottom',
  // 支持所有文本效果
  textShadow: true,
  animations: ['fadeIn'],
});
示波器元素
scene.addOscilloscope({
  audioPath: './path/to/audio.mp3',
  x: '50%',
  y: '50%',
  width: 1600,
  height: 200,
  waveColor: '#4ECDC4',
  backgroundColor: 'rgba(0, 0, 0, 0.3)',
  style: 'line',      // 'line', 'bars', 'particles', 'blob', 'circle', 'spectrum' 等
  lineWidth: 3,
  mirror: true,       // 是否镜像显示
  duration: 10,
  startTime: 0,
  animations: ['fadeIn'],
});
SVG 元素
scene.addSVG({
  src: './path/to/image.svg',
  x: '50%',
  y: '50%',
  width: 800,
  height: 600,
  duration: 5,
  startTime: 0,
  animations: ['fadeIn'],
});
JSON 元素(Paper.js 路径)
scene.addJSON({
  json: {
    type: 'Path',
    pathData: 'M 0,0 L 100,100',
    fillColor: '#4ECDC4',
  },
  x: '50%',
  y: '50%',
  duration: 5,
  startTime: 0,
});
ECharts 元素

将 ECharts 图表作为视频中的可视化元素进行渲染。图表动画与视频时间线同步:在元素的第一帧渲染时启动动画,不会在初始化阶段提前播放。

  • 用途:在场景中展示柱状图、折线图、饼图等数据可视化。
  • 依赖:需要安装 echarts
  • 关键参数:
    • option:ECharts 配置对象(与浏览器一致)。
    • renderer:渲染方式,'canvas'|'svg',默认 'canvas'
    • theme:ECharts 主题名称或对象。
    • backgroundColor:元素背景色(可与 option.backgroundColor 配合)。
    • x, y, width, height, anchor:定位与尺寸,单位与其他元素一致。
    • startTime, duration:时间线控制,决定元素何时出现与持续时长。
    • onFrame:每帧回调,可在时间线上通过 setOption 动态更新数据。
const option = { 
  animation: true, 
  animationDuration: 2000, 
  title: { text: 'ECharts 示例', textStyle: { color: '#fff' } }, 
  tooltip: {}, 
  xAxis: { data: ['A','B','C','D','E','F'], axisLine: { lineStyle: { color: '#aaa' } }, axisLabel: { color: '#ddd' } }, 
  yAxis: { axisLine: { lineStyle: { color: '#aaa' } }, axisLabel: { color: '#ddd' }, splitLine: { lineStyle: { color: '#333' } } }, 
  series: [{ type: 'bar', data: [5, 20, 36, 10, 10, 20], itemStyle: { color: '#00d9ff' } }] 
};

scene.addECharts({ 
  option, 
  x: '50%', 
  y: '55%', 
  width: 900, 
  height: 500, 
  backgroundColor: '#8fafeeff', 
  anchor: [0.5, 0.5], 
  startTime: 0, 
  duration: 6 
});
代码元素(Code)

用于展示带语法高亮的代码块,支持逐行、逐词、逐字的打字动画,行号、光标、自动滚动以及底部滚动留白。

scene.addCode({
  code: `function hello() {\n  const msg = 'Hello'\n  return msg\n}`,
  language: 'javascript',
  theme: 'dark',
  x: '50%',
  y: '55%',
  width: 700,
  height: 300,
  anchor: [0.5, 0.5],
  startTime: 0,
  duration: 6,
  fontSize: 24,
  showLineNumbers: true,
  showBorder: true,
  split: 'line',  // 打字模式:'line', 'word', 'letter'
  splitDelay: 0.1,
  borderRadius: 12,
  padding: 20
})

scene.addCode({
  code: `const items = [1,2,3,4]\nfor (let i = 0; i < 40; i++) {\n  console.log(items[i % items.length])\n}`,
  language: 'javascript',
  theme: 'dark',
  x: '50%',
  y: '55%',
  width: 800,
  height: 260,
  anchor: [0.5, 0.5],
  startTime: 0,
  duration: 8,
  fontSize: 22,
  showLineNumbers: true,
  showBorder: true,
  borderRadius: 10,
  padding: 18,
  paddingBottom: 26,
  cursor: true,
  cursorColor: '#00d9ff',
  cursorWidth: 2,
  split: 'letter',
  splitDelay: 0.06,
  splitDuration: 0.2,
  autoScroll: true,
  scrollPaddingBottom: 24
})

常用选项说明:

  • language 代码语言标识,例如 javascriptpythonjava
  • theme 主题,例如 darkmonokaidracula
  • showLineNumbers 是否显示行号
  • showBorderborderRadius 是否显示边框与圆角
  • split 打字模式:line(逐行)、word(逐词)、letter(逐字);配合 splitDelaysplitDuration
  • cursorcursorColorcursorWidth 光标样式
  • autoScroll 自动滚动使最新内容可见
  • paddingBottom 布局上的底部内边距
  • scrollPaddingBottom 打字滚动过程的底部留白
HTML 元素(任意 HTML/CSS → 视频帧)

Takumi 把任意 HTML/CSS 渲染为视频元素,支持 CSS 动画、中文、彩色 Emoji。

import { VideoBuilder } from 'fkbuilder';

builder.createTrack()
  .createScene({ duration: 5 })
    .addBackground({ color: '#1e1b4b' })
    .addHtml({
      x: 0, y: 0, width: 1280, height: 720, anchor: [0, 0],
      html: `
        <style>
          @keyframes fadeInUp {
            from { opacity: 0; transform: translateY(30px); }
            to   { opacity: 1; transform: translateY(0); }
          }
          .title { animation: fadeInUp 1s ease-out forwards; }
        </style>
        <h1 class="title" style="color:white;font-size:96px;text-align:center;">Hello HTML</h1>
      `,
      duration: 5,
    });

亮点

  • CSS 动画与视频时间轴同步:通过 timeMs 自动驱动 @keyframes
  • 彩色 Emoji:自动替换为 Twemoji SVG(CDN 加载,可离线缓存)
  • 中文开箱即用:自动注入跨平台 CJK 字体栈(微软雅黑 / 苹方 / Noto Sans CJK)
  • 零配置 Tailwindtailwind: true 直接用,不用装、不用编译

中文字重:微软雅黑只内置 400 / 700。font-weight: 800 / 900 会触发 fake-bold 合成,中文笔画会合并、糊掉。用 700(Bold)或换 SimHei 即可。详见 docs/html-element.md

详见 docs/html-element.md

转场效果

// 添加转场效果
// 注意:不需要指定 fromScene 和 toScene,系统会根据 startTime 自动找到对应的场景
track.addTransition({
  name: 'CrossZoom',  // 转场效果名称
  duration: 1,        // 转场时长(秒)
  startTime: scene2StartTime, // 转场结束时间(目标场景开始的时间)
});

// 使用示例:
let currentTime = 0;
const sceneDuration = 4;
const transitionDuration = 1;

// 场景1
const scene1 = track.createScene({
  duration: sceneDuration,
  startTime: currentTime,
});
currentTime += sceneDuration;

// 场景2(与场景1重叠,重叠部分用于转场)
const scene2StartTime = currentTime - transitionDuration;
const scene2 = track.createScene({
  duration: sceneDuration,
  startTime: scene2StartTime,
});

// 添加转场(从场景1转到场景2)
track.addTransition({
  name: 'CrossZoom',
  duration: transitionDuration,
  startTime: scene2StartTime, // 转场结束时间 = 场景2开始时间
});

常用转场效果:

  • fade - 淡入淡出
  • CrossZoom - 交叉缩放
  • CircleCrop - 圆形裁剪
  • LinearBlur - 线性模糊
  • Swirl - 漩涡
  • Directional - 方向擦除
  • Bounce - 弹跳
  • Dreamy - 梦幻
  • Radial - 径向
  • GridFlip - 网格翻转
  • Mosaic - 马赛克
  • PolkaDotsCurtain - 圆点窗帘
  • ZoomInCircles - 圆形缩放
  • directional-left/right/up/down - 方向性转场(别名)

支持所有 gl-transitions 转场效果。

动画系统

预设动画
// 使用预设动画名称
animations: ['fadeIn', 'bigIn', 'bounceIn', 'slideInLeft', 'rotate', 'scale']
自定义动画
import { TransformAnimation, KeyframeAnimation } from 'fkbuilder';

// 变换动画
const transform = new TransformAnimation({
  duration: 1.5,
  delay: 0,
  from: { scaleX: 0.5, scaleY: 0.5, rotation: 0, opacity: 0 },
  to: { scaleX: 1, scaleY: 1, rotation: 360, opacity: 1 },
  easing: 'ease-out',
});

// 关键帧动画
const keyframe = new KeyframeAnimation({
  duration: 2,
  keyframes: [
    { time: 0, value: { x: 0, y: 0 } },
    { time: 0.5, value: { x: 100, y: 50 } },
    { time: 1, value: { x: 200, y: 0 } },
  ],
  property: 'position',
  easing: 'ease-in-out',
});

// 添加到元素
element.addAnimation(transform);
element.addAnimation(keyframe);
onFrame 持续动画

onFrame 回调函数可以在每一帧更新元素,实现持续动画效果(如旋转、脉冲、闪烁等):

import { withContext } from 'fkbuilder';

// 持续旋转的圆形
const rotationSpeed = 3;
const onFrame = withContext((element, progress, time) => {
  element.rotation += rotationSpeed;
  const pulse = 1 + Math.sin(time * 4) * 0.2;
  if (element.config) {
    element.config.scaleX = pulse;
    element.config.scaleY = pulse;
  }
}, { rotationSpeed });

scene.addCircle({
  x: '50%',
  y: '50%',
  radius: 100,
  fillColor: '#4ECDC4',
  duration: 10,
  startTime: 0,
  onFrame: onFrame,
});

上下文关联(并行渲染支持):

在并行渲染中,闭包变量会丢失。使用 withContext 可以自动关联上下文变量:

import { withContext } from 'fkbuilder';

const rotationSpeed = 3;
const phaseOffset = 0.5;

// 使用 withContext 自动关联上下文
const onFrame = withContext((element, progress, time) => {
  element.rotation += rotationSpeed;
  const pulse = 1 + Math.sin(time * 4 + phaseOffset) * 0.2;
  if (element.config) {
    element.config.scaleX = pulse;
    element.config.scaleY = pulse;
  }
}, { rotationSpeed, phaseOffset }); // ES6 简写语法

element.onFrame = onFrame;

并行渲染

FKbuilder 支持 Worker Threads 并行渲染,大幅提升渲染性能。

await builder.render(outputPath, {
  parallel: true,        // 启用并行渲染
  usePipe: true,         // 使用管道模式(推荐,内存占用低)
  maxWorkers: 4,         // Worker 数量(默认根据 CPU 核心数)
});

渲染模式:

  • 串行渲染 (parallel: false) - 单线程渲染,支持所有功能
  • 并行渲染 (parallel: true) - 多线程渲染,支持大部分功能
    • 管道模式 (usePipe: true) - 实时写入 FFmpeg,内存占用低(推荐)
    • 文件模式 (usePipe: false) - 先保存帧文件,再编码,适合调试

并行渲染特性:

  • 支持所有元素类型
  • 支持动画和转场效果
  • 支持 onFrame 持续动画(需使用 withContext
  • 支持组件
  • 支持字体注册
  • 自动处理转场帧(主线程预处理)

预设动画列表

  • fadeIn - 淡入
  • fadeOut - 淡出
  • zoomIn - 放大进入
  • zoomOut - 放大退出
  • bigIn - 放大进入
  • bigOut - 放大退出
  • bounceIn - 弹跳进入
  • bounceOut - 弹跳退出
  • slideInLeft - 从左滑入
  • slideInRight - 从右滑入
  • slideInUp - 从上滑入
  • slideInDown - 从下滑入
  • slideInTop - 从顶部滑入
  • slideInBottom - 从底部滑入
  • slideOutLeft - 向左滑出
  • slideOutRight - 向右滑出
  • slideOutUp - 向上滑出
  • slideOutDown - 向下滑出
  • fadeInUp - 淡入上移
  • fadeInDown - 淡入下移
  • rotate - 旋转
  • scale - 缩放
  • bounce - 弹跳

转场效果列表

支持所有 gl-transitions 转场效果,包括:

  • fade - 淡入淡出
  • CrossZoom - 交叉缩放
  • CircleCrop - 圆形裁剪
  • LinearBlur - 线性模糊
  • Swirl - 漩涡
  • Directional - 方向擦除
  • Bounce - 弹跳
  • Dreamy - 梦幻
  • Radial - 径向
  • GridFlip - 网格翻转
  • Mosaic - 马赛克
  • PolkaDotsCurtain - 圆点窗帘
  • ZoomInCircles - 圆形缩放
  • directional-left/right/up/down - 方向性转场(别名)

更多转场效果请参考 gl-transitions

完整示例

多轨道多场景示例
import { VideoBuilder } from 'fkbuilder';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

async function createVideo() {
  const builder = new VideoBuilder({
    width: 1920,
    height: 1080,
    fps: 30,
  });

  // 轨道1:主内容
  const track1 = builder.createTrack({ zIndex: 1 });
  
  let currentTime = 0;
  const sceneDuration = 4;
  const transitionDuration = 1;

  // 场景1
  const scene1 = track1.createScene({
    duration: sceneDuration,
    startTime: currentTime,
  })
    .addBackground({ color: '#1a1a2e' })
    .addText({
      text: '场景 1',
      x: '50%',
      y: '50%',
      fontSize: 100,
      color: '#ffffff',
      textAlign: 'center',
      duration: sceneDuration,
      startTime: 0,
      animations: ['fadeIn'],
    });

  currentTime += sceneDuration;

  // 场景2
  const scene2StartTime = currentTime - transitionDuration;
  const scene2 = track1.createScene({
    duration: sceneDuration,
    startTime: scene2StartTime,
  })
    .addBackground({ color: '#2d3436' })
    .addText({
      text: '场景 2',
      x: '50%',
      y: '50%',
      fontSize: 100,
      color: '#ffffff',
      textAlign: 'center',
      duration: sceneDuration,
      startTime: 0,
      animations: ['fadeIn'],
    });

  // 添加转场(从场景1转到场景2)
  track1.addTransition({
    name: 'CrossZoom',
    duration: transitionDuration,
    startTime: scene2StartTime, // 转场结束时间 = 场景2开始时间
  });

  // 轨道2:叠加层
  const track2 = builder.createTrack({ zIndex: 2 });
  const overlay = track2.createScene({ duration: 8, startTime: 0 })
    .addText({
      text: '顶部标题',
      x: '50%',
      y: '10%',
      fontSize: 48,
      color: '#f39c12',
      textAlign: 'center',
      duration: 8,
      startTime: 0,
    });

  // 渲染视频
  const outputPath = path.join(__dirname, 'output/video.mp4');
  await builder.render(outputPath, {
    parallel: true,
    usePipe: true,
    maxWorkers: 4,
  });
}

createVideo().catch(console.error);
组件使用示例
import { VideoBuilder, Component } from 'fkbuilder';

const builder = new VideoBuilder({
  width: 1920,
  height: 1080,
  fps: 30,
});

const track = builder.createTrack({ zIndex: 1 });

// 创建一个可复用的卡片组件
const cardComponent = new Component({
  name: 'Card',
  width: 400,
  height: 300,
  x: '50%',
  y: '50%',
  anchor: [0.5, 0.5],
  startTime: 0,
  duration: 5,
});

// 在组件内添加元素(使用相对坐标)
cardComponent
  .addBackground({ color: '#2e3b3c' })
  .addRect({
    x: '50%',         // 相对于组件中心
    y: '50%',
    width: '90%',     // 相对于组件宽度
    height: '85%',    // 相对于组件高度
    fillColor: '#5acbed',
    borderRadius: 20,
  })
  .addText({
    text: '卡片标题',
    x: '50%',
    y: '30%',
    fontSize: 36,
    color: '#ffffff',
    textAlign: 'center',
  });

// 在场景中使用组件
const scene = track.createScene({ duration: 5, startTime: 0 });
scene.addBackground({ color: '#1a1a2e' });
scene.addComponent(cardComponent);

// 可以复用组件,改变位置和时间
const scene2 = track.createScene({ duration: 5, startTime: 5 });
scene2.addBackground({ color: '#1a1a2e' });
scene2.addComponent({
  ...cardComponent,
  x: '25%',  // 不同的位置
  y: '50%',
});

await builder.render('./output/video.mp4');
onFrame 持续动画示例
import { VideoBuilder, withContext } from 'fkbuilder';

const builder = new VideoBuilder({
  width: 1920,
  height: 1080,
  fps: 60,
});

const track = builder.createTrack({ zIndex: 1 });
const scene = track.createScene({ duration: 10, startTime: 0 });
scene.addBackground({ color: '#0a0a0a' });

// 持续旋转的圆形
const rotationSpeed = 3;
const onFrameRotate = withContext((element, progress, time) => {
  element.rotation += rotationSpeed;
}, { rotationSpeed });

scene.addCircle({
  x: '30%',
  y: '50%',
  radius: 100,
  fillColor: '#4ECDC4',
  duration: 10,
  startTime: 0,
  onFrame: onFrameRotate,
});

// 脉冲动画
const pulseSpeed = 4;
const pulseAmplitude = 0.2;
const onFramePulse = withContext((element, progress, time) => {
  const pulse = 1 + Math.sin(time * pulseSpeed) * pulseAmplitude;
  if (element.config) {
    element.config.scaleX = pulse;
    element.config.scaleY = pulse;
  }
}, { pulseSpeed, pulseAmplitude });

scene.addCircle({
  x: '70%',
  y: '50%',
  radius: 100,
  fillColor: '#FF6B6B',
  duration: 10,
  startTime: 0,
  onFrame: onFramePulse,
});

await builder.render('./output/video.mp4', {
  parallel: true,
  usePipe: true,
});
文字拆分动画示例
scene.addText({
  text: 'FKbuilder',
  x: '50%',
  y: '50%',
  fontSize: 120,
  color: '#ffffff',
  textAlign: 'center',
  duration: 5,
  startTime: 0,
  split: 'letter',        // 逐字拆分
  splitDelay: 0.1,        // 每个字符延迟 0.1 秒
  animations: ['fadeIn'], // 每个字符的动画
  textShadow: true,
  stroke: true,
  strokeColor: '#000000',
  strokeWidth: 2,
});
文本效果示例
scene.addText({
  text: '渐变文字',
  x: '50%',
  y: '50%',
  fontSize: 100,
  textAlign: 'center',
  duration: 5,
  startTime: 0,
  // 渐变效果
  gradient: true,
  gradientColors: ['#FF6B6B', '#4ECDC4', '#45B7D1'],
  gradientDirection: 'horizontal', // 'horizontal', 'vertical', 'diagonal'
  // 阴影效果
  textShadow: true,
  textShadowColor: '#000000',
  textShadowBlur: 20,
  textShadowOffsetX: 5,
  textShadowOffsetY: 5,
  // 发光效果
  textGlow: true,
  textGlowColor: '#FFFFFF',
  textGlowBlur: 30,
  textGlowIntensity: 1,
  // 描边效果
  stroke: true,
  strokeColor: '#000000',
  strokeWidth: 3,
  strokeStyle: 'solid', // 'solid', 'dashed', 'dotted'
});

单位系统

FKbuilder 支持多种单位,方便响应式设计:

  • 百分比 (%) - 相对于父容器
  • 视口单位 (vw, vh) - 相对于视频尺寸
  • 响应式像素 (rpx) - 类似小程序 rpx,750rpx = 100% width
  • 像素 (px) - 绝对像素值
element.addText({
  x: '50%',        // 水平居中
  y: '30vh',       // 距离顶部 30% 视频高度
  width: '80vw',   // 宽度为 80% 视频宽度
  fontSize: '5rpx', // 响应式字体大小
});

项目结构

FKbuilder/
├── src/
│   ├── core/              # 核心类(VideoMaker, Renderer, VideoExporter)
│   ├── elements/          # 元素类(Text, Image, Video, Shape 等)
│   ├── layers/            # 图层类
│   ├── animations/        # 动画类
│   ├── builder/           # 构建器类(VideoBuilder, Track, Scene, Component, Transition)
│   ├── utils/             # 工具函数
│   ├── workers/           # Worker 线程(并行渲染)
│   └── types/             # 类型定义
├── examples/              # 使用示例
├── assets/                # 资源文件
├── output/                # 输出目录
└── docs/                  # 文档

示例文件

查看 examples/ 目录获取更多示例:

  • cool-video.js - 酷炫视频示例
  • cool-video-with-context.js - 上下文关联示例
  • test-component.js - 组件使用示例
  • demo-video.js - 完整功能演示
  • project-intro-video.js - 项目简介视频示例
  • test-worker-parallel-rendering.js - 并行渲染性能测试
  • html-element-basic.js - HTML 元素基础用法
  • html-element-chinese-default.js - 默认中文支持(自动注入微软雅黑)
  • html-element-emoji.js - 彩色 Emoji 渲染(多场景)
  • html-element-keyframes.js - CSS @keyframes 动画
  • html-element-tailwind-zero.js - 零配置 Tailwind 集成
  • html-element-tailwind-custom-theme.js - 自定义主题(预编译 CSS)

运行示例:

node examples/cool-video.js
node examples/test-component.js
node examples/demo-video.js
node examples/html-element-tailwind-zero.js        # 推荐先看这个

性能优化

并行渲染

对于长视频(>100 帧),建议使用并行渲染:

await builder.render(outputPath, {
  parallel: true,
  usePipe: true,
  maxWorkers: 4,  // 根据 CPU 核心数调整
});
管道模式

管道模式可以大幅降低内存占用,推荐使用:

await builder.render(outputPath, {
  usePipe: true,  // 使用管道模式(默认)
});

API 参考

VideoBuilder
const builder = new VideoBuilder(config);
builder.createTrack(config);
builder.render(outputPath, options);
builder.export(outputPath, options);
builder.build();
builder.initialize();
Track
const track = builder.createTrack(config);
track.createScene(config);
track.addTransition(config);
track.addComponent(component);
Scene
const scene = track.createScene(config);
scene.addBackground(config);
scene.addText(config);
scene.addImage(config);
scene.addVideo(config);
scene.addRect(config);
scene.addCircle(config);
scene.addPath(config);
scene.addSVG(config);
scene.addJSON(config);
scene.addAudio(config);
scene.addSubtitle(config);
scene.addOscilloscope(config);
scene.addComponent(component);
Component
const component = new Component(config);
component.addBackground(config);
component.addText(config);
component.addImage(config);
// ... 支持所有元素类型
工具函数
import { withContext, autoContext, smartContext } from 'fkbuilder';

// 上下文关联(用于并行渲染)
const onFrame = withContext((element, progress, time) => {
  // 使用上下文变量
}, { variable1, variable2 });

许可证

MIT

贡献

欢迎提交 Issue 和 Pull Request!

相关链接