Core-SDK
Core-SDK 是画布渲染部分的 SDK,传入工程数据(JSON)可以将数据绘制到 Canvas 上。可基于该 SDK 进行二次开发,开发视频相关的小程序
,H5
,PC视频编辑器
等基于 web 的在线工具。
使用方法如下:
import { VideoCoreSDK } from "@h5/videoCoreSDK";
const vc = new VideoCoreSDK({
data: MovieData, // 必填,工程数据
movieId: "movieID", // 实例内部唯一标识,多个实例不能相同
env: "preview", // 必填,渲染模式:editor(编辑模式,可拖动编辑); preview(预览模式,只能预览,内存消耗更小)
registerId: "", // 必填,注册ID,和域名进行绑定的
EModuleEffectSourcePath: '/assets/effectcanvas/', // 特效资源模块加载路径
workerPath: "assets", // 选填,decode.worker.js的引用目录,默认是assets
stopControl: true, // 停止使用控制器,默认是启用了控制器
scale: 1, // 选填,画布缩放比例,默认是1
currentTime: 0, // 选填,默认开始时间是0
plugins: [], // 选填,扩展插件
});
const core = await vc.init();
/**
* 假设工程数据是movieData,修改数据->更新视图
*/
// 1、获取工程数据中第一个元素
const [element] = movieData.elements;
// 2、修改第一个元素的坐标为[100, 200]
element.style.x = 100;
element.style.y = 200;
// 3、更新视图
core.update();
可以通过new VideoCore(...)
获取到vc
实例,再通过vc.init()
获取到core
,core
实例中包含了很多属性
和方法
,下面就挨个介绍这些属性和方法以及使用技巧。
属性说明
下面只列出了实例core
的属性,:后面的表示属性的数据类型,私有属性都是_开头的
.movieId: string
实例的唯一标识,可以是一个随机字符串,默认是'movieId'
.workerPath: string
worker 的地址,默认是/assets/worker/decode.worker.js
,导出视频的时候需要使用这个 worker 去解码视频帧
.currentTime: number
当前显示的时间
.times: [number, number] | null
导出的时候可以传入 times 表示导出指定某一段时间的视频,单位是秒
.controlModeType: 'editElement' | 'editMask'
控制器的模式,分为元素编辑模式和遮罩编辑模式,在遮罩编辑模式下只可以编辑遮罩
.bodyContainer: PIXI.Container
body 容器,用于存放 PIXI 元素
.captionContainer: PIXI.Container
字幕容器,用于存放字幕元素
.data: types.MovieData
动画 JSON 数据
.events: events.EventsName
事件名称的实例,事件可以通过触发事件名称进行调用
// 更新视图
pubsub.publish(core.events.UPDATE_STAGE);
// 事件名称和说明:
events.UPDATE_STAGE; // 更新视图
events.VISIBLE_CONTROL; // 控制器显示隐藏
events.STOP_GROUP_DRAG; // 禁用组的框选
events.SORT_CONTAINER; // 重新排序container
events.UPDATE_CONTROL_TARGET; // target尺寸变化后更新控制器
events.UPDATE_CONTROL_LIST; // 控制器更新list
events.TRIGGER_CONTROL; // 触发控制器选中元素
events.TRIGGER_CONTROL_NO_CALLBACK; // 只触发控制器,不调用onSelected回调
events.UPDATE_MOVIE; // 更新Movie.tsx
events.CONTROL_CHANGE_END; // 控制器结束
events.CONTROL_CHANGE_START; // 控制器开始
.record: RecordObject
历史记录方法集合,env 为 editor 才会有此参数
export interface RecordItem {
desc: string; // 描述信息
}
export interface RecordObject {
add: (item: RecordItem) => void; // 添加历史记录
debounceAdd: (item: RecordItem) => void; // 使用防抖函数添加历史记录
redo: () => void;
undo: () => void;
manager: RecordManager; // 历史记录的数据管理
}
.resourceManage: ResourceManage
资源管理器实例,请参考类:packages\video-core\src\react-pixi\manage\resourceManage.ts
.movieSize: { width: number; height: number }
视频尺寸
.app: Application | undefined
pixijs 实例
.playing: boolean
是否在播放模式下,默认未在播放
.env: 'editor' | 'preview' | 'export'
当前的运行环境,editor 表示编辑器模式下,preview 表示预览模式下,export 表示导出模式下
.groups: types.BaseElement[][]
根据 trackIndex 对数据进行分组后的数据
.zIndexObjects: Record<string, number>
记录元素的 zIndex 数据,方便控制器元素使用
.cacheControlElementIds: string[]
控制器记录元素 ID 的数组
.usedMediaInfo: Record<string, types.UsedMediaItem>
缓存全部的媒体资源视频&音频,用于合成音频使用
.elementReadyMark: Record<string, 'start' | 'success' | 'error'>
记录图层准备成功,此处为了处理 react 中的异步问题,tring 可以是 elementId,或者其他参数
.renderAsyncMark: Record<string, 'start' | 'success' | 'error'>
参考格式:{elementId_time: 'start' | 'success' | 'error'}
绘制的过程是异步的,用于检测是否绘制成功了,绘制之前把元素的 id 和时间放入对象中,绘制成功后时间是 null,如果都绘制完成了标 记应该是{}
,1 秒都还没绘制出来就不做处理了,所以为了确保性能问题,每个画面的绘制时间必须要控制在 1 秒内
.controlElements: ControlChangeValues[]
记录控制器变化后的数据
export interface ControlChangeValues {
elementId: string; // 目标元素到ID
x: number;
y: number;
alpha?: number;
width: number;
height: number;
rotation: number;
}
方法说明
get hideLockData(): number
隐藏和锁定是针对整个轨道而言,返回锁定,隐藏显示元素记录,在计算 group 的时候就要设置该参数
return Record<number, { hide: boolean; lock: boolean }>;
getPixiContainerById(ids: string[]
): PIXI.Container[]
通过 ids 获取 pixi container 对象
pixiContainerToImageById(id: string
): Promise<HTMLImageElement>
通过 id 找到 pixi 的 container,然后再导出成图片
initHideLock(hideLock: Record<number, { hide: boolean; lock: boolean }>
)
时间轴中的轨道的隐藏,锁定信息会记录到 movieData._hideLock ={} 中,需要对其进行初始化,_hideLock 中的 key 是 trackIndex
getHideLock(trackIndex: number
): { hide: boolean;lock: boolean;}
获取轨道的 hide,lock 参数
setHideLock(params: { trackIndex: number; hide?: boolean; lock?: boolean }
, updateMovie?: boolean
)
设置指定轨道(trackIndex)的隐藏,锁定,第二个参数表示是否要更新 movie
changeControlMode(modeType: 'editElement' | 'editMask'
, id: string
)
切换编辑模式,分别是元素编辑 和 遮罩编辑。
getFrameItem(elementData: types.BaseElement
): types.FrameItem | null
获取当前帧数据,如果当前时间节点有数据将返回对应的帧数据(误差 0.1 秒)
asyncFrameAnimateStatus(elementData: types.BaseElement
, status: types.FrameItem | null
)
将帧动画的数据和元素的状态进行同步,可以理解为通过帧数据更新元素的显示状态
getFrameStatusByCurrentTime(elementData: types.BaseElement
, currentTime?: number
): types.FrameItem | null
获取指定时间位置的帧状态,如果第二个参数不传默认使用游标位置的时间
getFrameStatus(elementData: types.BaseElement
, relativeTime: number | null
): types.FrameItem | null
获取指定时间位置的帧状态
removeTrackMedias(trackIndex: number
, resourceId: string
)
移除媒体数据,删除元素的时候调用
checkSupportTransition(elementId: string
): boolean
判断元素后是否支持插入转场数据,只有相邻的两个视频,图片元素之间才可以插入转场
removeInvalidTransition()
去掉无效的转场动画
play()
播放视频
pause()
暂停视频
sortZIndexNewData()
保存的时候重置 zindex,返回新的数据,之所以会重置 zindex 参数是因为插入新轨道的时候下标可能出现小数,重置会重新更新为整数
step(time: number
)
设置视频时间
runAnimate()
执行 play 操作,fps 默认是 32 帧,requestAnimationFrame 的频率可能会在 60fps,这里需要通过 FPS 来播放,之所以不使用 setTimeout 来操 作,是因为 setTimeout 会导致误差很大而且没法纠正时间
updateControl(type: 'updateTarget' | 'updateList' | 'trigger' | 'triggerNoCallback' | 'visible' | 'stopGroupDrag'
, doms?: HTMLElement[] | SVGElement[] | string[] | { visible: boolean; elementId: string } | boolean
)
更新控制器的方法
updateTarget: target 尺寸变化后更新控制器
updateList: targets 列表变化后更新控制器
trigger: 触发元素被选中
triggerNoCallback: 只触发控制器,不调用 onSelected 回调
visible: 显示隐藏控制器 { visible, elementId }
stopGroupDrag: 禁用&启用组的框选
// 触发控制器选中 elementId1
movie.updateControl("trigger", ["elementId1"]);
updateSortTracks()
轨道排序更新,需要重新调用此方法去更新 pixi 中 z-index 的问题
getTotalTime()
获取视频的总时长
getElementDataByIds(ids: string[]
)
通过 ids 获取元素
getElementDataByTypes(types: types.ElementType[]
, data?: types.MovieData
): types.BaseElement[]
通过类型获取元素
getCloneData()
获取 data 的 clone 数据,会重新计算 trackIndex,使其变成整数,从 1 开始
addResource(url: string
, styleSize?: types.StyleSize
): Promise<types.Resource>
添加资源,资源会同步添加到 resourceManage 缓存起来
export interface StyleSize {
width: number;
height: number;
}
addElementByResource(resource: types.Resource
, params: { elementType: types.ElementType; time: number; trackIndex?: number; duration?: number }
)
通过资源数据添加元素
core.addElementByResource(resource, {
elementType: "image", // 插入图片
time: 10, // 从10秒开始
trackIndex: 2, // 插入到第二个轨道
duration: 5, // 持续显示5秒
});
addElementNoSource( info: Record<string | 'attrs', any>
, params: { elementType: types.ElementType; time: number; trackIndex?: number; duration?: number }
)
添加那种没有 resource 的资源的元素,比如:text, effect, cutScene 等
update(time?: number
)
更新 Movie 组件,比如修改了某个元素的_dirty 参数,可以调用此函数,修改了数据结构也可以调用此方法,export 环境中,使用 update 更新组件,因为在导出过程中,绘制是一个异步的过程,这里需要判断是否绘制成功
capture(): string
截取当前视图的画面,返回 base64 图片
controlChangeStart(elementIds: string[]
)
控制器选中的时候会触发该方法,不需要单独调用
controlChangeEnd(elementIds: string[]
)
控制器结束的回调函数,不需要单独调用
destroy()
销毁实例,内存回收
事件相关
onControlChangeEnd: ((elementIds: string[]) => void)
绑定控制器变化结束的事件
onControlChangeStart: ((elementIds: string[]) => void)
绑定控制器开始的事件
onEachSourceProgress: (n: { src: string; p: number; total: number }) => void
每个资源加载进度都会触发该事件
triggerCurrentTime: (t: number) => void
触发 currentTime 变化的事件
triggerRecordSelectElements: (ids: string[]) => void
触发元素选中