@omnimedia/omnitool 1.1.0-104 → 1.1.0-105

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.
package/README.md CHANGED
@@ -56,6 +56,17 @@ const timeline = omni.timeline(o => {
56
56
  })
57
57
  ```
58
58
 
59
+ You can label your items:
60
+
61
+ ```ts
62
+ const visual = o.sequence(
63
+ "Main sequence",
64
+ o.video(clip, {label: "Intro"}),
65
+ o.transition.fade(500, {label: "Fade"}),
66
+ o.text("Hello world", {label: "Title"})
67
+ )
68
+ ```
69
+
59
70
  Declarative helper style (no explicit `o` in timeline declarations):
60
71
 
61
72
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnimedia/omnitool",
3
- "version": "1.1.0-104",
3
+ "version": "1.1.0-105",
4
4
  "description": "open source video processing tools",
5
5
  "license": "MIT",
6
6
  "author": "Przemysław Gałęzki",
@@ -5,6 +5,7 @@ import {TransformOptions, Vec2} from "../types.js"
5
5
  import {Transcription, TranscriptSegment} from "../../features/speech/transcribe/types.js"
6
6
 
7
7
  export type CaptionOptions = {
8
+ label?: string
8
9
  itemId?: Item.Caption["itemId"]
9
10
  start?: number
10
11
  duration?: number
@@ -26,6 +26,10 @@ export enum Kind {
26
26
  Image
27
27
  }
28
28
 
29
+ export type ItemMeta = {
30
+ label?: string
31
+ }
32
+
29
33
  export namespace Item {
30
34
  export type TextStyle = {
31
35
  id: Id
@@ -60,7 +64,7 @@ export namespace Item {
60
64
  id: Id
61
65
  kind: Kind.Gap
62
66
  duration: number
63
- }
67
+ } & ItemMeta
64
68
 
65
69
  export type Sequence = {
66
70
  id: Id
@@ -68,7 +72,7 @@ export namespace Item {
68
72
  childrenIds: Id[]
69
73
  spatialId?: Id
70
74
  filterIds?: Id[]
71
- }
75
+ } & ItemMeta
72
76
 
73
77
  export type Stack = {
74
78
  id: Id
@@ -76,7 +80,7 @@ export namespace Item {
76
80
  childrenIds: Id[]
77
81
  spatialId?: Id
78
82
  filterIds?: Id[]
79
- }
83
+ } & ItemMeta
80
84
 
81
85
  export type Video = {
82
86
  id: Id
@@ -87,7 +91,7 @@ export namespace Item {
87
91
  spatialId?: Id
88
92
  animationIds?: Id[]
89
93
  filterIds?: Id[]
90
- }
94
+ } & ItemMeta
91
95
 
92
96
  export type Image = {
93
97
  id: Id
@@ -97,7 +101,7 @@ export namespace Item {
97
101
  spatialId?: Id
98
102
  animationIds?: Id[]
99
103
  filterIds?: Id[]
100
- }
104
+ } & ItemMeta
101
105
 
102
106
  export type Audio = {
103
107
  id: Id
@@ -106,7 +110,7 @@ export namespace Item {
106
110
  start: number
107
111
  duration: number
108
112
  gain?: number
109
- }
113
+ } & ItemMeta
110
114
 
111
115
  export type Text = {
112
116
  id: Id
@@ -117,7 +121,7 @@ export namespace Item {
117
121
  animationIds?: Id[]
118
122
  styleId?: Id
119
123
  filterIds?: Id[]
120
- }
124
+ } & ItemMeta
121
125
 
122
126
 
123
127
  export type Caption = {
@@ -134,14 +138,14 @@ export namespace Item {
134
138
  animationIds?: Id[]
135
139
  styleId?: Id
136
140
  filterIds?: Id[]
137
- }
141
+ } & ItemMeta
138
142
 
139
143
  export type Transition = {
140
144
  id: Id
141
145
  kind: Kind.Transition
142
146
  name: TransitionName
143
147
  duration: number
144
- }
148
+ } & ItemMeta
145
149
 
146
150
  export type Any = (
147
151
  | Sequence
@@ -1,4 +1,4 @@
1
- import type {Item} from "./item.js"
1
+ import type {Item, ItemMeta} from "./item.js"
2
2
 
3
3
  export const transitionNames = [
4
4
  "Bounce",
@@ -78,7 +78,7 @@ export type Transition = {
78
78
  }
79
79
 
80
80
  export interface TransitionAction {
81
- (duration: number): Item.Transition
81
+ (duration: number, options?: ItemMeta): Item.Transition
82
82
  }
83
83
 
84
84
  export type TransitionActions = {
@@ -10,7 +10,7 @@ import {filters, FilterParams, FilterType} from "../parts/filters.js"
10
10
  import {CaptionOptions, CaptionSourceItem} from "../parts/captions.js"
11
11
  import {Transcription} from "../../features/speech/transcribe/types.js"
12
12
  import {AnimationPreset, PresetOptions} from "../parts/animations/types.js"
13
- import {Crop, FilterableItem, Item, VisualAnimatableItem} from "../parts/item.js"
13
+ import {Crop, FilterableItem, Item, ItemMeta, VisualAnimatableItem} from "../parts/item.js"
14
14
  import {animationPresets, visualAnimations} from "../parts/animations/registry.js"
15
15
  import {Anim, AnimateAction, Interpolation, Keyframes, TrackTransform, Transform, Vec2, VisualAnimationInput, VisualAnimations} from "../types.js"
16
16
 
@@ -22,8 +22,9 @@ type BuildPresetAnimateActions = {
22
22
  [TKey in AnimationPreset]: BuildPresetAnimateAction
23
23
  }
24
24
  type BuildTransitionActions = {
25
- [TKey in TransitionName]: (duration: number) => Build<Item.Transition>
25
+ [TKey in TransitionName]: (duration: number, options?: ItemMeta) => Build<Item.Transition>
26
26
  }
27
+ type ContainerInput = [label: string, ...items: Build[]] | Build[]
27
28
 
28
29
  function createTimeline(): TimelineFile {
29
30
  return {
@@ -42,12 +43,24 @@ export function timeline(root: Build): TimelineFile {
42
43
  return o.timeline
43
44
  }
44
45
 
45
- export function sequence(...items: Build[]): Build<Item.Sequence> {
46
- return o => o.sequence(...items.map(item => item(o)))
46
+ export function sequence(...input: ContainerInput): Build<Item.Sequence> {
47
+ const [first, ...rest] = input
48
+ const label = typeof first === "string" ? first : undefined
49
+ const items = (label ? rest : input) as Build[]
50
+ return o => {
51
+ const built = items.map(item => item(o))
52
+ return label ? o.sequence(label, ...built) : o.sequence(...built)
53
+ }
47
54
  }
48
55
 
49
- export function stack(...items: Build[]): Build<Item.Stack> {
50
- return o => o.stack(...items.map(item => item(o)))
56
+ export function stack(...input: ContainerInput): Build<Item.Stack> {
57
+ const [first, ...rest] = input
58
+ const label = typeof first === "string" ? first : undefined
59
+ const items = (label ? rest : input) as Build[]
60
+ return o => {
61
+ const built = items.map(item => item(o))
62
+ return label ? o.stack(label, ...built) : o.stack(...built)
63
+ }
51
64
  }
52
65
 
53
66
  export function video(
@@ -55,6 +68,7 @@ export function video(
55
68
  options?: {
56
69
  start?: number,
57
70
  duration?: number
71
+ label?: string
58
72
  }
59
73
  ): Build<Item.Video> {
60
74
  return o => o.video(media, options)
@@ -64,6 +78,7 @@ export function image(
64
78
  media: Media,
65
79
  options?: {
66
80
  duration?: number
81
+ label?: string
67
82
  }
68
83
  ): Build<Item.Image> {
69
84
  return o => o.image(media, options)
@@ -75,6 +90,7 @@ export function audio(
75
90
  start?: number,
76
91
  duration?: number,
77
92
  gain?: number
93
+ label?: string
78
94
  }
79
95
  ): Build<Item.Audio> {
80
96
  return o => o.audio(media, options)
@@ -85,6 +101,7 @@ export function text(
85
101
  options?: {
86
102
  duration?: number,
87
103
  styles?: TextStyleOptions
104
+ label?: string
88
105
  }
89
106
  ): Build<Item.Text> {
90
107
  return o => o.text(content, options)
@@ -98,8 +115,8 @@ export function captions(
98
115
  return o => o.captions(item(o), transcript, options)
99
116
  }
100
117
 
101
- export function gap(duration: number): Build<Item.Gap> {
102
- return o => o.gap(duration)
118
+ export function gap(duration: number, options?: ItemMeta): Build<Item.Gap> {
119
+ return o => o.gap(duration, options)
103
120
  }
104
121
 
105
122
  export function spatial(transform?: Transform, crop?: Crop): Build<Item.Spatial> {
@@ -232,7 +249,7 @@ export function textStyle(style: TextStyleOptions): Build<Item.TextStyle> {
232
249
 
233
250
  function makeTransitionActions(): BuildTransitionActions {
234
251
  const entries = Object.keys(transitions)
235
- .map(key => [key, (duration: number) => (o: O) => o.transition[key as TransitionName](duration)])
252
+ .map(key => [key, (duration: number, options?: ItemMeta) => (o: O) => o.transition[key as TransitionName](duration, options)])
236
253
  return Object.fromEntries(entries) as BuildTransitionActions
237
254
  }
238
255
 
@@ -6,7 +6,7 @@ import {Id, TimelineFile} from "../parts/basics.js"
6
6
  import {FilterAction, FilterActions} from "../parts/filters.js"
7
7
  import {filters, FilterParams, FilterType} from "../parts/filters.js"
8
8
  import {Transcription} from "../../features/speech/transcribe/types.js"
9
- import {Crop, FilterableItem, Item, Kind, VisualAnimatableItem} from "../parts/item.js"
9
+ import {Crop, FilterableItem, Item, ItemMeta, Kind, VisualAnimatableItem} from "../parts/item.js"
10
10
  import {animationPresets, makeAnimationPresets, visualAnimations} from "../parts/animations/registry.js"
11
11
  import {TransitionAction, TransitionActions, transitions, TransitionName} from "../parts/transitions.js"
12
12
  import {AnimationPreset, PresetAnimateAction, PresetAnimateActions, PresetAnimation, PresetOptions} from "../parts/animations/types.js"
@@ -17,6 +17,8 @@ type VisualAnimateActions = {
17
17
  [TKey in keyof VisualAnimations]-?: AnimateAction<TKey>
18
18
  }
19
19
 
20
+ type ContainerInput = [label: string, ...items: Item.Any[]] | Item.Any[]
21
+
20
22
  export class O {
21
23
  constructor(public state: {timeline: TimelineFile}) {}
22
24
 
@@ -229,20 +231,28 @@ export class O {
229
231
  presets: this.#makePresetAnimateActions(),
230
232
  }
231
233
 
232
- sequence = (...items: Item.Any[]): Item.Sequence => {
234
+ sequence = (...input: ContainerInput): Item.Sequence => {
235
+ const [first, ...rest] = input
236
+ const label = typeof first === "string" ? first : undefined
237
+ const items = (label ? rest : input) as Item.Any[]
233
238
  const item = {
234
239
  id: this.getId(),
235
240
  kind: Kind.Sequence,
241
+ label,
236
242
  childrenIds: items.map(item => item.id)
237
243
  } as Item.Sequence
238
244
  this.register(item)
239
245
  return item
240
246
  }
241
247
 
242
- stack = (...items: Item.Any[]): Item.Stack => {
248
+ stack = (...input: ContainerInput): Item.Stack => {
249
+ const [first, ...rest] = input
250
+ const label = typeof first === "string" ? first : undefined
251
+ const items = (label ? rest : input) as Item.Any[]
243
252
  const item = {
244
253
  kind: Kind.Stack,
245
254
  id: this.getId(),
255
+ label,
246
256
  childrenIds: items.map(item => item.id)
247
257
  } as Item.Stack
248
258
  this.register(item)
@@ -254,6 +264,7 @@ export class O {
254
264
  options?: {
255
265
  start?: number,
256
266
  duration?: number
267
+ label?: string
257
268
  }): Item.Video => {
258
269
 
259
270
  if(!media.hasVideo)
@@ -262,6 +273,7 @@ export class O {
262
273
  const item: Item.Video = {
263
274
  kind: Kind.Video,
264
275
  id: this.getId(),
276
+ label: options?.label,
265
277
  mediaHash: media.datafile.checksum.hash,
266
278
  start: options?.start ?? 0,
267
279
  duration: options?.duration ?? media.duration
@@ -274,6 +286,7 @@ export class O {
274
286
  media: Media,
275
287
  options?: {
276
288
  duration?: number
289
+ label?: string
277
290
  }): Item.Image => {
278
291
 
279
292
  if(!media.isImage)
@@ -282,6 +295,7 @@ export class O {
282
295
  const item: Item.Image = {
283
296
  kind: Kind.Image,
284
297
  id: this.getId(),
298
+ label: options?.label,
285
299
  mediaHash: media.datafile.checksum.hash,
286
300
  duration: options?.duration ?? 2000
287
301
  }
@@ -295,6 +309,7 @@ export class O {
295
309
  start?: number,
296
310
  duration?: number,
297
311
  gain?: number
312
+ label?: string
298
313
  }): Item.Audio => {
299
314
 
300
315
  if(!media.hasAudio)
@@ -303,6 +318,7 @@ export class O {
303
318
  const item: Item.Audio = {
304
319
  kind: Kind.Audio,
305
320
  id: this.getId(),
321
+ label: options?.label,
306
322
  mediaHash: media.datafile.checksum.hash,
307
323
  start: options?.start ?? 0,
308
324
  duration: options?.duration ?? media.duration,
@@ -315,10 +331,12 @@ export class O {
315
331
  text = (content: string, options?: {
316
332
  duration?: number,
317
333
  styles?: TextStyleOptions
334
+ label?: string
318
335
  }): Item.Text => {
319
336
 
320
337
  const item = {
321
338
  id: this.getId(),
339
+ label: options?.label,
322
340
  content,
323
341
  kind: Kind.Text,
324
342
  duration: options?.duration ?? 2000
@@ -341,6 +359,7 @@ export class O {
341
359
  const item: Item.Caption = {
342
360
  id: this.getId(),
343
361
  kind: Kind.Caption,
362
+ label: options?.label,
344
363
  transcript,
345
364
  itemId: options?.itemId,
346
365
  start,
@@ -386,10 +405,11 @@ export class O {
386
405
  {presets: this.#makeCaptionPresetActions()}
387
406
  ) as CaptionActions
388
407
 
389
- gap = (duration: number): Item.Gap => {
408
+ gap = (duration: number, options?: ItemMeta): Item.Gap => {
390
409
  const item = {
391
410
  id: this.getId(),
392
411
  kind: Kind.Gap,
412
+ label: options?.label,
393
413
  duration
394
414
  } as Item.Gap
395
415
  this.register(item)
@@ -397,10 +417,11 @@ export class O {
397
417
  }
398
418
 
399
419
  #makeTransition = (key: TransitionName): TransitionAction => {
400
- return (duration: number): Item.Transition => {
420
+ return (duration: number, options?: ItemMeta): Item.Transition => {
401
421
  const item: Item.Transition = {
402
422
  id: this.getId(),
403
423
  kind: Kind.Transition,
424
+ label: options?.label,
404
425
  name: transitions[key].name,
405
426
  duration,
406
427
  }