@omnimedia/omnitool 1.1.0-55 → 1.1.0-56

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 (32) hide show
  1. package/package.json +1 -1
  2. package/s/demo/demo.bundle.ts +5 -3
  3. package/s/demo/routines/waveform-test.ts +30 -5
  4. package/s/index.html.ts +1 -2
  5. package/s/timeline/parts/waveform/parts/collect.ts +72 -0
  6. package/s/timeline/parts/waveform/parts/render.ts +45 -0
  7. package/s/timeline/parts/waveform/parts/types.ts +24 -0
  8. package/s/timeline/parts/waveform/waveform.ts +152 -0
  9. package/s/timeline/parts/waveform.ts +0 -61
  10. package/x/demo/demo.bundle.js +2 -0
  11. package/x/demo/demo.bundle.js.map +1 -1
  12. package/x/demo/demo.bundle.min.js +11 -84
  13. package/x/demo/demo.bundle.min.js.map +4 -4
  14. package/x/demo/routines/waveform-test.js +24 -4
  15. package/x/demo/routines/waveform-test.js.map +1 -1
  16. package/x/index.html +3 -3
  17. package/x/index.html.js +1 -1
  18. package/x/timeline/parts/waveform/parts/collect.d.ts +11 -0
  19. package/x/timeline/parts/waveform/parts/collect.js +56 -0
  20. package/x/timeline/parts/waveform/parts/collect.js.map +1 -0
  21. package/x/timeline/parts/waveform/parts/render.d.ts +5 -0
  22. package/x/timeline/parts/waveform/parts/render.js +29 -0
  23. package/x/timeline/parts/waveform/parts/render.js.map +1 -0
  24. package/x/timeline/parts/waveform/parts/types.d.ts +21 -0
  25. package/x/timeline/parts/waveform/parts/types.js +2 -0
  26. package/x/timeline/parts/waveform/parts/types.js.map +1 -0
  27. package/x/timeline/parts/waveform/waveform.d.ts +17 -0
  28. package/x/timeline/parts/waveform/waveform.js +125 -0
  29. package/x/timeline/parts/waveform/waveform.js.map +1 -0
  30. package/x/timeline/parts/waveform.d.ts +1 -9
  31. package/x/timeline/parts/waveform.js +1 -48
  32. package/x/timeline/parts/waveform.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnimedia/omnitool",
3
- "version": "1.1.0-55",
3
+ "version": "1.1.0-56",
4
4
  "description": "open source video processing tools",
5
5
  "license": "MIT",
6
6
  "author": "Przemysław Gałęzki",
@@ -26,8 +26,11 @@ let exportState: {timeline: TimelineFile; omni: Omni} | null = null
26
26
  }
27
27
 
28
28
  const setProgress = (card: HTMLElement, state: "idle" | "running" | "done") => {
29
- const progress = card.querySelector(".progress") as HTMLProgressElement
30
- const status = card.querySelector(".status") as HTMLSpanElement
29
+ const progress = card.querySelector(".progress") as HTMLProgressElement | null
30
+ const status = card.querySelector(".status") as HTMLSpanElement | null
31
+
32
+ if (!progress || !status)
33
+ return
31
34
 
32
35
  if (state === "running") {
33
36
  progress.removeAttribute("value")
@@ -124,4 +127,3 @@ exportButton.addEventListener("click", async () => {
124
127
  await exportState.omni.render(exportState.timeline)
125
128
  setProgress(exportCard, "done")
126
129
  })
127
-
@@ -1,14 +1,39 @@
1
+
1
2
  import {Driver} from "../../driver/driver.js"
2
- import {Waveform} from "../../timeline/parts/waveform.js"
3
+ import {Waveform} from "../../timeline/parts/waveform/waveform.js"
3
4
 
4
5
  export async function waveformTest(driver: Driver, source: File, root: HTMLElement) {
5
- const container = root.querySelector(".waveform-canvas") as HTMLElement
6
+ const container = root.querySelector(".waveform-canvas") as HTMLDivElement
6
7
  const widthSlider = root.querySelector(".width") as HTMLInputElement
8
+
7
9
  container.replaceChildren()
8
- const waveform = await Waveform.init(driver, source, container)
10
+ container.style.position = "relative"
11
+ container.style.height = "96px"
12
+ container.style.overflow = "hidden"
13
+
14
+ const waveform = await Waveform.init(driver, source, {
15
+ tileHeight: 96,
16
+ onChange: () => renderTiles()
17
+ })
9
18
 
10
- widthSlider.oninput = () => {
19
+ const renderTiles = () => {
11
20
  const width = +widthSlider.value
12
- waveform.width = width
21
+ const zoom = pixelsPerSecond(width, waveform.duration)
22
+ waveform.zoom = zoom
23
+ container.style.width = `${width}px`
24
+ container.replaceChildren(...[...waveform.getTiles().values()].map(tile => {
25
+ tile.canvas.style.position = "absolute"
26
+ tile.canvas.style.top = "0"
27
+ tile.canvas.style.left = `${tile.startTime * pixelsPerSecond(width, waveform.duration)}px`
28
+ tile.canvas.style.height = "100%"
29
+ return tile.canvas
30
+ }))
13
31
  }
32
+
33
+ widthSlider.oninput = renderTiles
34
+ waveform.range = [0, waveform.duration]
35
+ }
36
+
37
+ function pixelsPerSecond(width: number, duration: number) {
38
+ return duration > 0 ? width / duration : 0
14
39
  }
package/s/index.html.ts CHANGED
@@ -85,7 +85,7 @@ export default ssg.page(import.meta.url, async orb => ({
85
85
  </div>
86
86
  <div class="waveform-controls">
87
87
  <label>width</label>
88
- <input class="width" type="range" min="100" max="1000000" value="1000" />
88
+ <input class="width" type="range" min="100" max="1000000" value="1000" step="100" />
89
89
  </div>
90
90
  <div class="waveform-canvas"></div>
91
91
  </article>
@@ -134,4 +134,3 @@ export default ssg.page(import.meta.url, async orb => ({
134
134
  </section>
135
135
  `,
136
136
  }))
137
-
@@ -0,0 +1,72 @@
1
+
2
+ import {Driver} from "../../../../driver/driver.js"
3
+ import {DecoderSource} from "../../../../driver/fns/schematic.js"
4
+
5
+ export const PEAK_LEVELS = [2048, 1024, 512, 256, 128, 64, 32] as const
6
+
7
+ export async function collectPeakLevels(driver: Driver, source: DecoderSource) {
8
+ const duration = (await driver.getAudioDuration(source)) ?? 0
9
+ const readable = driver.decodeAudio({source}).readable
10
+ const finestSamplesPerPeak = PEAK_LEVELS[PEAK_LEVELS.length - 1]
11
+ const finestPeaks: number[] = []
12
+
13
+ let currentMax = 0
14
+ let sampleCount = 0
15
+ let sampleRate = 0
16
+
17
+ for await (const audioData of readable) {
18
+ sampleRate ||= audioData.sampleRate
19
+
20
+ const frames = audioData.numberOfFrames
21
+ const plane = new Float32Array(frames)
22
+ audioData.copyTo(plane, {planeIndex: 0})
23
+
24
+ for (let i = 0; i < plane.length; i++) {
25
+ const amplitude = Math.abs(plane[i]!)
26
+ if (amplitude > currentMax) currentMax = amplitude
27
+
28
+ sampleCount++
29
+ if (sampleCount >= finestSamplesPerPeak) {
30
+ finestPeaks.push(currentMax)
31
+ currentMax = 0
32
+ sampleCount = 0
33
+ }
34
+ }
35
+
36
+ audioData.close()
37
+ }
38
+
39
+ if (sampleCount > 0) finestPeaks.push(currentMax)
40
+
41
+ const base = new Float32Array(finestPeaks)
42
+ const levels = PEAK_LEVELS.map(samplesPerPeak => {
43
+ const factor = Math.max(1, Math.round(samplesPerPeak / finestSamplesPerPeak))
44
+ const peaks = factor === 1 ? base : downsampleMax(base, factor)
45
+ return {
46
+ samplesPerPeak,
47
+ peaks,
48
+ peaksPerSecond: sampleRate > 0 ? sampleRate / samplesPerPeak : 0,
49
+ }
50
+ })
51
+
52
+ return {duration, levels}
53
+ }
54
+
55
+ function downsampleMax(peaks: Float32Array, factor: number) {
56
+ const downsampled = new Float32Array(Math.ceil(peaks.length / factor))
57
+
58
+ for (let i = 0; i < downsampled.length; i++) {
59
+ let maxPeak = 0
60
+ const start = i * factor
61
+ const end = Math.min(start + factor, peaks.length)
62
+
63
+ for (let j = start; j < end; j++) {
64
+ if (peaks[j]! > maxPeak) maxPeak = peaks[j]!
65
+ }
66
+
67
+ downsampled[i] = maxPeak
68
+ }
69
+
70
+ return downsampled
71
+ }
72
+
@@ -0,0 +1,45 @@
1
+
2
+ export function renderTile(
3
+ peaks: Float32Array,
4
+ opts: {
5
+ width: number
6
+ height: number
7
+ color: string
8
+ }
9
+ ) {
10
+ const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1
11
+ const canvas = document.createElement("canvas")
12
+ canvas.width = opts.width * dpr
13
+ canvas.height = opts.height * dpr
14
+ canvas.style.width = `${opts.width}px`
15
+ canvas.style.height = `${opts.height}px`
16
+
17
+ const ctx = canvas.getContext("2d")
18
+ if (!ctx) return canvas
19
+
20
+ ctx.scale(dpr, dpr)
21
+ ctx.fillStyle = opts.color
22
+
23
+ const centerY = opts.height / 2
24
+ const columns = Math.max(1, opts.width)
25
+ const peaksPerPixel = peaks.length / columns
26
+
27
+ for (let px = 0; px < columns; px++) {
28
+ const startIndex = Math.floor(px * peaksPerPixel)
29
+ const endIndex = Math.max(
30
+ startIndex + 1,
31
+ Math.floor((px + 1) * peaksPerPixel)
32
+ )
33
+
34
+ let maxPeak = 0
35
+ for (let i = startIndex; i < endIndex && i < peaks.length; i++) {
36
+ if (peaks[i]! > maxPeak) maxPeak = peaks[i]!
37
+ }
38
+
39
+ const barHeight = maxPeak * opts.height
40
+ ctx.fillRect(px, centerY - barHeight / 2, 1, barHeight)
41
+ }
42
+
43
+ return canvas
44
+ }
45
+
@@ -0,0 +1,24 @@
1
+ export interface WaveformTileData {
2
+ startTime: number
3
+ endTime: number
4
+ peaks: Float32Array
5
+ canvas: HTMLCanvasElement
6
+ }
7
+
8
+ export interface WaveformOptions {
9
+ tileSize?: number
10
+ zoom?: number
11
+ tileWidth?: number
12
+ tileHeight?: number
13
+ preloadMargin?: number
14
+ color?: string
15
+ onChange?: (tiles: WaveformTileData[]) => void
16
+ }
17
+
18
+ export type WaveformTimeRange = [start: number, end: number]
19
+
20
+ export type WaveformPeakLevel = {
21
+ samplesPerPeak: number
22
+ peaks: Float32Array
23
+ peaksPerSecond: number
24
+ }
@@ -0,0 +1,152 @@
1
+
2
+ import {renderTile} from "./parts/render.js"
3
+ import {Driver} from "../../../driver/driver.js"
4
+ import {collectPeakLevels} from "./parts/collect.js"
5
+ import {DecoderSource} from "../../../driver/fns/schematic.js"
6
+ import {WaveformOptions, WaveformPeakLevel, WaveformTileData, WaveformTimeRange} from "./parts/types.js"
7
+
8
+ const MAX_TILE_WIDTH = 4096
9
+
10
+ export class Waveform {
11
+ #tiles = new Map<number, WaveformTileData>()
12
+ #activeRange: WaveformTimeRange = [0, 0]
13
+
14
+ #zoom
15
+ #levels
16
+ #onChange
17
+ #updateQueued = false
18
+
19
+ readonly color
20
+ readonly duration
21
+ readonly tileSize
22
+ readonly tileHeight
23
+ readonly preloadMargin
24
+
25
+ private constructor(levels: WaveformPeakLevel[], duration: number, options: WaveformOptions) {
26
+ this.#levels = levels
27
+ this.duration = duration
28
+ this.tileSize = options.tileSize ?? 1
29
+ this.#zoom = options.zoom ?? ((options.tileWidth ?? 256) / this.tileSize)
30
+ this.tileHeight = options.tileHeight ?? 96
31
+ this.preloadMargin = options.preloadMargin ?? 2
32
+ this.color = options.color ?? "rgb(3, 148, 129)"
33
+ this.#onChange = options.onChange
34
+ }
35
+
36
+ static async init(driver: Driver, source: DecoderSource, options: WaveformOptions = {}) {
37
+ const {duration, levels} = await collectPeakLevels(driver, source)
38
+ return new Waveform(levels, duration, options)
39
+ }
40
+
41
+ set zoom(value: number) {
42
+ const next = Math.max(1, value)
43
+ if (next === this.#zoom)
44
+ return
45
+
46
+ this.#zoom = next
47
+ this.#tiles.clear()
48
+ this.#queueUpdate()
49
+ }
50
+
51
+ get zoom() {
52
+ return this.#zoom
53
+ }
54
+
55
+ #computeActiveRange([start, end]: WaveformTimeRange, margin = 1): WaveformTimeRange {
56
+ const visibleSize = end - start
57
+ return [
58
+ Math.max(0, start - visibleSize * margin),
59
+ Math.min(this.duration, end + visibleSize * margin),
60
+ ]
61
+ }
62
+
63
+ set range(visibleRange: WaveformTimeRange) {
64
+ const [visibleStart, visibleEnd] = visibleRange
65
+ const visibleSize = visibleEnd - visibleStart
66
+ const [activeStart, activeEnd] = this.#activeRange
67
+
68
+ const leftTrigger = activeStart + visibleSize
69
+ const rightTrigger = activeEnd - visibleSize
70
+
71
+ if (visibleStart >= leftTrigger && visibleEnd <= rightTrigger) return
72
+
73
+ this.#activeRange = this.#computeActiveRange(visibleRange, this.preloadMargin)
74
+ this.#queueUpdate()
75
+ }
76
+
77
+ #queueUpdate() {
78
+ if (this.#updateQueued) return
79
+ this.#updateQueued = true
80
+
81
+ queueMicrotask(() => {
82
+ this.#updateQueued = false
83
+ this.#generateTiles()
84
+ })
85
+ }
86
+
87
+ #generateTiles() {
88
+ const [rangeStart, rangeEnd] = this.#activeRange
89
+ const neededStarts = new Set<number>()
90
+ const level = this.#levelForZoom()
91
+
92
+ const firstStart = Math.max(0, Math.floor(rangeStart / this.tileSize) * this.tileSize)
93
+ const lastStart = Math.min(this.duration, rangeEnd)
94
+
95
+ for (let startTime = firstStart; startTime <= lastStart; startTime += this.tileSize) {
96
+ neededStarts.add(startTime)
97
+ }
98
+
99
+ for (const startTime of neededStarts) {
100
+ if (!this.#tiles.has(startTime)) {
101
+ const endTime = Math.min(startTime + this.tileSize, this.duration)
102
+ this.#tiles.set(startTime, this.#buildTileData(startTime, endTime, level))
103
+ }
104
+ }
105
+
106
+ for (const startTime of this.#tiles.keys()) {
107
+ if (!neededStarts.has(startTime)) this.#tiles.delete(startTime)
108
+ }
109
+
110
+ this.#emit()
111
+ }
112
+
113
+ #buildTileData(startTime: number, endTime: number, level: WaveformPeakLevel): WaveformTileData {
114
+ const peaks = this.#slicePeaks(level, startTime, endTime)
115
+ return {
116
+ startTime,
117
+ endTime,
118
+ peaks,
119
+ canvas: renderTile(peaks, {
120
+ width: this.#tilePixelWidth(startTime, endTime),
121
+ height: this.tileHeight,
122
+ color: this.color,
123
+ }),
124
+ }
125
+ }
126
+
127
+ #levelForZoom() {
128
+ return this.#levels.find(level => level.peaksPerSecond >= this.#zoom)
129
+ ?? this.#levels[this.#levels.length - 1]!
130
+ }
131
+
132
+ #slicePeaks(level: WaveformPeakLevel, startTime: number, endTime: number) {
133
+ if (!level.peaksPerSecond) return new Float32Array()
134
+ const from = Math.max(0, Math.floor(startTime * level.peaksPerSecond))
135
+ const to = Math.max(from + 1, Math.min(level.peaks.length, Math.ceil(endTime * level.peaksPerSecond)))
136
+ return level.peaks.slice(from, to)
137
+ }
138
+
139
+ #tilePixelWidth(startTime: number, endTime: number) {
140
+ return Math.min(MAX_TILE_WIDTH, Math.max(1, Math.ceil((endTime - startTime) * this.#zoom)))
141
+ }
142
+
143
+ #emit() {
144
+ if (!this.#onChange) return
145
+ this.#onChange([...this.#tiles.values()].sort((a, b) => a.startTime - b.startTime))
146
+ }
147
+
148
+ getTiles() {
149
+ return this.#tiles
150
+ }
151
+ }
152
+
@@ -1,61 +0,0 @@
1
- import WaveSurfer from "wavesurfer.js"
2
-
3
- import {Driver} from "../../driver/driver.js"
4
- import {DecoderSource} from "../../driver/fns/schematic.js"
5
-
6
- export class Waveform {
7
- wavesurfer: WaveSurfer
8
-
9
- constructor(peaks: number[], container: HTMLElement, duration: number) {
10
- this.wavesurfer = WaveSurfer.create({
11
- container,
12
- waveColor: 'rgb(200, 0, 200)',
13
- progressColor: 'rgb(100, 0, 100)',
14
- barWidth: 10,
15
- barRadius: 10,
16
- barGap: 2,
17
- peaks: [peaks],
18
- duration
19
- })
20
- }
21
-
22
- static async init(driver: Driver, source: DecoderSource, container: HTMLElement) {
23
- const reader = driver.decodeAudio({source}).readable.getReader()
24
-
25
- const peaks: number[] = []
26
- let buffer: number[] = []
27
- const samplesPerPeak = 1024
28
- const duration = await driver.getAudioDuration(source)
29
-
30
- while (true) {
31
- const {done, value: audioData} = await reader.read()
32
- if (done) break
33
-
34
- const frames = audioData.numberOfFrames
35
- const plane = new Float32Array(frames)
36
- audioData.copyTo(plane, {planeIndex: 0}) // Use left channel only
37
-
38
- for (let i = 0; i < plane.length; i++) {
39
- buffer.push(plane[i])
40
- if (buffer.length >= samplesPerPeak) {
41
- const chunk = buffer.splice(0, samplesPerPeak)
42
- const min = Math.min(...chunk)
43
- const max = Math.max(...chunk)
44
- peaks.push(min, max)
45
- }
46
- }
47
-
48
- audioData.close()
49
- }
50
-
51
- return new Waveform(peaks, container, duration ?? 0)
52
- }
53
-
54
- // set zoom(value: number) {
55
- // this.wavesurfer.zoom(value)
56
- // }
57
-
58
- set width(value: number) {
59
- this.wavesurfer.setOptions({width: value})
60
- }
61
- }
@@ -23,6 +23,8 @@ let exportState = null;
23
23
  const setProgress = (card, state) => {
24
24
  const progress = card.querySelector(".progress");
25
25
  const status = card.querySelector(".status");
26
+ if (!progress || !status)
27
+ return;
26
28
  if (state === "running") {
27
29
  progress.removeAttribute("value");
28
30
  status.textContent = "running";
@@ -1 +1 @@
1
- {"version":3,"file":"demo.bundle.js","sourceRoot":"","sources":["../../s/demo/demo.bundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"demo.bundle.js","sourceRoot":"","sources":["../../s/demo/demo.bundle.ts"],"names":[],"mappings":"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"}