@94ai/nf-audio 3.3.60 → 3.3.62

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
  },
@@ -56,6 +60,10 @@ const _sfc_main = {
56
60
  type: Number,
57
61
  default: 0
58
62
  },
63
+ showJumpTime: {
64
+ type: Boolean,
65
+ default: true
66
+ },
59
67
  // 快退秒数
60
68
  backSecond: {
61
69
  type: Number,
@@ -70,7 +78,7 @@ const _sfc_main = {
70
78
  multipleArray: {
71
79
  type: Array,
72
80
  default() {
73
- return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0"];
81
+ return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0", "10.0"];
74
82
  }
75
83
  },
76
84
  // 默认速度
@@ -93,6 +101,45 @@ const _sfc_main = {
93
101
  },
94
102
  data() {
95
103
  return {
104
+ audioWorkletProcessor: `
105
+ class TickWorkletProcessor extends AudioWorkletProcessor {
106
+ constructor() {
107
+ super();
108
+ this.port.onmessage = this.handleMessage.bind(this);
109
+ this.end = true
110
+ }
111
+
112
+ handleMessage(event) {
113
+ const { command, start, end, currentTime } = event.data;
114
+ if (command === 'start') {
115
+ this.end = false
116
+ } else if (command === 'end') {
117
+ this.end = true
118
+ }
119
+ }
120
+
121
+ process(inputs, outputs) {
122
+ this.port.postMessage({
123
+ command: 'tick'
124
+ });
125
+ const input = inputs[0];
126
+ const output = outputs[0];
127
+ for (let channel = 0; channel < input.length; ++channel) {
128
+ const inputChannel = input[channel];
129
+ const outputChannel = output[channel];
130
+ for (let i = 0; i < inputChannel.length; ++i) {
131
+ outputChannel[i] = inputChannel[i];
132
+ }
133
+ }
134
+ return !this.end;
135
+ }
136
+ }
137
+
138
+ registerProcessor('tick', TickWorkletProcessor);
139
+ `,
140
+ audioCtx: void 0,
141
+ audioSource: void 0,
142
+ processor: void 0,
96
143
  betweenPlaying: false,
97
144
  // 播放还是暂停
98
145
  paused: true,
@@ -123,6 +170,28 @@ const _sfc_main = {
123
170
  this.volumeValue = this.initVolumnValue * 100;
124
171
  this.syncSpeed();
125
172
  },
173
+ beforeDestroy() {
174
+ var _a, _b, _c, _d;
175
+ this.betweenPlaying = false;
176
+ try {
177
+ (_a = this.audioCtx) == null ? void 0 : _a.close();
178
+ } catch (e) {
179
+ } finally {
180
+ this.audioCtx = void 0;
181
+ }
182
+ try {
183
+ (_b = this.audioSource) == null ? void 0 : _b.disconnect();
184
+ } catch (e) {
185
+ } finally {
186
+ this.audioSource = void 0;
187
+ }
188
+ try {
189
+ (_d = (_c = this.processor) == null ? void 0 : _c.port) == null ? void 0 : _d.close();
190
+ } catch (e) {
191
+ } finally {
192
+ this.processor = void 0;
193
+ }
194
+ },
126
195
  methods: {
127
196
  locationToTime(time) {
128
197
  this.betweenPlaying = false;
@@ -176,8 +245,11 @@ const _sfc_main = {
176
245
  handlePauseOrPlay() {
177
246
  if (!this.disabled) {
178
247
  if (this.audio.readyState >= 2) {
179
- this.audio.paused ? this.audio.play() : this.audio.pause();
180
- this.audio.playbackRate = this.speed;
248
+ if (this.audio.paused) {
249
+ this.playAudio();
250
+ } else {
251
+ this.pauseAudio();
252
+ }
181
253
  this.paused = !this.paused;
182
254
  this.betweenPlaying = false;
183
255
  this.$emit("pauseOrPlay", this.paused);
@@ -185,19 +257,70 @@ const _sfc_main = {
185
257
  console.log("Audio is not ready yet.");
186
258
  nfMessage.Message.warning(this.unloadTip);
187
259
  this.paused = true;
260
+ this.betweenPlaying = false;
188
261
  }
189
262
  }
190
263
  },
264
+ suspendAudioCtx() {
265
+ var _a, _b, _c;
266
+ try {
267
+ (_b = (_a = this.processor) == null ? void 0 : _a.port) == null ? void 0 : _b.postMessage({
268
+ command: "end"
269
+ });
270
+ } catch (e) {
271
+ }
272
+ try {
273
+ (_c = this.audioCtx) == null ? void 0 : _c.suspend();
274
+ } catch (e) {
275
+ }
276
+ },
277
+ async startAudioCtx() {
278
+ if (!this.audioCtx) {
279
+ this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
280
+ this.audioSource = this.audioCtx.createMediaElementSource(this.audio);
281
+ await this.audioCtx.audioWorklet.addModule("data:application/javascript," + encodeURIComponent(this.audioWorkletProcessor));
282
+ this.processor = new AudioWorkletNode(this.audioCtx, "tick");
283
+ this.audioSource.connect(this.processor).connect(this.audioCtx.destination);
284
+ this.processor.port.onmessage = (event) => {
285
+ if (event.data.command === "tick") {
286
+ if (this.betweenPlaying) {
287
+ if (this.betweenStart && this.betweenEnd) {
288
+ if (this.debuglog) {
289
+ console.log(this.audio.currentTime);
290
+ }
291
+ if (this.audio.currentTime >= this.betweenEnd) {
292
+ this.pause();
293
+ }
294
+ }
295
+ }
296
+ }
297
+ };
298
+ } else {
299
+ this.audioCtx.resume();
300
+ }
301
+ this.processor.port.postMessage({
302
+ command: "start"
303
+ });
304
+ },
191
305
  pause() {
192
- this.audio.pause();
306
+ this.pauseAudio();
193
307
  this.paused = true;
194
308
  this.betweenPlaying = false;
195
309
  },
196
- play() {
197
- this.audio.play();
310
+ async play() {
311
+ await this.playAudio();
198
312
  this.paused = false;
199
313
  this.betweenPlaying = false;
200
314
  },
315
+ pauseAudio() {
316
+ this.audio.pause();
317
+ this.suspendAudioCtx();
318
+ },
319
+ async playAudio() {
320
+ this.audio.playbackRate = this.speed;
321
+ await this.startAudioCtx();
322
+ this.audio.play();
323
+ },
201
324
  //视频在可以播放时触发
202
325
  getDuration() {
203
326
  this.totalTime = timeFormat(this.audio.duration);
@@ -213,18 +336,16 @@ const _sfc_main = {
213
336
  this.$refs.progressCurrent.style.width = MoveX + "px";
214
337
  this.$refs.progressBar.style.left = MoveX - this.$refs.progressBar.clientWidth / 2 + "px";
215
338
  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
339
  }
225
340
  },
226
341
  betweenPlay() {
227
342
  if (!this.disabled) {
343
+ if (this.audio.duration === 0) {
344
+ nfMessage.Message.warning(this.unloadTip);
345
+ this.paused = true;
346
+ this.betweenPlaying = false;
347
+ return false;
348
+ }
228
349
  this.betweenPlaying = true;
229
350
  this.jumpToTime(this.betweenStart);
230
351
  }
@@ -232,7 +353,7 @@ const _sfc_main = {
232
353
  handleAudioEnded() {
233
354
  this.$refs.progressCurrent.style.width = this.$refs.progressContainer.clientWidth + "px";
234
355
  this.$refs.progressBar.style.left = this.$refs.progressContainer.clientWidth - this.$refs.progressBar.clientWidth / 2 + "px";
235
- this.paused = true;
356
+ this.pause();
236
357
  },
237
358
  //点击进度条更新进度
238
359
  clickProgress(e) {
@@ -240,6 +361,7 @@ const _sfc_main = {
240
361
  if (this.audio.duration === 0) {
241
362
  nfMessage.Message.warning(this.unloadTip);
242
363
  this.paused = true;
364
+ this.betweenPlaying = false;
243
365
  return false;
244
366
  }
245
367
  if (!this.audio.paused) {
@@ -261,10 +383,10 @@ const _sfc_main = {
261
383
  if (this.audio.duration === 0) {
262
384
  nfMessage.Message.warning(this.unloadTip);
263
385
  this.paused = true;
386
+ this.betweenPlaying = false;
264
387
  return false;
265
388
  }
266
- this.audio.play();
267
- this.paused = false;
389
+ this.play();
268
390
  }
269
391
  },
270
392
  moveX(e) {
@@ -279,8 +401,9 @@ const _sfc_main = {
279
401
  //调整进度
280
402
  handleMousedown() {
281
403
  if (!this.disabled) {
282
- this.audio.pause();
404
+ this.pauseAudio();
283
405
  this.paused = true;
406
+ this.betweenPlaying = false;
284
407
  const progressContainer = this.$refs.progressContainer;
285
408
  this.moveMin = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft;
286
409
  this.moveMax = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft + progressContainer.clientWidth;
@@ -318,17 +441,18 @@ const _sfc_main = {
318
441
  },
319
442
  jumpToTime(time) {
320
443
  if (!this.disabled) {
321
- this.audio.pause();
444
+ this.pauseAudio();
322
445
  if (this.audio.duration === 0) {
323
446
  nfMessage.Message.warning(this.unloadTip);
324
447
  this.paused = true;
448
+ this.betweenPlaying = false;
325
449
  return false;
326
450
  }
327
451
  if (time >= this.audio.duration) {
328
452
  this.audio.currentTime = this.audio.duration;
329
453
  this.currentTime = timeFormat(this.audio.currentTime);
330
454
  this.calcMoveX();
331
- this.audio.play();
455
+ this.playAudio();
332
456
  if (time > this.audio.duration) {
333
457
  console.error(this.crossTimeTip);
334
458
  }
@@ -337,12 +461,12 @@ const _sfc_main = {
337
461
  this.audio.currentTime = time;
338
462
  this.currentTime = timeFormat(this.audio.currentTime);
339
463
  this.calcMoveX();
340
- this.audio.play();
464
+ this.playAudio();
341
465
  } else {
342
466
  this.audio.currentTime = 0;
343
467
  this.currentTime = timeFormat(this.audio.currentTime);
344
468
  this.calcMoveX();
345
- this.audio.play();
469
+ this.playAudio();
346
470
  }
347
471
  this.$emit("jumpToTime", time);
348
472
  }
@@ -402,7 +526,7 @@ var _sfc_render = function render() {
402
526
  "timeupdate": _vm.updateTime,
403
527
  "ended": _vm.handleAudioEnded
404
528
  }
405
- }), typeof _vm.jumpTime === "undefined" ? _vm._t("jump", function() {
529
+ }), _vm.showJumpTime ? _vm._t("jump", function() {
406
530
  return [_c("div", {
407
531
  staticClass: "nf-audio-fast"
408
532
  }, [_c("i", {
@@ -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
  },
@@ -54,6 +58,10 @@ const _sfc_main = {
54
58
  type: Number,
55
59
  default: 0
56
60
  },
61
+ showJumpTime: {
62
+ type: Boolean,
63
+ default: true
64
+ },
57
65
  // 快退秒数
58
66
  backSecond: {
59
67
  type: Number,
@@ -68,7 +76,7 @@ const _sfc_main = {
68
76
  multipleArray: {
69
77
  type: Array,
70
78
  default() {
71
- return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0"];
79
+ return ["1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "3.5", "4.0", "10.0"];
72
80
  }
73
81
  },
74
82
  // 默认速度
@@ -91,6 +99,45 @@ const _sfc_main = {
91
99
  },
92
100
  data() {
93
101
  return {
102
+ audioWorkletProcessor: `
103
+ class TickWorkletProcessor extends AudioWorkletProcessor {
104
+ constructor() {
105
+ super();
106
+ this.port.onmessage = this.handleMessage.bind(this);
107
+ this.end = true
108
+ }
109
+
110
+ handleMessage(event) {
111
+ const { command, start, end, currentTime } = event.data;
112
+ if (command === 'start') {
113
+ this.end = false
114
+ } else if (command === 'end') {
115
+ this.end = true
116
+ }
117
+ }
118
+
119
+ process(inputs, outputs) {
120
+ this.port.postMessage({
121
+ command: 'tick'
122
+ });
123
+ const input = inputs[0];
124
+ const output = outputs[0];
125
+ for (let channel = 0; channel < input.length; ++channel) {
126
+ const inputChannel = input[channel];
127
+ const outputChannel = output[channel];
128
+ for (let i = 0; i < inputChannel.length; ++i) {
129
+ outputChannel[i] = inputChannel[i];
130
+ }
131
+ }
132
+ return !this.end;
133
+ }
134
+ }
135
+
136
+ registerProcessor('tick', TickWorkletProcessor);
137
+ `,
138
+ audioCtx: void 0,
139
+ audioSource: void 0,
140
+ processor: void 0,
94
141
  betweenPlaying: false,
95
142
  // 播放还是暂停
96
143
  paused: true,
@@ -121,6 +168,28 @@ const _sfc_main = {
121
168
  this.volumeValue = this.initVolumnValue * 100;
122
169
  this.syncSpeed();
123
170
  },
171
+ beforeDestroy() {
172
+ var _a, _b, _c, _d;
173
+ this.betweenPlaying = false;
174
+ try {
175
+ (_a = this.audioCtx) == null ? void 0 : _a.close();
176
+ } catch (e) {
177
+ } finally {
178
+ this.audioCtx = void 0;
179
+ }
180
+ try {
181
+ (_b = this.audioSource) == null ? void 0 : _b.disconnect();
182
+ } catch (e) {
183
+ } finally {
184
+ this.audioSource = void 0;
185
+ }
186
+ try {
187
+ (_d = (_c = this.processor) == null ? void 0 : _c.port) == null ? void 0 : _d.close();
188
+ } catch (e) {
189
+ } finally {
190
+ this.processor = void 0;
191
+ }
192
+ },
124
193
  methods: {
125
194
  locationToTime(time) {
126
195
  this.betweenPlaying = false;
@@ -174,8 +243,11 @@ const _sfc_main = {
174
243
  handlePauseOrPlay() {
175
244
  if (!this.disabled) {
176
245
  if (this.audio.readyState >= 2) {
177
- this.audio.paused ? this.audio.play() : this.audio.pause();
178
- this.audio.playbackRate = this.speed;
246
+ if (this.audio.paused) {
247
+ this.playAudio();
248
+ } else {
249
+ this.pauseAudio();
250
+ }
179
251
  this.paused = !this.paused;
180
252
  this.betweenPlaying = false;
181
253
  this.$emit("pauseOrPlay", this.paused);
@@ -183,19 +255,70 @@ const _sfc_main = {
183
255
  console.log("Audio is not ready yet.");
184
256
  Message.warning(this.unloadTip);
185
257
  this.paused = true;
258
+ this.betweenPlaying = false;
186
259
  }
187
260
  }
188
261
  },
262
+ suspendAudioCtx() {
263
+ var _a, _b, _c;
264
+ try {
265
+ (_b = (_a = this.processor) == null ? void 0 : _a.port) == null ? void 0 : _b.postMessage({
266
+ command: "end"
267
+ });
268
+ } catch (e) {
269
+ }
270
+ try {
271
+ (_c = this.audioCtx) == null ? void 0 : _c.suspend();
272
+ } catch (e) {
273
+ }
274
+ },
275
+ async startAudioCtx() {
276
+ if (!this.audioCtx) {
277
+ this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
278
+ this.audioSource = this.audioCtx.createMediaElementSource(this.audio);
279
+ await this.audioCtx.audioWorklet.addModule("data:application/javascript," + encodeURIComponent(this.audioWorkletProcessor));
280
+ this.processor = new AudioWorkletNode(this.audioCtx, "tick");
281
+ this.audioSource.connect(this.processor).connect(this.audioCtx.destination);
282
+ this.processor.port.onmessage = (event) => {
283
+ if (event.data.command === "tick") {
284
+ if (this.betweenPlaying) {
285
+ if (this.betweenStart && this.betweenEnd) {
286
+ if (this.debuglog) {
287
+ console.log(this.audio.currentTime);
288
+ }
289
+ if (this.audio.currentTime >= this.betweenEnd) {
290
+ this.pause();
291
+ }
292
+ }
293
+ }
294
+ }
295
+ };
296
+ } else {
297
+ this.audioCtx.resume();
298
+ }
299
+ this.processor.port.postMessage({
300
+ command: "start"
301
+ });
302
+ },
189
303
  pause() {
190
- this.audio.pause();
304
+ this.pauseAudio();
191
305
  this.paused = true;
192
306
  this.betweenPlaying = false;
193
307
  },
194
- play() {
195
- this.audio.play();
308
+ async play() {
309
+ await this.playAudio();
196
310
  this.paused = false;
197
311
  this.betweenPlaying = false;
198
312
  },
313
+ pauseAudio() {
314
+ this.audio.pause();
315
+ this.suspendAudioCtx();
316
+ },
317
+ async playAudio() {
318
+ this.audio.playbackRate = this.speed;
319
+ await this.startAudioCtx();
320
+ this.audio.play();
321
+ },
199
322
  //视频在可以播放时触发
200
323
  getDuration() {
201
324
  this.totalTime = timeFormat(this.audio.duration);
@@ -211,18 +334,16 @@ const _sfc_main = {
211
334
  this.$refs.progressCurrent.style.width = MoveX + "px";
212
335
  this.$refs.progressBar.style.left = MoveX - this.$refs.progressBar.clientWidth / 2 + "px";
213
336
  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
337
  }
223
338
  },
224
339
  betweenPlay() {
225
340
  if (!this.disabled) {
341
+ if (this.audio.duration === 0) {
342
+ Message.warning(this.unloadTip);
343
+ this.paused = true;
344
+ this.betweenPlaying = false;
345
+ return false;
346
+ }
226
347
  this.betweenPlaying = true;
227
348
  this.jumpToTime(this.betweenStart);
228
349
  }
@@ -230,7 +351,7 @@ const _sfc_main = {
230
351
  handleAudioEnded() {
231
352
  this.$refs.progressCurrent.style.width = this.$refs.progressContainer.clientWidth + "px";
232
353
  this.$refs.progressBar.style.left = this.$refs.progressContainer.clientWidth - this.$refs.progressBar.clientWidth / 2 + "px";
233
- this.paused = true;
354
+ this.pause();
234
355
  },
235
356
  //点击进度条更新进度
236
357
  clickProgress(e) {
@@ -238,6 +359,7 @@ const _sfc_main = {
238
359
  if (this.audio.duration === 0) {
239
360
  Message.warning(this.unloadTip);
240
361
  this.paused = true;
362
+ this.betweenPlaying = false;
241
363
  return false;
242
364
  }
243
365
  if (!this.audio.paused) {
@@ -259,10 +381,10 @@ const _sfc_main = {
259
381
  if (this.audio.duration === 0) {
260
382
  Message.warning(this.unloadTip);
261
383
  this.paused = true;
384
+ this.betweenPlaying = false;
262
385
  return false;
263
386
  }
264
- this.audio.play();
265
- this.paused = false;
387
+ this.play();
266
388
  }
267
389
  },
268
390
  moveX(e) {
@@ -277,8 +399,9 @@ const _sfc_main = {
277
399
  //调整进度
278
400
  handleMousedown() {
279
401
  if (!this.disabled) {
280
- this.audio.pause();
402
+ this.pauseAudio();
281
403
  this.paused = true;
404
+ this.betweenPlaying = false;
282
405
  const progressContainer = this.$refs.progressContainer;
283
406
  this.moveMin = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft;
284
407
  this.moveMax = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft + progressContainer.clientWidth;
@@ -316,17 +439,18 @@ const _sfc_main = {
316
439
  },
317
440
  jumpToTime(time) {
318
441
  if (!this.disabled) {
319
- this.audio.pause();
442
+ this.pauseAudio();
320
443
  if (this.audio.duration === 0) {
321
444
  Message.warning(this.unloadTip);
322
445
  this.paused = true;
446
+ this.betweenPlaying = false;
323
447
  return false;
324
448
  }
325
449
  if (time >= this.audio.duration) {
326
450
  this.audio.currentTime = this.audio.duration;
327
451
  this.currentTime = timeFormat(this.audio.currentTime);
328
452
  this.calcMoveX();
329
- this.audio.play();
453
+ this.playAudio();
330
454
  if (time > this.audio.duration) {
331
455
  console.error(this.crossTimeTip);
332
456
  }
@@ -335,12 +459,12 @@ const _sfc_main = {
335
459
  this.audio.currentTime = time;
336
460
  this.currentTime = timeFormat(this.audio.currentTime);
337
461
  this.calcMoveX();
338
- this.audio.play();
462
+ this.playAudio();
339
463
  } else {
340
464
  this.audio.currentTime = 0;
341
465
  this.currentTime = timeFormat(this.audio.currentTime);
342
466
  this.calcMoveX();
343
- this.audio.play();
467
+ this.playAudio();
344
468
  }
345
469
  this.$emit("jumpToTime", time);
346
470
  }
@@ -400,7 +524,7 @@ var _sfc_render = function render() {
400
524
  "timeupdate": _vm.updateTime,
401
525
  "ended": _vm.handleAudioEnded
402
526
  }
403
- }), typeof _vm.jumpTime === "undefined" ? _vm._t("jump", function() {
527
+ }), _vm.showJumpTime ? _vm._t("jump", function() {
404
528
  return [_c("div", {
405
529
  staticClass: "nf-audio-fast"
406
530
  }, [_c("i", {
@@ -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>
@@ -16,7 +16,7 @@
16
16
  />
17
17
 
18
18
  <!-- 跳帧 -->
19
- <slot name="jump" v-if="typeof jumpTime === 'undefined'">
19
+ <slot name="jump" v-if="showJumpTime">
20
20
  <div class="nf-audio-fast">
21
21
  <i class="iconfont icon-zanting1 nf-audio-fast-icon"
22
22
  @click="locationToTime(jumpTime)"
@@ -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
  },
@@ -212,6 +216,10 @@ export default {
212
216
  type: Number,
213
217
  default: 0
214
218
  },
219
+ showJumpTime: {
220
+ type: Boolean,
221
+ default: true
222
+ },
215
223
  // 快退秒数
216
224
  backSecond: {
217
225
  type: Number,
@@ -226,7 +234,7 @@ export default {
226
234
  multipleArray: {
227
235
  type: Array,
228
236
  default() {
229
- return ['1.0', '1.25', '1.5', '1.75', '2.0', '2.5', '3.0', '3.5', '4.0']
237
+ return ['1.0', '1.25', '1.5', '1.75', '2.0', '2.5', '3.0', '3.5', '4.0', '10.0']
230
238
  }
231
239
  },
232
240
  // 默认速度
@@ -249,6 +257,45 @@ export default {
249
257
  },
250
258
  data() {
251
259
  return {
260
+ audioWorkletProcessor: `
261
+ class TickWorkletProcessor extends AudioWorkletProcessor {
262
+ constructor() {
263
+ super();
264
+ this.port.onmessage = this.handleMessage.bind(this);
265
+ this.end = true
266
+ }
267
+
268
+ handleMessage(event) {
269
+ const { command, start, end, currentTime } = event.data;
270
+ if (command === 'start') {
271
+ this.end = false
272
+ } else if (command === 'end') {
273
+ this.end = true
274
+ }
275
+ }
276
+
277
+ process(inputs, outputs) {
278
+ this.port.postMessage({
279
+ command: 'tick'
280
+ });
281
+ const input = inputs[0];
282
+ const output = outputs[0];
283
+ for (let channel = 0; channel < input.length; ++channel) {
284
+ const inputChannel = input[channel];
285
+ const outputChannel = output[channel];
286
+ for (let i = 0; i < inputChannel.length; ++i) {
287
+ outputChannel[i] = inputChannel[i];
288
+ }
289
+ }
290
+ return !this.end;
291
+ }
292
+ }
293
+
294
+ registerProcessor('tick', TickWorkletProcessor);
295
+ `,
296
+ audioCtx: undefined,
297
+ audioSource: undefined,
298
+ processor: undefined,
252
299
  betweenPlaying: false,
253
300
  // 播放还是暂停
254
301
  paused: true,
@@ -283,6 +330,30 @@ export default {
283
330
  this.volumeValue = this.initVolumnValue * 100
284
331
  this.syncSpeed()
285
332
  },
333
+ beforeDestroy() {
334
+ this.betweenPlaying = false
335
+ try {
336
+ this.audioCtx?.close()
337
+ } catch (e) {
338
+ //
339
+ } finally {
340
+ this.audioCtx = undefined
341
+ }
342
+ try {
343
+ this.audioSource?.disconnect()
344
+ } catch (e) {
345
+ //
346
+ } finally {
347
+ this.audioSource = undefined
348
+ }
349
+ try {
350
+ this.processor?.port?.close()
351
+ } catch (e) {
352
+ //
353
+ } finally {
354
+ this.processor = undefined
355
+ }
356
+ },
286
357
  methods: {
287
358
  locationToTime(time) {
288
359
  this.betweenPlaying = false
@@ -338,8 +409,11 @@ export default {
338
409
  if (!this.disabled) {
339
410
  if (this.audio.readyState >= 2) {
340
411
  // 如果音频资源已加载元数据或更多,可以播放
341
- this.audio.paused ? this.audio.play() : this.audio.pause()
342
- this.audio.playbackRate = this.speed
412
+ if(this.audio.paused) {
413
+ this.playAudio()
414
+ } else {
415
+ this.pauseAudio()
416
+ }
343
417
  this.paused = !this.paused
344
418
  this.betweenPlaying = false
345
419
  this.$emit('pauseOrPlay', this.paused)
@@ -347,25 +421,72 @@ export default {
347
421
  console.log('Audio is not ready yet.')
348
422
  Message.warning(this.unloadTip)
349
423
  this.paused = true
424
+ this.betweenPlaying = false
350
425
  }
351
426
  }
352
427
  },
428
+ suspendAudioCtx() {
429
+ try {
430
+ this.processor?.port?.postMessage({ command: 'end' });
431
+ } catch (e) {
432
+ //
433
+ }
434
+ try {
435
+ this.audioCtx?.suspend()
436
+ } catch (e) {
437
+ //
438
+ }
439
+ },
440
+ async startAudioCtx() {
441
+ if (!this.audioCtx) {
442
+ this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
443
+ this.audioSource = this.audioCtx.createMediaElementSource(this.audio);
444
+ await this.audioCtx.audioWorklet.addModule('data:application/javascript,' + encodeURIComponent(this.audioWorkletProcessor));
445
+ this.processor = new AudioWorkletNode(this.audioCtx, 'tick');
446
+ this.audioSource.connect(this.processor).connect(this.audioCtx.destination);
447
+ this.processor.port.onmessage = (event) => {
448
+ if (event.data.command === 'tick') {
449
+ if (this.betweenPlaying) {
450
+ if (this.betweenStart && this.betweenEnd) {
451
+ if (this.debuglog) {
452
+ console.log(this.audio.currentTime)
453
+ }
454
+ if (this.audio.currentTime >= this.betweenEnd) {
455
+ this.pause()
456
+ }
457
+ }
458
+ }
459
+ }
460
+ };
461
+ } else {
462
+ this.audioCtx.resume()
463
+ }
464
+ this.processor.port.postMessage({ command: 'start' });
465
+ },
353
466
  pause() {
354
- this.audio.pause()
467
+ this.pauseAudio()
355
468
  this.paused = true
356
469
  this.betweenPlaying = false
357
470
  },
358
- play() {
359
- this.audio.play()
471
+ async play() {
472
+ await this.playAudio()
360
473
  this.paused = false
361
474
  this.betweenPlaying = false
362
475
  },
476
+ pauseAudio() {
477
+ this.audio.pause()
478
+ this.suspendAudioCtx()
479
+ },
480
+ async playAudio() {
481
+ this.audio.playbackRate = this.speed
482
+ await this.startAudioCtx()
483
+ this.audio.play()
484
+ },
363
485
  //视频在可以播放时触发
364
486
  getDuration() {
365
487
  this.totalTime = timeFormat(this.audio.duration)
366
488
  this.audio.volume = this.volume
367
489
  },
368
-
369
490
  //进度条发生变化时触发
370
491
  updateTime() {
371
492
  if (!this.$refs.progressContainer) return
@@ -378,18 +499,16 @@ export default {
378
499
  this.$refs.progressCurrent.style.width = MoveX + 'px'
379
500
  this.$refs.progressBar.style.left = MoveX - (this.$refs.progressBar.clientWidth / 2) + 'px'
380
501
  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
502
  }
390
503
  },
391
504
  betweenPlay() {
392
505
  if (!this.disabled) {
506
+ if (this.audio.duration === 0) {
507
+ Message.warning(this.unloadTip)
508
+ this.paused = true
509
+ this.betweenPlaying = false
510
+ return false
511
+ }
393
512
  this.betweenPlaying = true
394
513
  this.jumpToTime(this.betweenStart)
395
514
  }
@@ -397,7 +516,7 @@ export default {
397
516
  handleAudioEnded() {
398
517
  this.$refs.progressCurrent.style.width = this.$refs.progressContainer.clientWidth + 'px'
399
518
  this.$refs.progressBar.style.left = this.$refs.progressContainer.clientWidth - (this.$refs.progressBar.clientWidth / 2) + 'px'
400
- this.paused = true
519
+ this.pause()
401
520
  },
402
521
  //点击进度条更新进度
403
522
  clickProgress(e) {
@@ -405,6 +524,7 @@ export default {
405
524
  if (this.audio.duration === 0) {
406
525
  Message.warning(this.unloadTip)
407
526
  this.paused = true
527
+ this.betweenPlaying = false
408
528
  return false
409
529
  }
410
530
  //如果不是正在移动 和 没有暂停播放就执行
@@ -430,10 +550,10 @@ export default {
430
550
  if (this.audio.duration === 0) {
431
551
  Message.warning(this.unloadTip)
432
552
  this.paused = true
553
+ this.betweenPlaying = false
433
554
  return false
434
555
  }
435
- this.audio.play()
436
- this.paused = false
556
+ this.play()
437
557
  }
438
558
  },
439
559
  moveX(e) {
@@ -448,8 +568,9 @@ export default {
448
568
  //调整进度
449
569
  handleMousedown() {
450
570
  if (!this.disabled) {
451
- this.audio.pause()
571
+ this.pauseAudio()
452
572
  this.paused = true
573
+ this.betweenPlaying = false
453
574
  const progressContainer = this.$refs.progressContainer
454
575
  //进度条 左 边距离页面左边的距离 移动最小值
455
576
  this.moveMin = progressContainer.offsetParent.offsetLeft + progressContainer.offsetLeft
@@ -494,17 +615,18 @@ export default {
494
615
  },
495
616
  jumpToTime(time) {
496
617
  if (!this.disabled) {
497
- this.audio.pause()
618
+ this.pauseAudio()
498
619
  if (this.audio.duration === 0) {
499
620
  Message.warning(this.unloadTip)
500
621
  this.paused = true
622
+ this.betweenPlaying = false
501
623
  return false
502
624
  }
503
625
  if (time >= this.audio.duration) {
504
626
  this.audio.currentTime = this.audio.duration
505
627
  this.currentTime = timeFormat(this.audio.currentTime)
506
628
  this.calcMoveX()
507
- this.audio.play()
629
+ this.playAudio()
508
630
  if (time > this.audio.duration) {
509
631
  console.error(this.crossTimeTip)
510
632
  }
@@ -513,12 +635,12 @@ export default {
513
635
  this.audio.currentTime = time
514
636
  this.currentTime = timeFormat(this.audio.currentTime)
515
637
  this.calcMoveX()
516
- this.audio.play()
638
+ this.playAudio()
517
639
  } else {
518
640
  this.audio.currentTime = 0
519
641
  this.currentTime = timeFormat(this.audio.currentTime)
520
642
  this.calcMoveX()
521
- this.audio.play()
643
+ this.playAudio()
522
644
  }
523
645
  this.$emit('jumpToTime', time)
524
646
  }
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.62",
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.62",
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": "eb66eba98360c212306e6c23a786e75bce214924"
34
34
  }