@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.
- package/README.md +54 -4
- package/package.json +2 -1
- package/s/driver/fns/schematic.ts +11 -2
- package/s/driver/parts/compositor.ts +46 -2
- package/s/driver/utils/find-pixi-filter.ts +24 -0
- package/s/timeline/index.ts +1 -1
- package/s/timeline/parts/filters.ts +484 -0
- package/s/timeline/parts/item.ts +17 -1
- package/s/timeline/renderers/parts/samplers/visual/parts/sample.ts +9 -3
- package/s/timeline/sugar/helpers.ts +35 -2
- package/s/timeline/sugar/o.ts +38 -1
- package/s/timeline/types.ts +2 -0
- package/x/WebGLRenderer-4CHIZDHY.js +2 -0
- package/x/WebGPURenderer-O6WXU2QR.js +2 -0
- package/x/browserAll-WNIOTNNP.js +2 -0
- package/x/{demo/chunk-USLRKDKD.js → chunk-23FOBGX6.js} +2 -2
- package/x/{chunk-A45M2HJC.js.map → chunk-23FOBGX6.js.map} +1 -1
- package/x/{chunk-MWCIWPRL.js → chunk-73XOWA4F.js} +3 -3
- package/x/{chunk-Q7JBQNE4.js → chunk-IAWJKNX5.js} +2 -2
- package/x/{demo/chunk-Q4MWBZHL.js → chunk-KCMVLWBS.js} +2 -2
- package/x/{chunk-4ONWQOPX.js.map → chunk-KCMVLWBS.js.map} +1 -1
- package/x/{chunk-D5CIWPNS.js → chunk-MR32SQ27.js} +2 -2
- package/x/{chunk-W5CN46AR.js → chunk-VCUJJYRJ.js} +3 -3
- package/x/{chunk-WFT3KTZG.js → chunk-XNIZ4L5W.js} +2 -2
- package/x/{chunk-OTQK6FAJ.js → chunk-ZLGNQFUI.js} +2 -2
- package/x/demo/WebGLRenderer-RSJAHIG2.js +2 -0
- package/x/demo/WebGPURenderer-MGFAJCYY.js +2 -0
- package/x/demo/browserAll-PTRBXBRP.js +2 -0
- package/x/demo/{chunk-P3PTHHFE.js → chunk-CUYOGHWU.js} +2 -2
- package/x/demo/{chunk-P3PTHHFE.js.map → chunk-CUYOGHWU.js.map} +1 -1
- package/x/demo/{chunk-IRDQEA6B.js → chunk-DGTDNJ7W.js} +2 -2
- package/x/demo/{chunk-T3METYEY.js → chunk-FZ5BYF63.js} +2 -2
- package/x/demo/{chunk-T3METYEY.js.map → chunk-FZ5BYF63.js.map} +1 -1
- package/x/demo/{chunk-PYG4RZZ2.js → chunk-KWN4NNES.js} +15 -15
- package/x/demo/{chunk-PYG4RZZ2.js.map → chunk-KWN4NNES.js.map} +1 -1
- package/x/{chunk-4ONWQOPX.js → demo/chunk-OJ3FPXW7.js} +2 -2
- package/x/demo/{chunk-Q4MWBZHL.js.map → chunk-OJ3FPXW7.js.map} +1 -1
- package/x/demo/{chunk-RWJ2UHV4.js → chunk-PSLUOGTZ.js} +3 -3
- package/x/demo/{chunk-RWJ2UHV4.js.map → chunk-PSLUOGTZ.js.map} +1 -1
- package/x/demo/{chunk-YISSXWBT.js → chunk-VLCVEIFU.js} +3 -3
- package/x/demo/{chunk-YISSXWBT.js.map → chunk-VLCVEIFU.js.map} +1 -1
- package/x/demo/chunk-ZWCPT5FR.js +2 -0
- package/x/demo/demo.bundle.min.js +4921 -11
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/demo/webworkerAll-JENRT6BT.js +2 -0
- package/x/driver/fns/schematic.d.ts +10 -1
- package/x/driver/parts/compositor.js +32 -1
- package/x/driver/parts/compositor.js.map +1 -1
- package/x/driver/utils/find-pixi-filter.d.ts +5 -0
- package/x/driver/utils/find-pixi-filter.js +13 -0
- package/x/driver/utils/find-pixi-filter.js.map +1 -0
- package/x/index.html +2 -2
- package/x/tests.bundle.min.js +4926 -16
- package/x/tests.bundle.min.js.map +4 -4
- package/x/tests.html +1 -1
- package/x/timeline/index.d.ts +1 -0
- package/x/timeline/index.js +1 -0
- package/x/timeline/index.js.map +1 -1
- package/x/timeline/parts/filters.d.ts +113 -0
- package/x/timeline/parts/filters.js +355 -0
- package/x/timeline/parts/filters.js.map +1 -0
- package/x/timeline/parts/item.d.ts +16 -2
- package/x/timeline/parts/item.js +1 -0
- package/x/timeline/parts/item.js.map +1 -1
- package/x/timeline/parts/waveform/parts/collect.d.ts +1 -1
- package/x/timeline/renderers/parts/samplers/visual/parts/sample.js +8 -2
- package/x/timeline/renderers/parts/samplers/visual/parts/sample.js.map +1 -1
- package/x/timeline/sugar/helpers.d.ts +11 -2
- package/x/timeline/sugar/helpers.js +15 -0
- package/x/timeline/sugar/helpers.js.map +1 -1
- package/x/timeline/sugar/o.d.ts +3 -1
- package/x/timeline/sugar/o.js +31 -0
- package/x/timeline/sugar/o.js.map +1 -1
- package/x/webworkerAll-RLCTMSDD.js +2 -0
- package/x/WebGLRenderer-7X274AYV.js +0 -2
- package/x/WebGPURenderer-XMCMEXAO.js +0 -2
- package/x/browserAll-LRGVU2GN.js +0 -2
- package/x/chunk-A45M2HJC.js +0 -2
- package/x/demo/WebGLRenderer-NLGJGAXK.js +0 -2
- package/x/demo/WebGPURenderer-RBOFXPL5.js +0 -2
- package/x/demo/browserAll-QEV2P3ED.js +0 -2
- package/x/demo/webworkerAll-ELLD4M57.js +0 -2
- package/x/webworkerAll-KR5SWEBU.js +0 -2
- /package/x/{WebGLRenderer-7X274AYV.js.map → WebGLRenderer-4CHIZDHY.js.map} +0 -0
- /package/x/{WebGPURenderer-XMCMEXAO.js.map → WebGPURenderer-O6WXU2QR.js.map} +0 -0
- /package/x/{browserAll-LRGVU2GN.js.map → browserAll-WNIOTNNP.js.map} +0 -0
- /package/x/{chunk-MWCIWPRL.js.map → chunk-73XOWA4F.js.map} +0 -0
- /package/x/{chunk-Q7JBQNE4.js.map → chunk-IAWJKNX5.js.map} +0 -0
- /package/x/{chunk-D5CIWPNS.js.map → chunk-MR32SQ27.js.map} +0 -0
- /package/x/{chunk-W5CN46AR.js.map → chunk-VCUJJYRJ.js.map} +0 -0
- /package/x/{chunk-WFT3KTZG.js.map → chunk-XNIZ4L5W.js.map} +0 -0
- /package/x/{chunk-OTQK6FAJ.js.map → chunk-ZLGNQFUI.js.map} +0 -0
- /package/x/demo/{WebGLRenderer-NLGJGAXK.js.map → WebGLRenderer-RSJAHIG2.js.map} +0 -0
- /package/x/demo/{WebGPURenderer-RBOFXPL5.js.map → WebGPURenderer-MGFAJCYY.js.map} +0 -0
- /package/x/demo/{browserAll-QEV2P3ED.js.map → browserAll-PTRBXBRP.js.map} +0 -0
- /package/x/demo/{chunk-IRDQEA6B.js.map → chunk-DGTDNJ7W.js.map} +0 -0
- /package/x/demo/{chunk-USLRKDKD.js.map → chunk-ZWCPT5FR.js.map} +0 -0
- /package/x/demo/{webworkerAll-ELLD4M57.js.map → webworkerAll-JENRT6BT.js.map} +0 -0
- /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
|
-
|
|
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-
|
|
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 {
|
|
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 {
|
|
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
|
+
}
|
package/s/timeline/index.ts
CHANGED
|
@@ -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
|
-
|