@omnimedia/omnitool 1.1.0-3 → 1.1.0-30
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/package.json +15 -10
- package/s/context.ts +0 -7
- package/s/demo/demo.bundle.ts +39 -5
- package/s/demo/demo.css +5 -0
- package/s/demo/routines/filmstrip-test.ts +2 -2
- package/s/demo/routines/transcode-test.ts +8 -4
- package/s/demo/routines/transcriber-test.ts +34 -0
- package/s/demo/routines/transitions-test.ts +43 -0
- package/s/demo/routines/waveform-test.ts +3 -2
- package/s/driver/driver.ts +19 -11
- package/s/driver/fns/host.ts +7 -6
- package/s/driver/fns/schematic.ts +47 -24
- package/s/driver/fns/work.ts +165 -156
- package/s/driver/utils/load-decoder-source.ts +3 -4
- package/s/features/speech/transcribe/default-spec.ts +11 -0
- package/s/features/speech/transcribe/parts/load-pipe.ts +19 -0
- package/s/features/speech/transcribe/parts/prep-audio.ts +23 -0
- package/s/features/speech/transcribe/parts/transcribe.ts +70 -0
- package/s/features/speech/transcribe/transcriber.ts +46 -0
- package/s/features/speech/transcribe/types.ts +82 -0
- package/s/features/speech/transcribe/worker.bundle.ts +40 -0
- package/s/features/transition/parts/fragment.ts +24 -0
- package/s/features/transition/parts/types.ts +94 -0
- package/s/features/transition/parts/uniforms.ts +29 -0
- package/s/features/transition/parts/vertex.ts +31 -0
- package/s/features/transition/transition.ts +60 -0
- package/s/index.html.ts +6 -1
- package/s/timeline/index.ts +1 -0
- package/s/timeline/parts/basics.ts +1 -1
- package/s/timeline/parts/compositor/export.ts +77 -0
- package/s/timeline/parts/compositor/parts/html-tree.ts +37 -0
- package/s/timeline/parts/compositor/parts/schedulers.ts +94 -0
- package/s/timeline/parts/compositor/parts/tree-builder.ts +196 -0
- package/s/timeline/parts/compositor/parts/webcodecs-tree.ts +30 -0
- package/s/timeline/parts/compositor/playback.ts +94 -0
- package/s/timeline/parts/compositor/samplers/html.ts +115 -0
- package/s/timeline/parts/compositor/samplers/webcodecs.ts +61 -0
- package/s/timeline/parts/item.ts +48 -6
- package/s/timeline/parts/media.ts +21 -0
- package/s/timeline/parts/waveform.ts +3 -4
- package/s/timeline/sugar/builders.ts +102 -0
- package/s/timeline/sugar/o.ts +162 -36
- package/s/timeline/sugar/omni-test.ts +5 -3
- package/s/timeline/sugar/omni.ts +26 -11
- package/s/timeline/types.ts +29 -0
- package/s/timeline/utils/audio-stream.ts +15 -0
- package/s/timeline/utils/checksum.ts +2 -1
- package/s/timeline/utils/matrix.ts +33 -0
- package/s/timeline/utils/video-cursor.ts +40 -0
- package/x/context.d.ts +1 -4
- package/x/context.js +1 -5
- package/x/context.js.map +1 -1
- package/x/demo/demo.bundle.js +26 -5
- package/x/demo/demo.bundle.js.map +1 -1
- package/x/demo/demo.bundle.min.js +606 -36
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/demo/demo.css +5 -0
- package/x/demo/routines/filmstrip-test.d.ts +1 -1
- package/x/demo/routines/filmstrip-test.js +2 -2
- package/x/demo/routines/filmstrip-test.js.map +1 -1
- package/x/demo/routines/transcode-test.js +8 -4
- package/x/demo/routines/transcode-test.js.map +1 -1
- package/x/demo/routines/transcriber-test.d.ts +4 -0
- package/x/demo/routines/transcriber-test.js +33 -0
- package/x/demo/routines/transcriber-test.js.map +1 -0
- package/x/demo/routines/transitions-test.d.ts +5 -0
- package/x/demo/routines/transitions-test.js +35 -0
- package/x/demo/routines/transitions-test.js.map +1 -0
- package/x/demo/routines/waveform-test.d.ts +2 -1
- package/x/demo/routines/waveform-test.js +2 -2
- package/x/demo/routines/waveform-test.js.map +1 -1
- package/x/driver/driver.d.ts +4 -6
- package/x/driver/driver.js +17 -10
- package/x/driver/driver.js.map +1 -1
- package/x/driver/driver.worker.bundle.min.js +2537 -148
- package/x/driver/driver.worker.bundle.min.js.map +4 -4
- package/x/driver/fns/host.d.ts +9 -2
- package/x/driver/fns/host.js +3 -3
- package/x/driver/fns/host.js.map +1 -1
- package/x/driver/fns/schematic.d.ts +41 -23
- package/x/driver/fns/work.d.ts +11 -4
- package/x/driver/fns/work.js +113 -107
- package/x/driver/fns/work.js.map +1 -1
- package/x/driver/utils/load-decoder-source.d.ts +2 -1
- package/x/driver/utils/load-decoder-source.js +2 -3
- package/x/driver/utils/load-decoder-source.js.map +1 -1
- package/x/features/speech/transcribe/default-spec.d.ts +2 -0
- package/x/features/speech/transcribe/default-spec.js +8 -0
- package/x/features/speech/transcribe/default-spec.js.map +1 -0
- package/x/features/speech/transcribe/parts/load-pipe.d.ts +2 -0
- package/x/features/speech/transcribe/parts/load-pipe.js +13 -0
- package/x/features/speech/transcribe/parts/load-pipe.js.map +1 -0
- package/x/features/speech/transcribe/parts/prep-audio.d.ts +5 -0
- package/x/features/speech/transcribe/parts/prep-audio.js +21 -0
- package/x/features/speech/transcribe/parts/prep-audio.js.map +1 -0
- package/x/features/speech/transcribe/parts/transcribe.d.ts +5 -0
- package/x/features/speech/transcribe/parts/transcribe.js +56 -0
- package/x/features/speech/transcribe/parts/transcribe.js.map +1 -0
- package/x/features/speech/transcribe/transcriber.d.ts +5 -0
- package/x/features/speech/transcribe/transcriber.js +33 -0
- package/x/features/speech/transcribe/transcriber.js.map +1 -0
- package/x/features/speech/transcribe/types.d.ts +66 -0
- package/x/features/speech/transcribe/types.js +2 -0
- package/x/features/speech/transcribe/types.js.map +1 -0
- package/x/features/speech/transcribe/worker.bundle.d.ts +1 -0
- package/x/features/speech/transcribe/worker.bundle.js +33 -0
- package/x/features/speech/transcribe/worker.bundle.js.map +1 -0
- package/x/features/speech/transcribe/worker.bundle.min.js +2916 -0
- package/x/features/speech/transcribe/worker.bundle.min.js.map +7 -0
- package/x/features/transition/parts/fragment.d.ts +1 -0
- package/x/features/transition/parts/fragment.js +25 -0
- package/x/features/transition/parts/fragment.js.map +1 -0
- package/x/features/transition/parts/types.d.ts +23 -0
- package/x/features/transition/parts/types.js +2 -0
- package/x/features/transition/parts/types.js.map +1 -0
- package/x/features/transition/parts/uniforms.d.ts +31 -0
- package/x/features/transition/parts/uniforms.js +27 -0
- package/x/features/transition/parts/uniforms.js.map +1 -0
- package/x/features/transition/parts/vertex.d.ts +1 -0
- package/x/features/transition/parts/vertex.js +32 -0
- package/x/features/transition/parts/vertex.js.map +1 -0
- package/x/features/transition/transition.d.ts +5 -0
- package/x/features/transition/transition.js +50 -0
- package/x/features/transition/transition.js.map +1 -0
- package/x/index.html +13 -3
- package/x/index.html.js +6 -1
- package/x/index.html.js.map +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/basics.d.ts +1 -1
- package/x/timeline/parts/compositor/export.d.ts +11 -0
- package/x/timeline/parts/compositor/export.js +64 -0
- package/x/timeline/parts/compositor/export.js.map +1 -0
- package/x/timeline/parts/compositor/parts/html-tree.d.ts +3 -0
- package/x/timeline/parts/compositor/parts/html-tree.js +40 -0
- package/x/timeline/parts/compositor/parts/html-tree.js.map +1 -0
- package/x/timeline/parts/compositor/parts/schedulers.d.ts +15 -0
- package/x/timeline/parts/compositor/parts/schedulers.js +69 -0
- package/x/timeline/parts/compositor/parts/schedulers.js.map +1 -0
- package/x/timeline/parts/compositor/parts/tree-builder.d.ts +37 -0
- package/x/timeline/parts/compositor/parts/tree-builder.js +160 -0
- package/x/timeline/parts/compositor/parts/tree-builder.js.map +1 -0
- package/x/timeline/parts/compositor/parts/webcodecs-tree.d.ts +3 -0
- package/x/timeline/parts/compositor/parts/webcodecs-tree.js +28 -0
- package/x/timeline/parts/compositor/parts/webcodecs-tree.js.map +1 -0
- package/x/timeline/parts/compositor/playback.d.ts +26 -0
- package/x/timeline/parts/compositor/playback.js +79 -0
- package/x/timeline/parts/compositor/playback.js.map +1 -0
- package/x/timeline/parts/compositor/samplers/html.d.ts +3 -0
- package/x/timeline/parts/compositor/samplers/html.js +106 -0
- package/x/timeline/parts/compositor/samplers/html.js.map +1 -0
- package/x/timeline/parts/compositor/samplers/webcodecs.d.ts +3 -0
- package/x/timeline/parts/compositor/samplers/webcodecs.js +52 -0
- package/x/timeline/parts/compositor/samplers/webcodecs.js.map +1 -0
- package/x/timeline/parts/item.d.ts +42 -8
- package/x/timeline/parts/item.js +7 -3
- package/x/timeline/parts/item.js.map +1 -1
- package/x/timeline/parts/media.d.ts +3 -0
- package/x/timeline/parts/media.js +17 -0
- package/x/timeline/parts/media.js.map +1 -1
- package/x/timeline/parts/waveform.d.ts +2 -1
- package/x/timeline/parts/waveform.js +2 -4
- package/x/timeline/parts/waveform.js.map +1 -1
- package/x/timeline/sugar/builders.d.ts +1 -0
- package/x/timeline/sugar/builders.js +104 -0
- package/x/timeline/sugar/builders.js.map +1 -0
- package/x/timeline/sugar/o.d.ts +27 -5
- package/x/timeline/sugar/o.js +135 -36
- package/x/timeline/sugar/o.js.map +1 -1
- package/x/timeline/sugar/omni-test.js +4 -2
- package/x/timeline/sugar/omni-test.js.map +1 -1
- package/x/timeline/sugar/omni.d.ts +8 -2
- package/x/timeline/sugar/omni.js +22 -9
- package/x/timeline/sugar/omni.js.map +1 -1
- package/x/timeline/types.d.ts +24 -0
- package/x/timeline/types.js +2 -0
- package/x/timeline/types.js.map +1 -0
- package/x/timeline/utils/audio-stream.d.ts +6 -0
- package/x/timeline/utils/audio-stream.js +17 -0
- package/x/timeline/utils/audio-stream.js.map +1 -0
- package/x/timeline/utils/checksum.js +2 -1
- package/x/timeline/utils/checksum.js.map +1 -1
- package/x/timeline/utils/matrix.d.ts +8 -0
- package/x/timeline/utils/matrix.js +26 -0
- package/x/timeline/utils/matrix.js.map +1 -0
- package/x/timeline/utils/video-cursor.d.ts +10 -0
- package/x/timeline/utils/video-cursor.js +36 -0
- package/x/timeline/utils/video-cursor.js.map +1 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
import {defer, once} from "@e280/stz"
|
|
3
|
+
import {Comrade, Host} from "@e280/comrade"
|
|
4
|
+
import {Pipeline} from "@huggingface/transformers"
|
|
5
|
+
|
|
6
|
+
import {loadPipe} from "./parts/load-pipe.js"
|
|
7
|
+
import {transcribe} from "./parts/transcribe.js"
|
|
8
|
+
import {TranscriberSchematic, TranscriberSpec} from "./types.js"
|
|
9
|
+
|
|
10
|
+
const deferred = defer<{pipe: Pipeline, spec: TranscriberSpec}>()
|
|
11
|
+
|
|
12
|
+
const makePrepare = (host: Host<TranscriberSchematic>) => once(async(spec: TranscriberSpec) => {
|
|
13
|
+
deferred.resolve({
|
|
14
|
+
spec,
|
|
15
|
+
pipe: await loadPipe({
|
|
16
|
+
spec,
|
|
17
|
+
onLoading: loading => host.loading(loading),
|
|
18
|
+
}),
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
await Comrade.worker<TranscriberSchematic>(shell => {
|
|
23
|
+
const prepare = makePrepare(shell.host)
|
|
24
|
+
return {
|
|
25
|
+
prepare,
|
|
26
|
+
async transcribe(request) {
|
|
27
|
+
const {pipe, spec} = await deferred.promise
|
|
28
|
+
return transcribe({
|
|
29
|
+
pipe,
|
|
30
|
+
spec,
|
|
31
|
+
request,
|
|
32
|
+
callbacks: {
|
|
33
|
+
onReport: report => shell.host.deliverReport(report),
|
|
34
|
+
onTranscription: transcription => shell.host.deliverTranscription(transcription),
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const fragment = (glsl: string) => `
|
|
2
|
+
precision highp float;
|
|
3
|
+
varying vec2 vTextureCoord;
|
|
4
|
+
varying vec2 _uv;
|
|
5
|
+
uniform sampler2D from, to;
|
|
6
|
+
uniform float progress, ratio, _fromR, _toR;
|
|
7
|
+
uniform float customUniform;
|
|
8
|
+
|
|
9
|
+
vec4 getFromColor(vec2 uv){
|
|
10
|
+
return texture2D(from, .5+(uv-.5)*vec2(max(ratio/_fromR,1.), max(_fromR/ratio,1.)));
|
|
11
|
+
}
|
|
12
|
+
vec4 getToColor(vec2 uv){
|
|
13
|
+
return texture2D(to, .5+(uv-.5)*vec2(max(ratio/_toR,1.), max(_toR/ratio,1.)));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// gl-transition code here
|
|
17
|
+
${glsl}
|
|
18
|
+
// gl-transition code end
|
|
19
|
+
|
|
20
|
+
void main(){
|
|
21
|
+
vec2 uv = vTextureCoord.xy;
|
|
22
|
+
gl_FragColor = transition(vTextureCoord);
|
|
23
|
+
}
|
|
24
|
+
`
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {Renderer} from "pixi.js"
|
|
2
|
+
|
|
3
|
+
export interface TransitionOptions {
|
|
4
|
+
name: Transition
|
|
5
|
+
renderer: Renderer
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface TransitionRendererOptions {
|
|
9
|
+
from: VideoFrame
|
|
10
|
+
to: VideoFrame
|
|
11
|
+
progress: number
|
|
12
|
+
width: number
|
|
13
|
+
height: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface GLTransition {
|
|
17
|
+
author: string
|
|
18
|
+
createdAt: string
|
|
19
|
+
glsl: string
|
|
20
|
+
license: string
|
|
21
|
+
name: Transition
|
|
22
|
+
updatedAt: string
|
|
23
|
+
defaultParams: any
|
|
24
|
+
paramsTypes: any
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type Transition =
|
|
28
|
+
| "Bounce"
|
|
29
|
+
| "BowTieHorizontal"
|
|
30
|
+
| "BowTieVertical"
|
|
31
|
+
| "ButterflyWaveScrawler"
|
|
32
|
+
| "CircleCrop"
|
|
33
|
+
| "ColourDistance"
|
|
34
|
+
| "CrazyParametricFun"
|
|
35
|
+
| "CrossZoom"
|
|
36
|
+
| "Directional"
|
|
37
|
+
| "DoomScreenTransition"
|
|
38
|
+
| "Dreamy"
|
|
39
|
+
| "DreamyZoom"
|
|
40
|
+
| "GlitchDisplace"
|
|
41
|
+
| "GlitchMemories"
|
|
42
|
+
| "GridFlip"
|
|
43
|
+
| "InvertedPageCurl"
|
|
44
|
+
| "LinearBlur"
|
|
45
|
+
| "Mosaic"
|
|
46
|
+
| "PolkaDotsCurtain"
|
|
47
|
+
| "Radial"
|
|
48
|
+
| "SimpleZoom"
|
|
49
|
+
| "StereoViewer"
|
|
50
|
+
| "Swirl"
|
|
51
|
+
| "WaterDrop"
|
|
52
|
+
| "ZoomInCircles"
|
|
53
|
+
| "angular"
|
|
54
|
+
| "burn"
|
|
55
|
+
| "cannabisleaf"
|
|
56
|
+
| "circle"
|
|
57
|
+
| "circleopen"
|
|
58
|
+
| "colorphase"
|
|
59
|
+
| "crosshatch"
|
|
60
|
+
| "crosswarp"
|
|
61
|
+
| "cube"
|
|
62
|
+
| "directionalwarp"
|
|
63
|
+
| "directionalwipe"
|
|
64
|
+
| "displacement"
|
|
65
|
+
| "doorway"
|
|
66
|
+
| "fade"
|
|
67
|
+
| "fadecolor"
|
|
68
|
+
| "fadegrayscale"
|
|
69
|
+
| "flyeye"
|
|
70
|
+
| "heart"
|
|
71
|
+
| "hexagonalize"
|
|
72
|
+
| "kaleidoscope"
|
|
73
|
+
| "luma"
|
|
74
|
+
| "luminance_melt"
|
|
75
|
+
| "morph"
|
|
76
|
+
| "multiply_blend"
|
|
77
|
+
| "perlin"
|
|
78
|
+
| "pinwheel"
|
|
79
|
+
| "pixelize"
|
|
80
|
+
| "polar_function"
|
|
81
|
+
| "randomsquares"
|
|
82
|
+
| "ripple"
|
|
83
|
+
| "rotate_scale_fade"
|
|
84
|
+
| "squareswire"
|
|
85
|
+
| "squeeze"
|
|
86
|
+
| "swap"
|
|
87
|
+
| "undulatingBurnOut"
|
|
88
|
+
| "wind"
|
|
89
|
+
| "windowblinds"
|
|
90
|
+
| "windowslice"
|
|
91
|
+
| "wipeDown"
|
|
92
|
+
| "wipeLeft"
|
|
93
|
+
| "wipeRight"
|
|
94
|
+
| "wipeUp"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {GLTransition} from "./types.js"
|
|
2
|
+
|
|
3
|
+
export const uniforms = {
|
|
4
|
+
custom: (transition: GLTransition) => Object.fromEntries(
|
|
5
|
+
Object.entries(transition.defaultParams).map(([name, value]) => [
|
|
6
|
+
name,
|
|
7
|
+
{
|
|
8
|
+
value,
|
|
9
|
+
type: getUniformType(transition.paramsTypes[name])
|
|
10
|
+
}
|
|
11
|
+
])
|
|
12
|
+
),
|
|
13
|
+
basics: {
|
|
14
|
+
_fromR: {value: 1, type: "f32"},
|
|
15
|
+
_toR: {value: 1, type: "f32"},
|
|
16
|
+
ratio: {value: 1, type: "f32"},
|
|
17
|
+
progress: {value: 0, type: "f32"},
|
|
18
|
+
customUniform: {value: 0, type: "f32"},
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const getUniformType = (type: string) => {
|
|
23
|
+
if(type === "f32" || type === "i32") {
|
|
24
|
+
return type
|
|
25
|
+
} else if(type === "float") {
|
|
26
|
+
return "f32"
|
|
27
|
+
}
|
|
28
|
+
else return `${type}<f32>`
|
|
29
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const vertex = `
|
|
2
|
+
in vec2 aPosition;
|
|
3
|
+
varying vec2 _uv; // gl-transition
|
|
4
|
+
uniform mat3 projectionMatrix;
|
|
5
|
+
uniform vec4 uInputSize;
|
|
6
|
+
uniform vec4 uOutputFrame;
|
|
7
|
+
out vec2 vTextureCoord;
|
|
8
|
+
uniform vec4 uOutputTexture;
|
|
9
|
+
|
|
10
|
+
vec4 filterVertexPosition( void )
|
|
11
|
+
{
|
|
12
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
13
|
+
|
|
14
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
15
|
+
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
16
|
+
|
|
17
|
+
return vec4(position, 0.0, 1.0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
vec2 filterTextureCoord( void )
|
|
21
|
+
{
|
|
22
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void main(void)
|
|
26
|
+
{
|
|
27
|
+
gl_Position = filterVertexPosition();
|
|
28
|
+
vTextureCoord = filterTextureCoord();
|
|
29
|
+
_uv = vec2(0.5, 0.5) * (aPosition +vec2(1.0, 1.0)); // gl-transition
|
|
30
|
+
}
|
|
31
|
+
`
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//@ts-ignore
|
|
2
|
+
import transitions from "gl-transitions"
|
|
3
|
+
import {Filter, GlProgram, Sprite, Texture, ImageSource} from "pixi.js"
|
|
4
|
+
|
|
5
|
+
import {vertex} from "./parts/vertex.js"
|
|
6
|
+
import {uniforms} from "./parts/uniforms.js"
|
|
7
|
+
import {fragment} from "./parts/fragment.js"
|
|
8
|
+
import {GLTransition, TransitionOptions, TransitionRendererOptions} from "./parts/types.js"
|
|
9
|
+
|
|
10
|
+
export function makeTransition({name, renderer}: TransitionOptions) {
|
|
11
|
+
const transition = transitions.find((t: GLTransition) => t.name === name) as GLTransition
|
|
12
|
+
const transitionSprite = new Sprite()
|
|
13
|
+
const transitionTexture = new Texture()
|
|
14
|
+
const sourceFrom = new ImageSource({})
|
|
15
|
+
const sourceTo = new ImageSource({})
|
|
16
|
+
|
|
17
|
+
const filter = new Filter({
|
|
18
|
+
glProgram: new GlProgram({
|
|
19
|
+
vertex,
|
|
20
|
+
fragment: fragment(transition.glsl),
|
|
21
|
+
}),
|
|
22
|
+
resources: {
|
|
23
|
+
from: sourceFrom,
|
|
24
|
+
to: sourceTo,
|
|
25
|
+
uniforms: {
|
|
26
|
+
...uniforms.basics,
|
|
27
|
+
...uniforms.custom(transition)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
transitionSprite.filters = [filter]
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
render({width, height, from, to, progress}: TransitionRendererOptions) {
|
|
36
|
+
if(transitionSprite.width !== width || transitionSprite.height !== height) {
|
|
37
|
+
transitionSprite.setSize({width, height})
|
|
38
|
+
transitionTexture.source.resize(width, height)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
sourceFrom.resource = from
|
|
42
|
+
sourceTo.resource = to
|
|
43
|
+
sourceFrom.update()
|
|
44
|
+
sourceTo.update()
|
|
45
|
+
|
|
46
|
+
filter.resources.uniforms.uniforms.progress = progress
|
|
47
|
+
|
|
48
|
+
renderer.render({
|
|
49
|
+
container: transitionSprite,
|
|
50
|
+
target: transitionTexture,
|
|
51
|
+
clear: false,
|
|
52
|
+
width,
|
|
53
|
+
height
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return transitionTexture
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
package/s/index.html.ts
CHANGED
|
@@ -30,7 +30,7 @@ export default ssg.page(import.meta.url, async orb => ({
|
|
|
30
30
|
<section>
|
|
31
31
|
<h1>Omnitool <small>v${orb.packageVersion()}</small></h1>
|
|
32
32
|
<button class=fetch>fetch</button>
|
|
33
|
-
<
|
|
33
|
+
<input type="file" class="file-input">
|
|
34
34
|
<div class=results></div>
|
|
35
35
|
<div class=filmstrip-demo>
|
|
36
36
|
<label for="viewable-range">viewable range:</label>
|
|
@@ -47,6 +47,11 @@ export default ssg.page(import.meta.url, async orb => ({
|
|
|
47
47
|
<label for="width">width:</label>
|
|
48
48
|
<input class="width" id="width" name="width" type="range" min="100" max="1000000" value="1000" />
|
|
49
49
|
</div>
|
|
50
|
+
<div class=player>
|
|
51
|
+
<input class="seek" type="number" min="0">
|
|
52
|
+
<button class=play>play</button>
|
|
53
|
+
<button class=stop>stop</button>
|
|
54
|
+
</div>
|
|
50
55
|
</section>
|
|
51
56
|
`,
|
|
52
57
|
}))
|
package/s/timeline/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./parts/media.js"
|
|
|
5
5
|
export * from "./parts/resource-pool.js"
|
|
6
6
|
export * from "./parts/resource.js"
|
|
7
7
|
export * from "./parts/filmstrip.js"
|
|
8
|
+
export * from "./parts/compositor/playback.js"
|
|
8
9
|
|
|
9
10
|
export * from "./sugar/o.js"
|
|
10
11
|
export * from "./sugar/omni.js"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {TimelineFile} from "../basics.js"
|
|
2
|
+
import {fixedStep} from "./parts/schedulers.js"
|
|
3
|
+
import {Driver} from "../../../driver/driver.js"
|
|
4
|
+
import {makeWebCodecsSampler} from "./samplers/webcodecs.js"
|
|
5
|
+
import {DecoderSource} from "../../../driver/fns/schematic.js"
|
|
6
|
+
import {buildWebCodecsNodeTree} from "./parts/webcodecs-tree.js"
|
|
7
|
+
|
|
8
|
+
export class Export {
|
|
9
|
+
#sampler
|
|
10
|
+
constructor(
|
|
11
|
+
private driver: Driver,
|
|
12
|
+
private framerate = 30,
|
|
13
|
+
private resolveMedia: (hash: string) => DecoderSource = _hash => "/assets/temp/gl.mp4"
|
|
14
|
+
) {
|
|
15
|
+
this.#sampler = makeWebCodecsSampler(this.driver, this.resolveMedia)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async #build(timeline: TimelineFile) {
|
|
19
|
+
const rootItem = new Map(timeline.items.map(i => [i.id, i])).get(timeline.rootId)!
|
|
20
|
+
const items = new Map(timeline.items.map(i => [i.id, i]))
|
|
21
|
+
return await buildWebCodecsNodeTree(rootItem, items, this.#sampler)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async render(timeline: TimelineFile) {
|
|
25
|
+
const root = await this.#build(timeline)
|
|
26
|
+
|
|
27
|
+
const videoStream = new TransformStream<VideoFrame, VideoFrame>()
|
|
28
|
+
const audioStream = new TransformStream<AudioData, AudioData>()
|
|
29
|
+
|
|
30
|
+
const encodePromise = this.driver.encode({
|
|
31
|
+
video: videoStream.readable,
|
|
32
|
+
audio: audioStream.readable,
|
|
33
|
+
config: {
|
|
34
|
+
audio: {codec: "opus", bitrate: 128000},
|
|
35
|
+
video: {codec: "vp9", bitrate: 1000000},
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const videoWriter = videoStream.writable.getWriter()
|
|
40
|
+
const audioWriter = audioStream.writable.getWriter()
|
|
41
|
+
|
|
42
|
+
const audioPromise = (async () => {
|
|
43
|
+
if (root.audio) {
|
|
44
|
+
for await (const chunk of root.audio.getStream()) {
|
|
45
|
+
await audioWriter.write(chunk)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
await audioWriter.close()
|
|
49
|
+
})()
|
|
50
|
+
|
|
51
|
+
const videoPromise = (async () => {
|
|
52
|
+
let i = 0
|
|
53
|
+
const dt = 1 / this.framerate
|
|
54
|
+
|
|
55
|
+
await fixedStep(
|
|
56
|
+
{fps: this.framerate, duration: root.duration ?? 0},
|
|
57
|
+
async t => {
|
|
58
|
+
const layers = await root.visuals?.sampleAt(t) ?? []
|
|
59
|
+
const composed = await this.driver.composite(layers)
|
|
60
|
+
const vf = new VideoFrame(composed, {
|
|
61
|
+
timestamp: Math.round(i * dt * 1_000_000),
|
|
62
|
+
duration: Math.round(dt * 1_000_000),
|
|
63
|
+
})
|
|
64
|
+
await videoWriter.write(vf)
|
|
65
|
+
composed.close()
|
|
66
|
+
i++
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
await videoWriter.close()
|
|
70
|
+
})()
|
|
71
|
+
|
|
72
|
+
await audioPromise
|
|
73
|
+
await videoPromise
|
|
74
|
+
await encodePromise
|
|
75
|
+
// this.#sampler.dispose()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {Item} from "../../item.js"
|
|
2
|
+
import {AudioPlaybackComponent, HTMLSampler, Node, TreeBuilder} from "./tree-builder.js"
|
|
3
|
+
|
|
4
|
+
class HTMLNodeBuilder extends TreeBuilder<AudioPlaybackComponent> {
|
|
5
|
+
constructor(protected items: Map<number, Item.Any>, protected sampler: HTMLSampler) {
|
|
6
|
+
super(items, sampler)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
composeAudio_Stack(children: Node<AudioPlaybackComponent>[]) {
|
|
10
|
+
return {
|
|
11
|
+
onTimeUpdate: (time: number) => {
|
|
12
|
+
for (const child of children) {
|
|
13
|
+
if (child.audio) child.audio.onTimeUpdate(time)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
composeAudio_Sequence(children: Node<AudioPlaybackComponent>[]) {
|
|
19
|
+
return {
|
|
20
|
+
onTimeUpdate: (time: number) => {
|
|
21
|
+
let localTime = time
|
|
22
|
+
for (const child of children) {
|
|
23
|
+
if (localTime < child.duration) {
|
|
24
|
+
if (child.audio) child.audio.onTimeUpdate(localTime)
|
|
25
|
+
break
|
|
26
|
+
}
|
|
27
|
+
localTime -= child.duration
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function buildHTMLNodeTree(root: Item.Any, items: Map<number, Item.Any>, sampler: HTMLSampler) {
|
|
35
|
+
const builder = new HTMLNodeBuilder(items, sampler)
|
|
36
|
+
return builder.build(root)
|
|
37
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export type RealtimeController = {
|
|
2
|
+
play(): void
|
|
3
|
+
pause(): void
|
|
4
|
+
seek(t: number): void
|
|
5
|
+
dispose(): void
|
|
6
|
+
setFPS(v: number): void
|
|
7
|
+
isPlaying(): boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const realtime = (
|
|
11
|
+
onTick: (tickTime: number) => void,
|
|
12
|
+
onUpdate: (currentTime: number) => void
|
|
13
|
+
): RealtimeController => {
|
|
14
|
+
|
|
15
|
+
let playing = false
|
|
16
|
+
let rafId: number | null = null
|
|
17
|
+
let fps = 60
|
|
18
|
+
|
|
19
|
+
let frameDuration = 1000 / fps
|
|
20
|
+
let composeTime = 0
|
|
21
|
+
let lastTime = 0
|
|
22
|
+
let accumulator = 0
|
|
23
|
+
let currentTime = 0
|
|
24
|
+
|
|
25
|
+
const tick = (now: number) => {
|
|
26
|
+
if (!playing) return
|
|
27
|
+
|
|
28
|
+
const deltaTime = now - lastTime
|
|
29
|
+
lastTime = now
|
|
30
|
+
|
|
31
|
+
accumulator += deltaTime
|
|
32
|
+
currentTime += deltaTime
|
|
33
|
+
onUpdate(currentTime)
|
|
34
|
+
|
|
35
|
+
while (accumulator >= frameDuration) {
|
|
36
|
+
onTick(composeTime)
|
|
37
|
+
composeTime += frameDuration
|
|
38
|
+
accumulator -= frameDuration
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
rafId = requestAnimationFrame(tick)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
play() {
|
|
46
|
+
if (playing) return
|
|
47
|
+
playing = true
|
|
48
|
+
lastTime = performance.now()
|
|
49
|
+
rafId = requestAnimationFrame(tick)
|
|
50
|
+
},
|
|
51
|
+
pause() {
|
|
52
|
+
if (!playing) return
|
|
53
|
+
playing = false
|
|
54
|
+
if (rafId !== null) cancelAnimationFrame(rafId)
|
|
55
|
+
rafId = null
|
|
56
|
+
},
|
|
57
|
+
seek(ms) {
|
|
58
|
+
composeTime = ms
|
|
59
|
+
accumulator = 0
|
|
60
|
+
currentTime = ms
|
|
61
|
+
onUpdate(ms)
|
|
62
|
+
},
|
|
63
|
+
dispose() {
|
|
64
|
+
this.pause()
|
|
65
|
+
},
|
|
66
|
+
isPlaying() {
|
|
67
|
+
return playing
|
|
68
|
+
},
|
|
69
|
+
setFPS(v) {
|
|
70
|
+
fps = v
|
|
71
|
+
frameDuration = 1000 / fps
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type FixedStepOptions = {
|
|
77
|
+
fps: number
|
|
78
|
+
duration: number
|
|
79
|
+
abort?: AbortSignal
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const fixedStep = async (
|
|
83
|
+
opts: FixedStepOptions,
|
|
84
|
+
onFrame: (t: number, index: number) => Promise<void> | void
|
|
85
|
+
) => {
|
|
86
|
+
const dt = 1 / opts.fps
|
|
87
|
+
const total = Math.ceil(opts.duration * opts.fps)
|
|
88
|
+
|
|
89
|
+
for (let i = 0; i < total; i++) {
|
|
90
|
+
if (opts.abort?.aborted) break
|
|
91
|
+
const t = i * dt
|
|
92
|
+
await onFrame(t, i)
|
|
93
|
+
}
|
|
94
|
+
}
|