@editframe/elements 0.5.0-beta.3 → 0.5.0-beta.5

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/dist/editor/msToTimeCode.mjs +15 -0
  2. package/dist/editor/util/EncodedAsset/EncodedAsset.mjs +537 -0
  3. package/dist/editor/util/MP4File.mjs +161 -0
  4. package/dist/elements/elements/CrossUpdateController.mjs +16 -0
  5. package/dist/elements/elements/EFAudio.mjs +37 -0
  6. package/dist/elements/elements/EFCaptions.mjs +172 -0
  7. package/dist/elements/elements/EFImage.mjs +67 -0
  8. package/dist/elements/elements/EFMedia.mjs +255 -0
  9. package/dist/elements/elements/EFSourceMixin.mjs +57 -0
  10. package/dist/elements/elements/EFTemporal.mjs +186 -0
  11. package/dist/elements/elements/EFTimegroup.mjs +230 -0
  12. package/dist/elements/elements/EFTimeline.mjs +12 -0
  13. package/dist/elements/elements/EFVideo.mjs +123 -0
  14. package/dist/elements/elements/EFWaveform.mjs +203 -0
  15. package/dist/elements/elements/FetchMixin.mjs +30 -0
  16. package/dist/elements/elements/TimegroupController.mjs +20 -0
  17. package/dist/elements/elements/durationConverter.mjs +8 -0
  18. package/dist/elements/elements/parseTimeToMs.mjs +13 -0
  19. package/dist/elements/elements/util.mjs +11 -0
  20. package/dist/elements/elements.css.mjs +1 -0
  21. package/dist/elements/elements.mjs +11 -0
  22. package/dist/elements/gui/EFFilmstrip.mjs +680 -0
  23. package/dist/elements/gui/EFWorkbench.mjs +234 -0
  24. package/dist/elements/gui/TWMixin.css.mjs +4 -0
  25. package/dist/elements/gui/TWMixin.mjs +27 -0
  26. package/dist/style.css +754 -0
  27. package/dist/util/awaitMicrotask.mjs +8 -0
  28. package/dist/util/memoize.mjs +15 -0
  29. package/package.json +9 -2
  30. package/dist/editframe-elements.css +0 -1
  31. package/dist/editframe-elements.mjs +0 -9089
  32. package/dist/editframe-elements.umd.js +0 -288
@@ -0,0 +1,203 @@
1
+ import { EFAudio } from "./EFAudio.mjs";
2
+ import { html, LitElement } from "lit";
3
+ import { property, customElement } from "lit/decorators.js";
4
+ import { EFVideo } from "./EFVideo.mjs";
5
+ import { EFTemporal } from "./EFTemporal.mjs";
6
+ import { CrossUpdateController } from "./CrossUpdateController.mjs";
7
+ import { TWMixin } from "../gui/TWMixin.mjs";
8
+ import { Task } from "@lit/task";
9
+ import * as d3 from "d3";
10
+ import { createRef, ref } from "lit/directives/ref.js";
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __decorateClass = (decorators, target, key, kind) => {
14
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
15
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
16
+ if (decorator = decorators[i])
17
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
18
+ if (kind && result)
19
+ __defProp(target, key, result);
20
+ return result;
21
+ };
22
+ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.svgRef = createRef();
26
+ this.mode = "bars";
27
+ this.color = "currentColor";
28
+ this.frameTask = new Task(this, {
29
+ args: () => [this.target.audioBufferTask.status],
30
+ task: async () => {
31
+ await this.target.audioBufferTask.taskComplete;
32
+ }
33
+ });
34
+ }
35
+ createRenderRoot() {
36
+ return this;
37
+ }
38
+ render() {
39
+ return html` <svg ${ref(this.svgRef)} class="h-full w-full" store></svg> `;
40
+ }
41
+ connectedCallback() {
42
+ super.connectedCallback();
43
+ if (this.target) {
44
+ new CrossUpdateController(this.target, this);
45
+ }
46
+ }
47
+ drawBars(svg, frequencyData) {
48
+ const waveWidth = svg.clientWidth * devicePixelRatio;
49
+ const waveHeight = svg.clientHeight;
50
+ const baseline = waveHeight / 2;
51
+ const barX = d3.scaleBand().domain(d3.range(frequencyData.length).map(String)).rangeRound([0, waveWidth]).paddingInner(0.5).paddingOuter(0.01);
52
+ const height = d3.scaleLinear().domain([0, 255]).range([0, baseline]);
53
+ const bars = d3.select(svg).selectAll("rect").data(frequencyData);
54
+ bars.enter().append("rect").merge(bars).attr("x", (_, i) => barX(String(i))).attr("y", (value) => baseline - height(value)).attr("width", barX.bandwidth()).attr("height", (value) => height(value) * 2);
55
+ bars.exit().remove();
56
+ }
57
+ drawBricks(svg, frequencyData) {
58
+ const waveWidth = svg.clientWidth * devicePixelRatio;
59
+ const waveHeight = svg.clientHeight * devicePixelRatio;
60
+ const brickWidth = waveWidth / frequencyData.length;
61
+ const brickHeightFactor = waveHeight / 255;
62
+ const brickPadding = 2;
63
+ d3.select(svg).selectAll("rect.brick").data(frequencyData).join("rect").attr("class", "brick").attr("x", (_d, i) => i * brickWidth).attr("y", (d) => waveHeight - d * brickHeightFactor).attr("width", brickWidth - brickPadding).attr("height", (d) => d * brickHeightFactor);
64
+ }
65
+ drawLine(svg, frequencyData) {
66
+ const waveWidth = svg.clientWidth * devicePixelRatio;
67
+ const waveHeight = svg.clientHeight * devicePixelRatio;
68
+ const xScale = d3.scaleLinear().domain([0, frequencyData.length - 1]).range([0, waveWidth]);
69
+ const yScale = d3.scaleLinear().domain([0, 255]).range([waveHeight, 0]);
70
+ const lineGenerator = d3.line().x((_d, i) => xScale(i)).y((d) => yScale(d)).curve(d3.curveCardinal);
71
+ d3.select(svg).selectAll("path").data([frequencyData]).join("path").attr("d", lineGenerator).attr("fill", "none");
72
+ }
73
+ drawRoundBars(svg, frequencyData) {
74
+ const waveWidth = svg.clientWidth * devicePixelRatio;
75
+ const waveHeight = svg.clientHeight;
76
+ const baseline = waveHeight / 2;
77
+ const barX = d3.scaleBand().domain(d3.range(frequencyData.length).map(String)).rangeRound([0, waveWidth]).paddingInner(0.5).paddingOuter(0.01);
78
+ const height = d3.scaleLinear().domain([0, 255]).range([0, baseline]);
79
+ const bars = d3.select(svg).selectAll("rect").data(frequencyData);
80
+ bars.enter().append("rect").merge(bars).attr("x", (_, i) => barX(String(i))).attr("y", (value) => baseline - height(value)).attr("width", barX.bandwidth()).attr("height", (value) => height(value) * 2).attr("fill", "white").attr("rx", barX.bandwidth() * 0.1).attr("ry", barX.bandwidth() * 0.1);
81
+ bars.exit().remove();
82
+ }
83
+ drawEqualizer(svg, frequencyData) {
84
+ const waveWidth = svg.clientWidth * devicePixelRatio;
85
+ const waveHeight = svg.clientHeight * devicePixelRatio;
86
+ const barWidth = waveWidth / frequencyData.length;
87
+ const barPadding = 1;
88
+ const heightScale = d3.scaleLinear().domain([0, 255]).range([0, waveHeight]);
89
+ d3.select(svg).selectAll("rect.equalizerBar").data(frequencyData).join("rect").attr("class", "equalizerBar").attr("x", (d, i) => i * barWidth + barPadding / 2).attr("y", (d) => waveHeight - heightScale(d)).attr("width", barWidth - barPadding).attr("height", (d) => heightScale(d));
90
+ svg.selectAll("rect.equalizerBar").transition().duration(100).attr("y", (d) => waveHeight - heightScale(d)).attr("height", (d) => heightScale(d));
91
+ }
92
+ drawCurve(svg, frequencyData) {
93
+ const waveWidth = svg.clientWidth * devicePixelRatio;
94
+ const waveHeight = svg.clientHeight * devicePixelRatio;
95
+ const xScale = d3.scaleLinear().domain([0, frequencyData.length - 1]).range([0, waveWidth]);
96
+ const yScale = d3.scaleLinear().domain([0, 255]).range([waveHeight, 0]);
97
+ const curveGenerator = d3.line().x((_, i) => xScale(i)).y((d) => yScale(d)).curve(d3.curveNatural);
98
+ d3.select(svg).selectAll("path.curve").data([frequencyData]).join("path").attr("class", "curve").attr("d", curveGenerator).attr("fill", "none");
99
+ }
100
+ drawPixel(svg, frequencyData) {
101
+ const waveWidth = svg.clientWidth * devicePixelRatio;
102
+ const waveHeight = svg.clientHeight;
103
+ const baseline = waveHeight / 2;
104
+ const barX = d3.scaleBand().domain(d3.range(frequencyData.length).map(String)).rangeRound([0, waveWidth]).paddingInner(0.01).paddingOuter(0.01);
105
+ const height = d3.scaleLinear().domain([0, 255]).range([0, baseline]);
106
+ const bars = d3.select(svg).selectAll("rect").data(frequencyData);
107
+ bars.enter().append("rect").merge(bars).attr("x", (_, i) => barX(String(i))).attr("y", (value) => baseline - height(value)).attr("width", barX.bandwidth()).attr("height", (value) => height(value) * 2);
108
+ bars.exit().remove();
109
+ }
110
+ drawWave(svg, frequencyData) {
111
+ const waveWidth = svg.clientWidth * devicePixelRatio;
112
+ const waveHeight = svg.clientHeight;
113
+ const baseline = waveHeight / 2;
114
+ const barX = d3.scaleBand().domain(d3.range(frequencyData.length).map(String)).rangeRound([0, waveWidth]);
115
+ const height = d3.scaleLinear().domain([0, 255]).range([0, baseline]);
116
+ const bars = d3.select(svg).selectAll("rect").data(frequencyData);
117
+ bars.enter().append("rect").merge(bars).attr("x", (_, i) => barX(String(i))).attr("y", (value) => baseline - height(value)).attr("width", barX.bandwidth()).attr("height", (value) => height(value) * 2);
118
+ bars.exit().remove();
119
+ }
120
+ update(arg) {
121
+ super.update(arg);
122
+ }
123
+ async updated() {
124
+ const svg = this.svgRef.value;
125
+ if (!svg) {
126
+ return;
127
+ }
128
+ if (!this.target.audioBufferTask.value) {
129
+ return;
130
+ }
131
+ if (this.target.ownCurrentTimeMs > 0) {
132
+ const audioContext = new OfflineAudioContext(1, 48e3 / 25, 48e3);
133
+ const audioBufferSource = audioContext.createBufferSource();
134
+ audioBufferSource.buffer = this.target.audioBufferTask.value.buffer;
135
+ const analyser = audioContext.createAnalyser();
136
+ analyser.fftSize = 256;
137
+ audioBufferSource.connect(analyser);
138
+ audioBufferSource.start(
139
+ 0,
140
+ Math.max(
141
+ 0,
142
+ (this.target.ownCurrentTimeMs - this.target.audioBufferTask.value.startOffsetMs) / 1e3
143
+ ),
144
+ 48e3 / 1e3
145
+ );
146
+ await audioContext.startRendering();
147
+ const frequencyData = new Uint8Array(analyser.frequencyBinCount);
148
+ analyser.getByteFrequencyData(frequencyData);
149
+ const rect = this.getBoundingClientRect();
150
+ svg.setAttribute("width", (rect.width * devicePixelRatio).toString());
151
+ svg.setAttribute("height", (rect.height * devicePixelRatio).toString());
152
+ switch (this.mode) {
153
+ case "bars":
154
+ this.drawBars(svg, frequencyData);
155
+ break;
156
+ case "bricks":
157
+ this.drawBricks(svg, frequencyData);
158
+ break;
159
+ case "curve":
160
+ this.drawCurve(svg, frequencyData);
161
+ break;
162
+ case "line":
163
+ this.drawLine(svg, frequencyData);
164
+ break;
165
+ case "pixel":
166
+ this.drawPixel(svg, frequencyData);
167
+ break;
168
+ case "wave":
169
+ this.drawWave(svg, frequencyData);
170
+ break;
171
+ case "roundBars":
172
+ this.drawRoundBars(svg, frequencyData);
173
+ break;
174
+ case "equalizer":
175
+ this.drawEqualizer(svg, frequencyData);
176
+ break;
177
+ }
178
+ }
179
+ }
180
+ get target() {
181
+ const target = document.querySelector(this.getAttribute("target") ?? "");
182
+ if (target instanceof EFAudio || target instanceof EFVideo) {
183
+ return target;
184
+ }
185
+ throw new Error("Invalid target, must be an EFAudio element");
186
+ }
187
+ };
188
+ EFWaveform.styles = [];
189
+ __decorateClass([
190
+ property({
191
+ type: String,
192
+ attribute: "mode"
193
+ })
194
+ ], EFWaveform.prototype, "mode", 2);
195
+ __decorateClass([
196
+ property({ type: String })
197
+ ], EFWaveform.prototype, "color", 2);
198
+ EFWaveform = __decorateClass([
199
+ customElement("ef-waveform")
200
+ ], EFWaveform);
201
+ export {
202
+ EFWaveform
203
+ };
@@ -0,0 +1,30 @@
1
+ import { consume } from "@lit/context";
2
+ import { fetchContext } from "../gui/EFWorkbench.mjs";
3
+ import { state } from "lit/decorators/state.js";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __decorateClass = (decorators, target, key, kind) => {
7
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
8
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
9
+ if (decorator = decorators[i])
10
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
11
+ if (kind && result)
12
+ __defProp(target, key, result);
13
+ return result;
14
+ };
15
+ function FetchMixin(superClass) {
16
+ class FetchElement extends superClass {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.fetch = fetch.bind(window);
20
+ }
21
+ }
22
+ __decorateClass([
23
+ consume({ context: fetchContext, subscribe: true }),
24
+ state()
25
+ ], FetchElement.prototype, "fetch", 2);
26
+ return FetchElement;
27
+ }
28
+ export {
29
+ FetchMixin
30
+ };
@@ -0,0 +1,20 @@
1
+ class TimegroupController {
2
+ constructor(host, child) {
3
+ this.host = host;
4
+ this.child = child;
5
+ this.host.addController(this);
6
+ }
7
+ remove() {
8
+ this.host.removeController(this);
9
+ }
10
+ hostDisconnected() {
11
+ this.host.removeController(this);
12
+ }
13
+ hostUpdated() {
14
+ this.child.requestUpdate();
15
+ this.child.currentTimeMs = this.host.currentTimeMs - (this.child.startTimeMs ?? 0);
16
+ }
17
+ }
18
+ export {
19
+ TimegroupController
20
+ };
@@ -0,0 +1,8 @@
1
+ import { parseTimeToMs } from "./parseTimeToMs.mjs";
2
+ const durationConverter = {
3
+ fromAttribute: (value) => parseTimeToMs(value),
4
+ toAttribute: (value) => `${value}s`
5
+ };
6
+ export {
7
+ durationConverter
8
+ };
@@ -0,0 +1,13 @@
1
+ const parseTimeToMs = (time) => {
2
+ if (time.endsWith("ms")) {
3
+ return parseFloat(time);
4
+ }
5
+ if (time.endsWith("s")) {
6
+ return parseFloat(time) * 1e3;
7
+ } else {
8
+ throw new Error("Time must be in milliseconds or seconds (10s, 10000ms)");
9
+ }
10
+ };
11
+ export {
12
+ parseTimeToMs
13
+ };
@@ -0,0 +1,11 @@
1
+ import { EFTimegroup } from "./EFTimegroup.mjs";
2
+ const getStartTimeMs = (element) => {
3
+ const nearestTimeGroup = element.closest("ef-timegroup");
4
+ if (!(nearestTimeGroup instanceof EFTimegroup)) {
5
+ return 0;
6
+ }
7
+ return nearestTimeGroup.startTimeMs;
8
+ };
9
+ export {
10
+ getStartTimeMs
11
+ };
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,11 @@
1
+ import "./elements.css.mjs";
2
+ import "./elements/EFTimegroup.mjs";
3
+ import "./elements/EFTimeline.mjs";
4
+ import "./elements/EFImage.mjs";
5
+ import "./elements/EFAudio.mjs";
6
+ import "./elements/EFVideo.mjs";
7
+ import "./elements/EFCaptions.mjs";
8
+ import "./elements/EFWaveform.mjs";
9
+ import "./gui/EFWorkbench.mjs";
10
+ import "./gui/EFFilmstrip.mjs";
11
+ window.EF_REGISTERED = true;