wavesurfer.js 6.1.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGES.md +20 -0
  2. package/LICENSE +1 -1
  3. package/README.md +0 -10
  4. package/dist/plugin/wavesurfer.cursor.js +4 -4
  5. package/dist/plugin/wavesurfer.cursor.js.map +1 -1
  6. package/dist/plugin/wavesurfer.cursor.min.js +2 -2
  7. package/dist/plugin/wavesurfer.cursor.min.js.map +1 -1
  8. package/dist/plugin/wavesurfer.elan.js +2 -2
  9. package/dist/plugin/wavesurfer.elan.js.map +1 -1
  10. package/dist/plugin/wavesurfer.elan.min.js +2 -2
  11. package/dist/plugin/wavesurfer.elan.min.js.map +1 -1
  12. package/dist/plugin/wavesurfer.markers.js +42 -7
  13. package/dist/plugin/wavesurfer.markers.js.map +1 -1
  14. package/dist/plugin/wavesurfer.markers.min.js +2 -2
  15. package/dist/plugin/wavesurfer.markers.min.js.map +1 -1
  16. package/dist/plugin/wavesurfer.mediasession.js +2 -2
  17. package/dist/plugin/wavesurfer.mediasession.js.map +1 -1
  18. package/dist/plugin/wavesurfer.mediasession.min.js +2 -2
  19. package/dist/plugin/wavesurfer.mediasession.min.js.map +1 -1
  20. package/dist/plugin/wavesurfer.microphone.js +2 -2
  21. package/dist/plugin/wavesurfer.microphone.js.map +1 -1
  22. package/dist/plugin/wavesurfer.microphone.min.js +2 -2
  23. package/dist/plugin/wavesurfer.microphone.min.js.map +1 -1
  24. package/dist/plugin/wavesurfer.minimap.js +2 -2
  25. package/dist/plugin/wavesurfer.minimap.js.map +1 -1
  26. package/dist/plugin/wavesurfer.minimap.min.js +2 -2
  27. package/dist/plugin/wavesurfer.minimap.min.js.map +1 -1
  28. package/dist/plugin/wavesurfer.playhead.js +2 -2
  29. package/dist/plugin/wavesurfer.playhead.js.map +1 -1
  30. package/dist/plugin/wavesurfer.playhead.min.js +2 -2
  31. package/dist/plugin/wavesurfer.playhead.min.js.map +1 -1
  32. package/dist/plugin/wavesurfer.regions.js +3 -3
  33. package/dist/plugin/wavesurfer.regions.js.map +1 -1
  34. package/dist/plugin/wavesurfer.regions.min.js +2 -2
  35. package/dist/plugin/wavesurfer.regions.min.js.map +1 -1
  36. package/dist/plugin/wavesurfer.spectrogram.js +15 -11
  37. package/dist/plugin/wavesurfer.spectrogram.js.map +1 -1
  38. package/dist/plugin/wavesurfer.spectrogram.min.js +2 -2
  39. package/dist/plugin/wavesurfer.spectrogram.min.js.map +1 -1
  40. package/dist/plugin/wavesurfer.timeline.js +2 -2
  41. package/dist/plugin/wavesurfer.timeline.js.map +1 -1
  42. package/dist/plugin/wavesurfer.timeline.min.js +2 -2
  43. package/dist/plugin/wavesurfer.timeline.min.js.map +1 -1
  44. package/dist/wavesurfer-html-init.js +2 -2
  45. package/dist/wavesurfer-html-init.js.map +1 -1
  46. package/dist/wavesurfer-html-init.min.js +2 -2
  47. package/dist/wavesurfer-html-init.min.js.map +1 -1
  48. package/dist/wavesurfer.js +34 -31
  49. package/dist/wavesurfer.js.map +1 -1
  50. package/dist/wavesurfer.min.js +2 -2
  51. package/dist/wavesurfer.min.js.map +1 -1
  52. package/package.json +18 -19
  53. package/src/drawer.multicanvas.js +4 -4
  54. package/src/plugin/cursor/index.js +2 -1
  55. package/src/plugin/markers/index.js +31 -5
  56. package/src/plugin/regions/index.js +1 -1
  57. package/src/plugin/spectrogram/index.js +13 -9
  58. package/src/wavesurfer.js +13 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wavesurfer.js",
3
- "version": "6.1.0",
3
+ "version": "6.3.0",
4
4
  "description": "Interactive navigable audio visualization using Web Audio and Canvas",
5
5
  "main": "dist/wavesurfer.js",
6
6
  "directories": {
@@ -55,17 +55,16 @@
55
55
  "visualization"
56
56
  ],
57
57
  "devDependencies": {
58
- "@babel/core": "^7.17.8",
59
- "@babel/eslint-parser": "^7.17.0",
60
- "@babel/plugin-proposal-class-properties": "^7.16.7",
61
- "@babel/preset-env": "^7.16.11",
62
- "@babel/register": "^7.17.7",
63
- "@chiragrupani/karma-chromium-edge-launcher": "^2.2.1",
64
- "babel-loader": "^8.2.4",
58
+ "@babel/core": "^7.19.3",
59
+ "@babel/eslint-parser": "^7.19.1",
60
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
61
+ "@babel/preset-env": "^7.19.3",
62
+ "@babel/register": "^7.18.9",
63
+ "@chiragrupani/karma-chromium-edge-launcher": "^2.2.2",
64
+ "babel-loader": "^8.2.5",
65
65
  "babel-plugin-add-module-exports": "^1.0.4",
66
66
  "babel-plugin-istanbul": "^6.1.1",
67
- "babel-plugin-proxy": "^1.1.0",
68
- "date-fns": "^2.28.0",
67
+ "date-fns": "^2.29.3",
69
68
  "debounce": "^1.2.1",
70
69
  "esdoc": "^1.1.0",
71
70
  "esdoc-accessor-plugin": "^1.0.0",
@@ -74,24 +73,24 @@
74
73
  "esdoc-ecmascript-proposal-plugin": "^1.0.0",
75
74
  "esdoc-integrate-test-plugin": "^1.0.0",
76
75
  "esdoc-standard-plugin": "^1.0.0",
77
- "eslint": "^8.11.0",
78
- "htmlhint": "^1.1.2",
76
+ "eslint": "^8.24.0",
77
+ "htmlhint": "^1.1.4",
79
78
  "in-publish": "^2.0.1",
80
- "jasmine-core": "^4.0.1",
81
- "karma": "^6.3.17",
79
+ "jasmine-core": "^4.4.0",
80
+ "karma": "^6.4.1",
82
81
  "karma-chrome-launcher": "3.1.1",
83
82
  "karma-coverage": "^2.2.0",
84
83
  "karma-firefox-launcher": "^2.1.2",
85
- "karma-jasmine": "4.0.1",
84
+ "karma-jasmine": "5.1.0",
86
85
  "karma-jasmine-matchers": "5.0.0",
87
86
  "karma-verbose-reporter": "0.0.8",
88
87
  "karma-webpack": "^5.0.0",
89
- "lint-staged": "^12.3.7",
88
+ "lint-staged": "^13.0.3",
90
89
  "load-script": "^2.0.0",
91
90
  "pre-commit": "^1.2.2",
92
- "webpack": "^5.70.0",
93
- "webpack-cli": "^4.9.2",
94
- "webpack-dev-server": "^4.7.4",
91
+ "webpack": "^5.74.0",
92
+ "webpack-cli": "^4.10.0",
93
+ "webpack-dev-server": "^4.11.1",
95
94
  "webpack-merge": "^5.8.0"
96
95
  },
97
96
  "homepage": "https://wavesurfer-js.org",
@@ -323,10 +323,10 @@ export default class MultiCanvas extends Drawer {
323
323
  // calculate the height of this bar according to the highest peak found
324
324
  let h = Math.round((peak / absmax) * halfH);
325
325
 
326
- // in case of silences, allow the user to specify that we
327
- // always draw *something* (normally a 1px high bar)
328
- if (h == 0 && this.params.barMinHeight) {
329
- h = this.params.barMinHeight;
326
+ // raise the bar height to the specified minimum height
327
+ // Math.max is used to replace any value smaller than barMinHeight (not just 0) with barMinHeight
328
+ if (this.params.barMinHeight) {
329
+ h = Math.max(h, this.params.barMinHeight);
330
330
  }
331
331
 
332
332
  this.fillRect(
@@ -90,7 +90,8 @@ export default class CursorPlugin {
90
90
  const bbox = this.wrapper.getBoundingClientRect();
91
91
  let y = 0;
92
92
  let x = this.wrapper.scrollLeft + event.clientX - bbox.left;
93
- let flip = bbox.right < event.clientX + this.displayTime.getBoundingClientRect().width;
93
+ const displayTimeWidth = this.displayTime ? this.displayTime.getBoundingClientRect().width : 0;
94
+ let flip = bbox.right < event.clientX + displayTimeWidth;
94
95
 
95
96
  if (this.params.showTime && this.params.followCursorY) {
96
97
  // follow y-position of the mouse
@@ -8,6 +8,8 @@
8
8
  * @property {?position} string "top" or "bottom", defaults to "bottom"
9
9
  * @property {?markerElement} element An HTML element to display instead of the default marker image
10
10
  * @property {?draggable} boolean Set marker as draggable, defaults to false
11
+ * @property {?boolean} preventContextMenu Determines whether the context menu
12
+ * is prevented from being opened, defaults to false
11
13
  */
12
14
 
13
15
 
@@ -159,7 +161,8 @@ export default class MarkersPlugin {
159
161
  label: params.label,
160
162
  color: params.color || DEFAULT_FILL_COLOR,
161
163
  position: params.position || DEFAULT_POSITION,
162
- draggable: !!params.draggable
164
+ draggable: !!params.draggable,
165
+ preventContextMenu: !!params.preventContextMenu
163
166
  };
164
167
 
165
168
  marker.el = this._createMarkerElement(marker, params.markerElement);
@@ -181,6 +184,18 @@ export default class MarkersPlugin {
181
184
  if (!marker) {
182
185
  return;
183
186
  }
187
+ let label = marker.el.getElementsByClassName("marker-label")[0];
188
+ if (label) {
189
+ if (label._onContextMenu) {
190
+ label.removeEventListener("contextmenu", label._onContextMenu);
191
+ }
192
+ if (label._onClick) {
193
+ label.removeEventListener("click", label._onClick);
194
+ }
195
+ if (label._onMouseDown) {
196
+ label.removeEventListener("mousedown", label._onMouseDown);
197
+ }
198
+ }
184
199
 
185
200
  this.wrapper.removeChild(marker.el);
186
201
  this.markers.splice(index, 1);
@@ -262,10 +277,11 @@ export default class MarkersPlugin {
262
277
  "align-items": "center",
263
278
  cursor: "pointer"
264
279
  });
280
+ labelDiv.classList.add("marker-label");
265
281
 
266
282
  el.appendChild(labelDiv);
267
283
 
268
- labelDiv.addEventListener("click", e => {
284
+ labelDiv._onClick = (e) => {
269
285
  e.stopPropagation();
270
286
  // Click event is caught when the marker-drop event was dispatched.
271
287
  // Drop event was dispatched at this moment, but this.dragging
@@ -275,12 +291,22 @@ export default class MarkersPlugin {
275
291
  }
276
292
  this.wavesurfer.setCurrentTime(marker.time);
277
293
  this.wavesurfer.fireEvent("marker-click", marker, e);
278
- });
294
+ };
295
+ labelDiv.addEventListener("click", labelDiv._onClick);
296
+
297
+ labelDiv._onContextMenu = (e) => {
298
+ if (marker.preventContextMenu) {
299
+ e.preventDefault();
300
+ }
301
+ this.wavesurfer.fireEvent("marker-contextmenu", marker, e);
302
+ };
303
+ labelDiv.addEventListener("contextmenu", labelDiv._onContextMenu);
279
304
 
280
305
  if (marker.draggable) {
281
- labelDiv.addEventListener("mousedown", e => {
306
+ labelDiv._onMouseDown = () => {
282
307
  this.selectedMarker = marker;
283
- });
308
+ };
309
+ labelDiv.addEventListener("mousedown", labelDiv._onMouseDown);
284
310
  }
285
311
  return el;
286
312
  }
@@ -299,7 +299,7 @@ export default class RegionsPlugin {
299
299
  );
300
300
 
301
301
  // set the region channel index based on the clicked area
302
- if (this.wavesurfer.params.splitChannels) {
302
+ if (this.wavesurfer.params.splitChannels && this.wavesurfer.params.splitChannelsOptions.splitDragSelection) {
303
303
  const y = (e.touches ? e.touches[0].clientY : e.clientY) - wrapperRect.top;
304
304
  const channelCount = this.wavesurfer.backend.buffer != null ? this.wavesurfer.backend.buffer.numberOfChannels : 1;
305
305
  const channelHeight = this.wrapper.clientHeight / channelCount;
@@ -10,6 +10,8 @@ import FFT from './fft';
10
10
  * a power of 2.
11
11
  * @property {boolean} splitChannels=false Render with separate spectrograms for
12
12
  * the channels of the audio
13
+ * @property {number} height=fftSamples/2 Height of the spectrogram view in CSS
14
+ * pixels
13
15
  * @property {boolean} labels Set to true to display frequency labels.
14
16
  * @property {number} noverlap Size of the overlapping window. Must be <
15
17
  * fftSamples. Auto deduced from canvas size by default.
@@ -128,7 +130,7 @@ export default class SpectrogramPlugin {
128
130
  this.pixelRatio = this.params.pixelRatio || ws.params.pixelRatio;
129
131
  this.fftSamples =
130
132
  this.params.fftSamples || ws.params.fftSamples || 512;
131
- this.height = this.fftSamples / 2;
133
+ this.height = this.params.height || this.fftSamples / 2;
132
134
  this.noverlap = params.noverlap;
133
135
  this.windowFunc = params.windowFunc;
134
136
  this.alpha = params.alpha;
@@ -185,11 +187,10 @@ export default class SpectrogramPlugin {
185
187
  const labelsEl = (this.labelsEl = document.createElement('canvas'));
186
188
  labelsEl.classList.add('spec-labels');
187
189
  this.drawer.style(labelsEl, {
188
- left: 0,
189
190
  position: 'absolute',
190
191
  zIndex: 9,
191
- height: `${this.height * this.channels / this.pixelRatio}px`,
192
- width: `${55 / this.pixelRatio}px`
192
+ height: `${this.height * this.channels}px`,
193
+ width: `55px`
193
194
  });
194
195
  this.wrapper.appendChild(labelsEl);
195
196
  this.loadLabels(
@@ -209,7 +210,7 @@ export default class SpectrogramPlugin {
209
210
  position: 'relative',
210
211
  userSelect: 'none',
211
212
  webkitUserSelect: 'none',
212
- height: `${this.height * this.channels / this.pixelRatio}px`
213
+ height: `${this.height * this.channels}px`
213
214
  });
214
215
 
215
216
  if (wsParams.fillParent || wsParams.scrollParent) {
@@ -256,8 +257,9 @@ export default class SpectrogramPlugin {
256
257
  updateCanvasStyle() {
257
258
  const width = Math.round(this.width / this.pixelRatio) + 'px';
258
259
  this.canvas.width = this.width;
259
- this.canvas.height = this.height * this.channels;
260
+ this.canvas.height = this.fftSamples / 2 * this.channels;
260
261
  this.canvas.style.width = width;
262
+ this.canvas.style.height = this.height + 'px';
261
263
  }
262
264
 
263
265
  drawSpectrogram(frequenciesData, my) {
@@ -267,7 +269,7 @@ export default class SpectrogramPlugin {
267
269
  }
268
270
 
269
271
  const spectrCc = my.spectrCc;
270
- const height = my.height;
272
+ const height = my.fftSamples / 2;
271
273
  const width = my.width;
272
274
  const freqFrom = my.buffer.sampleRate / 2;
273
275
  const freqMin = my.frequencyMin;
@@ -404,8 +406,10 @@ export default class SpectrogramPlugin {
404
406
 
405
407
  // prepare canvas element for labels
406
408
  const ctx = this.labelsEl.getContext('2d');
407
- this.labelsEl.height = this.height * this.channels;
408
- this.labelsEl.width = bgWidth;
409
+ const dispScale = window.devicePixelRatio;
410
+ this.labelsEl.height = this.height * this.channels * dispScale;
411
+ this.labelsEl.width = bgWidth * dispScale;
412
+ ctx.scale(dispScale, dispScale);
409
413
 
410
414
  if (!ctx) {
411
415
  return;
package/src/wavesurfer.js CHANGED
@@ -174,6 +174,8 @@ import MediaElementWebAudio from './mediaelement-webaudio';
174
174
  * @property {boolean} relativeNormalization=false determines whether
175
175
  * normalization is done per channel or maintains proportionality between
176
176
  * channels. Only applied when normalize and splitChannels are both true.
177
+ * @property {boolean} splitDragSelection=false determines if drag selection in regions
178
+ * plugin works separately on each channel or only one selection for all channels
177
179
  * @since 4.3.0
178
180
  */
179
181
 
@@ -298,7 +300,8 @@ export default class WaveSurfer extends util.Observer {
298
300
  overlay: false,
299
301
  channelColors: {},
300
302
  filterChannels: [],
301
- relativeNormalization: false
303
+ relativeNormalization: false,
304
+ splitDragSelection: false
302
305
  },
303
306
  vertical: false,
304
307
  waveColor: '#999',
@@ -501,6 +504,7 @@ export default class WaveSurfer extends util.Observer {
501
504
  this._onResize = util.debounce(
502
505
  () => {
503
506
  if (
507
+ this.drawer.wrapper &&
504
508
  prevWidth != this.drawer.wrapper.clientWidth &&
505
509
  !this.params.scrollParent
506
510
  ) {
@@ -1683,19 +1687,19 @@ export default class WaveSurfer extends util.Observer {
1683
1687
  /**
1684
1688
  * Save waveform image as data URI.
1685
1689
  *
1686
- * The default format is `'image/png'`. Other supported types are
1687
- * `'image/jpeg'` and `'image/webp'`.
1690
+ * The default format is `image/png`. Other supported types are
1691
+ * `image/jpeg` and `image/webp`.
1688
1692
  *
1689
1693
  * @param {string} format='image/png' A string indicating the image format.
1690
- * The default format type is `'image/png'`.
1694
+ * The default format type is `image/png`.
1691
1695
  * @param {number} quality=1 A number between 0 and 1 indicating the image
1692
1696
  * quality to use for image formats that use lossy compression such as
1693
- * `'image/jpeg'`` and `'image/webp'`.
1694
- * @param {string} type Image data type to return. Either 'dataURL' (default)
1695
- * or 'blob'.
1696
- * @return {string|string[]|Promise} When using `'dataURL'` type this returns
1697
+ * `image/jpeg` and `image/webp`.
1698
+ * @param {string} type Image data type to return. Either `dataURL` (default)
1699
+ * or `blob`.
1700
+ * @return {string|string[]|Promise} When using `dataURL` type this returns
1697
1701
  * a single data URL or an array of data URLs, one for each canvas. When using
1698
- * `'blob'` type this returns a `Promise` resolving with an array of `Blob`
1702
+ * `blob` type this returns a `Promise` resolving with an array of `Blob`
1699
1703
  * instances, one for each canvas.
1700
1704
  */
1701
1705
  exportImage(format, quality, type) {