@omnimedia/omnitool 1.1.0-100 → 1.1.0-103
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 +2 -0
- package/package.json +2 -1
- package/s/driver/driver.ts +4 -0
- package/s/driver/parts/compositor.ts +4 -0
- package/s/features/speech/transcribe/parts/prep-audio.ts +19 -14
- package/s/timeline/parts/basics.ts +1 -1
- package/s/timeline/parts/resource-pool.ts +2 -2
- package/s/timeline/parts/resource.ts +0 -1
- package/s/timeline/renderers/player/parts/playback.ts +6 -4
- package/s/timeline/renderers/player/player.ts +4 -0
- package/s/timeline/utils/checksum.ts +12 -9
- package/s/timeline/utils/datafile.ts +2 -12
- package/x/demo/demo.bundle.min.js +103 -103
- package/x/demo/demo.bundle.min.js.map +4 -4
- package/x/driver/driver.d.ts +1 -0
- package/x/driver/driver.js +3 -0
- package/x/driver/driver.js.map +1 -1
- package/x/driver/parts/compositor.d.ts +1 -0
- package/x/driver/parts/compositor.js +3 -0
- package/x/driver/parts/compositor.js.map +1 -1
- package/x/features/speech/transcribe/parts/prep-audio.js +17 -13
- package/x/features/speech/transcribe/parts/prep-audio.js.map +1 -1
- package/x/index.html +2 -2
- package/x/tests.bundle.min.js +109 -109
- package/x/tests.bundle.min.js.map +4 -4
- package/x/tests.html +1 -1
- package/x/timeline/parts/basics.d.ts +1 -1
- package/x/timeline/parts/resource-pool.js +2 -2
- package/x/timeline/parts/resource-pool.js.map +1 -1
- package/x/timeline/parts/resource.d.ts +0 -1
- package/x/timeline/renderers/player/parts/playback.js +5 -2
- package/x/timeline/renderers/player/parts/playback.js.map +1 -1
- package/x/timeline/renderers/player/player.d.ts +1 -0
- package/x/timeline/renderers/player/player.js +3 -0
- package/x/timeline/renderers/player/player.js.map +1 -1
- package/x/timeline/utils/checksum.d.ts +2 -4
- package/x/timeline/utils/checksum.js +11 -12
- package/x/timeline/utils/checksum.js.map +1 -1
- package/x/timeline/utils/datafile.d.ts +1 -2
- package/x/timeline/utils/datafile.js +3 -14
- package/x/timeline/utils/datafile.js.map +1 -1
package/README.md
CHANGED
|
@@ -509,6 +509,7 @@ const driver = await Driver.setup({workerUrl})
|
|
|
509
509
|
const player = await omni.playback(timeline)
|
|
510
510
|
|
|
511
511
|
document.body.appendChild(player.canvas)
|
|
512
|
+
player.resize(1280, 720)
|
|
512
513
|
await player.play()
|
|
513
514
|
player.playbackRate = 0.5 // slow motion
|
|
514
515
|
player.playbackRate = -1 // reverse
|
|
@@ -516,6 +517,7 @@ player.playbackRate = -1 // reverse
|
|
|
516
517
|
|
|
517
518
|
Notes:
|
|
518
519
|
- Call `await player.update(timeline)` if you update the timeline.
|
|
520
|
+
- Call `player.resize(width, height)` to resize the preview canvas.
|
|
519
521
|
- `playbackRate` supports slower, faster, and reverse visual playback. Audio currently plays only at `1`.
|
|
520
522
|
|
|
521
523
|
## 📤 Export
|
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-103",
|
|
4
4
|
"description": "open source video processing tools",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Przemysław Gałęzki",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@e280/strata": "^0.2.5",
|
|
39
39
|
"@e280/stz": "^0.2.15",
|
|
40
40
|
"@huggingface/transformers": "^3.8.1",
|
|
41
|
+
"@noble/hashes": "^2.2.0",
|
|
41
42
|
"comrade": "^0.0.3",
|
|
42
43
|
"gl-transitions": "^1.43.0",
|
|
43
44
|
"gsap": "^3.14.2",
|
package/s/driver/driver.ts
CHANGED
|
@@ -47,6 +47,10 @@ export class Compositor {
|
|
|
47
47
|
#activeObjects = new Map<number, {sprite: Container, dispose: () => void}>()
|
|
48
48
|
#cropMasks = new WeakMap<Container, Graphics>()
|
|
49
49
|
|
|
50
|
+
resize(width: number, height: number) {
|
|
51
|
+
this.pixi.renderer.resize(width, height)
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
async composite(
|
|
51
55
|
composition: Composition,
|
|
52
56
|
) {
|
|
@@ -4,20 +4,25 @@ import {Driver} from "../../../../driver/driver.js"
|
|
|
4
4
|
export async function prepAudio(driver: Driver, source: Blob) {
|
|
5
5
|
const arrayBuffer = await source.arrayBuffer()
|
|
6
6
|
const audioCTX = new AudioContext({sampleRate: 16000})
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
audio
|
|
7
|
+
try {
|
|
8
|
+
const audioData = await audioCTX.decodeAudioData(arrayBuffer)
|
|
9
|
+
let audio: Float32Array
|
|
10
|
+
|
|
11
|
+
if (audioData.numberOfChannels === 2) {
|
|
12
|
+
const SCALING_FACTOR = Math.sqrt(2)
|
|
13
|
+
const left = audioData.getChannelData(0)
|
|
14
|
+
const right = audioData.getChannelData(1)
|
|
15
|
+
audio = new Float32Array(left.length)
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < audioData.length; ++i)
|
|
18
|
+
audio[i] = (SCALING_FACTOR * (left[i] + right[i])) / 2
|
|
19
|
+
} else {
|
|
20
|
+
audio = audioData.getChannelData(0)
|
|
16
21
|
}
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
|
|
23
|
+
const duration = await driver.getAudioDuration(source)
|
|
24
|
+
return {audio, duration}
|
|
25
|
+
} finally {
|
|
26
|
+
await audioCTX.close()
|
|
19
27
|
}
|
|
20
|
-
const duration = await driver.getAudioDuration(source)
|
|
21
|
-
return {audio, duration}
|
|
22
28
|
}
|
|
23
|
-
|
|
@@ -12,14 +12,14 @@ export class ResourcePool {
|
|
|
12
12
|
async store(datafile: Datafile) {
|
|
13
13
|
const media = await Media.analyze(datafile)
|
|
14
14
|
const {hash} = media.datafile.checksum
|
|
15
|
-
const {filename,
|
|
15
|
+
const {filename, url, blob} = media.datafile
|
|
16
16
|
|
|
17
17
|
if (this.#map.has(hash)) {
|
|
18
18
|
const alreadyExists = this.#map.require(hash)
|
|
19
19
|
alreadyExists.filename = filename
|
|
20
20
|
}
|
|
21
21
|
else
|
|
22
|
-
this.#map.set(hash, {kind: "media", filename,
|
|
22
|
+
this.#map.set(hash, {kind: "media", filename, url, blob, duration: media.duration})
|
|
23
23
|
|
|
24
24
|
return media
|
|
25
25
|
}
|
|
@@ -184,9 +184,8 @@ export class Playback {
|
|
|
184
184
|
if (this.#audioStartSec === null)
|
|
185
185
|
return
|
|
186
186
|
|
|
187
|
-
for await (const {sample, timestamp} of this.audioSampler.sampleAudio(
|
|
188
|
-
this.timeline,
|
|
189
|
-
ms(from * 1000)
|
|
187
|
+
for await (const {sample, timestamp, gain} of this.audioSampler.sampleAudio(
|
|
188
|
+
this.timeline, ms(from * 1000)
|
|
190
189
|
)) {
|
|
191
190
|
|
|
192
191
|
if (signal.aborted || !this.#controller.isPlaying())
|
|
@@ -196,8 +195,11 @@ export class Playback {
|
|
|
196
195
|
await new Promise(r => setTimeout(r, 25))
|
|
197
196
|
|
|
198
197
|
const node = ctx.createBufferSource()
|
|
198
|
+
const itemGain = ctx.createGain()
|
|
199
199
|
node.buffer = sample.toAudioBuffer()
|
|
200
|
-
|
|
200
|
+
itemGain.gain.value = gain
|
|
201
|
+
node.connect(itemGain)
|
|
202
|
+
itemGain.connect(this.audioGain)
|
|
201
203
|
node.onended = () => this.audioNodes.delete(node)
|
|
202
204
|
this.audioNodes.add(node)
|
|
203
205
|
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import {hex, thumbprint} from "@e280/stz"
|
|
3
|
+
import {blake3} from "@noble/hashes/blake3.js"
|
|
3
4
|
|
|
4
5
|
import {Hash} from "../parts/basics.js"
|
|
5
6
|
|
|
6
7
|
export class Checksum {
|
|
7
8
|
constructor(
|
|
8
|
-
public data: Uint8Array,
|
|
9
|
-
public bytes: Uint8Array,
|
|
10
9
|
public hash: Hash,
|
|
11
10
|
public nickname: string,
|
|
12
11
|
) {}
|
|
13
12
|
|
|
14
|
-
static async make(
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
static async make(file: Blob) {
|
|
14
|
+
const hasher = blake3.create()
|
|
15
|
+
|
|
16
|
+
for await (const chunk of file.stream())
|
|
17
|
+
hasher.update(chunk)
|
|
18
|
+
|
|
19
|
+
const digest = hasher.digest()
|
|
20
|
+
const hash = hex.fromBytes(digest)
|
|
21
|
+
const nickname = thumbprint.sigil.fromBytes(digest)
|
|
22
|
+
return new this(hash, nickname)
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -4,29 +4,19 @@ import {Checksum} from "./checksum.js"
|
|
|
4
4
|
export class Datafile {
|
|
5
5
|
constructor(
|
|
6
6
|
public url: string,
|
|
7
|
-
public bytes: Uint8Array,
|
|
8
7
|
public blob: Blob,
|
|
9
8
|
public filename: string,
|
|
10
9
|
public checksum: Checksum,
|
|
11
10
|
) {}
|
|
12
11
|
|
|
13
12
|
static async make(file: Blob, name?: string) {
|
|
14
|
-
const
|
|
15
|
-
const bytes = new Uint8Array(buffer)
|
|
16
|
-
const checksum = await Checksum.make(bytes)
|
|
13
|
+
const checksum = await Checksum.make(file)
|
|
17
14
|
const filename = name ?? checksum.nickname
|
|
18
15
|
const url = URL.createObjectURL(file)
|
|
19
|
-
return new this(url,
|
|
16
|
+
return new this(url, file, filename, checksum)
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
static async load(path: string) {
|
|
23
|
-
// const file = await fetch(path)
|
|
24
|
-
// const buffer = await file.arrayBuffer()
|
|
25
|
-
// const bytes = new Uint8Array(buffer)
|
|
26
|
-
// const filename = file?.headers.get('Content-Disposition')?.split('filename=')[1] ?? "file"
|
|
27
|
-
// console.log(filename)
|
|
28
|
-
// const checksum = await Checksum.make(bytes)
|
|
29
|
-
// return new this(path, bytes, filename, checksum)
|
|
30
20
|
}
|
|
31
21
|
}
|
|
32
22
|
|