@realsee/vreo 0.1.3 → 0.1.6-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/docs/assets/search.js +1 -1
  2. package/docs/classes/Player.Player-1.html +6 -6
  3. package/docs/enums/Player.InfoPanelTypeEnum.html +1 -1
  4. package/docs/enums/Player.PanoEffectEnum.html +1 -1
  5. package/docs/enums/Player.PanoTagEnum.html +1 -1
  6. package/docs/enums/Player.VreoKeyframeEnum.html +13 -11
  7. package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
  8. package/docs/enums/fivePlugins.Rotation.html +1 -1
  9. package/docs/interfaces/Player.PlayerConfigs.html +1 -1
  10. package/docs/interfaces/Player.Vertex.html +1 -1
  11. package/docs/interfaces/Player.VreoKeyframe.html +1 -1
  12. package/docs/interfaces/Player.VreoUnit.html +1 -1
  13. package/docs/interfaces/Player.VreoVideo.html +1 -1
  14. package/docs/interfaces/fivePlugins.CameraMovementOptsCallback.html +1 -1
  15. package/docs/interfaces/fivePlugins.CameraMovementPluginExportType.html +2 -2
  16. package/docs/interfaces/fivePlugins.ModelTVVideoPluginData.html +1 -1
  17. package/docs/interfaces/fivePlugins.ModelTVVideoPluginExportType.html +1 -1
  18. package/docs/interfaces/fivePlugins.ModelTVVideoPluginParameterType.html +1 -1
  19. package/docs/interfaces/react.VreoActionCallbacks.html +6 -6
  20. package/docs/modules/Player.html +14 -12
  21. package/docs/modules/fivePlugins.html +2 -2
  22. package/docs/modules/react.html +1 -1
  23. package/lib/Player/index.d.ts +1 -0
  24. package/lib/Player/index.js +33 -28
  25. package/lib/Player/modules/VideoAgent/VideoAgentMesh.d.ts +2 -0
  26. package/lib/Player/modules/VideoAgent/VideoAgentMesh.js +59 -21
  27. package/lib/Player/modules/VideoAgent/VideoAgentScene.d.ts +1 -0
  28. package/lib/Player/modules/VideoAgent/VideoAgentScene.js +6 -0
  29. package/lib/Player/modules/VideoAgent/index.js +6 -0
  30. package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +13 -1
  31. package/lib/fivePlugins/CameraMovementPlugin/index.js +5 -4
  32. package/lib/fivePlugins/CameraMovementPlugin/typings.d.ts +1 -0
  33. package/lib/react/index.js +6 -2
  34. package/lib/typings/VreoUnit.d.ts +9 -2
  35. package/lib/typings/VreoUnit.js +1 -0
  36. package/package.json +2 -2
  37. package/resources/Player/Controller.ts +0 -3
  38. package/resources/Player/index.tsx +31 -25
  39. package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +62 -19
  40. package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +4 -0
  41. package/resources/Player/modules/VideoAgent/index.tsx +5 -0
  42. package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +12 -2
  43. package/resources/fivePlugins/CameraMovementPlugin/index.ts +8 -3
  44. package/resources/fivePlugins/CameraMovementPlugin/typings.ts +1 -0
  45. package/resources/react/index.tsx +5 -2
  46. package/resources/typings/VreoUnit.ts +9 -1
@@ -28,7 +28,19 @@ function UpdateVRPanorama() {
28
28
 
29
29
  var _ref = keyframe.data,
30
30
  panoIndex = _ref.panoIndex,
31
- images = _ref.images;
31
+ images = _ref.images,
32
+ work = _ref.work;
33
+
34
+ if (work) {
35
+ five.load(work);
36
+ return;
37
+ }
38
+
39
+ console.warn('not support.');
40
+ Object.keys(images).forEach(function (_key) {
41
+ var key = _key;
42
+ images[key] = images[key].replace(/https*:\/\//, '//');
43
+ });
32
44
  var newWorkJSON = JSON.parse(JSON.stringify((_five$work = five.work) === null || _five$work === void 0 ? void 0 : _five$work.raw.work)); // // 原Work数据不能被修改
33
45
 
34
46
  if (newWorkJSON.panorama && newWorkJSON.panorama.list && newWorkJSON.panorama.list[panoIndex]) {
@@ -204,18 +204,19 @@ var CameraMovementPlugin = function CameraMovementPlugin(five) {
204
204
 
205
205
  if (opts.asyncStartCallback) {
206
206
  opts.asyncStartCallback();
207
- }
207
+ } // 先切换模型再出旋转效果
208
+
208
209
 
209
- if (!(five.currentMode !== _five.Five.Mode.Panorama)) {
210
+ if (!(args.mode && five.currentMode !== args.mode)) {
210
211
  _context2.next = 5;
211
212
  break;
212
213
  }
213
214
 
214
215
  _context2.next = 5;
215
- return five.changeMode(_five.Five.Mode.Panorama);
216
+ return five.changeMode(args.mode);
216
217
 
217
218
  case 5:
218
- if (!(args.panoIndex !== undefined && args.panoIndex !== five.panoIndex)) {
219
+ if (!(args.mode === _five.Five.Mode.Panorama && five.currentMode === _five.Five.Mode.Panorama && args.panoIndex !== undefined && args.panoIndex !== five.panoIndex)) {
219
220
  _context2.next = 11;
220
221
  break;
221
222
  }
@@ -38,6 +38,7 @@ export declare type MoveOpts = {
38
38
  preload?: boolean;
39
39
  } & CameraMovementOptsCallback;
40
40
  export declare type RotateArgs = {
41
+ mode?: Mode;
41
42
  panoIndex: number;
42
43
  loop: boolean;
43
44
  rotateSpeed: number;
@@ -42,10 +42,14 @@ var VreoProvider = function VreoProvider(props) {
42
42
  player = _React$useState2[0],
43
43
  setPlayer = _React$useState2[1];
44
44
 
45
+ var playerRef = React.useRef(null);
45
46
  React.useEffect(function () {
46
- setPlayer(new _Player.Player(five));
47
+ playerRef.current = new _Player.Player(five);
48
+ setPlayer(playerRef.current);
47
49
  return function () {
48
- player === null || player === void 0 ? void 0 : player.dispose();
50
+ var _playerRef$current;
51
+
52
+ (_playerRef$current = playerRef.current) === null || _playerRef$current === void 0 ? void 0 : _playerRef$current.dispose();
49
53
  };
50
54
  }, []);
51
55
  if (!player) return /*#__PURE__*/React.createElement(React.Fragment, null);
@@ -1,4 +1,4 @@
1
- import { Mode, Pose, WorkCubeImage } from '@realsee/five';
1
+ import { Mode, Pose, WorkCubeImage, Work } from '@realsee/five';
2
2
  import { CameraMovementEffect, Rotation } from '../fivePlugins/CameraMovementPlugin/typings';
3
3
  export declare enum VreoKeyframeEnum {
4
4
  /** 运镜 */
@@ -38,7 +38,11 @@ export declare enum VreoKeyframeEnum {
38
38
  /**
39
39
  * 结束
40
40
  */
41
- Exit = "Exit"
41
+ Exit = "Exit",
42
+ /**
43
+ * 自定义剧本帧
44
+ */
45
+ Custom = "Custom"
42
46
  }
43
47
  /**
44
48
  * 支持自定义剧本关键帧配置项
@@ -111,6 +115,7 @@ export declare type PrompterData = {
111
115
  export declare type UpdateVRPanoramaData = {
112
116
  panoIndex: number;
113
117
  images: WorkCubeImage;
118
+ work?: Work;
114
119
  };
115
120
  /**
116
121
  * 顶点
@@ -202,3 +207,5 @@ export declare type VideoEffectData = {
202
207
  direction?: Vertex;
203
208
  vector?: Pick<Pose, 'longitude' | 'latitude'>;
204
209
  };
210
+ /** 自定义序列帧 */
211
+ export declare type CustomData = Record<string, any>;
@@ -22,6 +22,7 @@ exports.VreoKeyframeEnum = VreoKeyframeEnum;
22
22
  VreoKeyframeEnum["InfoPanel"] = "InfoPanel";
23
23
  VreoKeyframeEnum["VideoEffect"] = "VideoEffect";
24
24
  VreoKeyframeEnum["Exit"] = "Exit";
25
+ VreoKeyframeEnum["Custom"] = "Custom";
25
26
  })(VreoKeyframeEnum || (exports.VreoKeyframeEnum = VreoKeyframeEnum = {}));
26
27
 
27
28
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realsee/vreo",
3
- "version": "0.1.3",
3
+ "version": "0.1.6-alpha.2",
4
4
  "description": "Vreo (VR Video 缩写) 是基于如视三维渲染引擎 Five 和 用户界面构建库 React 实现的如视 3D 空间剧本播放器。",
5
5
  "keywords": [
6
6
  "realsee",
@@ -35,7 +35,7 @@
35
35
  "@babel/preset-env": "^7.16.4",
36
36
  "@babel/preset-react": "^7.16.0",
37
37
  "@babel/preset-typescript": "^7.16.0",
38
- "@realsee/five": "^5.0.0-alpha.57",
38
+ "@realsee/five": "^5.0.0-alpha.91",
39
39
  "@types/offscreencanvas": "^2019.6.4",
40
40
  "@types/react": "^17.0.37",
41
41
  "@types/react-dom": "^17.0.11",
@@ -152,6 +152,3 @@ export class Controller extends Subscribe<VreoKeyframeEvent> {
152
152
  }
153
153
 
154
154
  export const ControllerContext = React.createContext<Controller | null>(null)
155
-
156
-
157
-
@@ -9,18 +9,19 @@ import { reaction } from 'mobx'
9
9
  import { Drawer } from './modules/Drawer'
10
10
  import { PlayerConfigs } from './typings'
11
11
 
12
- const controller = new Controller()
13
-
14
12
  export class Player extends Subscribe<VreoKeyframeEvent> {
15
13
  $five: Five
14
+ private controller: Controller
16
15
  configs: Readonly<PlayerConfigs>
17
16
 
18
17
  constructor(five: Five, configs: Partial<PlayerConfigs> = {}) {
19
18
  super()
20
- this.$five = controller.$five = five
19
+ this.controller = new Controller()
20
+ this.$five = this.controller.$five = five
21
21
 
22
22
  if (!configs.containter) {
23
- const containter = document.createElement('div')
23
+ const containter = document.querySelector('#vreo-app') || document.createElement('div')
24
+ ReactDOM.unmountComponentAtNode(containter)
24
25
  containter.setAttribute('id', 'vreo-app')
25
26
  configs.containter = containter
26
27
  document.body.append(containter)
@@ -35,10 +36,10 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
35
36
  )
36
37
  )
37
38
 
38
- controller.configs = this.configs
39
+ this.controller.configs = this.configs
39
40
 
40
41
  ReactDOM.render(
41
- <ControllerContext.Provider value={controller}>
42
+ <ControllerContext.Provider value={this.controller}>
42
43
  <App></App>
43
44
  <Drawer />
44
45
  </ControllerContext.Provider>,
@@ -47,7 +48,7 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
47
48
 
48
49
  // 监听播放情况:抛出触发时机
49
50
  reaction(
50
- () => controller.playing,
51
+ () => this.controller.playing,
51
52
  (playing) => {
52
53
  this.emit(playing ? 'playing' : 'paused')
53
54
  }
@@ -55,56 +56,61 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
55
56
  }
56
57
 
57
58
  async load(vreoUnit: VreoUnit, currentTime = 0) {
58
- if (!controller.visible) {
59
- controller.setVisible(true)
59
+ if (!this.controller.visible) {
60
+ this.controller.setVisible(true)
60
61
  await new Promise((resolve) => {
61
62
  setTimeout(() => resolve(true), 500)
62
63
  })
63
64
  }
64
65
 
65
- if (controller.stopInterval) {
66
- controller.stopInterval()
67
- controller.stopInterval = undefined
66
+ if (this.controller.stopInterval) {
67
+ this.controller.stopInterval()
68
+ this.controller.stopInterval = undefined
68
69
  }
69
70
 
70
- controller.vreoUnit = vreoUnit
71
- controller.videoInstance?.pause()
71
+ this.controller.vreoUnit = vreoUnit
72
+ this.controller.videoInstance?.pause()
72
73
 
73
74
  if (vreoUnit.video.url) {
74
- if (controller.videoAgentScene?.videoAgentMesh.videoInstance) {
75
- controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
75
+ if (this.controller.videoAgentScene?.videoAgentMesh.videoInstance) {
76
+ this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
76
77
  }
77
- await controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url)
78
+ await this.controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url)
78
79
  this.play()
79
80
  }
80
- controller.run((type, keyframe) => this.emit(type, keyframe))
81
+ this.controller.run((type, keyframe) => this.emit(type, keyframe))
81
82
  return true
82
83
  }
83
84
 
84
85
  get paused() {
85
- return !controller.playing
86
+ return !this.controller.playing
86
87
  }
87
88
 
88
89
  play() {
89
- if (controller.playing) return true
90
- controller.setPlaying(true)
90
+ if (this.controller.playing) return true
91
+ this.controller.setPlaying(true)
91
92
  return true
92
93
  }
93
94
 
94
95
  pause() {
95
- controller.setPlaying(false)
96
+ this.controller.setPlaying(false)
96
97
  }
97
98
 
98
99
  show() {
99
- controller.setVisible(true)
100
+ this.controller.setVisible(true)
100
101
  }
101
102
 
102
103
  hide() {
103
- controller.setVisible(false)
104
+ this.controller.setVisible(false)
104
105
  }
105
106
 
106
107
  dispose() {
107
- controller.dispose()
108
+ this.pause()
109
+ this.controller.dispose()
110
+
111
+ if (this.configs.containter) {
112
+ ReactDOM.unmountComponentAtNode(this.configs.containter as Element)
113
+ }
108
114
  }
109
115
  }
110
116
 
@@ -57,6 +57,11 @@ void main(void) {
57
57
  }
58
58
  `
59
59
 
60
+ const cacheInstance: {
61
+ videoInstance?: HTMLVideoElement
62
+ audioInstance?: HTMLAudioElement
63
+ } = {}
64
+
60
65
  export interface VideoAgentMeshOptions {
61
66
  videoInstance?: HTMLVideoElement
62
67
  }
@@ -70,6 +75,7 @@ export class VideoAgentMesh extends THREE.Mesh {
70
75
  freeze: boolean
71
76
  paused: boolean
72
77
  audioInstance: HTMLAudioElement
78
+ $removeEventListener: () => void
73
79
 
74
80
  get videoInstance(): HTMLAudioElement {
75
81
  if (this.videoUrl?.endsWith('mp3')) {
@@ -96,13 +102,19 @@ export class VideoAgentMesh extends THREE.Mesh {
96
102
  options: VideoAgentMeshOptions = {},
97
103
  ) {
98
104
  if (!options.videoInstance) {
99
- const videoInstance = document.createElement('video')
100
- videoInstance.style.opacity = '0'
101
- videoInstance.style.display = 'none'
102
- document.body.append(videoInstance)
103
- options.videoInstance = videoInstance
104
- videoInstance.playsInline = true
105
- videoInstance.controls = false
105
+ if (cacheInstance.videoInstance) {
106
+ options.videoInstance = cacheInstance.videoInstance
107
+ } else {
108
+ const videoInstance = document.createElement('video')
109
+ videoInstance.style.opacity = '0'
110
+ videoInstance.style.display = 'none'
111
+ document.body.append(videoInstance)
112
+ options.videoInstance = videoInstance
113
+ cacheInstance.videoInstance = videoInstance
114
+ videoInstance.playsInline = true
115
+ videoInstance.controls = false
116
+ }
117
+
106
118
  }
107
119
 
108
120
  const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
@@ -123,24 +135,41 @@ export class VideoAgentMesh extends THREE.Mesh {
123
135
  this.paused = true
124
136
 
125
137
  {
126
- const audioInstance = document.createElement('audio')
127
- audioInstance.crossOrigin = ''
128
- // videoInstance.muted = true
129
- audioInstance.muted = false
130
- audioInstance.setAttribute('playsinline', 'true')
131
- audioInstance.setAttribute('webkit-playsinline', 'true')
132
- audioInstance.setAttribute('autoplay', 'false')
133
- audioInstance.setAttribute('style', 'display: none;')
134
- document.body.appendChild(audioInstance)
135
- this.audioInstance = audioInstance
138
+ if (cacheInstance.audioInstance) {
139
+ this.audioInstance = cacheInstance.audioInstance
140
+
141
+ } else {
142
+ const audioInstance = document.createElement('audio')
143
+ audioInstance.crossOrigin = ''
144
+ // videoInstance.muted = true
145
+ audioInstance.muted = false
146
+ audioInstance.setAttribute('playsinline', 'true')
147
+ audioInstance.setAttribute('webkit-playsinline', 'true')
148
+ audioInstance.setAttribute('autoplay', 'false')
149
+ audioInstance.setAttribute('style', 'display: none;')
150
+ document.body.appendChild(audioInstance)
151
+ this.audioInstance = audioInstance
152
+ cacheInstance.audioInstance = audioInstance
153
+ }
154
+
136
155
  }
156
+
137
157
  makeObservable(this, { paused: observable })
138
158
 
139
159
  const updatePaused = (paused: boolean) => runInAction(() => (this.paused = paused))
140
- this.videoInstance.addEventListener('pause', () => updatePaused(true))
141
- this.videoInstance.addEventListener('play', () => updatePaused(false))
160
+ const onPause = () => updatePaused(true)
161
+ const onPlay = () => updatePaused(false)
162
+
163
+ this.videoInstance.addEventListener('pause', onPause)
164
+ this.videoInstance.addEventListener('play', onPlay)
165
+
166
+ this.$removeEventListener = () => {
167
+ this.videoInstance.removeEventListener('pause', onPause)
168
+ this.videoInstance.removeEventListener('play', onPlay)
169
+ }
142
170
  }
143
171
 
172
+
144
173
  private async update(videoUrl: string) {
145
174
  if (this.videoUrl === videoUrl) {
146
175
  return
@@ -199,4 +228,18 @@ export class VideoAgentMesh extends THREE.Mesh {
199
228
  get currentTime() {
200
229
  return this.videoInstance.currentTime * 1000
201
230
  }
231
+
232
+ dispose() {
233
+ // 销毁事件监听
234
+ this.$removeEventListener()
235
+ if (cacheInstance.audioInstance) {
236
+ document.body.removeChild(cacheInstance.audioInstance)
237
+ cacheInstance.audioInstance = undefined
238
+ }
239
+
240
+ if (cacheInstance.videoInstance) {
241
+ document.body.removeChild(cacheInstance.videoInstance)
242
+ cacheInstance.videoInstance = undefined
243
+ }
244
+ }
202
245
  }
@@ -37,4 +37,8 @@ export class VideoAgentScene {
37
37
  }
38
38
  requestAnimationFrame(this.run)
39
39
  }
40
+
41
+ dispose = () => {
42
+ this.videoAgentMesh?.dispose()
43
+ }
40
44
  }
@@ -14,6 +14,11 @@ export function VideoAgent(props: { onClick?: () => void }) {
14
14
  }
15
15
  const videoAgentScene = new VideoAgentScene(ref.current)
16
16
  controller.videoAgentScene = videoAgentScene
17
+
18
+ return () => {
19
+ controller.dispose()
20
+ controller.videoAgentScene?.dispose()
21
+ }
17
22
  }, [])
18
23
 
19
24
  return (
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react'
2
- import { parseWork } from '@realsee/five'
2
+ import { parseWork, WorkCubeImage } from '@realsee/five'
3
3
  import { useController, useFiveInstance } from '../../../hooks'
4
4
  import { UpdateVRPanoramaData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
5
5
 
@@ -9,8 +9,18 @@ export function UpdateVRPanorama() {
9
9
 
10
10
  React.useEffect(() => {
11
11
  const callback = (keyframe: VreoKeyframe) => {
12
- const { panoIndex, images } = keyframe.data as UpdateVRPanoramaData
12
+ const { panoIndex, images, work } = keyframe.data as UpdateVRPanoramaData
13
13
 
14
+ if (work) {
15
+ five.load(work)
16
+ return
17
+ }
18
+
19
+ console.warn('not support.')
20
+ Object.keys(images).forEach((_key) => {
21
+ const key = _key as keyof WorkCubeImage
22
+ images[key] = images[key].replace(/https*:\/\//, '//')
23
+ })
14
24
  const newWorkJSON = JSON.parse(JSON.stringify(five.work?.raw.work))
15
25
 
16
26
  // // 原Work数据不能被修改
@@ -139,11 +139,16 @@ export const CameraMovementPlugin: FivePlugin<CameraMovementPluginParameterType,
139
139
  opts.asyncStartCallback()
140
140
  }
141
141
 
142
- if (five.currentMode !== Five.Mode.Panorama) {
143
- await five.changeMode(Five.Mode.Panorama)
142
+ // 先切换模型再出旋转效果
143
+ if (args.mode && five.currentMode !== args.mode) {
144
+ await five.changeMode(args.mode)
144
145
  }
145
146
 
146
- if (args.panoIndex !== undefined && args.panoIndex !== five.panoIndex) {
147
+ // 全景状态下,需要点位对齐
148
+ if (args.mode === Five.Mode.Panorama &&
149
+ five.currentMode === Five.Mode.Panorama &&
150
+ args.panoIndex !== undefined &&
151
+ args.panoIndex !== five.panoIndex) {
147
152
  if (opts.preload) await five.preloadPano(args.panoIndex)
148
153
  await new Promise((resolve, reject) => {
149
154
  five.moveToPano(args.panoIndex, {
@@ -46,6 +46,7 @@ export type MoveOpts = {
46
46
  } & CameraMovementOptsCallback
47
47
 
48
48
  export type RotateArgs = {
49
+ mode?: Mode
49
50
  panoIndex: number
50
51
  loop: boolean
51
52
  rotateSpeed: number
@@ -7,13 +7,16 @@ const VreoContext = React.createContext<Player | null>(null)
7
7
 
8
8
  export const VreoProvider: React.FC = (props) => {
9
9
  const five = unsafe__useFiveInstance()
10
+
10
11
  const [player, setPlayer] = React.useState<Player | null>(null)
12
+ const playerRef = React.useRef<Player | null>(null)
11
13
 
12
14
  React.useEffect(() => {
13
- setPlayer(new Player(five))
15
+ playerRef.current = new Player(five)
16
+ setPlayer(playerRef.current)
14
17
 
15
18
  return () => {
16
- player?.dispose()
19
+ playerRef.current?.dispose()
17
20
  }
18
21
  }, [])
19
22
 
@@ -1,4 +1,4 @@
1
- import { Mode, Pose, WorkCubeImage } from '@realsee/five'
1
+ import { Mode, Pose, WorkCubeImage, Work } from '@realsee/five'
2
2
  import { CameraMovementEffect, Rotation } from '../fivePlugins/CameraMovementPlugin/typings'
3
3
 
4
4
  export enum VreoKeyframeEnum {
@@ -40,6 +40,10 @@ export enum VreoKeyframeEnum {
40
40
  * 结束
41
41
  */
42
42
  Exit = 'Exit',
43
+ /**
44
+ * 自定义剧本帧
45
+ */
46
+ Custom = 'Custom',
43
47
  }
44
48
 
45
49
  /**
@@ -121,6 +125,7 @@ export type PrompterData = {
121
125
  export type UpdateVRPanoramaData = {
122
126
  panoIndex: number
123
127
  images: WorkCubeImage
128
+ work?: Work
124
129
  }
125
130
 
126
131
  /**
@@ -223,3 +228,6 @@ export type VideoEffectData = {
223
228
  direction?: Vertex
224
229
  vector?: Pick<Pose, 'longitude' | 'latitude'>
225
230
  }
231
+
232
+ /** 自定义序列帧 */
233
+ export type CustomData = Record<string, any>