工程数据
什么是工程数据?
视频在编辑过程中,会有一个JSON
数据用于记录当前编辑的视频的所有信息。这个JSON
数据就是所谓的工程数据。每次创建新的视频都会创建一个新的工程数据。
为了方便大家开发和阅读,我们使用JSON
来记录工程数据。
工程数据说明
使用Typescript
语法来表述数据结构
1、工程数据 MovieData
/**
* 工程数据
*/
interface MovieData {
title: string; // 名称
version: string; // 数据版本
ratio?: string; // 16:9
createTime: number; // 创建时间(时间戳)
updateTime: number; // 更新时间(时间戳)
poster: string; // 封面图片
width: number; // 原始尺寸
height: number;
background: Background; // 背景
transitions: TransitionItem[]; // 转场动画
captions: CaptionElement[]; // 字幕
elements: BaseElement[]; // 元素:图片、文本、特效、贴纸、视频、音频元素
resouces: Resource[]; // 资源文件
// 记录编辑器中的配置
_hideLock?: Record<number, { hide: boolean; lock: boolean }>;
}
2、背景 Background
interface Background {
disable?: boolean; // 启用禁用
color?: string; // 背景色
cropper?: {
// 是否裁剪背景图片
width: number;
height: number;
x: number;
y: number;
rotation?: number; // 旋转角度
};
resourceId?: string; // 背景图片的素材ID,和MovieData.resources中的素材ID对应
backgroundRepeat?: "no-repeat" | "repeat-x" | "repeat-y" | "repeat"; // 背景图平铺方式
backgroundSize?: "auto" | "contain" | "cover"; // 默认是'auto'
}
3、转场动画 TransitionItem
转场动画只能在两个相邻的图片,视频元素之间
interface TransitionItem {
id: string; // 唯一标识
_dirty: string; // 用于控制元素内部更新,如果变化了,会触发组件更新
_lock?: boolean; // 用户操作的锁定
_hidden?: boolean; // 用户操作的元素是否可见
name: string; // 图层名称
duration: number; // 持续时间,实际时间 = duration * speed;
startElementId: string; // 开始执行动画的元素ID
transitionName?: string; // 动画名称,如果存在就使用系统预设
glslCoding?: string; // glsl动画代码
paramsTypes?: Record<string, any>;
defaultParams?: Record<string, any>;
extend?: any; // 扩展字段
}
4、元素基础类 BaseElement
其他元素类都继承 BaseElement,其他元素类目前有:CaptionElement,TextElement,ImageElement,StickerElement,FilterElement,EffectElement,VideoElement,GroupElement,MaskElement,AudioElement,LottieElement。
// 下划线参数只在编辑的时候有用
interface BaseElement {
id: string; // 唯一标识
_dirty: string; // 用于控制元素内部更新,如果变化了,会触发组件更新
_animationDirty?: string; // 用于重置动画的
_frameDirty?: string; // 用于帧动画重置
_noControl?: boolean; // 无控制器
_filtersDirty?: string; // 用于触发filters更新的
_ratio?: number; // 记录宽高比,编辑器中用到的参数
scale?: number; // 缩放比例,默认是1
templateEnable?: boolean; // 模版模式下可修改(替换)的元素
filters?: {
name: string; // 滤镜类名
enabled: boolean;
params: Record<string, any>; // 自定义参数
}[]; // 滤镜 不显示的元素是没有filters的
frames?: FrameItem[]; // 帧动画参数
controlUnKeepRatio?: boolean; // 控制器不保持等比缩放
name: string; // 图层名称
duration: number; // 持续时间,实际时间 = duration * speed;
startTime: number; // 开始播放时间
type: string; // 类型
trackIndex: number; // 层级,可以是小数 比如 trackIndex 如果需要在 0 和 1插入新的轨道,新的轨道trackIndex可以是 0.5,所以trackIndex不可以是0,如果trackIndex是-1表示主轨道
extend?: any; // 扩展字段
}
// 帧动画
interface FrameItem {
id: string;
startTime: number;
// 帧数据
x?: number;
y?: number;
width?: number;
height?: number;
alpha?: number;
rotation?: number;
// 遮罩动画
maskX?: number;
maskY?: number;
maskWidth?: number;
maskHeight?: number;
maskBlur?: number;
maskRotation?: number;
maskAlpha?: number;
// 强度参数
intensity?: number;
// 音量
volume?: number;
// 文字
textScale?: number;
textColor?: string | string[];
textBgColor?: string;
textBorderColor?: string;
textGradientStops?: number[];
}
0// 元素样式
interface ElementStyle {
width?: number;
height?: number;
rotation?: number;
alpha: number;
x: number;
y: number;
}
// 滤镜参数
interface Filter {
name: string; // 滤镜类名
enabled: boolean;
params: Record<string, any>; // 自定义参数
}
// 2D帧动画
interface AnimationFrame {
id: string; // 唯一表示
progress: number; // 进度
transform: Transform; // transform变化
alpha?: number; // 透明度变化
width?: number; // 宽
height?: number; // 高
_dirty: string; // 待定字段
}
// transform参数
interface Transform {
translateX?: number;
translateY?: number;
rotation?: number;
scaleX?: number;
scaleY?: number;
skewX?: number;
skewY?: number;
}
// 动画元素
interface AnimationItem {
id: string;
oid: string; // 原始数据ID
type: AnimationType;
name: string;
ename: string; // 英文
start: number; // 动画开始时间
duration: number; // 动画总时间
frames: AnimationFrame[]; // 帧数据
_dirty?: string;
}
/**
* 动画类型
* enter 表示进入动画
* emphasize 表示强调动画,介于进入和离开之间的动画
* leave 表示离开动画
*/
type AnimationType = "enter" | "emphasize" | "leave";
// 裁剪
interface CropSize {
x: number;
y: number;
width: number;
height: number;
}
// 元素蒙版本质上是一张黑色背景白色元素的图片
interface ElementMask extends ElementStyle {
resourceId: string;
name: string;
blur: number; // 羽化半径
}
5、资源 Resource
资源数据存放在movieData.resouces
数组中,元素数据使用资源的方式是使用id
,比如图片数据中的数据是resourceId
。
interface Resource {
id: string;
name: string; // 名称
type: string; // 资源类型
url: string; // 资源地址
reverse?: boolean; // 是否倒放视频?
originId?: string; // 原始资源文件的id
thumb?: string; // 缩图
wave?: string; // 音波json
frames?: string; // 帧图
noAudioTracks?: boolean; // 无音轨
styleSize?: {
width: number;
height: number;
}; // 尺寸,视频和图片都有尺寸
fileSize?: number; // 文件大小
mustFetch: boolean; // 渲染之前是否必须要fetch文件
fileType: string; // 文件支持类型
from: "user" | "system" | "other"; // 资源来源
duration?: number; // 持续时间,视频和音频文件才有
extend?: any; // 扩展字段
attrs?: Record<string, any>; // 扩展字段
}
6、文字元素 TextElement
文字样式textStyle
参考:https://pixijs.io/pixi-text-style/#
interface TextElement extends BaseElement {
textScale?: number; // 文字缩放大小
text: string; // 字内容
textStyle: Record<string, any>;
textEnterAnimate?: AnimationItem; // 文字逐字动画
style: ElementStyle;
flipx: boolean; // 是否镜像翻转
filters?: Filter[]; // 滤镜 滤镜元素是没有filters的
}
7、字幕元素 CaptionElement
字幕元素继承TextElement
// 字幕
interface CaptionElement extends TextElement {
id: string;
type: "caption";
}
8、图片元素 ImageElement
图片支持的格式有png
,jpg
,jpeg
,gif
// 字幕
interface interface ImageElement extends BaseElement {
resourceId: string;
blendMode: PIXI.BLEND_MODES; // 混合模式
style: ElementStyle;
flipx: boolean; // 是否镜像翻转
fps?: number; // gif图会有fps参数
filters?: Array<Filter>; // 滤镜 滤镜元素是没有filters的
animates?: AnimationItem[];
isGif?: boolean;
mask?: ElementMask; // 蒙版
cropSize?: CropSize; // 裁剪
matting: {
// 抠像
enabled: boolean; // 是否启用
color: string; // 扣掉的颜色
filterType: number; // 滤镜类型(0~6)默认是0
lightLevel: number; // 修改明暗 默认:0.2 可选 0.1 - 0.7;
gridSize: number; // 修改噪点数,默认是0.8 可选 0.2 - 1.5;
emergence: number; // 羽化强度
};
}
9、贴纸元素 StickerElement
sticker 贴纸 和 image 本质上没什么区别,预留了一个类型,方便后续进行业务扩展
interface StickerElement extends ImageElement {}
10、滤镜元素 FilterElement
滤镜是叠加到整个画面的特殊效果,滤镜采用GLSL
语法写的,滤镜效果参考:https://pixijs.io/filters/examples
interface FilterElement extends BaseElement {
resourceId: string; // 滤镜图片URL
intensity: number; // 强度
}
11、特效元素 EffectElement
特效是滤镜的参数动态变化后的效果
interface EffectElement extends BaseElement {
effects: {
id: string;
name: string;
frames: {
id: string;
progress: number;
params: Record<string, any>;
}[];
}[];
}
12、视频元素 VideoElement
视频格式目前只支持mp4
其他格式的视频上传到服务器会先进行转码,转码成mp4
再导入到视频编辑器中进行编辑。
interface VideoElement extends BaseElement {
resourceId: string;
volume: number;
muted: boolean;
speed: number; // 默认是1
clipTime: number; // 截取开始时间,默认是0
style: ElementStyle;
blendMode: PIXI.BLEND_MODES; // 混合模式
cropSize?: CropSize; // 裁剪
matting: {
// 抠像
enabled: boolean; // 是否启用
color?: string; // 扣掉的颜色
filterType?: number; // 滤镜类型(0~6)默认是0
lightLevel?: number; // 修改明暗 默认:0.2 可选 0.1 - 0.7;
gridSize?: number; // 修改噪点数,默认是0.8 可选 0.2 - 1.5;
emergence?: number; // 羽化强度
};
separate: 0 | 1; // 音视频分离,默认是0未分离,1表示分离
fadeInTime: number; // 淡入n秒
fadeOutTime: number; // 淡出n秒
flipx: boolean; // 是否镜像翻转
animates?: AnimationItem[];
mask?: ElementMask; // 蒙版
}
13、组元素 GroupElement
预留的元素参数,方便后续扩展
interface GroupElement extends BaseElement {
style: ElementStyle;
animates?: AnimationItem[];
children: BaseElement[]; // 子元素
flipx: boolean; // 是否镜像翻转
mask?: ElementMask; // 蒙版
}
14、遮罩元素 MaskElement
遮罩元素主要在遮罩动画中有被使用
interface MaskElement extends BaseElement {
resourceId: string;
style: ElementStyle;
animates?: AnimationItem[];
mask?: ElementMask; // 蒙版
}
15、音频元素 AudioElement
音频元素支持的格式AAC
,mp3
格式,其他格式需要在服务端进行转码后使用。
interface AudioElement extends BaseElement {
resourceId: string;
volume: number; // 音量
muted: boolean; // 是否静音
speed: number; // 默认是1
clipTime: number; // 截取开始时间,默认是0
fadeInTime: number; // 淡入n秒
fadeOutTime: number; // 淡出n秒
}
16、Lottie 动画元素 LottieElement
lottie动画可以参考网站:https://lottiefiles.com
后台管理系统可以上传lottie动画,支持格式.lottie
interface LottieElement extends BaseElement {
resourceId: string; // 资源id
blendMode: PIXI.BLEND_MODES; // 混合模式
style: ElementStyle;
flipx: boolean; // 是否镜像翻转
filters?: Array<Filter>; // 滤镜 滤镜元素是没有filters的
animates?: AnimationItem[];
mask?: ElementMask; // 蒙版
cropSize?: CropSize; // 裁剪,相对于原始尺寸进行裁剪
initStartFrame: number; // 初始化开始帧
lottieSpeed: number; // 播放速度
// replaceText:
}
工程数据示例
下面是一个完整的初始化工程数据示例
// 工程数据demo
const projectData = {
title: "未命名", // 项目标题
createTime: 0, // 创建时间
updateTime: 0, // 更新时间
poster: "", // 封面
width: 1920, // 尺寸
height: 1080,
background: {
color: "#677C8A", // 背景
},
transitions: [], // 转场
captions: [], // 字幕内容信息,
elements: [], // 元素数据
resouces: [], // 资源文件数据,资源文件的ID会和元素数据的resourceId进行绑定
_hideLock: {}, // 轨道的锁定,隐藏操作数据
};