wavesurfer.js 7.0.0-alpha.0 → 7.0.0-alpha.10

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 (57) hide show
  1. package/README.md +13 -15
  2. package/dist/base-plugin.d.ts +4 -3
  3. package/dist/base-plugin.js +3 -2
  4. package/dist/decoder.d.ts +2 -4
  5. package/dist/decoder.js +16 -16
  6. package/dist/event-emitter.d.ts +3 -1
  7. package/dist/event-emitter.js +6 -2
  8. package/dist/index.d.ts +43 -18
  9. package/dist/index.js +105 -44
  10. package/dist/player-webaudio.js +5 -4
  11. package/dist/player.d.ts +11 -2
  12. package/dist/player.js +50 -4
  13. package/dist/plugins/multitrack.d.ts +46 -0
  14. package/dist/plugins/multitrack.js +274 -0
  15. package/dist/plugins/regions.d.ts +11 -6
  16. package/dist/plugins/regions.js +106 -74
  17. package/dist/plugins/timeline.d.ts +29 -0
  18. package/dist/plugins/timeline.js +119 -0
  19. package/dist/plugins/xmultitrack.d.ts +44 -0
  20. package/dist/plugins/xmultitrack.js +260 -0
  21. package/dist/react/useWavesurfer.d.ts +5 -0
  22. package/dist/react/useWavesurfer.js +20 -0
  23. package/dist/renderer.d.ts +9 -5
  24. package/dist/renderer.js +137 -91
  25. package/dist/timer.d.ts +2 -1
  26. package/dist/timer.js +6 -1
  27. package/dist/wavesurfer.Multitrack.min.js +1 -0
  28. package/dist/wavesurfer.Regions.min.js +1 -0
  29. package/dist/wavesurfer.Timeline.min.js +1 -0
  30. package/dist/wavesurfer.min.js +1 -0
  31. package/package.json +19 -5
  32. package/.eslintrc.json +0 -24
  33. package/.prettierrc +0 -8
  34. package/examples/audio.ogg +0 -0
  35. package/examples/bars.js +0 -19
  36. package/examples/basic.js +0 -8
  37. package/examples/gradient.js +0 -28
  38. package/examples/regions.js +0 -63
  39. package/examples/video.js +0 -19
  40. package/examples/webaudio.js +0 -14
  41. package/src/base-plugin.ts +0 -20
  42. package/src/decoder.ts +0 -41
  43. package/src/event-emitter.ts +0 -35
  44. package/src/fetcher.ts +0 -7
  45. package/src/index.ts +0 -252
  46. package/src/player-webaudio.ts +0 -34
  47. package/src/player.ts +0 -50
  48. package/src/plugins/regions.ts +0 -240
  49. package/src/renderer.ts +0 -250
  50. package/src/timer.ts +0 -27
  51. package/tsconfig.json +0 -105
  52. package/tutorial/index.html +0 -47
  53. package/tutorial/src/editor.js +0 -70
  54. package/tutorial/src/init.js +0 -66
  55. package/tutorial/src/url.js +0 -25
  56. package/tutorial/style.css +0 -211
  57. package/yarn-error.log +0 -1049
package/dist/renderer.js CHANGED
@@ -1,7 +1,17 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import EventEmitter from './event-emitter.js';
2
11
  class Renderer extends EventEmitter {
3
12
  constructor(options) {
4
13
  super();
14
+ this.timeout = null;
5
15
  this.options = options;
6
16
  let container = null;
7
17
  if (typeof this.options.container === 'string') {
@@ -17,24 +27,24 @@ class Renderer extends EventEmitter {
17
27
  const shadow = div.attachShadow({ mode: 'open' });
18
28
  shadow.innerHTML = `
19
29
  <style>
30
+ :host {
31
+ user-select: none;
32
+ }
20
33
  :host .scroll {
21
34
  overflow-x: auto;
22
- overflow-y: visible;
23
- user-select: none;
35
+ overflow-y: hidden;
24
36
  width: 100%;
25
- height: ${this.options.height}px;
26
37
  position: relative;
27
38
  }
28
39
  :host .wrapper {
29
40
  position: relative;
30
41
  width: fit-content;
31
42
  min-width: 100%;
32
- height: 100%;
33
43
  z-index: 2;
34
44
  }
35
45
  :host canvas {
36
46
  display: block;
37
- height: 100%;
47
+ height: ${this.options.height}px;
38
48
  min-width: 100%;
39
49
  image-rendering: pixelated;
40
50
  }
@@ -43,7 +53,6 @@ class Renderer extends EventEmitter {
43
53
  z-index: 2;
44
54
  top: 0;
45
55
  left: 0;
46
- height: 100%;
47
56
  pointer-events: none;
48
57
  clip-path: inset(100%);
49
58
  }
@@ -53,7 +62,8 @@ class Renderer extends EventEmitter {
53
62
  top: 0;
54
63
  left: 0;
55
64
  height: 100%;
56
- border-right: 1px solid ${this.options.progressColor};
65
+ border-right: 1px solid ${this.options.cursorColor || this.options.progressColor};
66
+ margin-left: -1px;
57
67
  }
58
68
  </style>
59
69
 
@@ -66,7 +76,7 @@ class Renderer extends EventEmitter {
66
76
  </div>
67
77
  `;
68
78
  this.container = div;
69
- this.shadowRoot = shadow;
79
+ this.scrollContainer = shadow.querySelector('.scroll');
70
80
  this.mainCanvas = shadow.querySelector('canvas');
71
81
  this.ctx = this.mainCanvas.getContext('2d', { desynchronized: true });
72
82
  this.progressCanvas = shadow.querySelector('.progress');
@@ -79,102 +89,141 @@ class Renderer extends EventEmitter {
79
89
  this.emit('click', { relativeX });
80
90
  });
81
91
  }
92
+ getContainer() {
93
+ return this.scrollContainer.querySelector('.wrapper');
94
+ }
82
95
  destroy() {
83
96
  this.container.remove();
84
97
  }
85
- renderLinePeaks(channelData, width, height) {
86
- const { ctx } = this;
87
- ctx.clearRect(0, 0, width, height);
88
- ctx.beginPath();
89
- ctx.moveTo(0, height / 2);
90
- // Channel 0 is left, 1 is right
91
- const leftChannel = channelData[0];
92
- const isMono = channelData.length === 1;
93
- const rightChannel = isMono ? leftChannel : channelData[1];
94
- // Draw left channel in the top half of the canvas
95
- let prevX = -1;
96
- let prevY = 0;
97
- for (let i = 0, len = leftChannel.length; i < len; i++) {
98
- const x = Math.round((i / leftChannel.length) * width);
99
- const y = Math.round(((1 - leftChannel[i]) * height) / 2);
100
- if (x !== prevX || y > prevY) {
101
- ctx.lineTo(x, y);
102
- prevX = x;
103
- prevY = y;
104
- }
98
+ delay(fn, delayMs = 100) {
99
+ if (this.timeout) {
100
+ clearTimeout(this.timeout);
105
101
  }
106
- // Draw right channel in the bottom half of the canvas
107
- prevX = -1;
108
- prevY = 0;
109
- for (let i = rightChannel.length - 1; i >= 0; i--) {
110
- const x = Math.round((i / rightChannel.length) * width);
111
- const y = Math.round(((1 + rightChannel[i]) * height) / 2);
112
- if (x !== prevX || (isMono ? y < -prevY : y > prevY)) {
113
- ctx.lineTo(x, y);
114
- prevX = x;
115
- prevY = y;
116
- }
117
- }
118
- ctx.strokeStyle = ctx.fillStyle = this.options.waveColor;
119
- ctx.stroke();
120
- ctx.fill();
121
- }
122
- renderBarPeaks(channelData, width, height) {
123
- var _a, _b;
124
- const { devicePixelRatio } = window;
125
- const { ctx } = this;
126
- ctx.clearRect(0, 0, width, height);
127
- const barWidthOption = this.options.barWidth || 1;
128
- const barWidth = barWidthOption * devicePixelRatio;
129
- const barGap = ((_a = this.options.barGap) !== null && _a !== void 0 ? _a : barWidthOption / 2) * devicePixelRatio;
130
- const barRadius = (_b = this.options.barRadius) !== null && _b !== void 0 ? _b : 0;
131
- const leftChannel = channelData[0];
132
- const isMono = channelData.length === 1;
133
- const rightChannel = isMono ? leftChannel : channelData[1];
134
- const barCount = Math.floor(width / (barWidth + barGap));
135
- const leftChannelBars = new Float32Array(barCount);
136
- const rightChannelBars = new Float32Array(barCount);
137
- const barIndexScale = barCount / leftChannel.length;
138
- const leftChannelLength = leftChannel.length;
139
- for (let i = 0; i < leftChannelLength; i++) {
140
- const barIndex = Math.round(i * barIndexScale);
141
- leftChannelBars[barIndex] = Math.max(leftChannelBars[barIndex], leftChannel[i]);
142
- rightChannelBars[barIndex] = (isMono ? Math.min : Math.max)(rightChannelBars[barIndex], rightChannel[i]);
143
- }
144
- ctx.beginPath();
145
- for (let i = 0; i < barCount; i++) {
146
- const leftBarHeight = Math.max(1, Math.round((leftChannelBars[i] * height) / 2));
147
- const rightBarHeight = Math.max(1, Math.round(Math.abs(rightChannelBars[i] * height) / 2));
148
- ctx.roundRect(i * (barWidth + barGap), height / 2 - leftBarHeight, barWidth, leftBarHeight + rightBarHeight, barRadius);
149
- }
150
- ctx.fillStyle = this.options.waveColor;
151
- ctx.fill();
102
+ return new Promise((resolve) => {
103
+ this.timeout = setTimeout(() => {
104
+ resolve(fn());
105
+ }, delayMs);
106
+ });
152
107
  }
153
- render(channelData, duration, minPxPerSec = this.options.minPxPerSec) {
154
- const { devicePixelRatio } = window;
155
- const width = Math.max(this.container.clientWidth * devicePixelRatio, duration * minPxPerSec);
156
- const { height } = this.options;
157
- this.mainCanvas.width = width;
158
- this.mainCanvas.height = height;
159
- this.mainCanvas.style.width = Math.round(width / devicePixelRatio) + 'px';
160
- const renderingFn = this.options.barWidth ? this.renderBarPeaks : this.renderLinePeaks;
161
- renderingFn.call(this, channelData, width, height);
162
- this.createProgressMask();
108
+ renderPeaks(channelData, width, height) {
109
+ var _a;
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ const { devicePixelRatio } = window;
112
+ const { ctx } = this;
113
+ const barWidth = this.options.barWidth != null ? this.options.barWidth * devicePixelRatio : 1;
114
+ const barGap = this.options.barGap != null ? this.options.barGap * devicePixelRatio : this.options.barWidth ? barWidth / 2 : 0;
115
+ const barRadius = (_a = this.options.barRadius) !== null && _a !== void 0 ? _a : 0;
116
+ const leftChannel = channelData[0];
117
+ const len = leftChannel.length;
118
+ const barCount = Math.floor(width / (barWidth + barGap));
119
+ const barIndexScale = barCount / len;
120
+ const halfHeight = height / 2;
121
+ const isMono = channelData.length === 1;
122
+ const rightChannel = isMono ? leftChannel : channelData[1];
123
+ const useNegative = isMono && rightChannel.some((v) => v < 0);
124
+ const draw = (start, end) => {
125
+ let prevX = 0;
126
+ let prevLeft = 0;
127
+ let prevRight = 0;
128
+ ctx.beginPath();
129
+ ctx.fillStyle = this.options.waveColor;
130
+ // Firefox shim until 2023.04.11
131
+ if (!ctx.roundRect)
132
+ ctx.roundRect = ctx.fillRect;
133
+ for (let i = start; i < end; i++) {
134
+ const barIndex = Math.round(i * barIndexScale);
135
+ if (barIndex > prevX) {
136
+ const leftBarHeight = Math.round(prevLeft * halfHeight);
137
+ const rightBarHeight = Math.round(prevRight * halfHeight);
138
+ ctx.roundRect(prevX * (barWidth + barGap), halfHeight - leftBarHeight, barWidth, leftBarHeight + rightBarHeight || 1, barRadius);
139
+ prevX = barIndex;
140
+ prevLeft = 0;
141
+ prevRight = 0;
142
+ }
143
+ const leftValue = useNegative ? leftChannel[i] : Math.abs(leftChannel[i]);
144
+ const rightValue = useNegative ? rightChannel[i] : Math.abs(rightChannel[i]);
145
+ if (leftValue > prevLeft) {
146
+ prevLeft = leftValue;
147
+ }
148
+ // If stereo, both channels are drawn as max values
149
+ // If mono with negative values, the bottom channel will be the min negative values
150
+ if (useNegative ? rightValue < -prevRight : rightValue > prevRight) {
151
+ prevRight = rightValue < 0 ? -rightValue : rightValue;
152
+ }
153
+ }
154
+ ctx.fill();
155
+ ctx.closePath();
156
+ };
157
+ // Clear the canvas
158
+ ctx.clearRect(0, 0, width, height);
159
+ // Draw the currently visible part of the waveform
160
+ const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;
161
+ const scale = len / scrollWidth;
162
+ const start = Math.floor(scrollLeft * scale);
163
+ const end = Math.ceil((scrollLeft + clientWidth) * scale);
164
+ draw(start, end);
165
+ // Draw the progress mask
166
+ this.createProgressMask();
167
+ // Draw the rest of the waveform with a timeout for better performance
168
+ if (start > 0) {
169
+ yield this.delay(() => {
170
+ draw(0, start);
171
+ });
172
+ }
173
+ if (end < len) {
174
+ yield this.delay(() => {
175
+ draw(end, len);
176
+ });
177
+ }
178
+ // Redraw the progress mask
179
+ this.delay(() => {
180
+ this.createProgressMask();
181
+ });
182
+ });
163
183
  }
164
184
  createProgressMask() {
165
185
  const progressCtx = this.progressCanvas.getContext('2d', { desynchronized: true });
166
- if (!progressCtx) {
167
- throw new Error('Failed to get canvas context');
168
- }
186
+ // Set the canvas to the same size as the main canvas
169
187
  this.progressCanvas.width = this.mainCanvas.width;
170
188
  this.progressCanvas.height = this.mainCanvas.height;
171
189
  this.progressCanvas.style.width = this.mainCanvas.style.width;
172
190
  this.progressCanvas.style.height = this.mainCanvas.style.height;
191
+ // Copy the waveform image to the progress canvas
192
+ // The main canvas itself is used as the source image
173
193
  progressCtx.drawImage(this.mainCanvas, 0, 0);
194
+ // Set the composition method to draw only where the waveform is drawn
174
195
  progressCtx.globalCompositeOperation = 'source-in';
175
196
  progressCtx.fillStyle = this.options.progressColor;
197
+ // This rectangle acts as a mask thanks to the composition method
176
198
  progressCtx.fillRect(0, 0, this.progressCanvas.width, this.progressCanvas.height);
177
199
  }
200
+ render(audioData) {
201
+ // Determine the width of the canvas
202
+ const { devicePixelRatio } = window;
203
+ const parentWidth = this.options.fillParent ? this.scrollContainer.clientWidth * devicePixelRatio : 0;
204
+ const scrollWidth = audioData.duration * this.options.minPxPerSec;
205
+ const isScrolling = scrollWidth > parentWidth;
206
+ const width = Math.max(1, isScrolling ? scrollWidth : parentWidth);
207
+ const { height } = this.options;
208
+ this.mainCanvas.width = width;
209
+ this.mainCanvas.height = height;
210
+ this.mainCanvas.style.width = Math.floor(scrollWidth / devicePixelRatio) + 'px';
211
+ // First two channels are used
212
+ const channelData = [audioData.getChannelData(0)];
213
+ if (audioData.numberOfChannels > 1) {
214
+ channelData.push(audioData.getChannelData(1));
215
+ }
216
+ this.renderPeaks(channelData, width, height);
217
+ }
218
+ zoom(audioData, minPxPerSec) {
219
+ // Remember the current cursor position
220
+ const oldCursorPosition = this.cursor.getBoundingClientRect().left;
221
+ this.options.minPxPerSec = minPxPerSec;
222
+ this.render(audioData);
223
+ // Adjust the scroll position so that the cursor stays in the same place
224
+ const newCursortPosition = this.cursor.getBoundingClientRect().left;
225
+ this.scrollContainer.scrollLeft += newCursortPosition - oldCursorPosition;
226
+ }
178
227
  renderProgress(progress, autoCenter = false) {
179
228
  this.progressCanvas.style.clipPath = `inset(0 ${100 - progress * 100}% 0 0)`;
180
229
  this.cursor.style.left = `${progress * 100}%`;
@@ -182,12 +231,9 @@ class Renderer extends EventEmitter {
182
231
  const center = this.container.clientWidth / 2;
183
232
  const fullWidth = this.mainCanvas.clientWidth;
184
233
  if (fullWidth * progress >= center) {
185
- this.container.scrollLeft = fullWidth * progress - center;
234
+ this.scrollContainer.scrollLeft = fullWidth * progress - center;
186
235
  }
187
236
  }
188
237
  }
189
- getContainer() {
190
- return this.shadowRoot.querySelector('.scroll');
191
- }
192
238
  }
193
239
  export default Renderer;
package/dist/timer.d.ts CHANGED
@@ -4,7 +4,8 @@ type TimerEvents = {
4
4
  };
5
5
  declare class Timer extends EventEmitter<TimerEvents> {
6
6
  private unsubscribe;
7
- constructor();
7
+ start(): void;
8
+ stop(): void;
8
9
  destroy(): void;
9
10
  }
10
11
  export default Timer;
package/dist/timer.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import EventEmitter from './event-emitter.js';
2
2
  class Timer extends EventEmitter {
3
3
  constructor() {
4
- super();
4
+ super(...arguments);
5
5
  this.unsubscribe = () => undefined;
6
+ }
7
+ start() {
6
8
  this.unsubscribe = this.on('tick', () => {
7
9
  requestAnimationFrame(() => {
8
10
  this.emit('tick');
@@ -10,6 +12,9 @@ class Timer extends EventEmitter {
10
12
  });
11
13
  this.emit('tick');
12
14
  }
15
+ stop() {
16
+ this.unsubscribe();
17
+ }
13
18
  destroy() {
14
19
  this.unsubscribe();
15
20
  }
@@ -0,0 +1 @@
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Multitrack=e():t.Multitrack=e()}(WaveSurfer,(()=>(()=>{"use strict";var t={139:(t,e,i)=>{i.d(e,{Z:()=>s});const s=class{constructor(){this.eventTarget=new EventTarget}emit(t,e){const i=new CustomEvent(String(t),{detail:e});this.eventTarget.dispatchEvent(i)}on(t,e,i){const s=t=>{t instanceof CustomEvent&&e(t.detail)},n=String(t);return this.eventTarget.addEventListener(n,s,{once:i}),()=>this.eventTarget.removeEventListener(n,s)}once(t,e){return this.on(t,e,!0)}}},59:(t,e,i)=>{i.d(e,{default:()=>d});var s=i(139);class n extends s.Z{constructor(t,e){super(),this.subscriptions=[],this.wavesurfer=t.wavesurfer,this.container=t.container,this.options=e}destroy(){this.subscriptions.forEach((t=>t()))}}const r=n,o={dragSelection:!0,draggable:!0,resizable:!0},a=(t,e)=>{for(const i in e)t.style[i]=e[i]||""},h=(t,e)=>{const i=document.createElement(t);return a(i,e),i},d=class extends r{constructor(t,e){super(t,e),this.dragStart=NaN,this.regions=[],this.createdRegion=null,this.modifiedRegion=null,this.isResizingLeft=!1,this.isMoving=!1,this.handleMouseDown=t=>{(this.options.draggable||this.options.resizable||this.options.dragSelection)&&(this.dragStart=t.clientX-this.container.getBoundingClientRect().left)},this.handleMouseMove=t=>{const e=t.clientX-this.container.getBoundingClientRect().left;if(this.options.draggable&&this.modifiedRegion&&this.isMoving)return this.moveRegion(this.modifiedRegion,e-this.dragStart),void(this.dragStart=e);if(this.options.resizable&&this.modifiedRegion)this.updateRegion(this.modifiedRegion,this.isResizingLeft?e:void 0,this.isResizingLeft?void 0:e);else if(this.options.dragSelection&&!isNaN(this.dragStart)){const e=t.clientX-this.wrapper.getBoundingClientRect().left;e-this.dragStart>=10&&(this.createdRegion?this.updateRegion(this.createdRegion,this.dragStart,e):(this.container.style.pointerEvents="none",this.createdRegion=this.createRegion(this.dragStart,e)))}},this.handleMouseUp=()=>{this.createdRegion&&(this.addRegion(this.createdRegion),this.createdRegion=null),this.modifiedRegion=null,this.isMoving=!1,this.dragStart=NaN,this.container.style.pointerEvents=""},this.options=Object.assign({},o,e),this.wrapper=this.initWrapper();const i=this.wavesurfer.once("decode",(()=>{this.container.appendChild(this.wrapper)}));this.subscriptions.push(i),this.container.addEventListener("mousedown",this.handleMouseDown),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}destroy(){this.container.removeEventListener("mousedown",this.handleMouseDown),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp,!0),this.wrapper.remove(),super.destroy()}initWrapper(){return h("div",{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",zIndex:"3",pointerEvents:"none"})}createRegionElement(t,e,i=""){const s=t===e,n=h("div",{position:"absolute",left:`${t}px`,width:e-t+"px",height:"100%",backgroundColor:s?"":"rgba(0, 0, 0, 0.1)",borderRadius:"2px",boxSizing:"border-box",borderLeft:"2px solid rgba(0, 0, 0, 0.5)",borderRight:s?"":"2px solid rgba(0, 0, 0, 0.5)",transition:"background-color 0.2s ease",cursor:this.options.draggable?"move":"",pointerEvents:"all",padding:"0.2em"});n.textContent=i;const r=h("div",{position:"absolute",left:"0",width:"6px",height:"100%",cursor:this.options.resizable?"ew-resize":"",pointerEvents:"all"});n.appendChild(r);const o=r.cloneNode();return a(o,{left:"",right:"0",borderLeft:""}),n.appendChild(o),r.addEventListener("mousedown",(t=>{this.options.resizable&&(t.stopPropagation(),this.modifiedRegion=this.regions.find((t=>t.element===n))||null,this.isResizingLeft=!0,this.isMoving=!1)})),o.addEventListener("mousedown",(t=>{this.options.resizable&&(t.stopPropagation(),this.modifiedRegion=this.regions.find((t=>t.element===n))||null,this.isResizingLeft=!1,this.isMoving=!1)})),n.addEventListener("mousedown",(()=>{this.options.draggable&&(this.modifiedRegion=this.regions.find((t=>t.element===n))||null,this.isMoving=!0)})),n.addEventListener("click",(()=>{const t=this.regions.find((t=>t.element===n));t&&this.emit("region-clicked",{region:t})})),this.wrapper.appendChild(n),n}createRegion(t,e,i=""){const s=this.wavesurfer.getDuration(),n=this.wrapper.clientWidth;return t=Math.max(0,Math.min(t,n-1)),e=Math.max(0,Math.min(e,n-1)),{element:this.createRegionElement(t,e,i),start:t,end:e,startTime:t/n*s,endTime:e/n*s,title:i}}addRegion(t){this.regions.push(t),this.emit("region-created",{region:t})}updateRegion(t,e,i){const s=this.wrapper.clientWidth;null!=e&&(e=Math.max(0,Math.min(e,s)),t.start=e,t.element.style.left=`${t.start}px`,t.startTime=e/this.wrapper.clientWidth*this.wavesurfer.getDuration()),null!=i&&(i=Math.max(0,Math.min(i,s)),t.end=i,t.element.style.width=t.end-t.start+"px",t.endTime=i/this.wrapper.clientWidth*this.wavesurfer.getDuration()),this.emit("region-updated",{region:t})}moveRegion(t,e){this.updateRegion(t,t.start+e,t.end+e)}add(t,e,i="",s=""){const n=this.wavesurfer.getDuration(),r=this.wrapper.clientWidth,o=t/n*r,a=e/n*r,h=this.createRegion(o,a,i);return this.addRegion(h),s&&this.setRegionColor(h,s),h}setRegionColor(t,e){t.element.style[t.startTime===t.endTime?"borderColor":"backgroundColor"]=e}}}},e={};function i(s){var n=e[s];if(void 0!==n)return n.exports;var r=e[s]={exports:{}};return t[s](r,r.exports,i),r.exports}i.d=(t,e)=>{for(var s in e)i.o(e,s)&&!i.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:e[s]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var s={};return(()=>{i.d(s,{default:()=>u});var t=i(139);class e extends t.Z{constructor(t){super(),this.timeout=null,this.options=t;let e=null;if("string"==typeof this.options.container?e=document.querySelector(this.options.container):this.options.container instanceof HTMLElement&&(e=this.options.container),!e)throw new Error("Container not found");const i=document.createElement("div"),s=i.attachShadow({mode:"open"});s.innerHTML=`\n <style>\n :host {\n user-select: none;\n }\n :host .scroll {\n overflow-x: auto;\n overflow-y: hidden;\n width: 100%;\n position: relative;\n }\n :host .wrapper {\n position: relative;\n width: fit-content;\n min-width: 100%;\n z-index: 2;\n }\n :host canvas {\n display: block;\n height: ${this.options.height}px;\n min-width: 100%;\n image-rendering: pixelated;\n }\n :host .progress {\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n pointer-events: none;\n clip-path: inset(100%);\n }\n :host .cursor {\n position: absolute;\n z-index: 3;\n top: 0;\n left: 0;\n height: 100%;\n border-right: 1px solid ${this.options.cursorColor||this.options.progressColor};\n margin-left: -1px;\n }\n </style>\n\n <div class="scroll">\n <div class="wrapper">\n <canvas></canvas>\n <canvas class="progress"></canvas>\n <div class="cursor"></div>\n </div>\n </div>\n `,this.container=i,this.scrollContainer=s.querySelector(".scroll"),this.mainCanvas=s.querySelector("canvas"),this.ctx=this.mainCanvas.getContext("2d",{desynchronized:!0}),this.progressCanvas=s.querySelector(".progress"),this.cursor=s.querySelector(".cursor"),e.appendChild(i),this.mainCanvas.addEventListener("click",(t=>{const e=this.mainCanvas.getBoundingClientRect(),i=(t.clientX-e.left)/e.width;this.emit("click",{relativeX:i})}))}getContainer(){return this.scrollContainer.querySelector(".wrapper")}destroy(){this.container.remove()}delay(t,e=100){return this.timeout&&clearTimeout(this.timeout),new Promise((i=>{this.timeout=setTimeout((()=>{i(t())}),e)}))}renderPeaks(t,e,i){var s,n,r,o,a;return n=this,r=void 0,a=function*(){const{devicePixelRatio:n}=window,{ctx:r}=this,o=null!=this.options.barWidth?this.options.barWidth*n:1,a=null!=this.options.barGap?this.options.barGap*n:this.options.barWidth?o/2:0,h=null!==(s=this.options.barRadius)&&void 0!==s?s:0,d=t[0],l=d.length,c=Math.floor(e/(o+a))/l,u=i/2,p=1===t.length,m=p?d:t[1],g=p&&m.some((t=>t<0)),v=(t,e)=>{let i=0,s=0,n=0;r.beginPath(),r.fillStyle=this.options.waveColor,r.roundRect||(r.roundRect=r.fillRect);for(let l=t;l<e;l++){const t=Math.round(l*c);if(t>i){const e=Math.round(s*u),d=Math.round(n*u);r.roundRect(i*(o+a),u-e,o,e+d||1,h),i=t,s=0,n=0}const e=g?d[l]:Math.abs(d[l]),p=g?m[l]:Math.abs(m[l]);e>s&&(s=e),(g?p<-n:p>n)&&(n=p<0?-p:p)}r.fill(),r.closePath()};r.clearRect(0,0,e,i);const{scrollLeft:f,scrollWidth:y,clientWidth:C}=this.scrollContainer,w=l/y,b=Math.floor(f*w),x=Math.ceil((f+C)*w);v(b,x),this.createProgressMask(),b>0&&(yield this.delay((()=>{v(0,b)}))),x<l&&(yield this.delay((()=>{v(x,l)}))),this.delay((()=>{this.createProgressMask()}))},new((o=void 0)||(o=Promise))((function(t,e){function i(t){try{h(a.next(t))}catch(t){e(t)}}function s(t){try{h(a.throw(t))}catch(t){e(t)}}function h(e){var n;e.done?t(e.value):(n=e.value,n instanceof o?n:new o((function(t){t(n)}))).then(i,s)}h((a=a.apply(n,r||[])).next())}))}createProgressMask(){const t=this.progressCanvas.getContext("2d",{desynchronized:!0});this.progressCanvas.width=this.mainCanvas.width,this.progressCanvas.height=this.mainCanvas.height,this.progressCanvas.style.width=this.mainCanvas.style.width,this.progressCanvas.style.height=this.mainCanvas.style.height,t.drawImage(this.mainCanvas,0,0),t.globalCompositeOperation="source-in",t.fillStyle=this.options.progressColor,t.fillRect(0,0,this.progressCanvas.width,this.progressCanvas.height)}render(t){const{devicePixelRatio:e}=window,i=this.options.fillParent?this.scrollContainer.clientWidth*e:0,s=t.duration*this.options.minPxPerSec,n=s>i,r=Math.max(1,n?s:i),{height:o}=this.options;this.mainCanvas.width=r,this.mainCanvas.height=o,this.mainCanvas.style.width=Math.floor(s/e)+"px";const a=[t.getChannelData(0)];t.numberOfChannels>1&&a.push(t.getChannelData(1)),this.renderPeaks(a,r,o)}zoom(t,e){const i=this.cursor.getBoundingClientRect().left;this.options.minPxPerSec=e,this.render(t);const s=this.cursor.getBoundingClientRect().left;this.scrollContainer.scrollLeft+=s-i}renderProgress(t,e=!1){if(this.progressCanvas.style.clipPath=`inset(0 ${100-100*t}% 0 0)`,this.cursor.style.left=100*t+"%",e){const e=this.container.clientWidth/2,i=this.mainCanvas.clientWidth;i*t>=e&&(this.scrollContainer.scrollLeft=i*t-e)}}}const n=e;class r extends t.Z{constructor(){super(...arguments),this.unsubscribe=()=>{}}start(){this.unsubscribe=this.on("tick",(()=>{requestAnimationFrame((()=>{this.emit("tick")}))})),this.emit("tick")}stop(){this.unsubscribe()}destroy(){this.unsubscribe()}}const o=r;const a={height:128,waveColor:"#999",progressColor:"#555",minPxPerSec:0,fillParent:!0,interactive:!0};class h extends t.Z{static create(t){return new h(t)}constructor(t){var e;super(),this.plugins=[],this.subscriptions=[],this.decodedData=null,this.options=Object.assign({},a,t),this.fetcher=new class{load(t){return e=this,i=void 0,n=function*(){return fetch(t).then((t=>t.arrayBuffer()))},new((s=void 0)||(s=Promise))((function(t,r){function o(t){try{h(n.next(t))}catch(t){r(t)}}function a(t){try{h(n.throw(t))}catch(t){r(t)}}function h(e){var i;e.done?t(e.value):(i=e.value,i instanceof s?i:new s((function(t){t(i)}))).then(o,a)}h((n=n.apply(e,i||[])).next())}));var e,i,s,n}},this.decoder=new class{initAudioContext(t){this.audioCtx=new AudioContext({latencyHint:"playback",sampleRate:t})}constructor(){this.audioCtx=null;try{this.initAudioContext(3e3)}catch(t){this.initAudioContext(8e3)}}decode(t){return e=this,i=void 0,n=function*(){if(!this.audioCtx)throw new Error("AudioContext is not initialized");return this.audioCtx.decodeAudioData(t)},new((s=void 0)||(s=Promise))((function(t,r){function o(t){try{h(n.next(t))}catch(t){r(t)}}function a(t){try{h(n.throw(t))}catch(t){r(t)}}function h(e){var i;e.done?t(e.value):(i=e.value,i instanceof s?i:new s((function(t){t(i)}))).then(o,a)}h((n=n.apply(e,i||[])).next())}));var e,i,s,n}destroy(){var t;null===(t=this.audioCtx)||void 0===t||t.close(),this.audioCtx=null}},this.timer=new o,this.player=new class{constructor({media:t,autoplay:e}){this.isExternalMedia=!1,this.hasPlayedOnce=!1,t?(this.media=t,this.isExternalMedia=!0):this.media=document.createElement("audio");const i=this.on("play",(()=>{this.hasPlayedOnce=!0,i()}));e&&(this.media.autoplay=!0)}on(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e)}destroy(){this.media.pause(),this.isExternalMedia||this.media.remove()}loadUrl(t){this.media.src=t}getCurrentTime(){return this.media.currentTime}play(){this.media.play()}pause(){this.media.pause()}isPlaying(){return this.media.currentTime>0&&!this.media.paused&&!this.media.ended}seekTo(t){if(this.media){const{hasPlayedOnce:e}=this;e||this.media.play(),this.media.currentTime=t,e||this.media.pause()}}getDuration(){return this.media.duration}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}setPlaybackRate(t,e){null!=e&&(this.media.preservesPitch=e),this.media.playbackRate=t}}({media:this.options.media,autoplay:this.options.autoplay}),this.renderer=new n({container:this.options.container,height:this.options.height,waveColor:this.options.waveColor,progressColor:this.options.progressColor,cursorColor:this.options.cursorColor,minPxPerSec:this.options.minPxPerSec,fillParent:this.options.fillParent,barWidth:this.options.barWidth,barGap:this.options.barGap,barRadius:this.options.barRadius}),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initReadyEvent();const i=this.options.url||(null===(e=this.options.media)||void 0===e?void 0:e.src);i&&this.load(i,this.options.peaks,this.options.duration)}initPlayerEvents(){this.subscriptions.push(this.player.on("timeupdate",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),this.emit("timeupdate",{currentTime:t})})),this.player.on("play",(()=>{this.emit("play"),this.timer.start()})),this.player.on("pause",(()=>{this.emit("pause"),this.timer.stop()})),this.player.on("canplay",(()=>{this.emit("canplay",{duration:this.getDuration()})})),this.player.on("seeking",(()=>{this.emit("seeking",{currentTime:this.getCurrentTime()})})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",(({relativeX:t})=>{if(this.options.interactive){const e=this.getDuration()*t;this.seekTo(e),this.emit("seekClick",{currentTime:this.getCurrentTime()})}})))}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),!0),this.emit("timeupdate",{currentTime:t})})))}initReadyEvent(){let t=!1,e=!1;const i=()=>{t&&e&&this.emit("ready",{duration:this.getDuration()})};this.subscriptions.push(this.on("decode",(()=>{t=!0,i()})),this.on("canplay",(()=>{e=!0,i()})),this.player.on("waiting",(()=>{e=!1,t=!1})))}load(t,e,i){return s=this,n=void 0,o=function*(){if(this.player.loadUrl(t),null==e){const e=yield this.fetcher.load(t),i=yield this.decoder.decode(e);this.decodedData=i}else i||(i=(yield new Promise((t=>{this.player.on("canplay",(()=>t(this.getDuration())),{once:!0})})))||0),this.decodedData={duration:i,numberOfChannels:e.length,sampleRate:e[0].length/i,getChannelData:t=>e[t]};this.renderer.render(this.decodedData),this.emit("decode",{duration:this.decodedData.duration})},new((r=void 0)||(r=Promise))((function(t,e){function i(t){try{h(o.next(t))}catch(t){e(t)}}function a(t){try{h(o.throw(t))}catch(t){e(t)}}function h(e){var s;e.done?t(e.value):(s=e.value,s instanceof r?s:new r((function(t){t(s)}))).then(i,a)}h((o=o.apply(s,n||[])).next())}));var s,n,r,o}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(this.decodedData,t)}play(){this.player.play()}pause(){this.player.pause()}seekTo(t){this.player.seekTo(t)}isPlaying(){return this.player.isPlaying()}getDuration(){var t;return this.player.getDuration()||(null===(t=this.decodedData)||void 0===t?void 0:t.duration)||0}getCurrentTime(){return this.player.getCurrentTime()}getVolume(){return this.player.getVolume()}setVolume(t){this.player.setVolume(t)}getMuted(){return this.player.getMuted()}setMuted(t){this.player.setMuted(t)}getPlaybackRate(){return this.player.getPlaybackRate()}setPlaybackRate(t,e){this.player.setPlaybackRate(t,e)}registerPlugin(t,e){const i=new t({wavesurfer:this,container:this.renderer.getContainer()},e);return this.plugins.push(i),i}getDecodedData(){return this.decodedData}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.plugins.forEach((t=>t.destroy())),this.timer.destroy(),this.player.destroy(),this.decoder.destroy(),this.renderer.destroy()}}const d=h;var l=i(59);class c{static create(t,e){return new c(t,e)}constructor(t,e){this.audios=[],this.wavesurfers=[],this.durations=[],this.currentTime=0,this.maxDuration=0,this.isDragging=!1,this.frameRequest=null,this.tracks=t.map((t=>Object.assign(Object.assign({},t),{startPosition:t.startPosition||0,peaks:t.peaks||(t.url?void 0:[new Float32Array])}))),this.options=e,this.rendering=function(t,e){let i=document.createElement("div");i.setAttribute("style","width: 100%; overflow-x: scroll; overflow-y: hidden; user-select: none;");const s=document.createElement("div");s.style.position="relative",i.appendChild(s),e.container.appendChild(i);const n=document.createElement("div");n.setAttribute("style","width: 1px; height: 100%; position: absolute; z-index: 10; top: 0; left: 0"),n.style.backgroundColor=e.cursorColor||e.progressColor||"#000",s.appendChild(n);const r=t.map((()=>{const t=document.createElement("div");return t.style.width="fit-content",s.appendChild(t),t})),o=()=>{r.forEach(((i,s)=>{const n=t[s].startPosition*e.minPxPerSec/devicePixelRatio;i.style.transform=`translateX(${n}px)`,t[s].draggable&&(i.style.cursor="ew-resize")}))};return o(),{containers:r,setContainerOffsets:o,setMainWidth:t=>{s.style.width=t/devicePixelRatio+"px"},updateCursor:t=>{n.style.left=`${Math.min(100,100*t)}%`},addClickHandler:t=>{s.addEventListener("click",(e=>{const i=s.getBoundingClientRect(),n=(e.clientX-i.left)/s.offsetWidth;t(n)}))},destroy:()=>{i.remove()}}}(this.tracks,this.options),this.initAudios().then((t=>{this.durations=t;const e=this.tracks.reduce(((e,i,s)=>Math.max(e,i.startPosition+t[s])),0);this.rendering.setMainWidth(e*this.options.minPxPerSec),this.rendering.addClickHandler((t=>{this.onSeek(t*e)})),this.maxDuration=e})),this.initWavesurfers(),this.rendering.containers.forEach(((t,e)=>{const i=function(t,e){const i=t.parentElement;if(!i)return;let s=null;t.addEventListener("mousedown",(t=>{const e=i.getBoundingClientRect();s=t.clientX-e.left}));const n=t=>{null!=s&&(t.stopPropagation(),s=null)},r=t=>{if(null==s)return;const n=i.getBoundingClientRect(),r=t.clientX-n.left,o=r-s;(o>1||o<-1)&&(s=r,e(o/i.offsetWidth))};return document.body.addEventListener("mouseup",n),document.body.addEventListener("mousemove",r),{destroy:()=>{document.body.removeEventListener("mouseup",n),document.body.removeEventListener("mousemove",r)}}}(t,(t=>this.onDrag(e,t)));this.wavesurfers[e].once("destroy",(()=>{null==i||i.destroy()}))}))}initAudios(){return this.audios=this.tracks.map((t=>new Audio(t.url||"data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA"))),Promise.all(this.audios.map((t=>new Promise((e=>{t.addEventListener("canplay",(()=>{e(t.duration)}),{once:!0})})))))}initWavesurfers(){const t=this.tracks.map(((t,e)=>{const i=d.create(Object.assign(Object.assign({},this.options),{container:this.rendering.containers[e],media:this.audios[e],peaks:t.peaks,cursorColor:"transparent",fillParent:!1,interactive:!1})),s=i.registerPlugin(l.default,{draggable:!1,resizable:!1,dragSelection:!1});return i.once("decode",(()=>{t.startCue&&s.add(t.startCue,t.startCue,"start"),t.endCue&&s.add(t.endCue,t.endCue,"end"),(t.markers||[]).forEach((t=>{s.add(t.time,t.time,t.label,t.color)}))})),i}));this.wavesurfers=t}updatePosition(t){this.currentTime=t,this.rendering.updateCursor(t/this.maxDuration);const e=!this.isPlaying();this.tracks.forEach(((i,s)=>{const n=this.audios[s],r=this.durations[s],o=t-i.startPosition;Math.abs(n.currentTime-o)>.3&&(n.currentTime=o),e||o<0||o>r?!n.paused&&n.pause():e||n.paused&&n.play();const a=o>=(i.startCue||0)&&o<(i.endCue||1/0)?1:0;a!==n.volume&&(n.volume=a)}))}onSeek(t){if(this.isDragging)return;const e=this.isPlaying();this.updatePosition(t),e&&this.play()}onDrag(t,e){const i=this.tracks[t];if(!i.draggable)return;this.isDragging=!0,setTimeout((()=>this.isDragging=!1),300);const s=i.startPosition+e*this.maxDuration;i.startPosition=s,this.rendering.setContainerOffsets()}findCurrentTracks(){const t=[];if(this.tracks.forEach(((e,i)=>{e.url&&this.currentTime>=e.startPosition&&this.currentTime<e.startPosition+this.durations[i]&&t.push(i)})),0===t.length){const e=Math.min(...this.tracks.filter((t=>t.url)).map((t=>t.startPosition)));t.push(this.tracks.findIndex((t=>t.startPosition===e)))}return t}startSync(){const t=()=>{const e=this.audios.reduce(((t,e,i)=>(e.paused||(t=Math.max(t,e.currentTime+this.tracks[i].startPosition)),t)),this.currentTime);e>this.currentTime&&this.updatePosition(e),this.frameRequest=requestAnimationFrame(t)};t()}play(){this.startSync(),this.findCurrentTracks().forEach((t=>{var e;null===(e=this.audios[t])||void 0===e||e.play()}))}pause(){this.audios.forEach((t=>t.pause()))}isPlaying(){return this.audios.some((t=>!t.paused))}destroy(){this.frameRequest&&cancelAnimationFrame(this.frameRequest),this.rendering.destroy(),this.audios.forEach((t=>{t.pause(),t.src=""})),this.wavesurfers.forEach((t=>{t.destroy()}))}}const u=c})(),s.default})()));
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Regions=t():e.Regions=t()}(WaveSurfer,(()=>(()=>{"use strict";var e={139:(e,t,i)=>{i.d(t,{Z:()=>n});const n=class{constructor(){this.eventTarget=new EventTarget}emit(e,t){const i=new CustomEvent(String(e),{detail:t});this.eventTarget.dispatchEvent(i)}on(e,t,i){const n=e=>{e instanceof CustomEvent&&t(e.detail)},s=String(e);return this.eventTarget.addEventListener(s,n,{once:i}),()=>this.eventTarget.removeEventListener(s,n)}once(e,t){return this.on(e,t,!0)}}}},t={};function i(n){var s=t[n];if(void 0!==s)return s.exports;var o=t[n]={exports:{}};return e[n](o,o.exports,i),o.exports}i.d=(e,t)=>{for(var n in t)i.o(t,n)&&!i.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var n={};return(()=>{i.d(n,{default:()=>d});var e=i(139);class t extends e.Z{constructor(e,t){super(),this.subscriptions=[],this.wavesurfer=e.wavesurfer,this.container=e.container,this.options=t}destroy(){this.subscriptions.forEach((e=>e()))}}const s=t,o={dragSelection:!0,draggable:!0,resizable:!0},r=(e,t)=>{for(const i in t)e.style[i]=t[i]||""},a=(e,t)=>{const i=document.createElement(e);return r(i,t),i},d=class extends s{constructor(e,t){super(e,t),this.dragStart=NaN,this.regions=[],this.createdRegion=null,this.modifiedRegion=null,this.isResizingLeft=!1,this.isMoving=!1,this.handleMouseDown=e=>{(this.options.draggable||this.options.resizable||this.options.dragSelection)&&(this.dragStart=e.clientX-this.container.getBoundingClientRect().left)},this.handleMouseMove=e=>{const t=e.clientX-this.container.getBoundingClientRect().left;if(this.options.draggable&&this.modifiedRegion&&this.isMoving)return this.moveRegion(this.modifiedRegion,t-this.dragStart),void(this.dragStart=t);if(this.options.resizable&&this.modifiedRegion)this.updateRegion(this.modifiedRegion,this.isResizingLeft?t:void 0,this.isResizingLeft?void 0:t);else if(this.options.dragSelection&&!isNaN(this.dragStart)){const t=e.clientX-this.wrapper.getBoundingClientRect().left;t-this.dragStart>=10&&(this.createdRegion?this.updateRegion(this.createdRegion,this.dragStart,t):(this.container.style.pointerEvents="none",this.createdRegion=this.createRegion(this.dragStart,t)))}},this.handleMouseUp=()=>{this.createdRegion&&(this.addRegion(this.createdRegion),this.createdRegion=null),this.modifiedRegion=null,this.isMoving=!1,this.dragStart=NaN,this.container.style.pointerEvents=""},this.options=Object.assign({},o,t),this.wrapper=this.initWrapper();const i=this.wavesurfer.once("decode",(()=>{this.container.appendChild(this.wrapper)}));this.subscriptions.push(i),this.container.addEventListener("mousedown",this.handleMouseDown),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}destroy(){this.container.removeEventListener("mousedown",this.handleMouseDown),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp,!0),this.wrapper.remove(),super.destroy()}initWrapper(){return a("div",{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",zIndex:"3",pointerEvents:"none"})}createRegionElement(e,t,i=""){const n=e===t,s=a("div",{position:"absolute",left:`${e}px`,width:t-e+"px",height:"100%",backgroundColor:n?"":"rgba(0, 0, 0, 0.1)",borderRadius:"2px",boxSizing:"border-box",borderLeft:"2px solid rgba(0, 0, 0, 0.5)",borderRight:n?"":"2px solid rgba(0, 0, 0, 0.5)",transition:"background-color 0.2s ease",cursor:this.options.draggable?"move":"",pointerEvents:"all",padding:"0.2em"});s.textContent=i;const o=a("div",{position:"absolute",left:"0",width:"6px",height:"100%",cursor:this.options.resizable?"ew-resize":"",pointerEvents:"all"});s.appendChild(o);const d=o.cloneNode();return r(d,{left:"",right:"0",borderLeft:""}),s.appendChild(d),o.addEventListener("mousedown",(e=>{this.options.resizable&&(e.stopPropagation(),this.modifiedRegion=this.regions.find((e=>e.element===s))||null,this.isResizingLeft=!0,this.isMoving=!1)})),d.addEventListener("mousedown",(e=>{this.options.resizable&&(e.stopPropagation(),this.modifiedRegion=this.regions.find((e=>e.element===s))||null,this.isResizingLeft=!1,this.isMoving=!1)})),s.addEventListener("mousedown",(()=>{this.options.draggable&&(this.modifiedRegion=this.regions.find((e=>e.element===s))||null,this.isMoving=!0)})),s.addEventListener("click",(()=>{const e=this.regions.find((e=>e.element===s));e&&this.emit("region-clicked",{region:e})})),this.wrapper.appendChild(s),s}createRegion(e,t,i=""){const n=this.wavesurfer.getDuration(),s=this.wrapper.clientWidth;return e=Math.max(0,Math.min(e,s-1)),t=Math.max(0,Math.min(t,s-1)),{element:this.createRegionElement(e,t,i),start:e,end:t,startTime:e/s*n,endTime:t/s*n,title:i}}addRegion(e){this.regions.push(e),this.emit("region-created",{region:e})}updateRegion(e,t,i){const n=this.wrapper.clientWidth;null!=t&&(t=Math.max(0,Math.min(t,n)),e.start=t,e.element.style.left=`${e.start}px`,e.startTime=t/this.wrapper.clientWidth*this.wavesurfer.getDuration()),null!=i&&(i=Math.max(0,Math.min(i,n)),e.end=i,e.element.style.width=e.end-e.start+"px",e.endTime=i/this.wrapper.clientWidth*this.wavesurfer.getDuration()),this.emit("region-updated",{region:e})}moveRegion(e,t){this.updateRegion(e,e.start+t,e.end+t)}add(e,t,i="",n=""){const s=this.wavesurfer.getDuration(),o=this.wrapper.clientWidth,r=e/s*o,a=t/s*o,d=this.createRegion(r,a,i);return this.addRegion(d),n&&this.setRegionColor(d,n),d}setRegionColor(e,t){e.element.style[e.startTime===e.endTime?"borderColor":"backgroundColor"]=t}}})(),n.default})()));
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Timeline=t():e.Timeline=t()}(WaveSurfer,(()=>(()=>{"use strict";var e={d:(t,n)=>{for(var i in n)e.o(n,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:n[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{default:()=>o});const n=class{constructor(){this.eventTarget=new EventTarget}emit(e,t){const n=new CustomEvent(String(e),{detail:t});this.eventTarget.dispatchEvent(n)}on(e,t,n){const i=e=>{e instanceof CustomEvent&&t(e.detail)},r=String(e);return this.eventTarget.addEventListener(r,i,{once:n}),()=>this.eventTarget.removeEventListener(r,i)}once(e,t){return this.on(e,t,!0)}},i=class extends n{constructor(e,t){super(),this.subscriptions=[],this.wavesurfer=e.wavesurfer,this.container=e.container,this.options=t}destroy(){this.subscriptions.forEach((e=>e()))}},r={height:20},o=class extends i{constructor(e,t){var n;super(e,t),this.options=Object.assign({},r,t),this.container=null!==(n=this.options.container)&&void 0!==n?n:this.container,this.wrapper=this.initWrapper(),this.container.appendChild(this.wrapper),this.subscriptions.push(this.wavesurfer.on("decode",(({duration:e})=>{this.initTimeline(e)})))}destroy(){this.wrapper.remove(),super.destroy()}initWrapper(){return document.createElement("div")}formatTime(e){return e/60>1?`${Math.round(e/60)}:${(e=Math.round(e%60))<10?"0":""}${e}`:""+Math.round(1e3*e)/1e3}defaultTimeInterval(e){return e>=25?1:5*e>=25?5:15*e>=25?15:60*Math.ceil(.5/e)}defaultPrimaryLabelInterval(e){return e>=25?10:5*e>=25?6:4}defaultSecondaryLabelInterval(e){return e>=25?5:2}initTimeline(e){var t,n,i;const r=Math.round(this.wrapper.scrollWidth*devicePixelRatio)/e,o=null!==(t=this.options.timeInterval)&&void 0!==t?t:this.defaultTimeInterval(r),s=null!==(n=this.options.primaryLabelInterval)&&void 0!==n?n:this.defaultPrimaryLabelInterval(r),a=null!==(i=this.options.secondaryLabelInterval)&&void 0!==i?i:this.defaultSecondaryLabelInterval(r),l=document.createElement("div");l.setAttribute("style",`\n height: ${this.options.height}px;\n overflow: hidden;\n display: flex;\n justify-content: space-between;\n align-items: flex-end;\n font-size: ${this.options.height/2}px;\n `);const d=document.createElement("div");d.setAttribute("style","\n width: 1px;\n height: 50%;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n overflow: visible;\n border-left: 1px solid currentColor;\n opacity: 0.25;\n ");for(let t=0;t<e;t+=o){const e=d.cloneNode(),n=t%s==0;(n||t%a==0)&&(e.style.height="100%",e.style.textIndent="3px",e.textContent=this.formatTime(t),n&&(e.style.opacity="1")),l.appendChild(e)}this.wrapper.appendChild(l),this.emit("ready")}};return t.default})()));
@@ -0,0 +1 @@
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.WaveSurfer=e():t.WaveSurfer=e()}(this,(()=>(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{default:()=>a});const i=class{constructor(){this.eventTarget=new EventTarget}emit(t,e){const i=new CustomEvent(String(t),{detail:e});this.eventTarget.dispatchEvent(i)}on(t,e,i){const s=t=>{t instanceof CustomEvent&&e(t.detail)},n=String(t);return this.eventTarget.addEventListener(n,s,{once:i}),()=>this.eventTarget.removeEventListener(n,s)}once(t,e){return this.on(t,e,!0)}};const s=class extends i{constructor(t){super(),this.timeout=null,this.options=t;let e=null;if("string"==typeof this.options.container?e=document.querySelector(this.options.container):this.options.container instanceof HTMLElement&&(e=this.options.container),!e)throw new Error("Container not found");const i=document.createElement("div"),s=i.attachShadow({mode:"open"});s.innerHTML=`\n <style>\n :host {\n user-select: none;\n }\n :host .scroll {\n overflow-x: auto;\n overflow-y: hidden;\n width: 100%;\n position: relative;\n }\n :host .wrapper {\n position: relative;\n width: fit-content;\n min-width: 100%;\n z-index: 2;\n }\n :host canvas {\n display: block;\n height: ${this.options.height}px;\n min-width: 100%;\n image-rendering: pixelated;\n }\n :host .progress {\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n pointer-events: none;\n clip-path: inset(100%);\n }\n :host .cursor {\n position: absolute;\n z-index: 3;\n top: 0;\n left: 0;\n height: 100%;\n border-right: 1px solid ${this.options.cursorColor||this.options.progressColor};\n margin-left: -1px;\n }\n </style>\n\n <div class="scroll">\n <div class="wrapper">\n <canvas></canvas>\n <canvas class="progress"></canvas>\n <div class="cursor"></div>\n </div>\n </div>\n `,this.container=i,this.scrollContainer=s.querySelector(".scroll"),this.mainCanvas=s.querySelector("canvas"),this.ctx=this.mainCanvas.getContext("2d",{desynchronized:!0}),this.progressCanvas=s.querySelector(".progress"),this.cursor=s.querySelector(".cursor"),e.appendChild(i),this.mainCanvas.addEventListener("click",(t=>{const e=this.mainCanvas.getBoundingClientRect(),i=(t.clientX-e.left)/e.width;this.emit("click",{relativeX:i})}))}getContainer(){return this.scrollContainer.querySelector(".wrapper")}destroy(){this.container.remove()}delay(t,e=100){return this.timeout&&clearTimeout(this.timeout),new Promise((i=>{this.timeout=setTimeout((()=>{i(t())}),e)}))}renderPeaks(t,e,i){var s,n,o,r,a;return n=this,o=void 0,a=function*(){const{devicePixelRatio:n}=window,{ctx:o}=this,r=null!=this.options.barWidth?this.options.barWidth*n:1,a=null!=this.options.barGap?this.options.barGap*n:this.options.barWidth?r/2:0,h=null!==(s=this.options.barRadius)&&void 0!==s?s:0,l=t[0],d=l.length,c=Math.floor(e/(r+a))/d,u=i/2,p=1===t.length,m=p?l:t[1],y=p&&m.some((t=>t<0)),v=(t,e)=>{let i=0,s=0,n=0;o.beginPath(),o.fillStyle=this.options.waveColor,o.roundRect||(o.roundRect=o.fillRect);for(let d=t;d<e;d++){const t=Math.round(d*c);if(t>i){const e=Math.round(s*u),l=Math.round(n*u);o.roundRect(i*(r+a),u-e,r,e+l||1,h),i=t,s=0,n=0}const e=y?l[d]:Math.abs(l[d]),p=y?m[d]:Math.abs(m[d]);e>s&&(s=e),(y?p<-n:p>n)&&(n=p<0?-p:p)}o.fill(),o.closePath()};o.clearRect(0,0,e,i);const{scrollLeft:g,scrollWidth:f,clientWidth:C}=this.scrollContainer,w=d/f,b=Math.floor(g*w),P=Math.ceil((g+C)*w);v(b,P),this.createProgressMask(),b>0&&(yield this.delay((()=>{v(0,b)}))),P<d&&(yield this.delay((()=>{v(P,d)}))),this.delay((()=>{this.createProgressMask()}))},new((r=void 0)||(r=Promise))((function(t,e){function i(t){try{h(a.next(t))}catch(t){e(t)}}function s(t){try{h(a.throw(t))}catch(t){e(t)}}function h(e){var n;e.done?t(e.value):(n=e.value,n instanceof r?n:new r((function(t){t(n)}))).then(i,s)}h((a=a.apply(n,o||[])).next())}))}createProgressMask(){const t=this.progressCanvas.getContext("2d",{desynchronized:!0});this.progressCanvas.width=this.mainCanvas.width,this.progressCanvas.height=this.mainCanvas.height,this.progressCanvas.style.width=this.mainCanvas.style.width,this.progressCanvas.style.height=this.mainCanvas.style.height,t.drawImage(this.mainCanvas,0,0),t.globalCompositeOperation="source-in",t.fillStyle=this.options.progressColor,t.fillRect(0,0,this.progressCanvas.width,this.progressCanvas.height)}render(t){const{devicePixelRatio:e}=window,i=this.options.fillParent?this.scrollContainer.clientWidth*e:0,s=t.duration*this.options.minPxPerSec,n=s>i,o=Math.max(1,n?s:i),{height:r}=this.options;this.mainCanvas.width=o,this.mainCanvas.height=r,this.mainCanvas.style.width=Math.floor(s/e)+"px";const a=[t.getChannelData(0)];t.numberOfChannels>1&&a.push(t.getChannelData(1)),this.renderPeaks(a,o,r)}zoom(t,e){const i=this.cursor.getBoundingClientRect().left;this.options.minPxPerSec=e,this.render(t);const s=this.cursor.getBoundingClientRect().left;this.scrollContainer.scrollLeft+=s-i}renderProgress(t,e=!1){if(this.progressCanvas.style.clipPath=`inset(0 ${100-100*t}% 0 0)`,this.cursor.style.left=100*t+"%",e){const e=this.container.clientWidth/2,i=this.mainCanvas.clientWidth;i*t>=e&&(this.scrollContainer.scrollLeft=i*t-e)}}},n=class extends i{constructor(){super(...arguments),this.unsubscribe=()=>{}}start(){this.unsubscribe=this.on("tick",(()=>{requestAnimationFrame((()=>{this.emit("tick")}))})),this.emit("tick")}stop(){this.unsubscribe()}destroy(){this.unsubscribe()}};const o={height:128,waveColor:"#999",progressColor:"#555",minPxPerSec:0,fillParent:!0,interactive:!0};class r extends i{static create(t){return new r(t)}constructor(t){var e;super(),this.plugins=[],this.subscriptions=[],this.decodedData=null,this.options=Object.assign({},o,t),this.fetcher=new class{load(t){return e=this,i=void 0,n=function*(){return fetch(t).then((t=>t.arrayBuffer()))},new((s=void 0)||(s=Promise))((function(t,o){function r(t){try{h(n.next(t))}catch(t){o(t)}}function a(t){try{h(n.throw(t))}catch(t){o(t)}}function h(e){var i;e.done?t(e.value):(i=e.value,i instanceof s?i:new s((function(t){t(i)}))).then(r,a)}h((n=n.apply(e,i||[])).next())}));var e,i,s,n}},this.decoder=new class{initAudioContext(t){this.audioCtx=new AudioContext({latencyHint:"playback",sampleRate:t})}constructor(){this.audioCtx=null;try{this.initAudioContext(3e3)}catch(t){this.initAudioContext(8e3)}}decode(t){return e=this,i=void 0,n=function*(){if(!this.audioCtx)throw new Error("AudioContext is not initialized");return this.audioCtx.decodeAudioData(t)},new((s=void 0)||(s=Promise))((function(t,o){function r(t){try{h(n.next(t))}catch(t){o(t)}}function a(t){try{h(n.throw(t))}catch(t){o(t)}}function h(e){var i;e.done?t(e.value):(i=e.value,i instanceof s?i:new s((function(t){t(i)}))).then(r,a)}h((n=n.apply(e,i||[])).next())}));var e,i,s,n}destroy(){var t;null===(t=this.audioCtx)||void 0===t||t.close(),this.audioCtx=null}},this.timer=new n,this.player=new class{constructor({media:t,autoplay:e}){this.isExternalMedia=!1,this.hasPlayedOnce=!1,t?(this.media=t,this.isExternalMedia=!0):this.media=document.createElement("audio");const i=this.on("play",(()=>{this.hasPlayedOnce=!0,i()}));e&&(this.media.autoplay=!0)}on(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e)}destroy(){this.media.pause(),this.isExternalMedia||this.media.remove()}loadUrl(t){this.media.src=t}getCurrentTime(){return this.media.currentTime}play(){this.media.play()}pause(){this.media.pause()}isPlaying(){return this.media.currentTime>0&&!this.media.paused&&!this.media.ended}seekTo(t){if(this.media){const{hasPlayedOnce:e}=this;e||this.media.play(),this.media.currentTime=t,e||this.media.pause()}}getDuration(){return this.media.duration}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}setPlaybackRate(t,e){null!=e&&(this.media.preservesPitch=e),this.media.playbackRate=t}}({media:this.options.media,autoplay:this.options.autoplay}),this.renderer=new s({container:this.options.container,height:this.options.height,waveColor:this.options.waveColor,progressColor:this.options.progressColor,cursorColor:this.options.cursorColor,minPxPerSec:this.options.minPxPerSec,fillParent:this.options.fillParent,barWidth:this.options.barWidth,barGap:this.options.barGap,barRadius:this.options.barRadius}),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initReadyEvent();const i=this.options.url||(null===(e=this.options.media)||void 0===e?void 0:e.src);i&&this.load(i,this.options.peaks,this.options.duration)}initPlayerEvents(){this.subscriptions.push(this.player.on("timeupdate",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),this.emit("timeupdate",{currentTime:t})})),this.player.on("play",(()=>{this.emit("play"),this.timer.start()})),this.player.on("pause",(()=>{this.emit("pause"),this.timer.stop()})),this.player.on("canplay",(()=>{this.emit("canplay",{duration:this.getDuration()})})),this.player.on("seeking",(()=>{this.emit("seeking",{currentTime:this.getCurrentTime()})})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",(({relativeX:t})=>{if(this.options.interactive){const e=this.getDuration()*t;this.seekTo(e),this.emit("seekClick",{currentTime:this.getCurrentTime()})}})))}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),!0),this.emit("timeupdate",{currentTime:t})})))}initReadyEvent(){let t=!1,e=!1;const i=()=>{t&&e&&this.emit("ready",{duration:this.getDuration()})};this.subscriptions.push(this.on("decode",(()=>{t=!0,i()})),this.on("canplay",(()=>{e=!0,i()})),this.player.on("waiting",(()=>{e=!1,t=!1})))}load(t,e,i){return s=this,n=void 0,r=function*(){if(this.player.loadUrl(t),null==e){const e=yield this.fetcher.load(t),i=yield this.decoder.decode(e);this.decodedData=i}else i||(i=(yield new Promise((t=>{this.player.on("canplay",(()=>t(this.getDuration())),{once:!0})})))||0),this.decodedData={duration:i,numberOfChannels:e.length,sampleRate:e[0].length/i,getChannelData:t=>e[t]};this.renderer.render(this.decodedData),this.emit("decode",{duration:this.decodedData.duration})},new((o=void 0)||(o=Promise))((function(t,e){function i(t){try{h(r.next(t))}catch(t){e(t)}}function a(t){try{h(r.throw(t))}catch(t){e(t)}}function h(e){var s;e.done?t(e.value):(s=e.value,s instanceof o?s:new o((function(t){t(s)}))).then(i,a)}h((r=r.apply(s,n||[])).next())}));var s,n,o,r}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(this.decodedData,t)}play(){this.player.play()}pause(){this.player.pause()}seekTo(t){this.player.seekTo(t)}isPlaying(){return this.player.isPlaying()}getDuration(){var t;return this.player.getDuration()||(null===(t=this.decodedData)||void 0===t?void 0:t.duration)||0}getCurrentTime(){return this.player.getCurrentTime()}getVolume(){return this.player.getVolume()}setVolume(t){this.player.setVolume(t)}getMuted(){return this.player.getMuted()}setMuted(t){this.player.setMuted(t)}getPlaybackRate(){return this.player.getPlaybackRate()}setPlaybackRate(t,e){this.player.setPlaybackRate(t,e)}registerPlugin(t,e){const i=new t({wavesurfer:this,container:this.renderer.getContainer()},e);return this.plugins.push(i),i}getDecodedData(){return this.decodedData}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.plugins.forEach((t=>t.destroy())),this.timer.destroy(),this.player.destroy(),this.decoder.destroy(),this.renderer.destroy()}}const a=r;return e.default})()));
package/package.json CHANGED
@@ -1,26 +1,40 @@
1
1
  {
2
2
  "name": "wavesurfer.js",
3
- "version": "7.0.0-alpha.0",
4
- "description": "",
3
+ "version": "7.0.0-alpha.10",
4
+ "description": "wavesurfer.js is an audio library that draws waveforms and plays audio in the browser.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist/"
9
+ ],
7
10
  "scripts": {
8
11
  "build": "tsc",
12
+ "build:dev": "tsc -w",
13
+ "build:umd": "tsc && webpack && webpack --config webpack.config.plugins.js",
14
+ "prepublishOnly": "npm run build:umd",
9
15
  "test": "echo \"Error: no test specified\" && exit 1",
10
16
  "lint": "eslint --ext .ts src --fix",
11
17
  "prettier": "prettier -w src",
12
- "docs": "npx typedoc src/index.ts"
18
+ "docs": "npx typedoc src/index.ts",
19
+ "serve": "browser-sync start --server --port 9090 --startPath / --watch '*'",
20
+ "start": "npm run build:dev & npm run serve"
13
21
  },
14
22
  "author": "katspaugh <katspaugh@gmail.com>",
15
23
  "license": "ISC",
16
24
  "devDependencies": {
25
+ "@types/react": "^18.0.28",
17
26
  "@typescript-eslint/eslint-plugin": "^5.54.0",
18
27
  "@typescript-eslint/parser": "^5.54.0",
28
+ "browser-sync": "^2.29.0",
19
29
  "eslint": "^8.35.0",
20
30
  "eslint-config-prettier": "^8.7.0",
21
31
  "eslint-plugin-prettier": "^4.2.1",
22
32
  "prettier": "^2.8.4",
33
+ "ts-loader": "^9.4.2",
23
34
  "typedoc": "^0.23.26",
24
- "typescript": "^4.9.5"
25
- }
35
+ "typescript": "^4.9.5",
36
+ "webpack": "^5.76.1",
37
+ "webpack-cli": "^5.0.1"
38
+ },
39
+ "dependencies": {}
26
40
  }
package/.eslintrc.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "env": {
3
- "browser": true,
4
- "es2021": true
5
- },
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/recommended",
9
- "prettier",
10
- "plugin:prettier/recommended"
11
- ],
12
- "overrides": [
13
- ],
14
- "parser": "@typescript-eslint/parser",
15
- "parserOptions": {
16
- "ecmaVersion": "latest",
17
- "sourceType": "module"
18
- },
19
- "plugins": [
20
- "@typescript-eslint"
21
- ],
22
- "rules": {
23
- }
24
- }
package/.prettierrc DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "tabWidth": 2,
3
- "printWidth": 120,
4
- "trailingComma": "all",
5
- "singleQuote": true,
6
- "semi": false,
7
- "endOfLine": "auto"
8
- }
Binary file
package/examples/bars.js DELETED
@@ -1,19 +0,0 @@
1
- import WaveSurfer from '/dist/index.js'
2
-
3
- const wavesurfer = WaveSurfer.create({
4
- container: document.body,
5
- waveColor: 'rgb(200, 0, 200)',
6
- progressColor: 'rgb(100, 0, 100)',
7
- url: 'https://wavesurfer-js.org/example/media/demo.wav',
8
-
9
- // Set a bar width
10
- barWidth: 2,
11
- // Optionally, specify the spacing between bars
12
- barGap: 1,
13
- // And the bar radius
14
- barRadius: 2,
15
- })
16
-
17
- wavesurfer.on('seek', function () {
18
- wavesurfer.play()
19
- })
package/examples/basic.js DELETED
@@ -1,8 +0,0 @@
1
- import WaveSurfer from '/dist/index.js'
2
-
3
- const wavesurfer = WaveSurfer.create({
4
- container: document.body,
5
- waveColor: 'rgb(200, 0, 200)',
6
- progressColor: 'rgb(100, 0, 100)',
7
- url: 'https://wavesurfer-js.org/example/media/demo.wav'
8
- })
@@ -1,28 +0,0 @@
1
- import WaveSurfer from '/dist/index.js'
2
-
3
- // Create a canvas gradient
4
- const ctx = document.createElement('canvas').getContext('2d')
5
- const gradient = ctx.createLinearGradient(0, 0, 0, 150)
6
- gradient.addColorStop(0, 'rgb(200, 0, 200)')
7
- gradient.addColorStop(0.7, 'rgb(100, 0, 100)')
8
- gradient.addColorStop(1, 'rgb(0, 0, 0)')
9
-
10
- // Default style with a gradient
11
- WaveSurfer.create({
12
- container: document.body,
13
- waveColor: gradient,
14
- height: 200,
15
- progressColor: 'rgba(0, 0, 100, 0.5)',
16
- url: 'https://wavesurfer-js.org/example/media/demo.wav'
17
- })
18
-
19
-
20
- // SoundCloud-style bars
21
- WaveSurfer.create({
22
- container: document.body,
23
- waveColor: gradient,
24
- height: 200,
25
- barWidth: 2,
26
- progressColor: 'rgba(0, 0, 100, 0.5)',
27
- url: 'https://wavesurfer-js.org/example/media/demo.wav'
28
- })