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代码语言标识,例如javascript、python、javatheme主题,例如dark、monokai、draculashowLineNumbers是否显示行号showBorder、borderRadius是否显示边框与圆角split打字模式:line(逐行)、word(逐词)、letter(逐字);配合splitDelay、splitDurationcursor、cursorColor、cursorWidth光标样式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)
- 零配置 Tailwind:
tailwind: true直接用,不用装、不用编译
中文字重:微软雅黑只内置 400 / 700。
font-weight: 800 / 900会触发 fake-bold 合成,中文笔画会合并、糊掉。用 700(Bold)或换 SimHei 即可。详见 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!