wavesurfer.js 7.0.0-alpha.8 → 7.0.0-alpha.9

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/dist/index.d.ts CHANGED
@@ -108,7 +108,7 @@ export declare class WaveSurfer extends EventEmitter<WaveSurferEvents> {
108
108
  /** Set playback rate, with an optional parameter to NOT preserve the pitch if false */
109
109
  setPlaybackRate(rate: number, preservePitch?: boolean): void;
110
110
  /** Register and initialize a plugin */
111
- registerPlugin<T extends BasePlugin<GeneralEventTypes, unknown>>(CustomPlugin: new (params: unknown, options: unknown) => T, options?: unknown): T;
111
+ registerPlugin<T extends BasePlugin<GeneralEventTypes, any>>(CustomPlugin: new (params: WaveSurferPluginParams, options: any) => T, options?: any): T;
112
112
  /** Get the decoded audio data */
113
113
  getDecodedData(): AudioBuffer | null;
114
114
  /** Unmount wavesurfer */
@@ -0,0 +1,44 @@
1
+ import { type WaveSurferOptions } from '../index.js';
2
+ type MultitrackTracks = Array<{
3
+ id: string | number;
4
+ url?: string;
5
+ peaks?: WaveSurferOptions['peaks'];
6
+ draggable?: boolean;
7
+ startPosition: number;
8
+ startCue?: number;
9
+ endCue?: number;
10
+ markers?: Array<{
11
+ id: string | number;
12
+ time: number;
13
+ label?: string;
14
+ color?: string;
15
+ }>;
16
+ }>;
17
+ type MultitrackOptions = {
18
+ container: HTMLElement;
19
+ minPxPerSec: number;
20
+ } & WaveSurferOptions;
21
+ declare class MultiTrack {
22
+ private tracks;
23
+ private options;
24
+ private audios;
25
+ private wavesurfers;
26
+ private durations;
27
+ private currentTime;
28
+ private maxDuration;
29
+ private rendering;
30
+ private isDragging;
31
+ static create(tracks: MultitrackTracks, options: MultitrackOptions): MultiTrack;
32
+ constructor(tracks: MultitrackTracks, options: MultitrackOptions);
33
+ private initAudios;
34
+ private initWavesurfers;
35
+ private updatePosition;
36
+ private onSeek;
37
+ private onDrag;
38
+ private findCurrentTracks;
39
+ play(): void;
40
+ pause(): void;
41
+ isPlaying(): boolean;
42
+ destroy(): void;
43
+ }
44
+ export default MultiTrack;
@@ -0,0 +1,260 @@
1
+ import WaveSurfer from '../index.js';
2
+ import RegionsPlugin from './regions.js';
3
+ class MultiTrack {
4
+ static create(tracks, options) {
5
+ return new MultiTrack(tracks, options);
6
+ }
7
+ constructor(tracks, options) {
8
+ this.audios = [];
9
+ this.wavesurfers = [];
10
+ this.durations = [];
11
+ this.currentTime = 0;
12
+ this.maxDuration = 0;
13
+ this.isDragging = false;
14
+ this.tracks = tracks.map((track) => (Object.assign(Object.assign({}, track), { startPosition: track.startPosition || 0 })));
15
+ this.options = options;
16
+ this.rendering = initRendering(this.tracks, this.options);
17
+ this.initAudios().then((durations) => {
18
+ this.durations = durations;
19
+ const maxDuration = this.tracks.reduce((max, track, index) => {
20
+ return Math.max(max, track.startPosition + durations[index]);
21
+ }, 0);
22
+ this.rendering.setMainWidth(maxDuration * this.options.minPxPerSec);
23
+ this.rendering.addClickHandler((position) => {
24
+ this.onSeek(position * maxDuration);
25
+ });
26
+ this.maxDuration = maxDuration;
27
+ });
28
+ this.initWavesurfers();
29
+ this.rendering.containers.forEach((container, index) => {
30
+ const drag = initDragging(container, (delta) => this.onDrag(index, delta));
31
+ this.wavesurfers[index].once('destroy', () => {
32
+ drag === null || drag === void 0 ? void 0 : drag.destroy();
33
+ });
34
+ });
35
+ }
36
+ initAudios() {
37
+ const emptyTrackUrl = 'data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA';
38
+ this.audios = this.tracks.map((track) => new Audio(track.url || emptyTrackUrl));
39
+ return Promise.all(this.audios.map((audio) => {
40
+ return new Promise((resolve) => {
41
+ audio.addEventListener('canplay', () => {
42
+ resolve(audio.duration);
43
+ }, { once: true });
44
+ });
45
+ }));
46
+ }
47
+ initWavesurfers() {
48
+ const wavesurfers = this.tracks.map((track, index) => {
49
+ // Create a wavesurfer instance
50
+ const ws = WaveSurfer.create(Object.assign(Object.assign({}, this.options), { container: this.rendering.containers[index], media: this.audios[index], peaks: track.peaks, cursorColor: 'transparent', fillParent: false, interactive: false }));
51
+ ws.on('timeupdate', ({ currentTime }) => {
52
+ if (ws.isPlaying() && currentTime + track.startPosition > this.currentTime) {
53
+ this.updatePosition(track.startPosition + currentTime);
54
+ }
55
+ });
56
+ const wsRegions = ws.registerPlugin(RegionsPlugin, {
57
+ draggable: false,
58
+ resizable: false,
59
+ dragSelection: false,
60
+ });
61
+ ws.once('decode', () => {
62
+ // Render start and end cues
63
+ if (track.startCue) {
64
+ wsRegions.add(track.startCue, track.startCue, 'start');
65
+ }
66
+ if (track.endCue) {
67
+ wsRegions.add(track.endCue, track.endCue, 'end');
68
+ }
69
+ // Render markers
70
+ ;
71
+ (track.markers || []).forEach((marker) => {
72
+ wsRegions.add(marker.time, marker.time, marker.label, marker.color);
73
+ });
74
+ });
75
+ return ws;
76
+ });
77
+ this.wavesurfers = wavesurfers;
78
+ }
79
+ updatePosition(time) {
80
+ const precisionSeconds = 0.3;
81
+ this.currentTime = time;
82
+ this.rendering.updateCursor(time / this.maxDuration);
83
+ const isPaused = !this.isPlaying();
84
+ // Update the current time of each audio
85
+ this.tracks.forEach((track, index) => {
86
+ const audio = this.audios[index];
87
+ const duration = this.durations[index];
88
+ const newTime = time - track.startPosition;
89
+ if (Math.abs(audio.currentTime - newTime) > precisionSeconds) {
90
+ audio.currentTime = newTime;
91
+ }
92
+ // If the position is out of the track bounds, pause it
93
+ if (isPaused || newTime < 0 || newTime > duration) {
94
+ !audio.paused && audio.pause();
95
+ }
96
+ else if (!isPaused) {
97
+ // If the position is in the track bounds, play it
98
+ audio.paused && audio.play();
99
+ }
100
+ // Unmute if cue is reached
101
+ const newVolume = newTime >= (track.startCue || 0) && newTime < (track.endCue || Infinity) ? 1 : 0;
102
+ if (newVolume !== audio.volume)
103
+ audio.volume = newVolume;
104
+ });
105
+ }
106
+ onSeek(time) {
107
+ if (this.isDragging)
108
+ return;
109
+ const wasPlaying = this.isPlaying();
110
+ this.updatePosition(time);
111
+ if (wasPlaying)
112
+ this.play();
113
+ }
114
+ onDrag(index, delta) {
115
+ const track = this.tracks[index];
116
+ if (!track.draggable)
117
+ return;
118
+ this.isDragging = true;
119
+ setTimeout(() => (this.isDragging = false), 300);
120
+ const newTime = track.startPosition + delta * this.maxDuration;
121
+ track.startPosition = newTime;
122
+ this.rendering.setContainerOffsets();
123
+ }
124
+ findCurrentTracks() {
125
+ // Find the audios at the current time
126
+ const indexes = [];
127
+ this.tracks.forEach((track, index) => {
128
+ if (track.url &&
129
+ this.currentTime >= track.startPosition &&
130
+ this.currentTime < track.startPosition + this.durations[index]) {
131
+ indexes.push(index);
132
+ }
133
+ });
134
+ if (indexes.length === 0) {
135
+ const minStartTime = Math.min(...this.tracks.filter((t) => t.url).map((track) => track.startPosition));
136
+ indexes.push(this.tracks.findIndex((track) => track.startPosition === minStartTime));
137
+ }
138
+ return indexes;
139
+ }
140
+ play() {
141
+ const indexes = this.findCurrentTracks();
142
+ indexes.forEach((index) => {
143
+ var _a;
144
+ (_a = this.audios[index]) === null || _a === void 0 ? void 0 : _a.play();
145
+ });
146
+ }
147
+ pause() {
148
+ this.audios.forEach((audio) => audio.pause());
149
+ }
150
+ isPlaying() {
151
+ return this.audios.some((audio) => !audio.paused);
152
+ }
153
+ destroy() {
154
+ this.rendering.destroy();
155
+ this.audios.forEach((audio) => {
156
+ audio.pause();
157
+ audio.src = '';
158
+ });
159
+ this.wavesurfers.forEach((ws) => {
160
+ ws.destroy();
161
+ });
162
+ }
163
+ }
164
+ function initRendering(tracks, options) {
165
+ // Create a common container for all tracks
166
+ let scroll = document.createElement('div');
167
+ scroll.setAttribute('style', 'width: 100%; overflow-x: scroll; overflow-y: hidden; user-select: none;');
168
+ const wrapper = document.createElement('div');
169
+ wrapper.style.position = 'relative';
170
+ scroll.appendChild(wrapper);
171
+ options.container.appendChild(scroll);
172
+ // Create a common cursor
173
+ const cursor = document.createElement('div');
174
+ cursor.setAttribute('style', 'width: 1px; height: 100%; position: absolute; z-index: 10; top: 0; left: 0');
175
+ cursor.style.backgroundColor = options.cursorColor || options.progressColor || '#000';
176
+ wrapper.appendChild(cursor);
177
+ // Create containers for each track
178
+ const containers = tracks.map(() => {
179
+ const container = document.createElement('div');
180
+ container.style.width = 'fit-content';
181
+ wrapper.appendChild(container);
182
+ return container;
183
+ });
184
+ // Set the positions of each container
185
+ const setContainerOffsets = () => {
186
+ containers.forEach((container, i) => {
187
+ const offset = (tracks[i].startPosition * options.minPxPerSec) / devicePixelRatio;
188
+ container.style.transform = `translateX(${offset}px)`;
189
+ if (tracks[i].draggable)
190
+ container.style.cursor = 'ew-resize';
191
+ });
192
+ };
193
+ setContainerOffsets();
194
+ return {
195
+ containers,
196
+ // Set the start offset
197
+ setContainerOffsets,
198
+ // Set the container width
199
+ setMainWidth: (width) => {
200
+ wrapper.style.width = `${width / devicePixelRatio}px`;
201
+ },
202
+ // Update cursor position
203
+ updateCursor: (position) => {
204
+ cursor.style.left = `${Math.min(100, position * 100)}%`;
205
+ },
206
+ // Click to seek
207
+ addClickHandler: (onClick) => {
208
+ wrapper.addEventListener('click', (e) => {
209
+ const rect = wrapper.getBoundingClientRect();
210
+ const x = e.clientX - rect.left;
211
+ const position = x / wrapper.offsetWidth;
212
+ onClick(position);
213
+ });
214
+ },
215
+ // Destroy the container
216
+ destroy: () => {
217
+ scroll.remove();
218
+ },
219
+ };
220
+ }
221
+ function initDragging(container, onDrag) {
222
+ const wrapper = container.parentElement;
223
+ if (!wrapper)
224
+ return;
225
+ // Dragging tracks to set position
226
+ let dragStart = null;
227
+ // Drag start
228
+ container.addEventListener('mousedown', (e) => {
229
+ const rect = wrapper.getBoundingClientRect();
230
+ dragStart = e.clientX - rect.left;
231
+ });
232
+ // Drag end
233
+ const onMouseUp = (e) => {
234
+ if (dragStart != null) {
235
+ e.stopPropagation();
236
+ dragStart = null;
237
+ }
238
+ };
239
+ // Drag move
240
+ const onMouseMove = (e) => {
241
+ if (dragStart == null)
242
+ return;
243
+ const rect = wrapper.getBoundingClientRect();
244
+ const x = e.clientX - rect.left;
245
+ const diff = x - dragStart;
246
+ if (diff > 1 || diff < -1) {
247
+ dragStart = x;
248
+ onDrag(diff / wrapper.offsetWidth);
249
+ }
250
+ };
251
+ document.body.addEventListener('mouseup', onMouseUp);
252
+ document.body.addEventListener('mousemove', onMouseMove);
253
+ return {
254
+ destroy: () => {
255
+ document.body.removeEventListener('mouseup', onMouseUp);
256
+ document.body.removeEventListener('mousemove', onMouseMove);
257
+ },
258
+ };
259
+ }
260
+ export default MultiTrack;
@@ -46,7 +46,7 @@ declare class RegionsPlugin extends BasePlugin<RegionsPluginEvents, RegionsPlugi
46
46
  private updateRegion;
47
47
  private moveRegion;
48
48
  /** Create a region at a given start and end time, with an optional title */
49
- add(startTime: number, endTime: number, title?: string): Region;
49
+ add(startTime: number, endTime: number, title?: string, color?: string): Region;
50
50
  /** Set the background color of a region */
51
51
  setRegionColor(region: Region, color: string): void;
52
52
  }
@@ -32,16 +32,16 @@ class RegionsPlugin extends BasePlugin {
32
32
  };
33
33
  this.handleMouseMove = (e) => {
34
34
  const dragEnd = e.clientX - this.container.getBoundingClientRect().left;
35
- if (this.modifiedRegion && this.isMoving) {
35
+ if (this.options.draggable && this.modifiedRegion && this.isMoving) {
36
36
  this.moveRegion(this.modifiedRegion, dragEnd - this.dragStart);
37
37
  this.dragStart = dragEnd;
38
38
  return;
39
39
  }
40
- if (this.modifiedRegion) {
40
+ if (this.options.resizable && this.modifiedRegion) {
41
41
  this.updateRegion(this.modifiedRegion, this.isResizingLeft ? dragEnd : undefined, this.isResizingLeft ? undefined : dragEnd);
42
42
  return;
43
43
  }
44
- if (!isNaN(this.dragStart)) {
44
+ if (this.options.dragSelection && !isNaN(this.dragStart)) {
45
45
  const dragEnd = e.clientX - this.wrapper.getBoundingClientRect().left;
46
46
  if (dragEnd - this.dragStart >= MIN_WIDTH) {
47
47
  if (!this.createdRegion) {
@@ -64,7 +64,7 @@ class RegionsPlugin extends BasePlugin {
64
64
  this.dragStart = NaN;
65
65
  this.container.style.pointerEvents = '';
66
66
  };
67
- this.options = Object.assign(Object.assign({}, defaultOptions), options);
67
+ this.options = Object.assign({}, defaultOptions, options);
68
68
  this.wrapper = this.initWrapper();
69
69
  const unsubscribe = this.wavesurfer.once('decode', () => {
70
70
  this.container.appendChild(this.wrapper);
@@ -196,13 +196,15 @@ class RegionsPlugin extends BasePlugin {
196
196
  this.updateRegion(region, region.start + delta, region.end + delta);
197
197
  }
198
198
  /** Create a region at a given start and end time, with an optional title */
199
- add(startTime, endTime, title = '') {
199
+ add(startTime, endTime, title = '', color = '') {
200
200
  const duration = this.wavesurfer.getDuration();
201
201
  const width = this.wrapper.clientWidth;
202
202
  const start = (startTime / duration) * width;
203
203
  const end = (endTime / duration) * width;
204
204
  const region = this.createRegion(start, end, title);
205
205
  this.addRegion(region);
206
+ if (color)
207
+ this.setRegionColor(region, color);
206
208
  return region;
207
209
  }
208
210
  /** Set the background color of a region */
@@ -2,6 +2,7 @@ import BasePlugin from '../base-plugin.js';
2
2
  import { WaveSurferPluginParams } from '../index.js';
3
3
  type TimelinePluginOptions = {
4
4
  height?: number;
5
+ container?: HTMLElement;
5
6
  timeInterval?: number;
6
7
  primaryLabelInterval?: number;
7
8
  secondaryLabelInterval?: number;
@@ -4,8 +4,10 @@ const defaultOptions = {
4
4
  };
5
5
  class TimelinePlugin extends BasePlugin {
6
6
  constructor(params, options) {
7
+ var _a;
7
8
  super(params, options);
8
9
  this.options = Object.assign({}, defaultOptions, options);
10
+ this.container = (_a = this.options.container) !== null && _a !== void 0 ? _a : this.container;
9
11
  this.wrapper = this.initWrapper();
10
12
  this.container.appendChild(this.wrapper);
11
13
  this.subscriptions.push(this.wavesurfer.on('decode', ({ duration }) => {
@@ -0,0 +1,44 @@
1
+ import { type WaveSurferOptions } from '../index.js';
2
+ type MultitrackTracks = Array<{
3
+ id: string | number;
4
+ url?: string;
5
+ peaks?: WaveSurferOptions['peaks'];
6
+ draggable?: boolean;
7
+ startPosition: number;
8
+ startCue?: number;
9
+ endCue?: number;
10
+ markers?: Array<{
11
+ id: string | number;
12
+ time: number;
13
+ label?: string;
14
+ color?: string;
15
+ }>;
16
+ }>;
17
+ type MultitrackOptions = {
18
+ container: HTMLElement;
19
+ minPxPerSec: number;
20
+ } & WaveSurferOptions;
21
+ declare class MultiTrack {
22
+ private tracks;
23
+ private options;
24
+ private audios;
25
+ private wavesurfers;
26
+ private durations;
27
+ private currentTime;
28
+ private maxDuration;
29
+ private rendering;
30
+ private isDragging;
31
+ static create(tracks: MultitrackTracks, options: MultitrackOptions): MultiTrack;
32
+ constructor(tracks: MultitrackTracks, options: MultitrackOptions);
33
+ private initAudios;
34
+ private initWavesurfers;
35
+ private updatePosition;
36
+ private onSeek;
37
+ private onDrag;
38
+ private findCurrentTracks;
39
+ play(): void;
40
+ pause(): void;
41
+ isPlaying(): boolean;
42
+ destroy(): void;
43
+ }
44
+ export default MultiTrack;
@@ -0,0 +1,260 @@
1
+ import WaveSurfer from '../index.js';
2
+ import RegionsPlugin from './regions.js';
3
+ class MultiTrack {
4
+ static create(tracks, options) {
5
+ return new MultiTrack(tracks, options);
6
+ }
7
+ constructor(tracks, options) {
8
+ this.audios = [];
9
+ this.wavesurfers = [];
10
+ this.durations = [];
11
+ this.currentTime = 0;
12
+ this.maxDuration = 0;
13
+ this.isDragging = false;
14
+ this.tracks = tracks.map((track) => (Object.assign(Object.assign({}, track), { startPosition: track.startPosition || 0 })));
15
+ this.options = options;
16
+ this.rendering = initRendering(this.tracks, this.options);
17
+ this.initAudios().then((durations) => {
18
+ this.durations = durations;
19
+ const maxDuration = this.tracks.reduce((max, track, index) => {
20
+ return Math.max(max, track.startPosition + durations[index]);
21
+ }, 0);
22
+ this.rendering.setMainWidth(maxDuration * this.options.minPxPerSec);
23
+ this.rendering.addClickHandler((position) => {
24
+ this.onSeek(position * maxDuration);
25
+ });
26
+ this.maxDuration = maxDuration;
27
+ });
28
+ this.initWavesurfers();
29
+ this.rendering.containers.forEach((container, index) => {
30
+ const drag = initDragging(container, (delta) => this.onDrag(index, delta));
31
+ this.wavesurfers[index].once('destroy', () => {
32
+ drag === null || drag === void 0 ? void 0 : drag.destroy();
33
+ });
34
+ });
35
+ }
36
+ initAudios() {
37
+ const emptyTrackUrl = 'data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA';
38
+ this.audios = this.tracks.map((track) => new Audio(track.url || emptyTrackUrl));
39
+ return Promise.all(this.audios.map((audio) => {
40
+ return new Promise((resolve) => {
41
+ audio.addEventListener('canplay', () => {
42
+ resolve(audio.duration);
43
+ }, { once: true });
44
+ });
45
+ }));
46
+ }
47
+ initWavesurfers() {
48
+ const wavesurfers = this.tracks.map((track, index) => {
49
+ // Create a wavesurfer instance
50
+ const ws = WaveSurfer.create(Object.assign(Object.assign({}, this.options), { container: this.rendering.containers[index], media: this.audios[index], peaks: track.peaks, cursorColor: 'transparent', fillParent: false, interactive: false }));
51
+ ws.on('timeupdate', ({ currentTime }) => {
52
+ if (ws.isPlaying() && currentTime + track.startPosition > this.currentTime) {
53
+ this.updatePosition(track.startPosition + currentTime);
54
+ }
55
+ });
56
+ const wsRegions = ws.registerPlugin(RegionsPlugin, {
57
+ draggable: false,
58
+ resizable: false,
59
+ dragSelection: false,
60
+ });
61
+ ws.once('decode', () => {
62
+ // Render start and end cues
63
+ if (track.startCue) {
64
+ wsRegions.add(track.startCue, track.startCue, 'start');
65
+ }
66
+ if (track.endCue) {
67
+ wsRegions.add(track.endCue, track.endCue, 'end');
68
+ }
69
+ // Render markers
70
+ ;
71
+ (track.markers || []).forEach((marker) => {
72
+ wsRegions.add(marker.time, marker.time, marker.label, marker.color);
73
+ });
74
+ });
75
+ return ws;
76
+ });
77
+ this.wavesurfers = wavesurfers;
78
+ }
79
+ updatePosition(time) {
80
+ const precisionSeconds = 0.3;
81
+ this.currentTime = time;
82
+ this.rendering.updateCursor(time / this.maxDuration);
83
+ const isPaused = !this.isPlaying();
84
+ // Update the current time of each audio
85
+ this.tracks.forEach((track, index) => {
86
+ const audio = this.audios[index];
87
+ const duration = this.durations[index];
88
+ const newTime = time - track.startPosition;
89
+ if (Math.abs(audio.currentTime - newTime) > precisionSeconds) {
90
+ audio.currentTime = newTime;
91
+ }
92
+ // If the position is out of the track bounds, pause it
93
+ if (isPaused || newTime < 0 || newTime > duration) {
94
+ !audio.paused && audio.pause();
95
+ }
96
+ else if (!isPaused) {
97
+ // If the position is in the track bounds, play it
98
+ audio.paused && audio.play();
99
+ }
100
+ // Unmute if cue is reached
101
+ const newVolume = newTime >= (track.startCue || 0) && newTime < (track.endCue || Infinity) ? 1 : 0;
102
+ if (newVolume !== audio.volume)
103
+ audio.volume = newVolume;
104
+ });
105
+ }
106
+ onSeek(time) {
107
+ if (this.isDragging)
108
+ return;
109
+ const wasPlaying = this.isPlaying();
110
+ this.updatePosition(time);
111
+ if (wasPlaying)
112
+ this.play();
113
+ }
114
+ onDrag(index, delta) {
115
+ const track = this.tracks[index];
116
+ if (!track.draggable)
117
+ return;
118
+ this.isDragging = true;
119
+ setTimeout(() => (this.isDragging = false), 300);
120
+ const newTime = track.startPosition + delta * this.maxDuration;
121
+ track.startPosition = newTime;
122
+ this.rendering.setContainerOffsets();
123
+ }
124
+ findCurrentTracks() {
125
+ // Find the audios at the current time
126
+ const indexes = [];
127
+ this.tracks.forEach((track, index) => {
128
+ if (track.url &&
129
+ this.currentTime >= track.startPosition &&
130
+ this.currentTime < track.startPosition + this.durations[index]) {
131
+ indexes.push(index);
132
+ }
133
+ });
134
+ if (indexes.length === 0) {
135
+ const minStartTime = Math.min(...this.tracks.filter((t) => t.url).map((track) => track.startPosition));
136
+ indexes.push(this.tracks.findIndex((track) => track.startPosition === minStartTime));
137
+ }
138
+ return indexes;
139
+ }
140
+ play() {
141
+ const indexes = this.findCurrentTracks();
142
+ indexes.forEach((index) => {
143
+ var _a;
144
+ (_a = this.audios[index]) === null || _a === void 0 ? void 0 : _a.play();
145
+ });
146
+ }
147
+ pause() {
148
+ this.audios.forEach((audio) => audio.pause());
149
+ }
150
+ isPlaying() {
151
+ return this.audios.some((audio) => !audio.paused);
152
+ }
153
+ destroy() {
154
+ this.rendering.destroy();
155
+ this.audios.forEach((audio) => {
156
+ audio.pause();
157
+ audio.src = '';
158
+ });
159
+ this.wavesurfers.forEach((ws) => {
160
+ ws.destroy();
161
+ });
162
+ }
163
+ }
164
+ function initRendering(tracks, options) {
165
+ // Create a common container for all tracks
166
+ let scroll = document.createElement('div');
167
+ scroll.setAttribute('style', 'width: 100%; overflow-x: scroll; overflow-y: hidden; user-select: none;');
168
+ const wrapper = document.createElement('div');
169
+ wrapper.style.position = 'relative';
170
+ scroll.appendChild(wrapper);
171
+ options.container.appendChild(scroll);
172
+ // Create a common cursor
173
+ const cursor = document.createElement('div');
174
+ cursor.setAttribute('style', 'width: 1px; height: 100%; position: absolute; z-index: 10; top: 0; left: 0');
175
+ cursor.style.backgroundColor = options.cursorColor || options.progressColor || '#000';
176
+ wrapper.appendChild(cursor);
177
+ // Create containers for each track
178
+ const containers = tracks.map(() => {
179
+ const container = document.createElement('div');
180
+ container.style.width = 'fit-content';
181
+ wrapper.appendChild(container);
182
+ return container;
183
+ });
184
+ // Set the positions of each container
185
+ const setContainerOffsets = () => {
186
+ containers.forEach((container, i) => {
187
+ const offset = (tracks[i].startPosition * options.minPxPerSec) / devicePixelRatio;
188
+ container.style.transform = `translateX(${offset}px)`;
189
+ if (tracks[i].draggable)
190
+ container.style.cursor = 'ew-resize';
191
+ });
192
+ };
193
+ setContainerOffsets();
194
+ return {
195
+ containers,
196
+ // Set the start offset
197
+ setContainerOffsets,
198
+ // Set the container width
199
+ setMainWidth: (width) => {
200
+ wrapper.style.width = `${width / devicePixelRatio}px`;
201
+ },
202
+ // Update cursor position
203
+ updateCursor: (position) => {
204
+ cursor.style.left = `${Math.min(100, position * 100)}%`;
205
+ },
206
+ // Click to seek
207
+ addClickHandler: (onClick) => {
208
+ wrapper.addEventListener('click', (e) => {
209
+ const rect = wrapper.getBoundingClientRect();
210
+ const x = e.clientX - rect.left;
211
+ const position = x / wrapper.offsetWidth;
212
+ onClick(position);
213
+ });
214
+ },
215
+ // Destroy the container
216
+ destroy: () => {
217
+ scroll.remove();
218
+ },
219
+ };
220
+ }
221
+ function initDragging(container, onDrag) {
222
+ const wrapper = container.parentElement;
223
+ if (!wrapper)
224
+ return;
225
+ // Dragging tracks to set position
226
+ let dragStart = null;
227
+ // Drag start
228
+ container.addEventListener('mousedown', (e) => {
229
+ const rect = wrapper.getBoundingClientRect();
230
+ dragStart = e.clientX - rect.left;
231
+ });
232
+ // Drag end
233
+ const onMouseUp = (e) => {
234
+ if (dragStart != null) {
235
+ e.stopPropagation();
236
+ dragStart = null;
237
+ }
238
+ };
239
+ // Drag move
240
+ const onMouseMove = (e) => {
241
+ if (dragStart == null)
242
+ return;
243
+ const rect = wrapper.getBoundingClientRect();
244
+ const x = e.clientX - rect.left;
245
+ const diff = x - dragStart;
246
+ if (diff > 1 || diff < -1) {
247
+ dragStart = x;
248
+ onDrag(diff / wrapper.offsetWidth);
249
+ }
250
+ };
251
+ document.body.addEventListener('mouseup', onMouseUp);
252
+ document.body.addEventListener('mousemove', onMouseMove);
253
+ return {
254
+ destroy: () => {
255
+ document.body.removeEventListener('mouseup', onMouseUp);
256
+ document.body.removeEventListener('mousemove', onMouseMove);
257
+ },
258
+ };
259
+ }
260
+ export default MultiTrack;
package/dist/renderer.js CHANGED
@@ -203,7 +203,7 @@ class Renderer extends EventEmitter {
203
203
  const parentWidth = this.options.fillParent ? this.scrollContainer.clientWidth * devicePixelRatio : 0;
204
204
  const scrollWidth = audioData.duration * this.options.minPxPerSec;
205
205
  const isScrolling = scrollWidth > parentWidth;
206
- const width = isScrolling ? scrollWidth : parentWidth;
206
+ const width = Math.max(1, isScrolling ? scrollWidth : parentWidth);
207
207
  const { height } = this.options;
208
208
  this.mainCanvas.width = width;
209
209
  this.mainCanvas.height = height;
@@ -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 o=n,r={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 o{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({},r,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 o=h("div",{position:"absolute",left:"0",width:"6px",height:"100%",cursor:this.options.resizable?"ew-resize":"",pointerEvents:"all"});n.appendChild(o);const r=o.cloneNode();return a(r,{left:"",right:"0",borderLeft:""}),n.appendChild(r),o.addEventListener("mousedown",(t=>{this.options.resizable&&(t.stopPropagation(),this.modifiedRegion=this.regions.find((t=>t.element===n))||null,this.isResizingLeft=!0,this.isMoving=!1)})),r.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(),o=this.wrapper.clientWidth,r=t/n*o,a=e/n*o,h=this.createRegion(r,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 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:()=>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,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,d=t[0],l=d.length,c=Math.floor(e/(r+a))/l,u=i/2,p=1===t.length,g=p?d:t[1],m=p&&g.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 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);o.roundRect(i*(r+a),u-e,r,e+d||1,h),i=t,s=0,n=0}const e=m?d[l]:Math.abs(d[l]),p=m?g[l]:Math.abs(g[l]);e>s&&(s=e),(m?p<-n:p>n)&&(n=p<0?-p:p)}o.fill(),o.closePath()};o.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((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)}}}const n=e;class o 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 r=o;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,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 r,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,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 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.tracks=t.map((t=>Object.assign(Object.assign({},t),{startPosition:t.startPosition||0}))),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 o=t.map((()=>{const t=document.createElement("div");return t.style.width="fit-content",s.appendChild(t),t})),r=()=>{o.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 r(),{containers:o,setContainerOffsets:r,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)},o=t=>{if(null==s)return;const n=i.getBoundingClientRect(),o=t.clientX-n.left,r=o-s;(r>1||r<-1)&&(s=o,e(r/i.offsetWidth))};return document.body.addEventListener("mouseup",n),document.body.addEventListener("mousemove",o),{destroy:()=>{document.body.removeEventListener("mouseup",n),document.body.removeEventListener("mousemove",o)}}}(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}));i.on("timeupdate",(({currentTime:e})=>{i.isPlaying()&&e+t.startPosition>this.currentTime&&this.updatePosition(t.startPosition+e)}));const 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],o=this.durations[s],r=t-i.startPosition;Math.abs(n.currentTime-r)>.3&&(n.currentTime=r),e||r<0||r>o?!n.paused&&n.pause():e||n.paused&&n.play();const a=r>=(i.startCue||0)&&r<(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}play(){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.rendering.destroy(),this.audios.forEach((t=>{t.pause(),t.src=""})),this.wavesurfers.forEach((t=>{t.destroy()}))}}const u=c})(),s.default})()));
@@ -1 +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={d:(t,i)=>{for(var n in i)e.o(i,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:i[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{default:()=>a});const i=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)}},n=class extends i{constructor(e,t){super(),this.subscriptions=[],this.wavesurfer=e.wavesurfer,this.container=e.container,this.options=t}destroy(){this.subscriptions.forEach((e=>e()))}},s={dragSelection:!0,draggable:!0,resizable:!0},o=(e,t)=>{for(const i in t)e.style[i]=t[i]||""},r=(e,t)=>{const i=document.createElement(e);return o(i,t),i},a=class extends n{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.modifiedRegion&&this.isMoving)return this.moveRegion(this.modifiedRegion,t-this.dragStart),void(this.dragStart=t);if(this.modifiedRegion)this.updateRegion(this.modifiedRegion,this.isResizingLeft?t:void 0,this.isResizingLeft?void 0:t);else if(!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(Object.assign({},s),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 r("div",{position:"absolute",top:"0",left:"0",width:"100%",height:"100%",zIndex:"3",pointerEvents:"none"})}createRegionElement(e,t,i=""){const n=e===t,s=r("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 a=r("div",{position:"absolute",left:"0",width:"6px",height:"100%",cursor:this.options.resizable?"ew-resize":"",pointerEvents:"all"});s.appendChild(a);const d=a.cloneNode();return o(d,{left:"",right:"0",borderLeft:""}),s.appendChild(d),a.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=""){const n=this.wavesurfer.getDuration(),s=this.wrapper.clientWidth,o=e/n*s,r=t/n*s,a=this.createRegion(o,r,i);return this.addRegion(a),a}setRegionColor(e,t){e.element.style[e.startTime===e.endTime?"borderColor":"backgroundColor"]=t}};return t.default})()));
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})()));
@@ -1 +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){super(e,t),this.options=Object.assign({},r,t),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})()));
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})()));
@@ -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.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?s:i,{height:o}=this.options;this.mainCanvas.width=n,this.mainCanvas.height=o,this.mainCanvas.style.width=Math.floor(s/e)+"px";const r=[t.getChannelData(0)];t.numberOfChannels>1&&r.push(t.getChannelData(1)),this.renderPeaks(r,n,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)}}},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})()));
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,6 +1,6 @@
1
1
  {
2
2
  "name": "wavesurfer.js",
3
- "version": "7.0.0-alpha.8",
3
+ "version": "7.0.0-alpha.9",
4
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",