wavesurfer.js 5.1.0 → 5.2.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.
- package/CHANGES.md +11 -0
- package/dist/plugin/wavesurfer.cursor.js +2 -2
- package/dist/plugin/wavesurfer.cursor.js.map +1 -1
- package/dist/plugin/wavesurfer.cursor.min.js +2 -2
- package/dist/plugin/wavesurfer.cursor.min.js.map +1 -1
- package/dist/plugin/wavesurfer.elan.js +2 -2
- package/dist/plugin/wavesurfer.elan.js.map +1 -1
- package/dist/plugin/wavesurfer.elan.min.js +2 -2
- package/dist/plugin/wavesurfer.elan.min.js.map +1 -1
- package/dist/plugin/wavesurfer.markers.js +2 -2
- package/dist/plugin/wavesurfer.markers.js.map +1 -1
- package/dist/plugin/wavesurfer.markers.min.js +2 -2
- package/dist/plugin/wavesurfer.markers.min.js.map +1 -1
- package/dist/plugin/wavesurfer.mediasession.js +2 -2
- package/dist/plugin/wavesurfer.mediasession.js.map +1 -1
- package/dist/plugin/wavesurfer.mediasession.min.js +2 -2
- package/dist/plugin/wavesurfer.mediasession.min.js.map +1 -1
- package/dist/plugin/wavesurfer.microphone.js +2 -2
- package/dist/plugin/wavesurfer.microphone.js.map +1 -1
- package/dist/plugin/wavesurfer.microphone.min.js +2 -2
- package/dist/plugin/wavesurfer.microphone.min.js.map +1 -1
- package/dist/plugin/wavesurfer.minimap.js +2 -2
- package/dist/plugin/wavesurfer.minimap.js.map +1 -1
- package/dist/plugin/wavesurfer.minimap.min.js +2 -2
- package/dist/plugin/wavesurfer.minimap.min.js.map +1 -1
- package/dist/plugin/wavesurfer.playhead.js +2 -2
- package/dist/plugin/wavesurfer.playhead.js.map +1 -1
- package/dist/plugin/wavesurfer.playhead.min.js +2 -2
- package/dist/plugin/wavesurfer.playhead.min.js.map +1 -1
- package/dist/plugin/wavesurfer.regions.js +37 -7
- package/dist/plugin/wavesurfer.regions.js.map +1 -1
- package/dist/plugin/wavesurfer.regions.min.js +2 -2
- package/dist/plugin/wavesurfer.regions.min.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.js +2 -2
- package/dist/plugin/wavesurfer.spectrogram.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.min.js +2 -2
- package/dist/plugin/wavesurfer.spectrogram.min.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.js +14 -11
- package/dist/plugin/wavesurfer.timeline.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.min.js +2 -2
- package/dist/plugin/wavesurfer.timeline.min.js.map +1 -1
- package/dist/wavesurfer-html-init.js +2 -2
- package/dist/wavesurfer-html-init.js.map +1 -1
- package/dist/wavesurfer-html-init.min.js +2 -2
- package/dist/wavesurfer-html-init.min.js.map +1 -1
- package/dist/wavesurfer.js +99 -21
- package/dist/wavesurfer.js.map +1 -1
- package/dist/wavesurfer.min.js +2 -2
- package/dist/wavesurfer.min.js.map +1 -1
- package/package.json +11 -11
- package/src/plugin/regions/region.js +33 -5
- package/src/plugin/timeline/index.js +11 -9
- package/src/util/index.js +1 -0
- package/src/util/silence-mode.js +35 -0
- package/src/wavesurfer.js +23 -13
- package/src/webaudio.js +10 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wavesurfer.js",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Interactive navigable audio visualization using Web Audio and Canvas",
|
|
5
5
|
"main": "dist/wavesurfer.js",
|
|
6
6
|
"directories": {
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"visualization"
|
|
56
56
|
],
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@babel/core": "^7.
|
|
59
|
-
"@babel/preset-env": "^7.
|
|
60
|
-
"@babel/register": "^7.
|
|
58
|
+
"@babel/core": "^7.15.0",
|
|
59
|
+
"@babel/preset-env": "^7.15.0",
|
|
60
|
+
"@babel/register": "^7.15.3",
|
|
61
61
|
"@chiragrupani/karma-chromium-edge-launcher": "^2.1.1",
|
|
62
62
|
"babel-eslint": "^10.1.0",
|
|
63
63
|
"babel-loader": "^8.2.2",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"babel-plugin-istanbul": "^6.0.0",
|
|
66
66
|
"babel-plugin-proxy": "^1.1.0",
|
|
67
67
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
68
|
-
"date-fns": "^2.
|
|
68
|
+
"date-fns": "^2.23.0",
|
|
69
69
|
"debounce": "^1.2.1",
|
|
70
70
|
"esdoc": "^1.1.0",
|
|
71
71
|
"esdoc-accessor-plugin": "^1.0.0",
|
|
@@ -74,10 +74,10 @@
|
|
|
74
74
|
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
|
|
75
75
|
"esdoc-integrate-test-plugin": "^1.0.0",
|
|
76
76
|
"esdoc-standard-plugin": "^1.0.0",
|
|
77
|
-
"eslint": "^7.
|
|
77
|
+
"eslint": "^7.32.0",
|
|
78
78
|
"htmlhint": "^0.15.1",
|
|
79
79
|
"in-publish": "^2.0.1",
|
|
80
|
-
"jasmine-core": "^3.
|
|
80
|
+
"jasmine-core": "^3.8.0",
|
|
81
81
|
"karma": "^6.3.4",
|
|
82
82
|
"karma-chrome-launcher": "3.1.0",
|
|
83
83
|
"karma-coverage": "^2.0.3",
|
|
@@ -86,12 +86,12 @@
|
|
|
86
86
|
"karma-jasmine-matchers": "4.0.2",
|
|
87
87
|
"karma-verbose-reporter": "0.0.6",
|
|
88
88
|
"karma-webpack": "^5.0.0",
|
|
89
|
-
"lint-staged": "^11.
|
|
89
|
+
"lint-staged": "^11.1.2",
|
|
90
90
|
"load-script": "^1.0.0",
|
|
91
91
|
"pre-commit": "^1.2.2",
|
|
92
|
-
"webpack": "^5.
|
|
93
|
-
"webpack-cli": "^4.
|
|
94
|
-
"webpack-dev-server": "^4.0.0-
|
|
92
|
+
"webpack": "^5.50.0",
|
|
93
|
+
"webpack-cli": "^4.8.0",
|
|
94
|
+
"webpack-dev-server": "^4.0.0-rc.0",
|
|
95
95
|
"webpack-merge": "^5.8.0"
|
|
96
96
|
},
|
|
97
97
|
"homepage": "https://wavesurfer-js.org",
|
|
@@ -87,7 +87,7 @@ export class Region {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/* Update region params. */
|
|
90
|
-
update(params) {
|
|
90
|
+
update(params, eventParams) {
|
|
91
91
|
if (params.start != null) {
|
|
92
92
|
this.start = Number(params.start);
|
|
93
93
|
}
|
|
@@ -125,7 +125,7 @@ export class Region {
|
|
|
125
125
|
|
|
126
126
|
this.updateRender();
|
|
127
127
|
this.fireEvent('update');
|
|
128
|
-
this.wavesurfer.fireEvent('region-updated', this);
|
|
128
|
+
this.wavesurfer.fireEvent('region-updated', this, eventParams);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/* Remove a single region. */
|
|
@@ -708,10 +708,33 @@ export class Region {
|
|
|
708
708
|
delta = this.start * -1;
|
|
709
709
|
}
|
|
710
710
|
|
|
711
|
+
const eventParams = {
|
|
712
|
+
direction: this._getDragDirection(delta),
|
|
713
|
+
action: 'drag'
|
|
714
|
+
};
|
|
715
|
+
|
|
711
716
|
this.update({
|
|
712
717
|
start: this.start + delta,
|
|
713
718
|
end: this.end + delta
|
|
714
|
-
});
|
|
719
|
+
}, eventParams);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Returns the direction of dragging region based on delta
|
|
724
|
+
* Negative delta means region is moving to the left
|
|
725
|
+
* Positive - to the right
|
|
726
|
+
* For zero delta the direction is not defined
|
|
727
|
+
* @param {number} delta Drag offset
|
|
728
|
+
* @returns {string|null} Direction 'left', 'right' or null
|
|
729
|
+
*/
|
|
730
|
+
_getDragDirection(delta) {
|
|
731
|
+
if (delta < 0) {
|
|
732
|
+
return 'left';
|
|
733
|
+
}
|
|
734
|
+
if (delta > 0) {
|
|
735
|
+
return 'right';
|
|
736
|
+
}
|
|
737
|
+
return null;
|
|
715
738
|
}
|
|
716
739
|
|
|
717
740
|
/**
|
|
@@ -724,6 +747,11 @@ export class Region {
|
|
|
724
747
|
*/
|
|
725
748
|
onResize(delta, direction) {
|
|
726
749
|
const duration = this.wavesurfer.getDuration();
|
|
750
|
+
const eventParams = {
|
|
751
|
+
action: 'resize',
|
|
752
|
+
direction: direction === 'start' ? 'right' : 'left'
|
|
753
|
+
};
|
|
754
|
+
|
|
727
755
|
if (direction === 'start') {
|
|
728
756
|
// Check if changing the start by the given delta would result in the region being smaller than minLength
|
|
729
757
|
// Ignore cases where we are making the region wider rather than shrinking it
|
|
@@ -738,7 +766,7 @@ export class Region {
|
|
|
738
766
|
this.update({
|
|
739
767
|
start: Math.min(this.start + delta, this.end),
|
|
740
768
|
end: Math.max(this.start + delta, this.end)
|
|
741
|
-
});
|
|
769
|
+
}, eventParams);
|
|
742
770
|
} else {
|
|
743
771
|
// Check if changing the end by the given delta would result in the region being smaller than minLength
|
|
744
772
|
// Ignore cases where we are making the region wider rather than shrinking it
|
|
@@ -753,7 +781,7 @@ export class Region {
|
|
|
753
781
|
this.update({
|
|
754
782
|
start: Math.min(this.end + delta, this.start),
|
|
755
783
|
end: Math.max(this.end + delta, this.start)
|
|
756
|
-
});
|
|
784
|
+
}, eventParams);
|
|
757
785
|
}
|
|
758
786
|
}
|
|
759
787
|
|
|
@@ -505,18 +505,20 @@ export default class TimelinePlugin {
|
|
|
505
505
|
|
|
506
506
|
this.canvases.forEach(canvas => {
|
|
507
507
|
const context = canvas.getContext('2d');
|
|
508
|
-
|
|
508
|
+
if (context) {
|
|
509
|
+
const canvasWidth = context.canvas.width;
|
|
509
510
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
511
|
+
if (xOffset > x + textWidth) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
513
514
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
515
|
+
if (xOffset + canvasWidth > x && context) {
|
|
516
|
+
textWidth = context.measureText(text).width;
|
|
517
|
+
context.fillText(text, x - xOffset, y);
|
|
518
|
+
}
|
|
518
519
|
|
|
519
|
-
|
|
520
|
+
xOffset += canvasWidth;
|
|
521
|
+
}
|
|
520
522
|
});
|
|
521
523
|
}
|
|
522
524
|
|
package/src/util/index.js
CHANGED
|
@@ -11,3 +11,4 @@ export { default as preventClick } from './prevent-click';
|
|
|
11
11
|
export { default as fetchFile } from './fetch';
|
|
12
12
|
export { default as clamp } from './clamp';
|
|
13
13
|
export { default as withOrientation } from './orientation';
|
|
14
|
+
export { default as ignoreSilenceMode } from './silence-mode';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ignores device silence mode when using the `WebAudio` backend.
|
|
3
|
+
*
|
|
4
|
+
* Many mobile devices contain a hardware button to mute the ringtone for incoming
|
|
5
|
+
* calls and messages. Unfortunately, on some platforms like iOS, this also mutes
|
|
6
|
+
* wavesurfer's audio when using the `WebAudio` backend. This function creates a
|
|
7
|
+
* temporary `<audio>` element that makes sure the WebAudio backend keeps playing
|
|
8
|
+
* when muting the device ringer.
|
|
9
|
+
*
|
|
10
|
+
* @since 5.2.0
|
|
11
|
+
*/
|
|
12
|
+
export default function ignoreSilenceMode() {
|
|
13
|
+
// Set the src to a short bit of url encoded as a silent mp3
|
|
14
|
+
// NOTE The silence MP3 must be high quality, when web audio sounds are played
|
|
15
|
+
// in parallel the web audio sound is mixed to match the bitrate of the html sound
|
|
16
|
+
// 0.01 seconds of silence VBR220-260 Joint Stereo 859B
|
|
17
|
+
const audioData = "data:audio/mpeg;base64,//uQxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAACcQCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA//////////////////////////////////////////////////////////////////8AAABhTEFNRTMuMTAwA8MAAAAAAAAAABQgJAUHQQAB9AAAAnGMHkkIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//sQxAADgnABGiAAQBCqgCRMAAgEAH///////////////7+n/9FTuQsQH//////2NG0jWUGlio5gLQTOtIoeR2WX////X4s9Atb/JRVCbBUpeRUq//////////////////9RUi0f2jn/+xDECgPCjAEQAABN4AAANIAAAAQVTEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==";
|
|
18
|
+
|
|
19
|
+
// disable iOS Airplay (setting the attribute in js doesn't work)
|
|
20
|
+
let tmp = document.createElement("div");
|
|
21
|
+
tmp.innerHTML = '<audio x-webkit-airplay="deny"></audio>';
|
|
22
|
+
|
|
23
|
+
let audioSilentMode = tmp.children.item(0);
|
|
24
|
+
audioSilentMode.src = audioData;
|
|
25
|
+
audioSilentMode.preload = "auto";
|
|
26
|
+
audioSilentMode.type = "audio/mpeg";
|
|
27
|
+
audioSilentMode.disableRemotePlayback = true;
|
|
28
|
+
|
|
29
|
+
// play
|
|
30
|
+
audioSilentMode.play();
|
|
31
|
+
|
|
32
|
+
// cleanup
|
|
33
|
+
audioSilentMode.remove();
|
|
34
|
+
tmp.remove();
|
|
35
|
+
}
|
package/src/wavesurfer.js
CHANGED
|
@@ -69,6 +69,8 @@ import MediaElementWebAudio from './mediaelement-webaudio';
|
|
|
69
69
|
* pixels.
|
|
70
70
|
* @property {boolean} hideScrollbar=false Whether to hide the horizontal
|
|
71
71
|
* scrollbar when one would normally be shown.
|
|
72
|
+
* @property {boolean} ignoreSilenceMode=false If true, ignores device silence mode
|
|
73
|
+
* when using the `WebAudio` backend.
|
|
72
74
|
* @property {boolean} interact=true Whether the mouse interaction will be
|
|
73
75
|
* enabled at initialization. You can switch this parameter at any time later
|
|
74
76
|
* on.
|
|
@@ -268,6 +270,7 @@ export default class WaveSurfer extends util.Observer {
|
|
|
268
270
|
forceDecode: false,
|
|
269
271
|
height: 128,
|
|
270
272
|
hideScrollbar: false,
|
|
273
|
+
ignoreSilenceMode: false,
|
|
271
274
|
interact: true,
|
|
272
275
|
loopSelection: true,
|
|
273
276
|
maxCanvasWidth: 4000,
|
|
@@ -813,6 +816,11 @@ export default class WaveSurfer extends util.Observer {
|
|
|
813
816
|
* wavesurfer.play(1, 5);
|
|
814
817
|
*/
|
|
815
818
|
play(start, end) {
|
|
819
|
+
if (this.params.ignoreSilenceMode) {
|
|
820
|
+
// ignores device hardware silence mode
|
|
821
|
+
util.ignoreSilenceMode();
|
|
822
|
+
}
|
|
823
|
+
|
|
816
824
|
this.fireEvent('interaction', () => this.play(start, end));
|
|
817
825
|
return this.backend.play(start, end);
|
|
818
826
|
}
|
|
@@ -1538,19 +1546,21 @@ export default class WaveSurfer extends util.Observer {
|
|
|
1538
1546
|
* @param {function} callback The function to call on complete
|
|
1539
1547
|
*/
|
|
1540
1548
|
decodeArrayBuffer(arraybuffer, callback) {
|
|
1541
|
-
this.
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1549
|
+
if (!this.isDestroyed) {
|
|
1550
|
+
this.arraybuffer = arraybuffer;
|
|
1551
|
+
this.backend.decodeArrayBuffer(
|
|
1552
|
+
arraybuffer,
|
|
1553
|
+
data => {
|
|
1554
|
+
// Only use the decoded data if we haven't been destroyed or
|
|
1555
|
+
// another decode started in the meantime
|
|
1556
|
+
if (!this.isDestroyed && this.arraybuffer == arraybuffer) {
|
|
1557
|
+
callback(data);
|
|
1558
|
+
this.arraybuffer = null;
|
|
1559
|
+
}
|
|
1560
|
+
},
|
|
1561
|
+
() => this.fireEvent('error', 'Error decoding audiobuffer')
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1554
1564
|
}
|
|
1555
1565
|
|
|
1556
1566
|
/**
|
package/src/webaudio.js
CHANGED
|
@@ -702,7 +702,16 @@ export default class WebAudio extends util.Observer {
|
|
|
702
702
|
this.scheduledPause = null;
|
|
703
703
|
|
|
704
704
|
this.startPosition += this.getPlayedTime();
|
|
705
|
-
|
|
705
|
+
try {
|
|
706
|
+
this.source && this.source.stop(0);
|
|
707
|
+
} catch (err) {
|
|
708
|
+
// Calling stop can throw the following 2 errors:
|
|
709
|
+
// - RangeError (The value specified for when is negative.)
|
|
710
|
+
// - InvalidStateNode (The node has not been started by calling start().)
|
|
711
|
+
// We can safely ignore both errors, because:
|
|
712
|
+
// - The range is surely correct
|
|
713
|
+
// - The node might not have been started yet, in which case we just want to carry on without causing any trouble.
|
|
714
|
+
}
|
|
706
715
|
|
|
707
716
|
this.setState(PAUSED);
|
|
708
717
|
|