@94ai/nf-audio 3.3.60 → 3.3.61

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.
@@ -10,6 +10,10 @@ function timeFormat(value) {
10
10
  const _sfc_main = {
11
11
  name: "nf-audio",
12
12
  props: {
13
+ debuglog: {
14
+ type: Boolean,
15
+ default: false
16
+ },
13
17
  size: {
14
18
  type: String
15
19
  },
@@ -70,7 +74,7 @@ const _sfc_main = {
70
74
  multipleArray: {
71
75
  type: Array,
72
76
  default() {
73
- return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0"];
77
+ return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0", "10.0"];
74
78
  }
75
79
  },
76
80
  // 默认速度
@@ -93,6 +97,45 @@ const _sfc_main = {
93
97
  },
94
98
  data() {
95
99
  return {
100
+ audioWorkletProcessor: `
101
+ class TickWorkletProcessor extends AudioWorkletProcessor {
102
+ constructor() {
103
+ super();
104
+ this.port.onmessage = this.handleMessage.bind(this);
105
+ this.end = true
106
+ }
107
+
108
+ handleMessage(event) {
109
+ const { command, start, end, currentTime } = event.data;
110
+ if (command === 'start') {
111
+ this.end = false
112
+ } else if (command === 'end') {
113
+ this.end = true
114
+ }
115
+ }
116
+
117
+ process(inputs, outputs) {
118
+ this.port.postMessage({
119
+ command: 'tick'
120
+ });
121
+ const input = inputs[0];
122
+ const output = outputs[0];
123
+ for (let channel = 0; channel < input.length; ++channel) {
124
+ const inputChannel = input[channel];
125
+ const outputChannel = output[channel];
126
+ for (let i = 0; i < inputChannel.length; ++i) {
127
+ outputChannel[i] = inputChannel[i];
128
+ }
129
+ }
130
+ return !this.end;
131
+ }
132
+ }
133
+
134
+ registerProcessor('tick', TickWorkletProcessor);
135
+ `,
136
+ audioCtx: void 0,
137
+ audioSource: void 0,
138
+ processor: void 0,
96
139
  betweenPlaying: false,
97
140
  // 播放还是暂停
98
141
  paused: true,
@@ -123,6 +166,28 @@ const _sfc_main = {
123
166
  this.volumeValue = this.initVolumnValue * 100;
124
167
  this.syncSpeed();
125
168
  },
169
+ beforeDestroy() {
170
+ var _a, _b, _c, _d;
171
+ this.betweenPlaying = false;
172
+ try {
173
+ (_a = this.audioCtx) == null ? void 0 : _a.close();
174
+ } catch (e) {
175
+ } finally {
176
+ this.audioCtx = void 0;
177
+ }
178
+ try {
179
+ (_b = this.audioSource) == null ? void 0 : _b.disconnect();
180
+ } catch (e) {
181
+ } finally {
182
+ this.audioSource = void 0;
183
+ }
184
+ try {
185
+ (_d = (_c = this.processor) == null ? void 0 : _c.port) == null ? void 0 : _d.close();
186
+ } catch (e) {
187
+ } finally {
188
+ this.processor = void 0;
189
+ }
190
+ },
126
191
  methods: {
127
192
  locationToTime(time) {
128
193
  this.betweenPlaying = false;
@@ -176,8 +241,11 @@ const _sfc_main = {
176
241
  handlePauseOrPlay() {
177
242
  if (!this.disabled) {
178
243
  if (this.audio.readyState >= 2) {
179
- this.audio.paused ? this.audio.play() : this.audio.pause();
180
- this.audio.playbackRate = this.speed;
244
+ if (this.audio.paused) {
245
+ this.playAudio();
246
+ } else {
247
+ this.pauseAudio();
248
+ }
181
249
  this.paused = !this.paused;
182
250
  this.betweenPlaying = false;
183
251
  this.$emit("pauseOrPlay", this.paused);
@@ -185,19 +253,70 @@ const _sfc_main = {
185
253
  console.log("Audio is not ready yet.");
186
254
  nfMessage.Message.warning(this.unloadTip);
187
255
  this.paused = true;
256
+ this.betweenPlaying = false;
188
257
  }
189
258
  }
190
259
  },
260
+ suspendAudioCtx() {
261
+ var _a, _b, _c;
262
+ try {
263
+ (_b = (_a = this.processor) == null ? void 0 : _a.port) == null ? void 0 : _b.postMessage({
264
+ command: "end"
265
+ });
266
+ } catch (e) {
267
+ }
268
+ try {
269
+ (_c = this.audioCtx) == null ? void 0 : _c.suspend();
270
+ } catch (e) {
271
+ }
272
+ },
273
+ async startAudioCtx() {
274
+ if (!this.audioCtx) {
275
+ this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
276
+ this.audioSource = this.audioCtx.createMediaElementSource(this.audio);
277
+ await this.audioCtx.audioWorklet.addModule("data:application/javascript," + encodeURIComponent(this.audioWorkletProcessor));
278
+ this.processor = new AudioWorkletNode(this.audioCtx, "tick");
279
+ this.audioSource.connect(this.processor).connect(this.audioCtx.destination);
280
+ this.processor.port.onmessage = (event) => {
281
+ if (event.data.command === "tick") {
282
+ if (this.betweenPlaying) {
283
+ if (this.betweenStart && this.betweenEnd) {
284
+ if (this.debuglog) {
285
+ console.log(this.audio.currentTime);
286
+ }
287
+ if (this.audio.currentTime >= this.betweenEnd) {
288
+ this.pause();
289
+ }
290
+ }
291
+ }
292
+ }
293
+ };
294
+ } else {
295
+ this.audioCtx.resume();
296
+ }
297
+ this.processor.port.postMessage({
298
+ command: "start"
299
+ });
300
+ },
191
301
  pause() {
192
- this.audio.pause();
302
+ this.pauseAudio();
193
303
  this.paused = true;
194
304
  this.betweenPlaying = false;
195
305
  },
196
- play() {
197
- this.audio.play();
306
+ async play() {
307
+ await this.playAudio();
198
308
  this.paused = false;
199
309
  this.betweenPlaying = false;
200
310
  },
311
+ pauseAudio() {
312
+ this.audio.pause();
313
+ this.suspendAudioCtx();
314
+ },
315
+ async playAudio() {
316
+ this.audio.playbackRate = this.speed;
317
+ await this.startAudioCtx();
318
+ this.audio.play();
319
+ },
201
320
  //视频在可以播放时触发
202
321
  getDuration() {
203
322
  this.totalTime = timeFormat(this.audio.duration);
@@ -213,18 +332,16 @@ const _sfc_main = {
213
332
  this.$refs.progressCurrent.style.width = MoveX + "px";
214
333
  this.$refs.progressBar.style.left = MoveX - this.$refs.progressBar.clientWidth / 2 + "px";
215
334
  this.paused = false;
216
- if (this.betweenPlaying) {
217
- if (this.betweenStart && this.betweenEnd) {
218
- console.log(this.audio.currentTime, "this.audio.currentTime");
219
- if (this.audio.currentTime >= this.betweenEnd) {
220
- this.pause();
221
- }
222
- }
223
- }
224
335
  }
225
336
  },
226
337
  betweenPlay() {
227
338
  if (!this.disabled) {
339
+ if (this.audio.duration === 0) {
340
+ nfMessage.Message.warning(this.unloadTip);
341
+ this.paused = true;
342
+ this.betweenPlaying = false;
343
+ return false;
344
+ }
228
345
  this.betweenPlaying = true;
229
346
  this.jumpToTime(this.betweenStart);
230
347
  }
@@ -232,7 +349,7 @@ const _sfc_main = {
232
349
  handleAudioEnded() {
233
350
  this.$refs.progressCurrent.style.width = this.$refs.progressContainer.clientWidth + "px";
234
351
  this.$refs.progressBar.style.left = this.$refs.progressContainer.clientWidth - this.$refs.progressBar.clientWidth / 2 + "px";
235
- this.paused = true;
352
+ this.pause();
236
353
  },
237
354
  //点击进度条更新进度
238
355
  clickProgress(e) {
@@ -240,6 +357,7 @@ const _sfc_main = {
240
357
  if (this.audio.duration === 0) {
241
358
  nfMessage.Message.warning(this.unloadTip);
242
359
  this.paused = true;
360
+ this.betweenPlaying = false;
243
361
  return false;
244
362
  }
245
363
  if (!this.audio.paused) {
@@ -261,10 +379,10 @@ const _sfc_main = {
261
379
  if (this.audio.duration === 0) {
262
380
  nfMessage.Message.warning(this.unloadTip);
263
381
  this.paused = true;
382
+ this.betweenPlaying = false;
264
383
  return false;
265
384
  }
266
- this.audio.play();
267
- this.paused = false;
385
+ this.play();
268
386
  }
269
387
  },
270
388
  moveX(e) {
@@ -279,8 +397,9 @@ const _sfc_main = {
279
397
  //调整进度
280
398
  handleMousedown() {
281
399
  if (!this.disabled) {
282
- this.audio.pause();
400
+ this.pauseAudio();
283
401
  this.paused = true;
402
+ this.betweenPlaying = false;
284
403
  const progressContainer = this.$refs.progressContainer;
285
404
  this.moveMin = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft;
286
405
  this.moveMax = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft + progressContainer.clientWidth;
@@ -318,17 +437,18 @@ const _sfc_main = {
318
437
  },
319
438
  jumpToTime(time) {
320
439
  if (!this.disabled) {
321
- this.audio.pause();
440
+ this.pauseAudio();
322
441
  if (this.audio.duration === 0) {
323
442
  nfMessage.Message.warning(this.unloadTip);
324
443
  this.paused = true;
444
+ this.betweenPlaying = false;
325
445
  return false;
326
446
  }
327
447
  if (time >= this.audio.duration) {
328
448
  this.audio.currentTime = this.audio.duration;
329
449
  this.currentTime = timeFormat(this.audio.currentTime);
330
450
  this.calcMoveX();
331
- this.audio.play();
451
+ this.playAudio();
332
452
  if (time > this.audio.duration) {
333
453
  console.error(this.crossTimeTip);
334
454
  }
@@ -337,12 +457,12 @@ const _sfc_main = {
337
457
  this.audio.currentTime = time;
338
458
  this.currentTime = timeFormat(this.audio.currentTime);
339
459
  this.calcMoveX();
340
- this.audio.play();
460
+ this.playAudio();
341
461
  } else {
342
462
  this.audio.currentTime = 0;
343
463
  this.currentTime = timeFormat(this.audio.currentTime);
344
464
  this.calcMoveX();
345
- this.audio.play();
465
+ this.playAudio();
346
466
  }
347
467
  this.$emit("jumpToTime", time);
348
468
  }
@@ -8,6 +8,10 @@ function timeFormat(value) {
8
8
  const _sfc_main = {
9
9
  name: "nf-audio",
10
10
  props: {
11
+ debuglog: {
12
+ type: Boolean,
13
+ default: false
14
+ },
11
15
  size: {
12
16
  type: String
13
17
  },
@@ -68,7 +72,7 @@ const _sfc_main = {
68
72
  multipleArray: {
69
73
  type: Array,
70
74
  default() {
71
- return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0"];
75
+ return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0", "10.0"];
72
76
  }
73
77
  },
74
78
  // 默认速度
@@ -91,6 +95,45 @@ const _sfc_main = {
91
95
  },
92
96
  data() {
93
97
  return {
98
+ audioWorkletProcessor: `
99
+ class TickWorkletProcessor extends AudioWorkletProcessor {
100
+ constructor() {
101
+ super();
102
+ this.port.onmessage = this.handleMessage.bind(this);
103
+ this.end = true
104
+ }
105
+
106
+ handleMessage(event) {
107
+ const { command, start, end, currentTime } = event.data;
108
+ if (command === 'start') {
109
+ this.end = false
110
+ } else if (command === 'end') {
111
+ this.end = true
112
+ }
113
+ }
114
+
115
+ process(inputs, outputs) {
116
+ this.port.postMessage({
117
+ command: 'tick'
118
+ });
119
+ const input = inputs[0];
120
+ const output = outputs[0];
121
+ for (let channel = 0; channel < input.length; ++channel) {
122
+ const inputChannel = input[channel];
123
+ const outputChannel = output[channel];
124
+ for (let i = 0; i < inputChannel.length; ++i) {
125
+ outputChannel[i] = inputChannel[i];
126
+ }
127
+ }
128
+ return !this.end;
129
+ }
130
+ }
131
+
132
+ registerProcessor('tick', TickWorkletProcessor);
133
+ `,
134
+ audioCtx: void 0,
135
+ audioSource: void 0,
136
+ processor: void 0,
94
137
  betweenPlaying: false,
95
138
  // 播放还是暂停
96
139
  paused: true,
@@ -121,6 +164,28 @@ const _sfc_main = {
121
164
  this.volumeValue = this.initVolumnValue * 100;
122
165
  this.syncSpeed();
123
166
  },
167
+ beforeDestroy() {
168
+ var _a, _b, _c, _d;
169
+ this.betweenPlaying = false;
170
+ try {
171
+ (_a = this.audioCtx) == null ? void 0 : _a.close();
172
+ } catch (e) {
173
+ } finally {
174
+ this.audioCtx = void 0;
175
+ }
176
+ try {
177
+ (_b = this.audioSource) == null ? void 0 : _b.disconnect();
178
+ } catch (e) {
179
+ } finally {
180
+ this.audioSource = void 0;
181
+ }
182
+ try {
183
+ (_d = (_c = this.processor) == null ? void 0 : _c.port) == null ? void 0 : _d.close();
184
+ } catch (e) {
185
+ } finally {
186
+ this.processor = void 0;
187
+ }
188
+ },
124
189
  methods: {
125
190
  locationToTime(time) {
126
191
  this.betweenPlaying = false;
@@ -174,8 +239,11 @@ const _sfc_main = {
174
239
  handlePauseOrPlay() {
175
240
  if (!this.disabled) {
176
241
  if (this.audio.readyState >= 2) {
177
- this.audio.paused ? this.audio.play() : this.audio.pause();
178
- this.audio.playbackRate = this.speed;
242
+ if (this.audio.paused) {
243
+ this.playAudio();
244
+ } else {
245
+ this.pauseAudio();
246
+ }
179
247
  this.paused = !this.paused;
180
248
  this.betweenPlaying = false;
181
249
  this.$emit("pauseOrPlay", this.paused);
@@ -183,19 +251,70 @@ const _sfc_main = {
183
251
  console.log("Audio is not ready yet.");
184
252
  Message.warning(this.unloadTip);
185
253
  this.paused = true;
254
+ this.betweenPlaying = false;
186
255
  }
187
256
  }
188
257
  },
258
+ suspendAudioCtx() {
259
+ var _a, _b, _c;
260
+ try {
261
+ (_b = (_a = this.processor) == null ? void 0 : _a.port) == null ? void 0 : _b.postMessage({
262
+ command: "end"
263
+ });
264
+ } catch (e) {
265
+ }
266
+ try {
267
+ (_c = this.audioCtx) == null ? void 0 : _c.suspend();
268
+ } catch (e) {
269
+ }
270
+ },
271
+ async startAudioCtx() {
272
+ if (!this.audioCtx) {
273
+ this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
274
+ this.audioSource = this.audioCtx.createMediaElementSource(this.audio);
275
+ await this.audioCtx.audioWorklet.addModule("data:application/javascript," + encodeURIComponent(this.audioWorkletProcessor));
276
+ this.processor = new AudioWorkletNode(this.audioCtx, "tick");
277
+ this.audioSource.connect(this.processor).connect(this.audioCtx.destination);
278
+ this.processor.port.onmessage = (event) => {
279
+ if (event.data.command === "tick") {
280
+ if (this.betweenPlaying) {
281
+ if (this.betweenStart && this.betweenEnd) {
282
+ if (this.debuglog) {
283
+ console.log(this.audio.currentTime);
284
+ }
285
+ if (this.audio.currentTime >= this.betweenEnd) {
286
+ this.pause();
287
+ }
288
+ }
289
+ }
290
+ }
291
+ };
292
+ } else {
293
+ this.audioCtx.resume();
294
+ }
295
+ this.processor.port.postMessage({
296
+ command: "start"
297
+ });
298
+ },
189
299
  pause() {
190
- this.audio.pause();
300
+ this.pauseAudio();
191
301
  this.paused = true;
192
302
  this.betweenPlaying = false;
193
303
  },
194
- play() {
195
- this.audio.play();
304
+ async play() {
305
+ await this.playAudio();
196
306
  this.paused = false;
197
307
  this.betweenPlaying = false;
198
308
  },
309
+ pauseAudio() {
310
+ this.audio.pause();
311
+ this.suspendAudioCtx();
312
+ },
313
+ async playAudio() {
314
+ this.audio.playbackRate = this.speed;
315
+ await this.startAudioCtx();
316
+ this.audio.play();
317
+ },
199
318
  //视频在可以播放时触发
200
319
  getDuration() {
201
320
  this.totalTime = timeFormat(this.audio.duration);
@@ -211,18 +330,16 @@ const _sfc_main = {
211
330
  this.$refs.progressCurrent.style.width = MoveX + "px";
212
331
  this.$refs.progressBar.style.left = MoveX - this.$refs.progressBar.clientWidth / 2 + "px";
213
332
  this.paused = false;
214
- if (this.betweenPlaying) {
215
- if (this.betweenStart && this.betweenEnd) {
216
- console.log(this.audio.currentTime, "this.audio.currentTime");
217
- if (this.audio.currentTime >= this.betweenEnd) {
218
- this.pause();
219
- }
220
- }
221
- }
222
333
  }
223
334
  },
224
335
  betweenPlay() {
225
336
  if (!this.disabled) {
337
+ if (this.audio.duration === 0) {
338
+ Message.warning(this.unloadTip);
339
+ this.paused = true;
340
+ this.betweenPlaying = false;
341
+ return false;
342
+ }
226
343
  this.betweenPlaying = true;
227
344
  this.jumpToTime(this.betweenStart);
228
345
  }
@@ -230,7 +347,7 @@ const _sfc_main = {
230
347
  handleAudioEnded() {
231
348
  this.$refs.progressCurrent.style.width = this.$refs.progressContainer.clientWidth + "px";
232
349
  this.$refs.progressBar.style.left = this.$refs.progressContainer.clientWidth - this.$refs.progressBar.clientWidth / 2 + "px";
233
- this.paused = true;
350
+ this.pause();
234
351
  },
235
352
  //点击进度条更新进度
236
353
  clickProgress(e) {
@@ -238,6 +355,7 @@ const _sfc_main = {
238
355
  if (this.audio.duration === 0) {
239
356
  Message.warning(this.unloadTip);
240
357
  this.paused = true;
358
+ this.betweenPlaying = false;
241
359
  return false;
242
360
  }
243
361
  if (!this.audio.paused) {
@@ -259,10 +377,10 @@ const _sfc_main = {
259
377
  if (this.audio.duration === 0) {
260
378
  Message.warning(this.unloadTip);
261
379
  this.paused = true;
380
+ this.betweenPlaying = false;
262
381
  return false;
263
382
  }
264
- this.audio.play();
265
- this.paused = false;
383
+ this.play();
266
384
  }
267
385
  },
268
386
  moveX(e) {
@@ -277,8 +395,9 @@ const _sfc_main = {
277
395
  //调整进度
278
396
  handleMousedown() {
279
397
  if (!this.disabled) {
280
- this.audio.pause();
398
+ this.pauseAudio();
281
399
  this.paused = true;
400
+ this.betweenPlaying = false;
282
401
  const progressContainer = this.$refs.progressContainer;
283
402
  this.moveMin = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft;
284
403
  this.moveMax = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft + progressContainer.clientWidth;
@@ -316,17 +435,18 @@ const _sfc_main = {
316
435
  },
317
436
  jumpToTime(time) {
318
437
  if (!this.disabled) {
319
- this.audio.pause();
438
+ this.pauseAudio();
320
439
  if (this.audio.duration === 0) {
321
440
  Message.warning(this.unloadTip);
322
441
  this.paused = true;
442
+ this.betweenPlaying = false;
323
443
  return false;
324
444
  }
325
445
  if (time >= this.audio.duration) {
326
446
  this.audio.currentTime = this.audio.duration;
327
447
  this.currentTime = timeFormat(this.audio.currentTime);
328
448
  this.calcMoveX();
329
- this.audio.play();
449
+ this.playAudio();
330
450
  if (time > this.audio.duration) {
331
451
  console.error(this.crossTimeTip);
332
452
  }
@@ -335,12 +455,12 @@ const _sfc_main = {
335
455
  this.audio.currentTime = time;
336
456
  this.currentTime = timeFormat(this.audio.currentTime);
337
457
  this.calcMoveX();
338
- this.audio.play();
458
+ this.playAudio();
339
459
  } else {
340
460
  this.audio.currentTime = 0;
341
461
  this.currentTime = timeFormat(this.audio.currentTime);
342
462
  this.calcMoveX();
343
- this.audio.play();
463
+ this.playAudio();
344
464
  }
345
465
  this.$emit("jumpToTime", time);
346
466
  }
@@ -0,0 +1,90 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Play Audio in Specified Range with AudioWorklet</title>
5
+ </head>
6
+ <body>
7
+ <div style="display: flex;align-items: center">
8
+ <audio id="myAudio" src="./20170206081849_A100187_34f7e6b8-thumb.mp3" controls></audio>
9
+ <button onclick="playAudioInSpecifiedRange(10, 12)">Play Audio in Range 1-20 seconds</button>
10
+ <button onclick="endAudioInSpecifiedRange()">End Audio</button>
11
+ </div>
12
+
13
+
14
+ <script>
15
+ let playAudioInSpecifiedRange
16
+ let endAudioInSpecifiedRange
17
+ addEventListener("DOMContentLoaded", async (event) => {
18
+ const audioWorkletProcessor = `
19
+ class TickWorkletProcessor extends AudioWorkletProcessor {
20
+ constructor() {
21
+ super();
22
+ this.port.onmessage = this.handleMessage.bind(this);
23
+ this.end = true
24
+ }
25
+
26
+ handleMessage(event) {
27
+ const { command, start, end } = event.data;
28
+ if (command === 'start') {
29
+ this.end = false
30
+ } else if (command === 'end') {
31
+ this.end = true
32
+ }
33
+ }
34
+
35
+ process(inputs, outputs) {
36
+ this.port.postMessage({
37
+ command: 'tick'
38
+ });
39
+ const input = inputs[0];
40
+ const output = outputs[0];
41
+ for (let channel = 0; channel < input.length; ++channel) {
42
+ const inputChannel = input[channel];
43
+ const outputChannel = output[channel];
44
+ for (let i = 0; i < inputChannel.length; ++i) {
45
+ outputChannel[i] = inputChannel[i];
46
+ }
47
+ }
48
+ return !this.end;
49
+ }
50
+ }
51
+ registerProcessor('tick', TickWorkletProcessor);
52
+ `
53
+ let ctx
54
+ let processor
55
+ let source
56
+
57
+ endAudioInSpecifiedRange = async () => {
58
+ myAudio.pause()
59
+ processor.port.postMessage({ command: 'end' });
60
+ ctx.suspend()
61
+ }
62
+
63
+ playAudioInSpecifiedRange = async (start, end) => {
64
+ if (!ctx) {
65
+ ctx = new (window.AudioContext || window.webkitAudioContext)();
66
+ await ctx.audioWorklet.addModule('data:application/javascript,' + encodeURIComponent(audioWorkletProcessor));
67
+ processor = new AudioWorkletNode(ctx, 'tick');
68
+ source = ctx.createMediaElementSource(myAudio);
69
+ source.connect(processor).connect(ctx.destination);
70
+ processor.port.onmessage = (event) => {
71
+ if (event.data.command === 'tick') {
72
+ if (myAudio.currentTime > end) {
73
+ myAudio.pause()
74
+ endAudioInSpecifiedRange()
75
+ }
76
+ console.log(myAudio.currentTime)
77
+ }
78
+ };
79
+ } else {
80
+ ctx.resume()
81
+ }
82
+ processor.port.postMessage({ command: 'start' });
83
+ myAudio.currentTime = start
84
+ await myAudio.play();
85
+ }
86
+ });
87
+ </script>
88
+
89
+ </body>
90
+ </html>
@@ -166,6 +166,10 @@ import { timeFormat } from './util'
166
166
  export default {
167
167
  name: 'nf-audio',
168
168
  props: {
169
+ debuglog: {
170
+ type: Boolean,
171
+ default: false
172
+ },
169
173
  size: {
170
174
  type: String,
171
175
  },
@@ -226,7 +230,7 @@ export default {
226
230
  multipleArray: {
227
231
  type: Array,
228
232
  default() {
229
- return ['1.0', '1.25', '1.5', '1.75', '2.0', '2.5', '3.0', '3.5', '4.0']
233
+ return ['1.0', '1.25', '1.5', '1.75', '2.0', '2.5', '3.0', '3.5', '4.0', '10.0']
230
234
  }
231
235
  },
232
236
  // 默认速度
@@ -249,6 +253,45 @@ export default {
249
253
  },
250
254
  data() {
251
255
  return {
256
+ audioWorkletProcessor: `
257
+ class TickWorkletProcessor extends AudioWorkletProcessor {
258
+ constructor() {
259
+ super();
260
+ this.port.onmessage = this.handleMessage.bind(this);
261
+ this.end = true
262
+ }
263
+
264
+ handleMessage(event) {
265
+ const { command, start, end, currentTime } = event.data;
266
+ if (command === 'start') {
267
+ this.end = false
268
+ } else if (command === 'end') {
269
+ this.end = true
270
+ }
271
+ }
272
+
273
+ process(inputs, outputs) {
274
+ this.port.postMessage({
275
+ command: 'tick'
276
+ });
277
+ const input = inputs[0];
278
+ const output = outputs[0];
279
+ for (let channel = 0; channel < input.length; ++channel) {
280
+ const inputChannel = input[channel];
281
+ const outputChannel = output[channel];
282
+ for (let i = 0; i < inputChannel.length; ++i) {
283
+ outputChannel[i] = inputChannel[i];
284
+ }
285
+ }
286
+ return !this.end;
287
+ }
288
+ }
289
+
290
+ registerProcessor('tick', TickWorkletProcessor);
291
+ `,
292
+ audioCtx: undefined,
293
+ audioSource: undefined,
294
+ processor: undefined,
252
295
  betweenPlaying: false,
253
296
  // 播放还是暂停
254
297
  paused: true,
@@ -283,6 +326,30 @@ export default {
283
326
  this.volumeValue = this.initVolumnValue * 100
284
327
  this.syncSpeed()
285
328
  },
329
+ beforeDestroy() {
330
+ this.betweenPlaying = false
331
+ try {
332
+ this.audioCtx?.close()
333
+ } catch (e) {
334
+ //
335
+ } finally {
336
+ this.audioCtx = undefined
337
+ }
338
+ try {
339
+ this.audioSource?.disconnect()
340
+ } catch (e) {
341
+ //
342
+ } finally {
343
+ this.audioSource = undefined
344
+ }
345
+ try {
346
+ this.processor?.port?.close()
347
+ } catch (e) {
348
+ //
349
+ } finally {
350
+ this.processor = undefined
351
+ }
352
+ },
286
353
  methods: {
287
354
  locationToTime(time) {
288
355
  this.betweenPlaying = false
@@ -338,8 +405,11 @@ export default {
338
405
  if (!this.disabled) {
339
406
  if (this.audio.readyState >= 2) {
340
407
  // 如果音频资源已加载元数据或更多,可以播放
341
- this.audio.paused ? this.audio.play() : this.audio.pause()
342
- this.audio.playbackRate = this.speed
408
+ if(this.audio.paused) {
409
+ this.playAudio()
410
+ } else {
411
+ this.pauseAudio()
412
+ }
343
413
  this.paused = !this.paused
344
414
  this.betweenPlaying = false
345
415
  this.$emit('pauseOrPlay', this.paused)
@@ -347,25 +417,72 @@ export default {
347
417
  console.log('Audio is not ready yet.')
348
418
  Message.warning(this.unloadTip)
349
419
  this.paused = true
420
+ this.betweenPlaying = false
350
421
  }
351
422
  }
352
423
  },
424
+ suspendAudioCtx() {
425
+ try {
426
+ this.processor?.port?.postMessage({ command: 'end' });
427
+ } catch (e) {
428
+ //
429
+ }
430
+ try {
431
+ this.audioCtx?.suspend()
432
+ } catch (e) {
433
+ //
434
+ }
435
+ },
436
+ async startAudioCtx() {
437
+ if (!this.audioCtx) {
438
+ this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
439
+ this.audioSource = this.audioCtx.createMediaElementSource(this.audio);
440
+ await this.audioCtx.audioWorklet.addModule('data:application/javascript,' + encodeURIComponent(this.audioWorkletProcessor));
441
+ this.processor = new AudioWorkletNode(this.audioCtx, 'tick');
442
+ this.audioSource.connect(this.processor).connect(this.audioCtx.destination);
443
+ this.processor.port.onmessage = (event) => {
444
+ if (event.data.command === 'tick') {
445
+ if (this.betweenPlaying) {
446
+ if (this.betweenStart && this.betweenEnd) {
447
+ if (this.debuglog) {
448
+ console.log(this.audio.currentTime)
449
+ }
450
+ if (this.audio.currentTime >= this.betweenEnd) {
451
+ this.pause()
452
+ }
453
+ }
454
+ }
455
+ }
456
+ };
457
+ } else {
458
+ this.audioCtx.resume()
459
+ }
460
+ this.processor.port.postMessage({ command: 'start' });
461
+ },
353
462
  pause() {
354
- this.audio.pause()
463
+ this.pauseAudio()
355
464
  this.paused = true
356
465
  this.betweenPlaying = false
357
466
  },
358
- play() {
359
- this.audio.play()
467
+ async play() {
468
+ await this.playAudio()
360
469
  this.paused = false
361
470
  this.betweenPlaying = false
362
471
  },
472
+ pauseAudio() {
473
+ this.audio.pause()
474
+ this.suspendAudioCtx()
475
+ },
476
+ async playAudio() {
477
+ this.audio.playbackRate = this.speed
478
+ await this.startAudioCtx()
479
+ this.audio.play()
480
+ },
363
481
  //视频在可以播放时触发
364
482
  getDuration() {
365
483
  this.totalTime = timeFormat(this.audio.duration)
366
484
  this.audio.volume = this.volume
367
485
  },
368
-
369
486
  //进度条发生变化时触发
370
487
  updateTime() {
371
488
  if (!this.$refs.progressContainer) return
@@ -378,18 +495,16 @@ export default {
378
495
  this.$refs.progressCurrent.style.width = MoveX + 'px'
379
496
  this.$refs.progressBar.style.left = MoveX - (this.$refs.progressBar.clientWidth / 2) + 'px'
380
497
  this.paused = false
381
- if (this.betweenPlaying) {
382
- if (this.betweenStart && this.betweenEnd) {
383
- console.log(this.audio.currentTime, 'this.audio.currentTime')
384
- if (this.audio.currentTime >= this.betweenEnd) {
385
- this.pause()
386
- }
387
- }
388
- }
389
498
  }
390
499
  },
391
500
  betweenPlay() {
392
501
  if (!this.disabled) {
502
+ if (this.audio.duration === 0) {
503
+ Message.warning(this.unloadTip)
504
+ this.paused = true
505
+ this.betweenPlaying = false
506
+ return false
507
+ }
393
508
  this.betweenPlaying = true
394
509
  this.jumpToTime(this.betweenStart)
395
510
  }
@@ -397,7 +512,7 @@ export default {
397
512
  handleAudioEnded() {
398
513
  this.$refs.progressCurrent.style.width = this.$refs.progressContainer.clientWidth + 'px'
399
514
  this.$refs.progressBar.style.left = this.$refs.progressContainer.clientWidth - (this.$refs.progressBar.clientWidth / 2) + 'px'
400
- this.paused = true
515
+ this.pause()
401
516
  },
402
517
  //点击进度条更新进度
403
518
  clickProgress(e) {
@@ -405,6 +520,7 @@ export default {
405
520
  if (this.audio.duration === 0) {
406
521
  Message.warning(this.unloadTip)
407
522
  this.paused = true
523
+ this.betweenPlaying = false
408
524
  return false
409
525
  }
410
526
  //如果不是正在移动 和 没有暂停播放就执行
@@ -430,10 +546,10 @@ export default {
430
546
  if (this.audio.duration === 0) {
431
547
  Message.warning(this.unloadTip)
432
548
  this.paused = true
549
+ this.betweenPlaying = false
433
550
  return false
434
551
  }
435
- this.audio.play()
436
- this.paused = false
552
+ this.play()
437
553
  }
438
554
  },
439
555
  moveX(e) {
@@ -448,8 +564,9 @@ export default {
448
564
  //调整进度
449
565
  handleMousedown() {
450
566
  if (!this.disabled) {
451
- this.audio.pause()
567
+ this.pauseAudio()
452
568
  this.paused = true
569
+ this.betweenPlaying = false
453
570
  const progressContainer = this.$refs.progressContainer
454
571
  //进度条 左 边距离页面左边的距离 移动最小值
455
572
  this.moveMin = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft
@@ -494,17 +611,18 @@ export default {
494
611
  },
495
612
  jumpToTime(time) {
496
613
  if (!this.disabled) {
497
- this.audio.pause()
614
+ this.pauseAudio()
498
615
  if (this.audio.duration === 0) {
499
616
  Message.warning(this.unloadTip)
500
617
  this.paused = true
618
+ this.betweenPlaying = false
501
619
  return false
502
620
  }
503
621
  if (time >= this.audio.duration) {
504
622
  this.audio.currentTime = this.audio.duration
505
623
  this.currentTime = timeFormat(this.audio.currentTime)
506
624
  this.calcMoveX()
507
- this.audio.play()
625
+ this.playAudio()
508
626
  if (time > this.audio.duration) {
509
627
  console.error(this.crossTimeTip)
510
628
  }
@@ -513,12 +631,12 @@ export default {
513
631
  this.audio.currentTime = time
514
632
  this.currentTime = timeFormat(this.audio.currentTime)
515
633
  this.calcMoveX()
516
- this.audio.play()
634
+ this.playAudio()
517
635
  } else {
518
636
  this.audio.currentTime = 0
519
637
  this.currentTime = timeFormat(this.audio.currentTime)
520
638
  this.calcMoveX()
521
- this.audio.play()
639
+ this.playAudio()
522
640
  }
523
641
  this.$emit('jumpToTime', time)
524
642
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@94ai/nf-audio",
3
- "version": "3.3.60",
3
+ "version": "3.3.61",
4
4
  "description": "> TODO: description",
5
5
  "keywords": [],
6
6
  "author": "liuxiangxiang <liuxiangxiang@94ai.com>",
@@ -14,7 +14,7 @@
14
14
  "url": "http://94ai.gitlab.com/zoujiahe/common-ui.git"
15
15
  },
16
16
  "dependencies": {
17
- "@94ai/nf-theme-chalk": "^3.3.60",
17
+ "@94ai/nf-theme-chalk": "^3.3.61",
18
18
  "vue-demi": "^0.14.5"
19
19
  },
20
20
  "peerDependenciesMeta": {
@@ -30,5 +30,5 @@
30
30
  "types": "lib/index.d.ts",
31
31
  "main": "lib/nf-audio.cjs.js",
32
32
  "module": "lib/nf-audio.esm-bundler.js",
33
- "gitHead": "29cda3344f971577a22be62897195114e3cdd761"
33
+ "gitHead": "068f8237a674ca19312826eeadeb8cb36be24ebf"
34
34
  }