wavesurfer.js 7.0.0-alpha.43 → 7.0.0-alpha.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,6 +38,7 @@ The "official" plugins have been completely rewritten and enhanced:
38
38
  * [Minimap](https://wavesurfer-ts.pages.dev/tutorial/#/examples/minimap.js) – a small waveform that serves as a scrollbar for the main waveform
39
39
  * [Envelope](https://wavesurfer-ts.pages.dev/tutorial/#/examples/envelope.js) – a graphical interface to add fade-in and -out effects and control volume
40
40
  * [Record](https://wavesurfer-ts.pages.dev/tutorial/#/examples/record.js) – records audio from the microphone and renders a waveform
41
+ * [Spectrogram](https://wavesurfer-ts.pages.dev/tutorial/#/examples/spectrogram.js) – visualization of an audio frequency spectrum
41
42
 
42
43
  ## Documentation
43
44
  See the documentation on wavesurfer.js [methods](https://wavesurfer-ts.pages.dev/docs/classes/wavesurfer.WaveSurfer), [options](https://wavesurfer-ts.pages.dev/docs/types/wavesurfer.WaveSurferOptions) and [events](https://wavesurfer-ts.pages.dev/docs/types/wavesurfer.WaveSurferEvents) on our website.
@@ -50,7 +51,7 @@ Most options, events, and methods are similar to those in previous versions.
50
51
  * The `backend` option is removed – HTML5 audio (or video) is the only playback mechanism. However, you can still connect wavesurfer to Web Audio via `MediaElementSourceNode`. See this [example](https://wavesurfer-ts.pages.dev/tutorial/#/examples/webaudio.js).
51
52
  * The Markers plugin is removed – use the Regions plugin with `startTime` equal to `endTime`.
52
53
  * No Microphone plugn – superseded by the new Record plugin with more features.
53
- * No Spectrogram, Cursor and Playhead plugins yet – to be done.
54
+ * No Cursor and Playhead plugins yet – to be done.
54
55
 
55
56
  ### Removed methods
56
57
  * `getFilters`, `setFilter` – as there's no Web Audio "backend"
@@ -1,19 +1,13 @@
1
1
  import EventEmitter, { type GeneralEventTypes } from './event-emitter.js';
2
2
  import type WaveSurfer from './wavesurfer.js';
3
3
  export type GenericPlugin = BasePlugin<GeneralEventTypes, unknown>;
4
- export type WaveSurferPluginParams = {
5
- wavesurfer: WaveSurfer;
6
- container: HTMLElement;
7
- wrapper: HTMLElement;
8
- };
9
4
  export declare class BasePlugin<EventTypes extends GeneralEventTypes, Options> extends EventEmitter<EventTypes> {
10
5
  protected wavesurfer?: WaveSurfer;
11
- protected container?: HTMLElement;
12
- protected wrapper?: HTMLElement;
13
6
  protected subscriptions: (() => void)[];
14
7
  protected options: Options;
15
8
  constructor(options: Options);
16
- init(params: WaveSurferPluginParams): void;
9
+ onInit(): void;
10
+ init(wavesurfer: WaveSurfer): void;
17
11
  destroy(): void;
18
12
  }
19
13
  export default BasePlugin;
@@ -5,10 +5,13 @@ export class BasePlugin extends EventEmitter {
5
5
  this.subscriptions = [];
6
6
  this.options = options;
7
7
  }
8
- init(params) {
9
- this.wavesurfer = params.wavesurfer;
10
- this.container = params.container;
11
- this.wrapper = params.wrapper;
8
+ onInit() {
9
+ // Overridden in plugin definition
10
+ return;
11
+ }
12
+ init(wavesurfer) {
13
+ this.wavesurfer = wavesurfer;
14
+ this.onInit();
12
15
  }
13
16
  destroy() {
14
17
  this.subscriptions.forEach((unsubscribe) => unsubscribe());
package/dist/decoder.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Decode an array buffer into an audio buffer */
2
- declare function decode(audioData: ArrayBuffer): Promise<AudioBuffer>;
2
+ declare function decode(audioData: ArrayBuffer, sampleRate?: number): Promise<AudioBuffer>;
3
3
  /** Create an audio buffer from pre-decoded audio data */
4
4
  declare function createBuffer(channelData: Float32Array[] | Array<number[]>, duration: number): AudioBuffer;
5
5
  declare const Decoder: {
package/dist/decoder.js CHANGED
@@ -1,8 +1,6 @@
1
1
  /** Decode an array buffer into an audio buffer */
2
- async function decode(audioData) {
3
- const audioCtx = new AudioContext({
4
- sampleRate: 8000, // the lowsest sample rate of all browsers
5
- });
2
+ async function decode(audioData, sampleRate = 8000) {
3
+ const audioCtx = new AudioContext({ sampleRate });
6
4
  const decode = audioCtx.decodeAudioData(audioData);
7
5
  decode.finally(() => audioCtx.close());
8
6
  return decode;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Envelope is a visual UI for controlling the audio volume and add fade-in and fade-out effects.
3
3
  */
4
- import BasePlugin, { type WaveSurferPluginParams } from '../base-plugin.js';
4
+ import BasePlugin from '../base-plugin.js';
5
5
  export type EnvelopePluginOptions = {
6
6
  fadeInStart?: number;
7
7
  fadeInEnd?: number;
@@ -38,20 +38,28 @@ declare class EnvelopePlugin extends BasePlugin<EnvelopePluginEvents, EnvelopePl
38
38
  private volume;
39
39
  private isFadingIn;
40
40
  private isFadingOut;
41
+ private readonly naturalVolumeExponent;
41
42
  constructor(options: EnvelopePluginOptions);
42
43
  static create(options: EnvelopePluginOptions): EnvelopePlugin;
43
44
  /** Called by wavesurfer, don't call manually */
44
- init(params: WaveSurferPluginParams): void;
45
+ onInit(): void;
45
46
  private makeDraggable;
46
47
  private renderPolyline;
47
48
  private initSvg;
48
49
  destroy(): void;
49
50
  private initWebAudio;
51
+ private invertNaturalVolume;
50
52
  private naturalVolume;
51
- private onVolumeChange;
53
+ private setGainValue;
54
+ private onVolumeDrag;
52
55
  private initFadeEffects;
56
+ /** Get the current audio volume */
53
57
  getCurrentVolume(): number;
54
- setStartTime(time: number): void;
55
- setEndTime(time: number): void;
58
+ /** Set the fade-in start time */
59
+ setStartTime(time: number, moveDragPoint?: boolean): void;
60
+ /** Set the fade-out end time */
61
+ setEndTime(time: number, moveDragPoint?: boolean): void;
62
+ /** Set the volume of the audio */
63
+ setVolume(volume: number): void;
56
64
  }
57
65
  export default EnvelopePlugin;
@@ -22,6 +22,8 @@ class EnvelopePlugin extends BasePlugin {
22
22
  this.volume = 1;
23
23
  this.isFadingIn = false;
24
24
  this.isFadingOut = false;
25
+ // Adjust the exponent to change the curve of the volume control
26
+ this.naturalVolumeExponent = 1.5;
25
27
  this.options = Object.assign({}, defaultOptions, options);
26
28
  this.options.lineColor = this.options.lineColor || defaultOptions.lineColor;
27
29
  this.options.dragPointFill = this.options.dragPointFill || defaultOptions.dragPointFill;
@@ -32,8 +34,7 @@ class EnvelopePlugin extends BasePlugin {
32
34
  return new EnvelopePlugin(options);
33
35
  }
34
36
  /** Called by wavesurfer, don't call manually */
35
- init(params) {
36
- super.init(params);
37
+ onInit() {
37
38
  if (!this.wavesurfer) {
38
39
  throw Error('WaveSurfer is not initialized');
39
40
  }
@@ -88,13 +89,17 @@ class EnvelopePlugin extends BasePlugin {
88
89
  });
89
90
  }
90
91
  renderPolyline() {
91
- if (!this.svg || !this.wrapper || !this.wavesurfer)
92
+ if (!this.svg || !this.wavesurfer)
92
93
  return;
93
94
  const polyline = this.svg.querySelector('polyline');
94
95
  const points = polyline.points;
95
- const top = points.getItem(1).y;
96
- const width = this.wrapper.clientWidth;
96
+ const width = this.svg.clientWidth;
97
+ const height = this.svg.clientHeight;
97
98
  const duration = this.wavesurfer.getDuration();
99
+ const offset = this.options.dragPointSize / 2;
100
+ const top = height - this.invertNaturalVolume(this.volume) * height + offset;
101
+ points.getItem(1).y = top;
102
+ points.getItem(2).y = top;
98
103
  points.getItem(0).x = (this.options.fadeInStart / duration) * width;
99
104
  points.getItem(3).x = (this.options.fadeOutEnd / duration) * width;
100
105
  const line = this.svg.querySelector('line');
@@ -111,10 +116,11 @@ class EnvelopePlugin extends BasePlugin {
111
116
  }
112
117
  }
113
118
  initSvg() {
114
- if (!this.wrapper || !this.wavesurfer)
119
+ if (!this.wavesurfer)
115
120
  return;
116
- const width = this.wrapper.clientWidth;
117
- const height = this.wrapper.clientHeight;
121
+ const wrapper = this.wavesurfer.getWrapper();
122
+ const width = wrapper.clientWidth;
123
+ const height = wrapper.clientHeight;
118
124
  const duration = this.wavesurfer.getDuration();
119
125
  // SVG element
120
126
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
@@ -140,13 +146,12 @@ class EnvelopePlugin extends BasePlugin {
140
146
  svg.appendChild(line);
141
147
  const points = polyline.points;
142
148
  const offset = this.options.dragPointSize / 2;
143
- const top = height - this.volume * height + offset;
144
149
  points.getItem(0).x = (this.options.fadeInStart / duration) * width;
145
150
  points.getItem(0).y = height;
146
151
  points.getItem(1).x = (this.options.fadeInEnd / duration) * width;
147
- points.getItem(1).y = top;
152
+ points.getItem(1).y = 0;
148
153
  points.getItem(2).x = (this.options.fadeOutStart / duration) * width;
149
- points.getItem(2).y = top;
154
+ points.getItem(2).y = 0;
150
155
  points.getItem(3).x = (this.options.fadeOutEnd / duration) * width;
151
156
  points.getItem(3).y = height;
152
157
  // Drag points
@@ -160,7 +165,7 @@ class EnvelopePlugin extends BasePlugin {
160
165
  circle.setAttribute('style', 'cursor: ew-resize; pointer-events: all;');
161
166
  svg.appendChild(circle);
162
167
  });
163
- this.wrapper.appendChild(svg);
168
+ this.wavesurfer.getWrapper().appendChild(svg);
164
169
  // Initial polyline
165
170
  this.renderPolyline();
166
171
  // On top line drag
@@ -168,12 +173,8 @@ class EnvelopePlugin extends BasePlugin {
168
173
  const newTop = points.getItem(1).y + dy - offset;
169
174
  if (newTop < -0.5 || newTop > height)
170
175
  return;
171
- points.getItem(1).y = newTop + offset;
172
- points.getItem(2).y = newTop + offset;
173
- this.renderPolyline();
174
176
  const newVolume = Math.min(1, Math.max(0, (height - newTop) / height));
175
- this.onVolumeChange(newVolume);
176
- this.renderPolyline();
177
+ this.onVolumeDrag(newVolume);
177
178
  };
178
179
  // On points drag
179
180
  const onDragX = (dx, dy, index) => {
@@ -223,7 +224,7 @@ class EnvelopePlugin extends BasePlugin {
223
224
  const audioContext = new window.AudioContext();
224
225
  // Create a GainNode for controlling the volume
225
226
  this.gainNode = audioContext.createGain();
226
- this.gainNode.gain.value = this.volume;
227
+ this.setGainValue();
227
228
  // Create a MediaElementAudioSourceNode using the audio element
228
229
  const source = audioContext.createMediaElementSource(audio);
229
230
  // Connect the source to the GainNode, and the GainNode to the destination (speakers)
@@ -231,20 +232,25 @@ class EnvelopePlugin extends BasePlugin {
231
232
  this.gainNode.connect(audioContext.destination);
232
233
  this.audioContext = audioContext;
233
234
  }
235
+ invertNaturalVolume(value) {
236
+ const minValue = 0.0001;
237
+ const maxValue = 1;
238
+ const interpolatedValue = Math.pow((value - minValue) / (maxValue - minValue), 1 / this.naturalVolumeExponent);
239
+ return interpolatedValue;
240
+ }
234
241
  naturalVolume(value) {
235
242
  const minValue = 0.0001;
236
243
  const maxValue = 1;
237
- const exponent = 3; // Adjust the exponent to change the curve of the volume control
238
- const interpolatedValue = minValue + (maxValue - minValue) * Math.pow(value, exponent);
244
+ const interpolatedValue = minValue + (maxValue - minValue) * Math.pow(value, this.naturalVolumeExponent);
239
245
  return interpolatedValue;
240
246
  }
241
- onVolumeChange(volume) {
242
- volume = this.naturalVolume(volume);
243
- this.volume = volume;
244
- this.emit('volume-change', volume);
245
- if (!this.gainNode)
246
- return;
247
- this.gainNode.gain.value = volume;
247
+ setGainValue() {
248
+ if (this.gainNode) {
249
+ this.gainNode.gain.value = this.volume;
250
+ }
251
+ }
252
+ onVolumeDrag(volume) {
253
+ this.setVolume(this.naturalVolume(volume));
248
254
  }
249
255
  initFadeEffects() {
250
256
  if (!this.audioContext || !this.wavesurfer)
@@ -269,6 +275,11 @@ class EnvelopePlugin extends BasePlugin {
269
275
  // Fade out
270
276
  if (!this.isFadingOut && currentTime >= this.options.fadeOutStart && currentTime <= this.options.fadeOutEnd) {
271
277
  this.isFadingOut = true;
278
+ /**
279
+ * Set the gain at this point in time to the current volume, otherwise
280
+ * the audio will start fading out from the fade-in point.
281
+ */
282
+ this.gainNode.gain.setValueAtTime(this.volume, this.audioContext.currentTime);
272
283
  // Set the target gain (volume) to 0 (silent) over N seconds
273
284
  this.gainNode.gain.linearRampToValueAtTime(0, this.audioContext.currentTime + (this.options.fadeOutEnd - currentTime));
274
285
  return;
@@ -285,21 +296,39 @@ class EnvelopePlugin extends BasePlugin {
285
296
  }
286
297
  if (cancelRamp) {
287
298
  this.gainNode.gain.cancelScheduledValues(this.audioContext.currentTime);
288
- this.gainNode.gain.value = this.volume;
299
+ this.setGainValue();
289
300
  }
290
301
  });
291
302
  this.subscriptions.push(unsub);
292
303
  }
304
+ /** Get the current audio volume */
293
305
  getCurrentVolume() {
294
306
  return this.gainNode ? this.gainNode.gain.value : this.volume;
295
307
  }
296
- setStartTime(time) {
308
+ /** Set the fade-in start time */
309
+ setStartTime(time, moveDragPoint) {
310
+ const rampLength = this.options.fadeInEnd - this.options.fadeInStart;
297
311
  this.options.fadeInStart = time;
312
+ if (moveDragPoint) {
313
+ this.options.fadeInEnd = time + rampLength;
314
+ }
298
315
  this.renderPolyline();
299
316
  }
300
- setEndTime(time) {
317
+ /** Set the fade-out end time */
318
+ setEndTime(time, moveDragPoint) {
319
+ const rampLength = this.options.fadeOutEnd - this.options.fadeOutStart;
301
320
  this.options.fadeOutEnd = time;
321
+ if (moveDragPoint) {
322
+ this.options.fadeOutStart = time - rampLength;
323
+ }
302
324
  this.renderPolyline();
303
325
  }
326
+ /** Set the volume of the audio */
327
+ setVolume(volume) {
328
+ this.volume = volume;
329
+ this.setGainValue();
330
+ this.renderPolyline();
331
+ this.emit('volume-change', volume);
332
+ }
304
333
  }
305
334
  export default EnvelopePlugin;
@@ -1 +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.Envelope=e():t.Envelope=e()}(WaveSurfer,(()=>(()=>{"use strict";var t={284:(t,e,i)=>{i.d(e,{Z:()=>o});var s=i(139);class n extends s.Z{constructor(t){super(),this.subscriptions=[],this.options=t}init(t){this.wavesurfer=t.wavesurfer,this.container=t.container,this.wrapper=t.wrapper}destroy(){this.subscriptions.forEach((t=>t()))}}const o=n},139:(t,e,i)=>{i.d(e,{Z:()=>s});const s=class{constructor(){this.listeners={}}on(t,e){return this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),()=>this.un(t,e)}once(t,e){const i=this.on(t,e),s=this.on(t,(()=>{i(),s()}));return i}un(t,e){this.listeners[t]&&(e?this.listeners[t].delete(e):delete this.listeners[t])}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}}},e={};function i(s){var n=e[s];if(void 0!==n)return n.exports;var o=e[s]={exports:{}};return t[s](o,o.exports,i),o.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:()=>o});var t=i(284);const e={fadeInStart:0,fadeOutEnd:0,fadeInEnd:0,fadeOutStart:0,lineWidth:4,lineColor:"rgba(0, 0, 255, 0.5)",dragPointSize:10,dragPointFill:"rgba(255, 255, 255, 0.8)",dragPointStroke:"rgba(255, 255, 255, 0.8)"};class n extends t.Z{constructor(t){super(t),this.svg=null,this.audioContext=null,this.gainNode=null,this.volume=1,this.isFadingIn=!1,this.isFadingOut=!1,this.options=Object.assign({},e,t),this.options.lineColor=this.options.lineColor||e.lineColor,this.options.dragPointFill=this.options.dragPointFill||e.dragPointFill,this.options.dragPointStroke=this.options.dragPointStroke||e.dragPointStroke,this.volume=this.options.volume??1}static create(t){return new n(t)}init(t){if(super.init(t),!this.wavesurfer)throw Error("WaveSurfer is not initialized");let e;this.subscriptions.push(this.wavesurfer.once("decode",(t=>{this.options.fadeInStart=this.options.fadeInStart||0,this.options.fadeOutEnd=this.options.fadeOutEnd||t,this.options.fadeInEnd=this.options.fadeInEnd||this.options.fadeInStart,this.options.fadeOutStart=this.options.fadeOutStart||this.options.fadeOutEnd,this.initWebAudio(),this.initSvg(),this.initFadeEffects()}))),this.subscriptions.push(this.wavesurfer.on("zoom",(()=>{e&&clearTimeout(e),e=setTimeout((()=>{this.svg?.remove(),this.initSvg()}),100)})))}makeDraggable(t,e){t.addEventListener("mousedown",(t=>{let i=t.clientX,s=t.clientY;const n=this.wavesurfer?.options.interact||!0;let o;this.wavesurfer?.toggleInteraction(!1);const r=t=>{const n=t.clientX-i,o=t.clientY-s;i=t.clientX,s=t.clientY,e(n,o)},a=()=>{document.removeEventListener("mousemove",r),document.removeEventListener("mouseup",a),o&&clearTimeout(o),o=setTimeout((()=>{this.wavesurfer?.toggleInteraction(n)}),100)};document.addEventListener("mousemove",r),document.addEventListener("mouseup",a),t.preventDefault(),t.stopPropagation()}))}renderPolyline(){if(!this.svg||!this.wrapper||!this.wavesurfer)return;const t=this.svg.querySelector("polyline"),e=t.points,i=e.getItem(1).y,s=this.wrapper.clientWidth,n=this.wavesurfer.getDuration();e.getItem(0).x=this.options.fadeInStart/n*s,e.getItem(3).x=this.options.fadeOutEnd/n*s;const o=this.svg.querySelector("line");o.setAttribute("x1",e.getItem(1).x.toString()),o.setAttribute("x2",e.getItem(2).x.toString()),o.setAttribute("y1",i.toString()),o.setAttribute("y2",i.toString());const r=this.svg.querySelectorAll("circle");for(let e=0;e<r.length;e++){const s=r[e],n=t.points.getItem(e+1);s.setAttribute("cx",n.x.toString()),s.setAttribute("cy",i.toString())}}initSvg(){if(!this.wrapper||!this.wavesurfer)return;const t=this.wrapper.clientWidth,e=this.wrapper.clientHeight,i=this.wavesurfer.getDuration(),s=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttribute("width","100%"),s.setAttribute("height","100%"),s.setAttribute("viewBox",`0 0 ${t} ${e}`),s.setAttribute("preserveAspectRatio","none"),s.setAttribute("style","position: absolute; left: 0; top: 0; z-index: 4; pointer-events: none;"),this.svg=s;const n=document.createElementNS("http://www.w3.org/2000/svg","polyline");n.setAttribute("points","0,0 0,0 0,0 0,0"),n.setAttribute("stroke",this.options.lineColor),n.setAttribute("stroke-width",this.options.lineWidth),n.setAttribute("fill","none"),n.setAttribute("style","pointer-events: none"),s.appendChild(n);const o=document.createElementNS("http://www.w3.org/2000/svg","line");o.setAttribute("stroke","none"),o.setAttribute("stroke-width",(3*this.options.lineWidth).toString()),o.setAttribute("style","cursor: ns-resize; pointer-events: all;"),s.appendChild(o);const r=n.points,a=this.options.dragPointSize/2,h=e-this.volume*e+a;r.getItem(0).x=this.options.fadeInStart/i*t,r.getItem(0).y=e,r.getItem(1).x=this.options.fadeInEnd/i*t,r.getItem(1).y=h,r.getItem(2).x=this.options.fadeOutStart/i*t,r.getItem(2).y=h,r.getItem(3).x=this.options.fadeOutEnd/i*t,r.getItem(3).y=e,[1,2].forEach((()=>{const t=document.createElementNS("http://www.w3.org/2000/svg","circle");t.setAttribute("r",(this.options.dragPointSize/2).toString()),t.setAttribute("fill",this.options.dragPointFill),t.setAttribute("stroke",this.options.dragPointStroke||this.options.dragPointFill),t.setAttribute("stroke-width","2"),t.setAttribute("style","cursor: ew-resize; pointer-events: all;"),s.appendChild(t)})),this.wrapper.appendChild(s),this.renderPolyline();const u=t=>{const i=r.getItem(1).y+t-a;if(i<-.5||i>e)return;r.getItem(1).y=i+a,r.getItem(2).y=i+a,this.renderPolyline();const s=Math.min(1,Math.max(0,(e-i)/e));this.onVolumeChange(s),this.renderPolyline()},d=(e,s,o)=>{const r=n.points.getItem(o),a=r.x+e,h=a/t*i;1===o&&h>this.options.fadeOutStart||h<this.options.fadeInStart||2===o&&h<this.options.fadeInEnd||h>this.options.fadeOutEnd||(r.x=a,1===o?(this.options.fadeInEnd=h,this.emit("fade-in-change",h)):2===o&&(this.options.fadeOutStart=h,this.emit("fade-out-change",h)),s>1||s<-1?u(s):this.renderPolyline())};this.makeDraggable(o,((t,e)=>u(e)));const l=s.querySelectorAll("circle");for(let t=0;t<l.length;t++){const e=t+1;this.makeDraggable(l[t],((t,i)=>d(t,i,e)))}}destroy(){this.svg?.remove(),super.destroy()}initWebAudio(){const t=this.wavesurfer?.getMediaElement();if(!t)return null;this.volume=this.options.volume??t.volume;const e=new window.AudioContext;this.gainNode=e.createGain(),this.gainNode.gain.value=this.volume,e.createMediaElementSource(t).connect(this.gainNode),this.gainNode.connect(e.destination),this.audioContext=e}naturalVolume(t){return 1e-4+.9999*Math.pow(t,3)}onVolumeChange(t){t=this.naturalVolume(t),this.volume=t,this.emit("volume-change",t),this.gainNode&&(this.gainNode.gain.value=t)}initFadeEffects(){if(!this.audioContext||!this.wavesurfer)return;const t=this.wavesurfer.on("timeupdate",(t=>{if(!this.audioContext||!this.gainNode)return;if(!this.wavesurfer?.isPlaying())return;if("suspended"===this.audioContext.state&&this.audioContext.resume(),!this.isFadingIn&&t>=this.options.fadeInStart&&t<=this.options.fadeInEnd)return this.isFadingIn=!0,this.gainNode.gain.setValueAtTime(0,this.audioContext.currentTime),void this.gainNode.gain.linearRampToValueAtTime(this.volume,this.audioContext.currentTime+(this.options.fadeInEnd-t));if(!this.isFadingOut&&t>=this.options.fadeOutStart&&t<=this.options.fadeOutEnd)return this.isFadingOut=!0,void this.gainNode.gain.linearRampToValueAtTime(0,this.audioContext.currentTime+(this.options.fadeOutEnd-t));let e=!1;this.isFadingIn&&(t<this.options.fadeInStart||t>this.options.fadeInEnd)&&(this.isFadingIn=!1,e=!0),this.isFadingOut&&(t<this.options.fadeOutStart||t>=this.options.fadeOutEnd)&&(this.isFadingOut=!1,e=!0),e&&(this.gainNode.gain.cancelScheduledValues(this.audioContext.currentTime),this.gainNode.gain.value=this.volume)}));this.subscriptions.push(t)}getCurrentVolume(){return this.gainNode?this.gainNode.gain.value:this.volume}setStartTime(t){this.options.fadeInStart=t,this.renderPolyline()}setEndTime(t){this.options.fadeOutEnd=t,this.renderPolyline()}}const o=n})(),s.default})()));
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Envelope=e():t.Envelope=e()}(WaveSurfer,(()=>(()=>{"use strict";var t={284:(t,e,i)=>{i.d(e,{Z:()=>o});var s=i(139);class n extends s.Z{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}init(t){this.wavesurfer=t,this.onInit()}destroy(){this.subscriptions.forEach((t=>t()))}}const o=n},139:(t,e,i)=>{i.d(e,{Z:()=>s});const s=class{constructor(){this.listeners={}}on(t,e){return this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),()=>this.un(t,e)}once(t,e){const i=this.on(t,e),s=this.on(t,(()=>{i(),s()}));return i}un(t,e){this.listeners[t]&&(e?this.listeners[t].delete(e):delete this.listeners[t])}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}}},e={};function i(s){var n=e[s];if(void 0!==n)return n.exports;var o=e[s]={exports:{}};return t[s](o,o.exports,i),o.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:()=>o});var t=i(284);const e={fadeInStart:0,fadeOutEnd:0,fadeInEnd:0,fadeOutStart:0,lineWidth:4,lineColor:"rgba(0, 0, 255, 0.5)",dragPointSize:10,dragPointFill:"rgba(255, 255, 255, 0.8)",dragPointStroke:"rgba(255, 255, 255, 0.8)"};class n extends t.Z{constructor(t){super(t),this.svg=null,this.audioContext=null,this.gainNode=null,this.volume=1,this.isFadingIn=!1,this.isFadingOut=!1,this.naturalVolumeExponent=1.5,this.options=Object.assign({},e,t),this.options.lineColor=this.options.lineColor||e.lineColor,this.options.dragPointFill=this.options.dragPointFill||e.dragPointFill,this.options.dragPointStroke=this.options.dragPointStroke||e.dragPointStroke,this.volume=this.options.volume??1}static create(t){return new n(t)}onInit(){if(!this.wavesurfer)throw Error("WaveSurfer is not initialized");let t;this.subscriptions.push(this.wavesurfer.once("decode",(t=>{this.options.fadeInStart=this.options.fadeInStart||0,this.options.fadeOutEnd=this.options.fadeOutEnd||t,this.options.fadeInEnd=this.options.fadeInEnd||this.options.fadeInStart,this.options.fadeOutStart=this.options.fadeOutStart||this.options.fadeOutEnd,this.initWebAudio(),this.initSvg(),this.initFadeEffects()}))),this.subscriptions.push(this.wavesurfer.on("zoom",(()=>{t&&clearTimeout(t),t=setTimeout((()=>{this.svg?.remove(),this.initSvg()}),100)})))}makeDraggable(t,e){t.addEventListener("mousedown",(t=>{let i=t.clientX,s=t.clientY;const n=this.wavesurfer?.options.interact||!0;let o;this.wavesurfer?.toggleInteraction(!1);const r=t=>{const n=t.clientX-i,o=t.clientY-s;i=t.clientX,s=t.clientY,e(n,o)},a=()=>{document.removeEventListener("mousemove",r),document.removeEventListener("mouseup",a),o&&clearTimeout(o),o=setTimeout((()=>{this.wavesurfer?.toggleInteraction(n)}),100)};document.addEventListener("mousemove",r),document.addEventListener("mouseup",a),t.preventDefault(),t.stopPropagation()}))}renderPolyline(){if(!this.svg||!this.wavesurfer)return;const t=this.svg.querySelector("polyline"),e=t.points,i=this.svg.clientWidth,s=this.svg.clientHeight,n=this.wavesurfer.getDuration(),o=this.options.dragPointSize/2,r=s-this.invertNaturalVolume(this.volume)*s+o;e.getItem(1).y=r,e.getItem(2).y=r,e.getItem(0).x=this.options.fadeInStart/n*i,e.getItem(3).x=this.options.fadeOutEnd/n*i;const a=this.svg.querySelector("line");a.setAttribute("x1",e.getItem(1).x.toString()),a.setAttribute("x2",e.getItem(2).x.toString()),a.setAttribute("y1",r.toString()),a.setAttribute("y2",r.toString());const u=this.svg.querySelectorAll("circle");for(let e=0;e<u.length;e++){const i=u[e],s=t.points.getItem(e+1);i.setAttribute("cx",s.x.toString()),i.setAttribute("cy",r.toString())}}initSvg(){if(!this.wavesurfer)return;const t=this.wavesurfer.getWrapper(),e=t.clientWidth,i=t.clientHeight,s=this.wavesurfer.getDuration(),n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width","100%"),n.setAttribute("height","100%"),n.setAttribute("viewBox",`0 0 ${e} ${i}`),n.setAttribute("preserveAspectRatio","none"),n.setAttribute("style","position: absolute; left: 0; top: 0; z-index: 4; pointer-events: none;"),this.svg=n;const o=document.createElementNS("http://www.w3.org/2000/svg","polyline");o.setAttribute("points","0,0 0,0 0,0 0,0"),o.setAttribute("stroke",this.options.lineColor),o.setAttribute("stroke-width",this.options.lineWidth),o.setAttribute("fill","none"),o.setAttribute("style","pointer-events: none"),n.appendChild(o);const r=document.createElementNS("http://www.w3.org/2000/svg","line");r.setAttribute("stroke","none"),r.setAttribute("stroke-width",(3*this.options.lineWidth).toString()),r.setAttribute("style","cursor: ns-resize; pointer-events: all;"),n.appendChild(r);const a=o.points,u=this.options.dragPointSize/2;a.getItem(0).x=this.options.fadeInStart/s*e,a.getItem(0).y=i,a.getItem(1).x=this.options.fadeInEnd/s*e,a.getItem(1).y=0,a.getItem(2).x=this.options.fadeOutStart/s*e,a.getItem(2).y=0,a.getItem(3).x=this.options.fadeOutEnd/s*e,a.getItem(3).y=i,[1,2].forEach((()=>{const t=document.createElementNS("http://www.w3.org/2000/svg","circle");t.setAttribute("r",(this.options.dragPointSize/2).toString()),t.setAttribute("fill",this.options.dragPointFill),t.setAttribute("stroke",this.options.dragPointStroke||this.options.dragPointFill),t.setAttribute("stroke-width","2"),t.setAttribute("style","cursor: ew-resize; pointer-events: all;"),n.appendChild(t)})),this.wavesurfer.getWrapper().appendChild(n),this.renderPolyline();const h=t=>{const e=a.getItem(1).y+t-u;if(e<-.5||e>i)return;const s=Math.min(1,Math.max(0,(i-e)/i));this.onVolumeDrag(s)},d=(t,i,n)=>{const r=o.points.getItem(n),a=r.x+t,u=a/e*s;1===n&&u>this.options.fadeOutStart||u<this.options.fadeInStart||2===n&&u<this.options.fadeInEnd||u>this.options.fadeOutEnd||(r.x=a,1===n?(this.options.fadeInEnd=u,this.emit("fade-in-change",u)):2===n&&(this.options.fadeOutStart=u,this.emit("fade-out-change",u)),i>1||i<-1?h(i):this.renderPolyline())};this.makeDraggable(r,((t,e)=>h(e)));const l=n.querySelectorAll("circle");for(let t=0;t<l.length;t++){const e=t+1;this.makeDraggable(l[t],((t,i)=>d(t,i,e)))}}destroy(){this.svg?.remove(),super.destroy()}initWebAudio(){const t=this.wavesurfer?.getMediaElement();if(!t)return null;this.volume=this.options.volume??t.volume;const e=new window.AudioContext;this.gainNode=e.createGain(),this.setGainValue(),e.createMediaElementSource(t).connect(this.gainNode),this.gainNode.connect(e.destination),this.audioContext=e}invertNaturalVolume(t){return Math.pow((t-1e-4)/.9999,1/this.naturalVolumeExponent)}naturalVolume(t){return 1e-4+.9999*Math.pow(t,this.naturalVolumeExponent)}setGainValue(){this.gainNode&&(this.gainNode.gain.value=this.volume)}onVolumeDrag(t){this.setVolume(this.naturalVolume(t))}initFadeEffects(){if(!this.audioContext||!this.wavesurfer)return;const t=this.wavesurfer.on("timeupdate",(t=>{if(!this.audioContext||!this.gainNode)return;if(!this.wavesurfer?.isPlaying())return;if("suspended"===this.audioContext.state&&this.audioContext.resume(),!this.isFadingIn&&t>=this.options.fadeInStart&&t<=this.options.fadeInEnd)return this.isFadingIn=!0,this.gainNode.gain.setValueAtTime(0,this.audioContext.currentTime),void this.gainNode.gain.linearRampToValueAtTime(this.volume,this.audioContext.currentTime+(this.options.fadeInEnd-t));if(!this.isFadingOut&&t>=this.options.fadeOutStart&&t<=this.options.fadeOutEnd)return this.isFadingOut=!0,this.gainNode.gain.setValueAtTime(this.volume,this.audioContext.currentTime),void this.gainNode.gain.linearRampToValueAtTime(0,this.audioContext.currentTime+(this.options.fadeOutEnd-t));let e=!1;this.isFadingIn&&(t<this.options.fadeInStart||t>this.options.fadeInEnd)&&(this.isFadingIn=!1,e=!0),this.isFadingOut&&(t<this.options.fadeOutStart||t>=this.options.fadeOutEnd)&&(this.isFadingOut=!1,e=!0),e&&(this.gainNode.gain.cancelScheduledValues(this.audioContext.currentTime),this.setGainValue())}));this.subscriptions.push(t)}getCurrentVolume(){return this.gainNode?this.gainNode.gain.value:this.volume}setStartTime(t,e){const i=this.options.fadeInEnd-this.options.fadeInStart;this.options.fadeInStart=t,e&&(this.options.fadeInEnd=t+i),this.renderPolyline()}setEndTime(t,e){const i=this.options.fadeOutEnd-this.options.fadeOutStart;this.options.fadeOutEnd=t,e&&(this.options.fadeOutStart=t-i),this.renderPolyline()}setVolume(t){this.volume=t,this.setGainValue(),this.renderPolyline(),this.emit("volume-change",t)}}const o=n})(),s.default})()));
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Minimap is a tiny copy of the main waveform serving as a navigation tool.
3
3
  */
4
- import BasePlugin, { type WaveSurferPluginParams } from '../base-plugin.js';
4
+ import BasePlugin from '../base-plugin.js';
5
5
  import { type WaveSurferOptions } from '../wavesurfer.js';
6
6
  export type MinimapPluginOptions = {
7
7
  overlayColor?: string;
@@ -21,10 +21,11 @@ declare class MinimapPlugin extends BasePlugin<MinimapPluginEvents, MinimapPlugi
21
21
  private minimapWrapper;
22
22
  private miniWavesurfer;
23
23
  private overlay;
24
+ private container;
24
25
  constructor(options: MinimapPluginOptions);
25
26
  static create(options: MinimapPluginOptions): MinimapPlugin;
26
27
  /** Called by wavesurfer, don't call manually */
27
- init(params: WaveSurferPluginParams): void;
28
+ onInit(): void;
28
29
  private initMinimapWrapper;
29
30
  private initOverlay;
30
31
  private initMinimap;
@@ -12,6 +12,7 @@ class MinimapPlugin extends BasePlugin {
12
12
  constructor(options) {
13
13
  super(options);
14
14
  this.miniWavesurfer = null;
15
+ this.container = null;
15
16
  this.options = Object.assign({}, defaultOptions, options);
16
17
  this.minimapWrapper = this.initMinimapWrapper();
17
18
  this.overlay = this.initOverlay();
@@ -20,22 +21,21 @@ class MinimapPlugin extends BasePlugin {
20
21
  return new MinimapPlugin(options);
21
22
  }
22
23
  /** Called by wavesurfer, don't call manually */
23
- init(params) {
24
- super.init(params);
24
+ onInit() {
25
25
  if (!this.wavesurfer) {
26
26
  throw Error('WaveSurfer is not initialized');
27
27
  }
28
28
  if (this.options.container) {
29
- let container = null;
30
29
  if (typeof this.options.container === 'string') {
31
- container = document.querySelector(this.options.container);
30
+ this.container = document.querySelector(this.options.container);
32
31
  }
33
32
  else if (this.options.container instanceof HTMLElement) {
34
- container = this.options.container;
33
+ this.container = this.options.container;
35
34
  }
36
- container?.appendChild(this.minimapWrapper);
35
+ this.container?.appendChild(this.minimapWrapper);
37
36
  }
38
37
  else {
38
+ this.container = this.wavesurfer.getWrapper().parentElement;
39
39
  this.container?.insertAdjacentElement(this.options.insertPosition, this.minimapWrapper);
40
40
  }
41
41
  this.subscriptions.push(this.wavesurfer.on('decode', () => {
@@ -55,7 +55,7 @@ class MinimapPlugin extends BasePlugin {
55
55
  return div;
56
56
  }
57
57
  initMinimap() {
58
- if (!this.wavesurfer || !this.wrapper)
58
+ if (!this.wavesurfer)
59
59
  return;
60
60
  const data = this.wavesurfer.getDecodedData();
61
61
  const media = this.wavesurfer.getMediaElement();
@@ -70,7 +70,7 @@ class MinimapPlugin extends BasePlugin {
70
70
  peaks: [data.getChannelData(0)],
71
71
  duration: data.duration,
72
72
  });
73
- const overlayWidth = Math.round((this.minimapWrapper.clientWidth / this.wrapper.clientWidth) * 100);
73
+ const overlayWidth = Math.round((this.minimapWrapper.clientWidth / this.wavesurfer.getWrapper().clientWidth) * 100);
74
74
  this.overlay.style.width = `${overlayWidth}%`;
75
75
  this.subscriptions.push(this.wavesurfer.on('timeupdate', (currentTime) => {
76
76
  const offset = Math.max(0, Math.min((currentTime / data.duration) * 100 - overlayWidth / 2, 100 - overlayWidth)).toFixed(2);
@@ -1 +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.Minimap=e():t.Minimap=e()}(WaveSurfer,(()=>(()=>{"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:()=>m});const i=class{constructor(){this.listeners={}}on(t,e){return this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),()=>this.un(t,e)}once(t,e){const i=this.on(t,e),s=this.on(t,(()=>{i(),s()}));return i}un(t,e){this.listeners[t]&&(e?this.listeners[t].delete(e):delete this.listeners[t])}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}},s=class extends i{constructor(t){super(),this.subscriptions=[],this.options=t}init(t){this.wavesurfer=t.wavesurfer,this.container=t.container,this.wrapper=t.wrapper}destroy(){this.subscriptions.forEach((t=>t()))}},n={decode:async function(t){const e=new AudioContext({sampleRate:8e3}),i=e.decodeAudioData(t);return i.finally((()=>e.close())),i},createBuffer:function(t,e){if("number"==typeof t[0]&&(t=[t]),t[0].some((t=>t>1||t<-1))){const e=Math.max(...t[0]);t=t.map((t=>t.map((t=>t/e))))}return{length:t[0].length,duration:e,numberOfChannels:t.length,sampleRate:t[0].length/e,getChannelData:e=>t?.[e],copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};class r extends i{constructor(t,e){super(),this.options={height:0},this.timeout=null,this.isScrolling=!1,this.channelData=null,this.duration=null,this.resizeObserver=null,this.options={...e};let i=null;if("string"==typeof t.container?i=document.querySelector(t.container):t.container instanceof HTMLElement&&(i=t.container),!i)throw new Error("Container not found");const[s,n]=this.initHtml();i.appendChild(s),this.container=s,this.scrollContainer=n.querySelector(".scroll"),this.wrapper=n.querySelector(".wrapper"),this.canvasWrapper=n.querySelector(".canvases"),this.progressWrapper=n.querySelector(".progress"),this.initEvents()}initEvents(){this.wrapper.addEventListener("click",(t=>{const e=this.wrapper.getBoundingClientRect(),i=(t.clientX-e.left)/e.width;this.emit("click",i)})),this.scrollContainer.addEventListener("scroll",(()=>{const{scrollLeft:t,scrollWidth:e,clientWidth:i}=this.scrollContainer,s=t/e,n=(t+i)/e;this.emit("scroll",s,n)})),this.resizeObserver=new ResizeObserver((()=>{this.delay((()=>this.reRender()),100)})),this.resizeObserver.observe(this.scrollContainer)}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"});return e.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 .noScrollbar {\n scrollbar-color: transparent;\n scrollbar-width: none;\n }\n :host .noScrollbar::-webkit-scrollbar {\n display: none;\n -webkit-appearance: none;\n }\n :host .wrapper {\n position: relative;\n overflow: visible;\n z-index: 2;\n }\n :host .canvases {\n position: relative;\n height: ${this.options.height}px;\n }\n :host canvas {\n display: block;\n position: absolute;\n top: 0;\n image-rendering: pixelated;\n height: ${this.options.height}px;\n }\n :host .progress {\n pointer-events: none;\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n overflow: hidden;\n box-sizing: border-box;\n }\n </style>\n\n <div class="scroll">\n <div class="wrapper">\n <div class="canvases"></div>\n <div class="progress"></div>\n </div>\n </div>\n `,[t,e]}setOptions(t){this.options=t,this.reRender()}getContainer(){return this.scrollContainer}getWrapper(){return this.wrapper}destroy(){this.container.remove(),this.resizeObserver?.disconnect()}delay(t,e=10){return this.timeout&&clearTimeout(this.timeout),new Promise((i=>{this.timeout=setTimeout((()=>{i(t())}),e)}))}async renderPeaks(t,e,i,s){const n=null!=this.options.barWidth?this.options.barWidth*s:1,o=null!=this.options.barGap?this.options.barGap*s:this.options.barWidth?n/2:0,a=this.options.barRadius??0,h=this.options.barHeight??1,l=t[0],c=l.length,d=Math.floor(e/(n+o))/c,p=i/2,u=1===t.length,m=u?l:t[1],g=u&&m.some((t=>t<0)),y=(t,i)=>{let r=0,u=0,y=0;const f=document.createElement("canvas");f.width=Math.round(e*(i-t)/c),f.height=this.options.height,f.style.width=`${Math.floor(f.width/s)}px`,f.style.height=`${this.options.height}px`,f.style.left=`${Math.floor(t*e/s/c)}px`,this.canvasWrapper.appendChild(f);const v=f.getContext("2d",{desynchronized:!0});v.beginPath(),v.fillStyle=this.options.waveColor??"",v.roundRect||(v.roundRect=v.fillRect);for(let e=t;e<i;e++){const i=Math.round((e-t)*d);if(i>r){const t=Math.round(u*p*h),e=Math.round(y*p*h);v.roundRect(r*(n+o),p-t,n,t+(e||1),a),r=i,u=0,y=0}const s=g?l[e]:Math.abs(l[e]),c=g?m[e]:Math.abs(m[e]);s>u&&(u=s),(g?c<-y:c>y)&&(y=c<0?-c:c)}v.fill(),v.closePath();const b=f.cloneNode();this.progressWrapper.appendChild(b);const w=b.getContext("2d",{desynchronized:!0});f.width>0&&f.height>0&&w.drawImage(f,0,0),w.globalCompositeOperation="source-in",w.fillStyle=this.options.progressColor??"",w.fillRect(0,0,f.width,f.height)};this.canvasWrapper.innerHTML="",this.progressWrapper.innerHTML="";const{scrollLeft:f,scrollWidth:v,clientWidth:b}=this.scrollContainer,w=c/v;let C=Math.min(r.MAX_CANVAS_WIDTH,b);C-=C%((n+o)/s);const W=Math.floor(Math.abs(f)*w),M=Math.ceil(W+C*w);y(W,M);const E=M-W;for(let t=M;t<c;t+=E)await this.delay((()=>{y(t,Math.min(c,t+E))}));for(let t=W-1;t>=0;t-=E)await this.delay((()=>{y(Math.max(0,t-E),t)}))}render(t,e){const i=window.devicePixelRatio||1,s=this.scrollContainer.clientWidth,n=Math.ceil(e*(this.options.minPxPerSec||0));this.isScrolling=n>s;const r=this.options.fillParent&&!this.isScrolling,o=(r?s:n)*i,{height:a}=this.options;this.wrapper.style.width=r?"100%":`${n}px`,this.scrollContainer.style.overflowX=this.isScrolling?"auto":"hidden",this.scrollContainer.classList.toggle("noScrollbar",!!this.options.hideScrollbar),this.progressWrapper.style.borderRightStyle="solid",this.progressWrapper.style.borderRightColor=`${this.options.cursorColor||this.options.progressColor}`,this.progressWrapper.style.borderRightWidth=`${this.options.cursorWidth}px`,this.canvasWrapper.style.height=`${this.options.height}px`,this.renderPeaks(t,o,a,i),this.channelData=t,this.duration=e}reRender(){if(!this.channelData||!this.duration)return;const t=this.progressWrapper.clientWidth;this.render(this.channelData,this.duration);const e=this.progressWrapper.clientWidth;this.scrollContainer.scrollLeft+=e-t}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){const{clientWidth:i,scrollLeft:s,scrollWidth:n}=this.scrollContainer,r=n*t,o=i/2;if(r>s+(e&&this.options.autoCenter?o:i)||r<s)if(this.options.autoCenter){const t=o/20;r-(s+o)>=t&&r<s+i?this.scrollContainer.scrollLeft+=t:this.scrollContainer.scrollLeft=r-o}else this.scrollContainer.scrollLeft=r;{const{scrollLeft:t}=this.scrollContainer,e=t/n,s=(t+i)/n;this.emit("scroll",e,s)}}renderProgress(t,e){isNaN(t)||(this.progressWrapper.style.width=100*t+"%",this.isScrolling&&this.options.autoScroll&&this.scrollIntoView(t,e))}}r.MAX_CANVAS_WIDTH=4e3;const o=r,a=class extends i{constructor(t){super(),this.subscriptions=[],this.isExternalMedia=!1,t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),t.autoplay&&(this.media.autoplay=!0),null!=t.playbackRate&&(this.media.playbackRate=t.playbackRate)}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e)}onceMediaEvent(t,e){return this.onMediaEvent(t,e,{once:!0})}loadUrl(t){this.media.src=t}destroy(){this.media.pause(),this.subscriptions.forEach((t=>t())),this.isExternalMedia||this.media.remove()}play(){return this.media.play()}pause(){this.media.pause()}isPlaying(){return this.media.currentTime>0&&!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=t}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}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}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}},h=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()}},l={height:128,waveColor:"#999",progressColor:"#555",cursorWidth:1,minPxPerSec:0,fillParent:!0,interact:!0,autoScroll:!0,autoCenter:!0};class c extends a{static create(t){return new c(t)}constructor(t){super({media:t.media,autoplay:t.autoplay,playbackRate:t.audioRate}),this.plugins=[],this.decodedData=null,this.canPlay=!1,this.options=Object.assign({},l,t),this.fetcher=new class{async load(t){return fetch(t).then((t=>t.arrayBuffer()))}},this.timer=new h,this.renderer=new o({container:this.options.container},this.options),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initReadyEvent(),this.initPlugins();const e=this.options.url||this.options.media?.src;e&&this.load(e,this.options.peaks,this.options.duration)}setOptions(t){this.options={...this.options,...t},this.renderer.setOptions(this.options)}initPlayerEvents(){this.subscriptions.push(this.onMediaEvent("timeupdate",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),this.emit("timeupdate",t)})),this.onMediaEvent("play",(()=>{this.emit("play"),this.timer.start()})),this.onMediaEvent("pause",(()=>{this.emit("pause"),this.timer.stop(),this.getCurrentTime()>=this.getDuration()&&this.emit("finish")})),this.onMediaEvent("canplay",(()=>{this.canPlay=!0,this.emit("canplay",this.getDuration())})),this.onMediaEvent("seeking",(()=>{this.emit("seeking",this.getCurrentTime())})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",(t=>{this.options.interact&&(this.canPlay&&this.seekTo(t),this.emit("interaction"))})),this.renderer.on("scroll",((t,e)=>{const i=this.getDuration();this.emit("scroll",t*i,e*i)})))}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),!0),this.emit("timeupdate",t),this.emit("audioprocess",t)})))}initReadyEvent(){const t=()=>{this.decodedData&&this.canPlay&&this.emit("ready",this.getDuration())};this.subscriptions.push(this.on("decode",t),this.on("canplay",t))}initPlugins(){this.options.plugins?.length&&this.options.plugins.forEach((t=>{this.registerPlugin(t)}))}registerPlugin(t){return t.init({wavesurfer:this,container:this.renderer.getContainer(),wrapper:this.renderer.getWrapper()}),this.plugins.push(t),t}getActivePlugins(){return this.plugins}async load(t,e,i){if(this.decodedData=null,this.canPlay=!1,this.loadUrl(t),this.emit("load",t),e)i||(i=await new Promise((t=>{this.onceMediaEvent("loadedmetadata",(()=>t(this.getMediaElement().duration)))}))||0),this.decodedData=n.createBuffer(e,i);else{const e=await this.fetcher.load(t);this.decodedData=await n.decode(e)}this.renderAudio(),this.emit("decode",this.getDuration()),this.emit("redraw")}renderAudio(){if(!this.decodedData)return;const t=[this.decodedData.getChannelData(0)];this.decodedData.numberOfChannels>1&&t.push(this.decodedData.getChannelData(1)),this.renderer.render(t,this.decodedData.duration)}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(t),this.emit("zoom",t)}getDecodedData(){return this.decodedData}getDuration(){const t=super.getDuration();return t>0&&t<1/0?t:this.decodedData?.duration||0}toggleInteraction(t){this.options.interact=t}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}playPause(){return this.isPlaying()?(this.pause(),Promise.resolve()):this.play()}stop(){this.pause(),this.setTime(0)}skip(t){this.setTime(this.getCurrentTime()+t)}empty(){this.load("",[[0]],.001)}destroy(){this.emit("destroy"),this.plugins.forEach((t=>t.destroy())),this.timer.destroy(),this.renderer.destroy(),super.destroy()}}const d=c,p={height:50,overlayColor:"rgba(100, 100, 100, 0.1)",insertPosition:"afterend"};class u extends s{constructor(t){super(t),this.miniWavesurfer=null,this.options=Object.assign({},p,t),this.minimapWrapper=this.initMinimapWrapper(),this.overlay=this.initOverlay()}static create(t){return new u(t)}init(t){if(super.init(t),!this.wavesurfer)throw Error("WaveSurfer is not initialized");if(this.options.container){let t=null;"string"==typeof this.options.container?t=document.querySelector(this.options.container):this.options.container instanceof HTMLElement&&(t=this.options.container),t?.appendChild(this.minimapWrapper)}else this.container?.insertAdjacentElement(this.options.insertPosition,this.minimapWrapper);this.subscriptions.push(this.wavesurfer.on("decode",(()=>{this.initMinimap()})))}initMinimapWrapper(){const t=document.createElement("div");return t.style.position="relative",t}initOverlay(){const t=document.createElement("div");return t.setAttribute("style","position: absolute; z-index: 2; left: 0; top: 0; bottom: 0;"),t.style.backgroundColor=this.options.overlayColor,this.minimapWrapper.appendChild(t),t}initMinimap(){if(!this.wavesurfer||!this.wrapper)return;const t=this.wavesurfer.getDecodedData(),e=this.wavesurfer.getMediaElement();if(!t||!e)return;this.miniWavesurfer=d.create({...this.options,container:this.minimapWrapper,minPxPerSec:0,fillParent:!0,media:e,peaks:[t.getChannelData(0)],duration:t.duration});const i=Math.round(this.minimapWrapper.clientWidth/this.wrapper.clientWidth*100);this.overlay.style.width=`${i}%`,this.subscriptions.push(this.wavesurfer.on("timeupdate",(e=>{const s=Math.max(0,Math.min(e/t.duration*100-i/2,100-i)).toFixed(2);this.overlay.style.left=`${s}%`}))),this.subscriptions.push(this.miniWavesurfer.on("interaction",(()=>{this.wavesurfer&&this.miniWavesurfer&&this.wavesurfer.setTime(this.miniWavesurfer.getCurrentTime()),this.container&&(this.container.scrollLeft=this.minimapWrapper.scrollLeft/this.minimapWrapper.scrollWidth*this.container.scrollWidth),this.emit("interaction")})),this.miniWavesurfer.on("ready",(()=>{this.emit("ready")})))}destroy(){this.miniWavesurfer?.destroy(),this.minimapWrapper.remove(),super.destroy()}}const m=u;return e.default})()));
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Minimap=e():t.Minimap=e()}(WaveSurfer,(()=>(()=>{"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:()=>m});const i=class{constructor(){this.listeners={}}on(t,e){return this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),()=>this.un(t,e)}once(t,e){const i=this.on(t,e),s=this.on(t,(()=>{i(),s()}));return i}un(t,e){this.listeners[t]&&(e?this.listeners[t].delete(e):delete this.listeners[t])}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}},s=class extends i{constructor(t){super(),this.subscriptions=[],this.options=t}onInit(){}init(t){this.wavesurfer=t,this.onInit()}destroy(){this.subscriptions.forEach((t=>t()))}},n={decode:async function(t,e=8e3){const i=new AudioContext({sampleRate:e}),s=i.decodeAudioData(t);return s.finally((()=>i.close())),s},createBuffer:function(t,e){if("number"==typeof t[0]&&(t=[t]),t[0].some((t=>t>1||t<-1))){const e=Math.max(...t[0]);t=t.map((t=>t.map((t=>t/e))))}return{length:t[0].length,duration:e,numberOfChannels:t.length,sampleRate:t[0].length/e,getChannelData:e=>t?.[e],copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};class r extends i{constructor(t,e){super(),this.options={height:0},this.timeout=null,this.isScrolling=!1,this.channelData=null,this.duration=null,this.resizeObserver=null,this.options={...e};let i=null;if("string"==typeof t.container?i=document.querySelector(t.container):t.container instanceof HTMLElement&&(i=t.container),!i)throw new Error("Container not found");const[s,n]=this.initHtml();i.appendChild(s),this.container=s,this.scrollContainer=n.querySelector(".scroll"),this.wrapper=n.querySelector(".wrapper"),this.canvasWrapper=n.querySelector(".canvases"),this.progressWrapper=n.querySelector(".progress"),this.initEvents()}initEvents(){this.wrapper.addEventListener("click",(t=>{const e=this.wrapper.getBoundingClientRect(),i=(t.clientX-e.left)/e.width;this.emit("click",i)})),this.scrollContainer.addEventListener("scroll",(()=>{const{scrollLeft:t,scrollWidth:e,clientWidth:i}=this.scrollContainer,s=t/e,n=(t+i)/e;this.emit("scroll",s,n)})),this.resizeObserver=new ResizeObserver((()=>{this.delay((()=>this.reRender()),100)})),this.resizeObserver.observe(this.scrollContainer)}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"});return e.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 .noScrollbar {\n scrollbar-color: transparent;\n scrollbar-width: none;\n }\n :host .noScrollbar::-webkit-scrollbar {\n display: none;\n -webkit-appearance: none;\n }\n :host .wrapper {\n position: relative;\n overflow: visible;\n z-index: 2;\n }\n :host .canvases {\n position: relative;\n height: ${this.options.height}px;\n }\n :host canvas {\n display: block;\n position: absolute;\n top: 0;\n image-rendering: pixelated;\n height: ${this.options.height}px;\n }\n :host .progress {\n pointer-events: none;\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n overflow: hidden;\n box-sizing: border-box;\n }\n </style>\n\n <div class="scroll">\n <div class="wrapper">\n <div class="canvases"></div>\n <div class="progress"></div>\n </div>\n </div>\n `,[t,e]}setOptions(t){this.options=t,this.reRender()}getWrapper(){return this.wrapper}getScroll(){return this.scrollContainer.scrollLeft}destroy(){this.container.remove(),this.resizeObserver?.disconnect()}delay(t,e=10){return this.timeout&&clearTimeout(this.timeout),new Promise((i=>{this.timeout=setTimeout((()=>{i(t())}),e)}))}async renderPeaks(t,e,i,s){const n=null!=this.options.barWidth?this.options.barWidth*s:1,o=null!=this.options.barGap?this.options.barGap*s:this.options.barWidth?n/2:0,a=this.options.barRadius??0,h=this.options.barHeight??1,l=t[0],c=l.length,d=Math.floor(e/(n+o))/c,p=i/2,u=1===t.length,m=u?l:t[1],g=u&&m.some((t=>t<0)),y=(t,i)=>{let r=0,u=0,y=0;const f=document.createElement("canvas");f.width=Math.round(e*(i-t)/c),f.height=this.options.height,f.style.width=`${Math.floor(f.width/s)}px`,f.style.height=`${this.options.height}px`,f.style.left=`${Math.floor(t*e/s/c)}px`,this.canvasWrapper.appendChild(f);const v=f.getContext("2d",{desynchronized:!0});v.beginPath(),v.fillStyle=this.options.waveColor??"",v.roundRect||(v.roundRect=v.fillRect);for(let e=t;e<i;e++){const i=Math.round((e-t)*d);if(i>r){const t=Math.round(u*p*h),e=Math.round(y*p*h);v.roundRect(r*(n+o),p-t,n,t+(e||1),a),r=i,u=0,y=0}const s=g?l[e]:Math.abs(l[e]),c=g?m[e]:Math.abs(m[e]);s>u&&(u=s),(g?c<-y:c>y)&&(y=c<0?-c:c)}v.fill(),v.closePath();const b=f.cloneNode();this.progressWrapper.appendChild(b);const w=b.getContext("2d",{desynchronized:!0});f.width>0&&f.height>0&&w.drawImage(f,0,0),w.globalCompositeOperation="source-in",w.fillStyle=this.options.progressColor??"",w.fillRect(0,0,f.width,f.height)};this.canvasWrapper.innerHTML="",this.progressWrapper.innerHTML="";const{scrollLeft:f,scrollWidth:v,clientWidth:b}=this.scrollContainer,w=c/v;let W=Math.min(r.MAX_CANVAS_WIDTH,b);W-=W%((n+o)/s);const C=Math.floor(Math.abs(f)*w),M=Math.ceil(C+W*w);y(C,M);const E=M-C;for(let t=M;t<c;t+=E)await this.delay((()=>{y(t,Math.min(c,t+E))}));for(let t=C-1;t>=0;t-=E)await this.delay((()=>{y(Math.max(0,t-E),t)}))}render(t,e){const i=window.devicePixelRatio||1,s=this.scrollContainer.clientWidth,n=Math.ceil(e*(this.options.minPxPerSec||0));this.isScrolling=n>s;const r=this.options.fillParent&&!this.isScrolling,o=(r?s:n)*i,{height:a}=this.options;this.wrapper.style.width=r?"100%":`${n}px`,this.scrollContainer.style.overflowX=this.isScrolling?"auto":"hidden",this.scrollContainer.classList.toggle("noScrollbar",!!this.options.hideScrollbar),this.progressWrapper.style.borderRightStyle="solid",this.progressWrapper.style.borderRightColor=`${this.options.cursorColor||this.options.progressColor}`,this.progressWrapper.style.borderRightWidth=`${this.options.cursorWidth}px`,this.canvasWrapper.style.height=`${this.options.height}px`,this.renderPeaks(t,o,a,i),this.channelData=t,this.duration=e}reRender(){if(!this.channelData||!this.duration)return;const t=this.progressWrapper.clientWidth;this.render(this.channelData,this.duration);const e=this.progressWrapper.clientWidth;this.scrollContainer.scrollLeft+=e-t}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){const{clientWidth:i,scrollLeft:s,scrollWidth:n}=this.scrollContainer,r=n*t,o=i/2;if(r>s+(e&&this.options.autoCenter?o:i)||r<s)if(this.options.autoCenter){const t=o/20;r-(s+o)>=t&&r<s+i?this.scrollContainer.scrollLeft+=t:this.scrollContainer.scrollLeft=r-o}else this.scrollContainer.scrollLeft=r;{const{scrollLeft:t}=this.scrollContainer,e=t/n,s=(t+i)/n;this.emit("scroll",e,s)}}renderProgress(t,e){isNaN(t)||(this.progressWrapper.style.width=100*t+"%",this.isScrolling&&this.options.autoScroll&&this.scrollIntoView(t,e))}}r.MAX_CANVAS_WIDTH=4e3;const o=r,a=class extends i{constructor(t){super(),this.subscriptions=[],this.isExternalMedia=!1,t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),t.autoplay&&(this.media.autoplay=!0),null!=t.playbackRate&&(this.media.playbackRate=t.playbackRate)}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e)}onceMediaEvent(t,e){return this.onMediaEvent(t,e,{once:!0})}loadUrl(t){this.media.src=t}destroy(){this.media.pause(),this.subscriptions.forEach((t=>t())),this.isExternalMedia||this.media.remove()}play(){return this.media.play()}pause(){this.media.pause()}isPlaying(){return this.media.currentTime>0&&!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=t}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}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}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}},h=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()}},l={height:128,waveColor:"#999",progressColor:"#555",cursorWidth:1,minPxPerSec:0,fillParent:!0,interact:!0,autoScroll:!0,autoCenter:!0};class c extends a{static create(t){return new c(t)}constructor(t){super({media:t.media,autoplay:t.autoplay,playbackRate:t.audioRate}),this.plugins=[],this.decodedData=null,this.canPlay=!1,this.options=Object.assign({},l,t),this.fetcher=new class{async load(t){return fetch(t).then((t=>t.arrayBuffer()))}},this.timer=new h,this.renderer=new o({container:this.options.container},this.options),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initReadyEvent(),this.initPlugins();const e=this.options.url||this.options.media?.src;e&&this.load(e,this.options.peaks,this.options.duration)}setOptions(t){this.options={...this.options,...t},this.renderer.setOptions(this.options)}initPlayerEvents(){this.subscriptions.push(this.onMediaEvent("timeupdate",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),this.emit("timeupdate",t)})),this.onMediaEvent("play",(()=>{this.emit("play"),this.timer.start()})),this.onMediaEvent("pause",(()=>{this.emit("pause"),this.timer.stop(),this.getCurrentTime()>=this.getDuration()&&this.emit("finish")})),this.onMediaEvent("canplay",(()=>{this.canPlay=!0,this.emit("canplay",this.getDuration())})),this.onMediaEvent("seeking",(()=>{this.emit("seeking",this.getCurrentTime())})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",(t=>{this.options.interact&&(this.canPlay&&this.seekTo(t),this.emit("interaction"))})),this.renderer.on("scroll",((t,e)=>{const i=this.getDuration();this.emit("scroll",t*i,e*i)})))}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.getDuration(),!0),this.emit("timeupdate",t),this.emit("audioprocess",t)})))}initReadyEvent(){const t=()=>{this.decodedData&&this.canPlay&&this.emit("ready",this.getDuration())};this.subscriptions.push(this.on("decode",t),this.on("canplay",t))}initPlugins(){this.options.plugins?.length&&this.options.plugins.forEach((t=>{this.registerPlugin(t)}))}registerPlugin(t){return t.init(this),this.plugins.push(t),t}getWrapper(){return this.renderer.getWrapper()}getScroll(){return this.renderer.getScroll()}getActivePlugins(){return this.plugins}async load(t,e,i){if(this.decodedData=null,this.canPlay=!1,this.loadUrl(t),this.emit("load",t),e)i||(i=await new Promise((t=>{this.onceMediaEvent("loadedmetadata",(()=>t(this.getMediaElement().duration)))}))||0),this.decodedData=n.createBuffer(e,i);else{const e=await this.fetcher.load(t);this.decodedData=await n.decode(e,this.options.sampleRate)}this.renderAudio(),this.emit("decode",this.getDuration()),this.emit("redraw")}renderAudio(){if(!this.decodedData)return;const t=[this.decodedData.getChannelData(0)];this.decodedData.numberOfChannels>1&&t.push(this.decodedData.getChannelData(1)),this.renderer.render(t,this.decodedData.duration)}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(t),this.emit("zoom",t)}getDecodedData(){return this.decodedData}getDuration(){const t=super.getDuration();return t>0&&t<1/0?t:this.decodedData?.duration||0}toggleInteraction(t){this.options.interact=t}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}playPause(){return this.isPlaying()?(this.pause(),Promise.resolve()):this.play()}stop(){this.pause(),this.setTime(0)}skip(t){this.setTime(this.getCurrentTime()+t)}empty(){this.load("",[[0]],.001)}destroy(){this.emit("destroy"),this.plugins.forEach((t=>t.destroy())),this.timer.destroy(),this.renderer.destroy(),super.destroy()}}const d=c,p={height:50,overlayColor:"rgba(100, 100, 100, 0.1)",insertPosition:"afterend"};class u extends s{constructor(t){super(t),this.miniWavesurfer=null,this.container=null,this.options=Object.assign({},p,t),this.minimapWrapper=this.initMinimapWrapper(),this.overlay=this.initOverlay()}static create(t){return new u(t)}onInit(){if(!this.wavesurfer)throw Error("WaveSurfer is not initialized");this.options.container?("string"==typeof this.options.container?this.container=document.querySelector(this.options.container):this.options.container instanceof HTMLElement&&(this.container=this.options.container),this.container?.appendChild(this.minimapWrapper)):(this.container=this.wavesurfer.getWrapper().parentElement,this.container?.insertAdjacentElement(this.options.insertPosition,this.minimapWrapper)),this.subscriptions.push(this.wavesurfer.on("decode",(()=>{this.initMinimap()})))}initMinimapWrapper(){const t=document.createElement("div");return t.style.position="relative",t}initOverlay(){const t=document.createElement("div");return t.setAttribute("style","position: absolute; z-index: 2; left: 0; top: 0; bottom: 0;"),t.style.backgroundColor=this.options.overlayColor,this.minimapWrapper.appendChild(t),t}initMinimap(){if(!this.wavesurfer)return;const t=this.wavesurfer.getDecodedData(),e=this.wavesurfer.getMediaElement();if(!t||!e)return;this.miniWavesurfer=d.create({...this.options,container:this.minimapWrapper,minPxPerSec:0,fillParent:!0,media:e,peaks:[t.getChannelData(0)],duration:t.duration});const i=Math.round(this.minimapWrapper.clientWidth/this.wavesurfer.getWrapper().clientWidth*100);this.overlay.style.width=`${i}%`,this.subscriptions.push(this.wavesurfer.on("timeupdate",(e=>{const s=Math.max(0,Math.min(e/t.duration*100-i/2,100-i)).toFixed(2);this.overlay.style.left=`${s}%`}))),this.subscriptions.push(this.miniWavesurfer.on("interaction",(()=>{this.wavesurfer&&this.miniWavesurfer&&this.wavesurfer.setTime(this.miniWavesurfer.getCurrentTime()),this.container&&(this.container.scrollLeft=this.minimapWrapper.scrollLeft/this.minimapWrapper.scrollWidth*this.container.scrollWidth),this.emit("interaction")})),this.miniWavesurfer.on("ready",(()=>{this.emit("ready")})))}destroy(){this.miniWavesurfer?.destroy(),this.minimapWrapper.remove(),super.destroy()}}const m=u;return e.default})()));