@omnimedia/omnitool 1.1.0-76 → 1.1.0-77

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 (99) hide show
  1. package/README.md +54 -4
  2. package/package.json +2 -1
  3. package/s/driver/fns/schematic.ts +11 -2
  4. package/s/driver/parts/compositor.ts +46 -2
  5. package/s/driver/utils/find-pixi-filter.ts +24 -0
  6. package/s/timeline/index.ts +1 -1
  7. package/s/timeline/parts/filters.ts +484 -0
  8. package/s/timeline/parts/item.ts +17 -1
  9. package/s/timeline/renderers/parts/samplers/visual/parts/sample.ts +9 -3
  10. package/s/timeline/sugar/helpers.ts +35 -2
  11. package/s/timeline/sugar/o.ts +38 -1
  12. package/s/timeline/types.ts +2 -0
  13. package/x/WebGLRenderer-4CHIZDHY.js +2 -0
  14. package/x/WebGPURenderer-O6WXU2QR.js +2 -0
  15. package/x/browserAll-WNIOTNNP.js +2 -0
  16. package/x/{demo/chunk-USLRKDKD.js → chunk-23FOBGX6.js} +2 -2
  17. package/x/{chunk-A45M2HJC.js.map → chunk-23FOBGX6.js.map} +1 -1
  18. package/x/{chunk-MWCIWPRL.js → chunk-73XOWA4F.js} +3 -3
  19. package/x/{chunk-Q7JBQNE4.js → chunk-IAWJKNX5.js} +2 -2
  20. package/x/{demo/chunk-Q4MWBZHL.js → chunk-KCMVLWBS.js} +2 -2
  21. package/x/{chunk-4ONWQOPX.js.map → chunk-KCMVLWBS.js.map} +1 -1
  22. package/x/{chunk-D5CIWPNS.js → chunk-MR32SQ27.js} +2 -2
  23. package/x/{chunk-W5CN46AR.js → chunk-VCUJJYRJ.js} +3 -3
  24. package/x/{chunk-WFT3KTZG.js → chunk-XNIZ4L5W.js} +2 -2
  25. package/x/{chunk-OTQK6FAJ.js → chunk-ZLGNQFUI.js} +2 -2
  26. package/x/demo/WebGLRenderer-RSJAHIG2.js +2 -0
  27. package/x/demo/WebGPURenderer-MGFAJCYY.js +2 -0
  28. package/x/demo/browserAll-PTRBXBRP.js +2 -0
  29. package/x/demo/{chunk-P3PTHHFE.js → chunk-CUYOGHWU.js} +2 -2
  30. package/x/demo/{chunk-P3PTHHFE.js.map → chunk-CUYOGHWU.js.map} +1 -1
  31. package/x/demo/{chunk-IRDQEA6B.js → chunk-DGTDNJ7W.js} +2 -2
  32. package/x/demo/{chunk-T3METYEY.js → chunk-FZ5BYF63.js} +2 -2
  33. package/x/demo/{chunk-T3METYEY.js.map → chunk-FZ5BYF63.js.map} +1 -1
  34. package/x/demo/{chunk-PYG4RZZ2.js → chunk-KWN4NNES.js} +15 -15
  35. package/x/demo/{chunk-PYG4RZZ2.js.map → chunk-KWN4NNES.js.map} +1 -1
  36. package/x/{chunk-4ONWQOPX.js → demo/chunk-OJ3FPXW7.js} +2 -2
  37. package/x/demo/{chunk-Q4MWBZHL.js.map → chunk-OJ3FPXW7.js.map} +1 -1
  38. package/x/demo/{chunk-RWJ2UHV4.js → chunk-PSLUOGTZ.js} +3 -3
  39. package/x/demo/{chunk-RWJ2UHV4.js.map → chunk-PSLUOGTZ.js.map} +1 -1
  40. package/x/demo/{chunk-YISSXWBT.js → chunk-VLCVEIFU.js} +3 -3
  41. package/x/demo/{chunk-YISSXWBT.js.map → chunk-VLCVEIFU.js.map} +1 -1
  42. package/x/demo/chunk-ZWCPT5FR.js +2 -0
  43. package/x/demo/demo.bundle.min.js +4921 -11
  44. package/x/demo/demo.bundle.min.js.map +4 -4
  45. package/x/demo/webworkerAll-JENRT6BT.js +2 -0
  46. package/x/driver/fns/schematic.d.ts +10 -1
  47. package/x/driver/parts/compositor.js +32 -1
  48. package/x/driver/parts/compositor.js.map +1 -1
  49. package/x/driver/utils/find-pixi-filter.d.ts +5 -0
  50. package/x/driver/utils/find-pixi-filter.js +13 -0
  51. package/x/driver/utils/find-pixi-filter.js.map +1 -0
  52. package/x/index.html +2 -2
  53. package/x/tests.bundle.min.js +4926 -16
  54. package/x/tests.bundle.min.js.map +4 -4
  55. package/x/tests.html +1 -1
  56. package/x/timeline/index.d.ts +1 -0
  57. package/x/timeline/index.js +1 -0
  58. package/x/timeline/index.js.map +1 -1
  59. package/x/timeline/parts/filters.d.ts +113 -0
  60. package/x/timeline/parts/filters.js +355 -0
  61. package/x/timeline/parts/filters.js.map +1 -0
  62. package/x/timeline/parts/item.d.ts +16 -2
  63. package/x/timeline/parts/item.js +1 -0
  64. package/x/timeline/parts/item.js.map +1 -1
  65. package/x/timeline/parts/waveform/parts/collect.d.ts +1 -1
  66. package/x/timeline/renderers/parts/samplers/visual/parts/sample.js +8 -2
  67. package/x/timeline/renderers/parts/samplers/visual/parts/sample.js.map +1 -1
  68. package/x/timeline/sugar/helpers.d.ts +11 -2
  69. package/x/timeline/sugar/helpers.js +15 -0
  70. package/x/timeline/sugar/helpers.js.map +1 -1
  71. package/x/timeline/sugar/o.d.ts +3 -1
  72. package/x/timeline/sugar/o.js +31 -0
  73. package/x/timeline/sugar/o.js.map +1 -1
  74. package/x/webworkerAll-RLCTMSDD.js +2 -0
  75. package/x/WebGLRenderer-7X274AYV.js +0 -2
  76. package/x/WebGPURenderer-XMCMEXAO.js +0 -2
  77. package/x/browserAll-LRGVU2GN.js +0 -2
  78. package/x/chunk-A45M2HJC.js +0 -2
  79. package/x/demo/WebGLRenderer-NLGJGAXK.js +0 -2
  80. package/x/demo/WebGPURenderer-RBOFXPL5.js +0 -2
  81. package/x/demo/browserAll-QEV2P3ED.js +0 -2
  82. package/x/demo/webworkerAll-ELLD4M57.js +0 -2
  83. package/x/webworkerAll-KR5SWEBU.js +0 -2
  84. /package/x/{WebGLRenderer-7X274AYV.js.map → WebGLRenderer-4CHIZDHY.js.map} +0 -0
  85. /package/x/{WebGPURenderer-XMCMEXAO.js.map → WebGPURenderer-O6WXU2QR.js.map} +0 -0
  86. /package/x/{browserAll-LRGVU2GN.js.map → browserAll-WNIOTNNP.js.map} +0 -0
  87. /package/x/{chunk-MWCIWPRL.js.map → chunk-73XOWA4F.js.map} +0 -0
  88. /package/x/{chunk-Q7JBQNE4.js.map → chunk-IAWJKNX5.js.map} +0 -0
  89. /package/x/{chunk-D5CIWPNS.js.map → chunk-MR32SQ27.js.map} +0 -0
  90. /package/x/{chunk-W5CN46AR.js.map → chunk-VCUJJYRJ.js.map} +0 -0
  91. /package/x/{chunk-WFT3KTZG.js.map → chunk-XNIZ4L5W.js.map} +0 -0
  92. /package/x/{chunk-OTQK6FAJ.js.map → chunk-ZLGNQFUI.js.map} +0 -0
  93. /package/x/demo/{WebGLRenderer-NLGJGAXK.js.map → WebGLRenderer-RSJAHIG2.js.map} +0 -0
  94. /package/x/demo/{WebGPURenderer-RBOFXPL5.js.map → WebGPURenderer-MGFAJCYY.js.map} +0 -0
  95. /package/x/demo/{browserAll-QEV2P3ED.js.map → browserAll-PTRBXBRP.js.map} +0 -0
  96. /package/x/demo/{chunk-IRDQEA6B.js.map → chunk-DGTDNJ7W.js.map} +0 -0
  97. /package/x/demo/{chunk-USLRKDKD.js.map → chunk-ZWCPT5FR.js.map} +0 -0
  98. /package/x/demo/{webworkerAll-ELLD4M57.js.map → webworkerAll-JENRT6BT.js.map} +0 -0
  99. /package/x/{webworkerAll-KR5SWEBU.js.map → webworkerAll-RLCTMSDD.js.map} +0 -0
package/README.md CHANGED
@@ -37,10 +37,11 @@ const timeline = omni.timeline(o => {
37
37
  styles: {fill: "white", fontSize: 48}
38
38
  })
39
39
  const xfade = o.transition.crossfade(500)
40
+ const softened = o.filter.blur.make({strength: 8, quality: 4})
40
41
 
41
42
  return o.sequence(
42
43
  o.stack(
43
- o.video(clip, {start: 0, duration: 3000}),
44
+ o.video(clip, {start: 0, duration: 3000, filterIds: [softened.id]}),
44
45
  caption
45
46
  ),
46
47
  o.gap(400),
@@ -56,7 +57,7 @@ Declarative helper style (no explicit `o` in timeline declarations):
56
57
  ```ts
57
58
  import {
58
59
  Driver, Omni, Datafile,
59
- timeline, stack, video, audio, text, gap, transition
60
+ timeline, stack, video, audio, text, gap, transition, filter
60
61
  } from "@omnimedia/omnitool"
61
62
 
62
63
  const driver = await Driver.setup()
@@ -65,7 +66,10 @@ const {clip} = await omni.load({clip: Datafile.make(file)})
65
66
 
66
67
  const timeline = timeline(
67
68
  stack(
68
- video(clip, {start: 0, duration: 3000}),
69
+ filter.blur(
70
+ video(clip, {start: 0, duration: 3000}),
71
+ {strength: 8, quality: 4}
72
+ ),
69
73
  text("Hello world", {duration: 1500}),
70
74
  ),
71
75
  gap(400),
@@ -75,6 +79,52 @@ const timeline = timeline(
75
79
  )
76
80
  ```
77
81
 
82
+ ## 🎛 Filters
83
+
84
+ Inline filter application:
85
+
86
+ ```ts
87
+ const timeline = omni.timeline(o =>
88
+ o.stack(
89
+ o.filter.blur(
90
+ o.video(clip, {duration: 3000}),
91
+ {strength: 8, quality: 4}
92
+ ),
93
+ o.filter.glow(
94
+ o.text("Hello world", {duration: 3000}),
95
+ {distance: 12, outerStrength: 2, color: "#ffffff"}
96
+ )
97
+ )
98
+ )
99
+ ```
100
+
101
+ Reusable filter items:
102
+
103
+ ```ts
104
+ const timeline = omni.timeline(o => {
105
+ const blur = o.filter.blur.make({strength: 8, quality: 4})
106
+
107
+ return o.stack(
108
+ o.video(clip, {duration: 3000, filterIds: [blur.id]}),
109
+ o.text("Caption", {duration: 3000, styles: {fill: "white"}})
110
+ )
111
+ })
112
+ ```
113
+
114
+ Filter metadata for UI:
115
+
116
+ ```ts
117
+ import {
118
+ filterTypes,
119
+ filterSchemas,
120
+ getFilterDefaultParams
121
+ } from "@omnimedia/omnitool"
122
+
123
+ const available = Object.entries(filterTypes)
124
+ const schema = filterSchemas.BlurFilter
125
+ const defaults = getFilterDefaultParams("BlurFilter")
126
+ ```
127
+
78
128
  ## 🧭 Spatial Transforms
79
129
 
80
130
  ```ts
@@ -156,6 +206,7 @@ Timeline items:
156
206
  - 6 `Spatial`
157
207
  - 7 `Transition`
158
208
  - 8 `TextStyle`
209
+ - 9 `Filter`
159
210
 
160
211
  ## 🗺️ Roadmap
161
212
  - CLI commands:
@@ -180,4 +231,3 @@ omnitool ai "make a 15s promo for tea"
180
231
  - smooth seeking
181
232
  - keyframes
182
233
  - server-side, not just browsers
183
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnimedia/omnitool",
3
- "version": "1.1.0-76",
3
+ "version": "1.1.0-77",
4
4
  "description": "open source video processing tools",
5
5
  "license": "MIT",
6
6
  "author": "Przemysław Gałęzki",
@@ -43,6 +43,7 @@
43
43
  "gsap": "^3.14.2",
44
44
  "lit": "^3.3.2",
45
45
  "mediabunny": "^1.27.3",
46
+ "pixi-filters": "^6.1.5",
46
47
  "pixi.js": "^8.14.3",
47
48
  "wavesurfer.js": "^7.12.1"
48
49
  },
@@ -3,9 +3,10 @@ import {TextStyleOptions} from "pixi.js"
3
3
  import {AsSchematic} from "@e280/comrade"
4
4
  import type {AudioEncodingConfig, StreamTargetChunk, VideoEncodingConfig} from "mediabunny"
5
5
 
6
- import {Mat6} from "../../timeline/utils/matrix.js"
7
6
  import {Id} from "../../timeline/index.js"
8
7
  import {Crop} from "../../timeline/parts/item.js"
8
+ import {Mat6} from "../../timeline/utils/matrix.js"
9
+ import {FilterParams, FilterType} from "../../timeline/parts/filters.js"
9
10
 
10
11
  export type DriverSchematic = AsSchematic<{
11
12
 
@@ -74,6 +75,13 @@ export interface MuxOpts {
74
75
 
75
76
  export type Composition = Layer | (Layer | Composition)[]
76
77
 
78
+ export type FilterSpec = {
79
+ [TFilter in FilterType]: {
80
+ type: TFilter
81
+ params?: FilterParams<TFilter>
82
+ }
83
+ }[FilterType]
84
+
77
85
  export type TextLayer = {
78
86
  id: Id
79
87
  kind: 'text'
@@ -81,6 +89,7 @@ export type TextLayer = {
81
89
  style?: TextStyleOptions
82
90
  matrix?: Mat6
83
91
  crop?: Crop
92
+ filters?: FilterSpec[]
84
93
  }
85
94
 
86
95
  export type ImageLayer = {
@@ -89,6 +98,7 @@ export type ImageLayer = {
89
98
  frame: VideoFrame
90
99
  matrix?: Mat6
91
100
  crop?: Crop
101
+ filters?: FilterSpec[]
92
102
  }
93
103
 
94
104
  export type TransitionLayer = {
@@ -112,4 +122,3 @@ export type Audio = {
112
122
  }
113
123
 
114
124
  export type Layer = TextLayer | ImageLayer | TransitionLayer | GapLayer
115
-
@@ -1,10 +1,23 @@
1
1
 
2
2
  import {pub} from "@e280/stz"
3
- import {autoDetectRenderer, Container, FederatedPointerEvent, Graphics, Renderer, Sprite, Text, Texture} from "pixi.js"
3
+ import {
4
+ autoDetectRenderer,
5
+ ColorMatrixFilter,
6
+ Container,
7
+ FederatedPointerEvent,
8
+ Filter,
9
+ Graphics,
10
+ Renderer,
11
+ Sprite,
12
+ Text,
13
+ Texture
14
+ } from "pixi.js"
15
+ import * as PixiFilters from "pixi-filters"
4
16
 
5
17
  import {Id} from "../../timeline/index.js"
6
18
  import {Crop} from "../../timeline/parts/item.js"
7
- import {Composition, Layer} from "../fns/schematic.js"
19
+ import {findPixiFilter} from "../utils/find-pixi-filter.js"
20
+ import {Composition, FilterSpec, Layer} from "../fns/schematic.js"
8
21
  import {Mat6, mat6ToMatrix} from "../../timeline/utils/matrix.js"
9
22
  import {makeTransition} from "../../features/transition/transition.js"
10
23
 
@@ -99,6 +112,7 @@ export class Compositor {
99
112
  const sprite = this.#findOrCreate<Text>(layer)!
100
113
  this.#applyTransform(sprite, layer.matrix)
101
114
  this.#applyCrop(sprite, layer.crop)
115
+ this.#applyFilters(sprite, layer.filters)
102
116
  parent.addChild(sprite)
103
117
  return {
104
118
  dispose: () => {}
@@ -119,6 +133,7 @@ export class Compositor {
119
133
  sprite.texture = texture
120
134
  this.#applyTransform(sprite, layer.matrix)
121
135
  this.#applyCrop(sprite, layer.crop)
136
+ this.#applyFilters(sprite, layer.filters)
122
137
  parent.addChild(sprite)
123
138
 
124
139
  return {
@@ -183,6 +198,35 @@ export class Compositor {
183
198
  this.#cropMasks.set(target, mask)
184
199
  }
185
200
 
201
+ #applyFilters(target: Container, specs: FilterSpec[] | undefined) {
202
+ if (!specs?.length) {
203
+ target.filters = null
204
+ return
205
+ }
206
+
207
+ target.filters = specs
208
+ .map((spec): Filter | undefined => {
209
+ switch (spec.type) {
210
+ case "ColorMatrixFilter": {
211
+ const {matrix, ...params} = spec.params ?? {}
212
+ const filter = new ColorMatrixFilter(params)
213
+ if (matrix)
214
+ filter.matrix = matrix
215
+ return filter
216
+ }
217
+ case "EmbossFilter":
218
+ return new PixiFilters.EmbossFilter(spec.params?.strength)
219
+ case "PixelateFilter":
220
+ return new PixiFilters.PixelateFilter(spec.params?.size)
221
+ default: {
222
+ const PixiFilter = findPixiFilter(spec.type)
223
+ return PixiFilter ? new PixiFilter(spec.params) : undefined
224
+ }
225
+ }
226
+ })
227
+ .filter((filter): filter is Filter => !!filter)
228
+ }
229
+
186
230
  #findOrCreate<T = Container>(layer: Layer) {
187
231
  const object = this.#activeObjects.get(layer.id)
188
232
  if(!object) {
@@ -0,0 +1,24 @@
1
+ import {
2
+ AlphaFilter,
3
+ BlurFilter,
4
+ ColorMatrixFilter,
5
+ NoiseFilter,
6
+ Filter,
7
+ } from "pixi.js"
8
+ import * as PixiFilters from "pixi-filters"
9
+
10
+ import type {FilterType} from "../../timeline/parts/filters.js"
11
+
12
+ type FilterConstructor = new (options?: any) => Filter
13
+
14
+ const pixiFilters: Partial<Record<FilterType, FilterConstructor>> = {
15
+ AlphaFilter,
16
+ BlurFilter,
17
+ ColorMatrixFilter,
18
+ NoiseFilter,
19
+ ...PixiFilters
20
+ }
21
+
22
+ export function findPixiFilter(type: FilterType) {
23
+ return pixiFilters[type]
24
+ }
@@ -1,5 +1,6 @@
1
1
 
2
2
  export * from "./parts/basics.js"
3
+ export * from "./parts/filters.js"
3
4
  export * from "./parts/item.js"
4
5
  export * from "./parts/media.js"
5
6
  export * from "./parts/resource-pool.js"
@@ -16,4 +17,3 @@ export * from "./sugar/omni.js"
16
17
 
17
18
  export * from "./utils/checksum.js"
18
19
  export * from "./utils/datafile.js"
19
-