audio-channel-queue 1.12.0 → 1.13.2
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/README.md +68 -15
- package/dist/core.d.ts +1 -1
- package/dist/core.js +8 -4
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +2 -42
- package/dist/events.d.ts +1 -1
- package/dist/events.js +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +19 -3
- package/dist/info.d.ts +1 -1
- package/dist/info.js +4 -2
- package/dist/pause.d.ts +1 -1
- package/dist/pause.js +35 -9
- package/dist/queue-manipulation.d.ts +1 -1
- package/dist/queue-manipulation.js +1 -1
- package/dist/types.d.ts +38 -1
- package/dist/types.js +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/dist/volume.d.ts +41 -1
- package/dist/volume.js +194 -19
- package/dist/web-audio.d.ts +156 -0
- package/dist/web-audio.js +327 -0
- package/package.json +9 -5
- package/src/core.ts +17 -5
- package/src/errors.ts +3 -51
- package/src/events.ts +1 -1
- package/src/index.ts +23 -2
- package/src/info.ts +4 -2
- package/src/pause.ts +41 -11
- package/src/queue-manipulation.ts +1 -1
- package/src/types.ts +41 -1
- package/src/utils.ts +1 -1
- package/src/volume.ts +230 -18
- package/src/web-audio.ts +331 -0
package/README.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# ⚠️ DEPRECATED - This package has been renamed
|
|
2
|
+
|
|
3
|
+
This package is deprecated and will no longer receive updates.
|
|
4
|
+
|
|
5
|
+
**Please use [`AudioQ`](https://www.npmjs.com/package/audioq) instead:**
|
|
6
|
+
|
|
7
|
+
\`\`\`bash
|
|
8
|
+
npm install audioq
|
|
9
|
+
\`\`\`
|
|
10
|
+
|
|
11
|
+
All future development will happen in the new package.
|
|
12
|
+
|
|
1
13
|
# Audio Channel Queue
|
|
2
14
|
The purpose of this package is to help manage the playback of audio files.
|
|
3
15
|
|
|
@@ -5,20 +17,20 @@ The purpose of this package is to help manage the playback of audio files.
|
|
|
5
17
|
|
|
6
18
|
📚 [Docs](https://tonycarpenter21.github.io/audio-queue-docs/)
|
|
7
19
|
|
|
8
|
-
##
|
|
20
|
+
## Key Features
|
|
9
21
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
22
|
+
- **Multi-channel queue management** - Independent audio queues for concurrent playback
|
|
23
|
+
- **Pause/Resume functionality** - Full playback control for individual channels or all channels
|
|
24
|
+
- **Volume control with ducking** - Dynamic volume management, global volume control, and automatic background audio reduction
|
|
25
|
+
- **Loop support** - Seamless audio looping for background music and ambient sounds
|
|
26
|
+
- **Priority queueing** - Add urgent audio to the front of any queue
|
|
27
|
+
- **Real-time progress tracking** - Comprehensive playback monitoring and metadata
|
|
28
|
+
- **Event-driven architecture** - Extensive callback system for UI integration
|
|
29
|
+
- **TypeScript support** - Full type definitions and IntelliSense support
|
|
30
|
+
- **Zero dependencies** - Lightweight and self-contained
|
|
31
|
+
- **Backward compatible** - All existing APIs continue to work
|
|
20
32
|
|
|
21
|
-
This package offers TypeScript support
|
|
33
|
+
This package offers TypeScript support, has zero dependencies, and is released under the MIT license.
|
|
22
34
|
|
|
23
35
|
To preview this package and see how it works with visualized code examples, check out the demo that can be found here: [Audio Channel Queue Demo](https://tonycarpenter21.github.io/audio-queue-demo/). (A link to the demo repo can be found here: [Audio Channel Queue Demo Repo](https://github.com/tonycarpenter21/audio-queue-demo).)
|
|
24
36
|
|
|
@@ -32,18 +44,18 @@ Documentation can be found [here](https://tonycarpenter21.github.io/audio-queue-
|
|
|
32
44
|
|
|
33
45
|
This package is designed for **browser environments** and uses the Web Audio API (`HTMLAudioElement`). It is **not** intended for Node.js server-side use.
|
|
34
46
|
|
|
35
|
-
###
|
|
47
|
+
### **Supported Browsers:**
|
|
36
48
|
- **Chrome 51+** (June 2016)
|
|
37
49
|
- **Firefox 54+** (June 2017)
|
|
38
50
|
- **Safari 10+** (September 2016)
|
|
39
51
|
- **Edge 15+** (April 2017)
|
|
40
52
|
- **Mobile browsers** with HTML5 audio support
|
|
41
53
|
|
|
42
|
-
###
|
|
54
|
+
### **Development Requirements:**
|
|
43
55
|
- **Node.js 14+** (for building and testing only)
|
|
44
56
|
- **TypeScript 4.5+** (included in devDependencies)
|
|
45
57
|
|
|
46
|
-
###
|
|
58
|
+
### **Not Supported:**
|
|
47
59
|
- Node.js server environments (no HTMLAudioElement)
|
|
48
60
|
- Internet Explorer (lacks ES6 support)
|
|
49
61
|
- Web Workers (no DOM access)
|
|
@@ -197,6 +209,47 @@ await setAllChannelsVolume(0.6); // Set all channels to 60% volume
|
|
|
197
209
|
await setAllChannelsVolume(0.0); // Mute all channels
|
|
198
210
|
```
|
|
199
211
|
|
|
212
|
+
### Global Volume Control
|
|
213
|
+
```typescript
|
|
214
|
+
// Set a global volume multiplier that affects all channels while preserving their relative levels.
|
|
215
|
+
setGlobalVolume(volume);
|
|
216
|
+
await setGlobalVolume(0.5); // Set global volume to 50%
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// Get the current global volume level.
|
|
221
|
+
getGlobalVolume();
|
|
222
|
+
const globalVol = getGlobalVolume(); // Returns current global volume (0-1)
|
|
223
|
+
console.log(`Global volume: ${(getGlobalVolume() * 100).toFixed(0)}%`);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**How Global Volume Works:**
|
|
227
|
+
The global volume acts as a **global volume multiplier** - it scales all channel volumes proportionally while preserving their individual settings. This is perfect for implementing a global volume slider in your UI.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// Example: Setting up different audio types with a global volume control
|
|
231
|
+
await setChannelVolume(0, 0.3); // SFX channel at 30%
|
|
232
|
+
await setChannelVolume(1, 0.7); // Music channel at 70%
|
|
233
|
+
await setChannelVolume(2, 0.5); // Voice channel at 50%
|
|
234
|
+
|
|
235
|
+
// User adjusts global volume slider to 50%
|
|
236
|
+
await setGlobalVolume(0.5);
|
|
237
|
+
|
|
238
|
+
// Actual playback volumes become:
|
|
239
|
+
// - SFX: 30% × 50% = 15%
|
|
240
|
+
// - Music: 70% × 50% = 35%
|
|
241
|
+
// - Voice: 50% × 50% = 25%
|
|
242
|
+
|
|
243
|
+
// Channel volumes remain at their original settings (0.3, 0.7, 0.5)
|
|
244
|
+
// So when global volume is increased, ratios are preserved
|
|
245
|
+
await setGlobalVolume(1.0); // Back to full volume
|
|
246
|
+
// - SFX: 30% × 100% = 30%
|
|
247
|
+
// - Music: 70% × 100% = 70%
|
|
248
|
+
// - Voice: 50% × 100% = 50%
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Note:** `setAllChannelsVolume()` sets all channels to the **same** volume, while `setGlobalVolume()` **multiplies** all channels by the same amount, preserving their relative differences.
|
|
252
|
+
|
|
200
253
|
### Volume Ducking (Background Audio Reduction)
|
|
201
254
|
```typescript
|
|
202
255
|
// Automatically reduce other channels' volume when priority audio plays.
|
package/dist/core.d.ts
CHANGED
package/dist/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Core queue management functions for the
|
|
3
|
+
* @fileoverview Core queue management functions for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
6
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -183,7 +183,7 @@ const checkQueueLimit = (channel, channelNumber, maxQueueSize) => {
|
|
|
183
183
|
(0, events_1.cleanupProgressTracking)(removedAudio, channelNumber, info_1.audioChannels);
|
|
184
184
|
if (globalQueueConfig.showQueueWarnings) {
|
|
185
185
|
// eslint-disable-next-line no-console
|
|
186
|
-
console.
|
|
186
|
+
console.warn(`Dropped oldest queued item to make room for new audio`);
|
|
187
187
|
}
|
|
188
188
|
return true;
|
|
189
189
|
}
|
|
@@ -244,6 +244,8 @@ const queueAudio = (audioUrl_1, ...args_1) => __awaiter(void 0, [audioUrl_1, ...
|
|
|
244
244
|
(0, errors_1.setupAudioErrorHandling)(audio, channelNumber, validatedUrl, (error) => __awaiter(void 0, void 0, void 0, function* () {
|
|
245
245
|
yield (0, errors_1.handleAudioError)(audio, channelNumber, validatedUrl, error);
|
|
246
246
|
}));
|
|
247
|
+
// Initialize Web Audio API support if needed
|
|
248
|
+
yield (0, volume_1.initializeWebAudioForAudio)(audio, channelNumber);
|
|
247
249
|
// Apply options if provided
|
|
248
250
|
if (options) {
|
|
249
251
|
if (typeof options.loop === 'boolean') {
|
|
@@ -316,9 +318,10 @@ const playAudioQueue = (channelNumber) => __awaiter(void 0, void 0, void 0, func
|
|
|
316
318
|
if (!channel || channel.queue.length === 0)
|
|
317
319
|
return;
|
|
318
320
|
const currentAudio = channel.queue[0];
|
|
319
|
-
// Apply channel volume if not already set
|
|
321
|
+
// Apply channel volume with global volume multiplier if not already set
|
|
320
322
|
if (currentAudio.volume === 1.0 && channel.volume !== undefined) {
|
|
321
|
-
|
|
323
|
+
const globalVolume = (0, volume_1.getGlobalVolume)();
|
|
324
|
+
currentAudio.volume = channel.volume * globalVolume;
|
|
322
325
|
}
|
|
323
326
|
(0, events_1.setupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
|
|
324
327
|
// Apply volume ducking when audio starts
|
|
@@ -378,6 +381,7 @@ const playAudioQueue = (channelNumber) => __awaiter(void 0, void 0, void 0, func
|
|
|
378
381
|
// For non-looping audio, remove from queue and play next
|
|
379
382
|
currentAudio.pause();
|
|
380
383
|
(0, events_1.cleanupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
|
|
384
|
+
(0, volume_1.cleanupWebAudioForAudio)(currentAudio, channelNumber);
|
|
381
385
|
channel.queue.shift();
|
|
382
386
|
channel.isPaused = false; // Reset pause state
|
|
383
387
|
// Restore volume levels AFTER removing audio from queue
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Error handling, retry logic, and recovery mechanisms for the
|
|
2
|
+
* @fileoverview Error handling, retry logic, and recovery mechanisms for the audioq package
|
|
3
3
|
*/
|
|
4
4
|
import { AudioErrorInfo, AudioErrorCallback, AudioErrorType, RetryConfig, ErrorRecoveryOptions, ExtendedAudioQueueChannel } from './types';
|
|
5
5
|
/**
|
package/dist/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Error handling, retry logic, and recovery mechanisms for the
|
|
3
|
+
* @fileoverview Error handling, retry logic, and recovery mechanisms for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
6
|
if (k2 === undefined) k2 = k;
|
|
@@ -56,7 +56,6 @@ let globalErrorRecovery = {
|
|
|
56
56
|
showUserFeedback: false
|
|
57
57
|
};
|
|
58
58
|
const retryAttempts = new WeakMap();
|
|
59
|
-
const loadTimeouts = new WeakMap();
|
|
60
59
|
/**
|
|
61
60
|
* Subscribes to audio error events for a specific channel
|
|
62
61
|
* @param channelNumber - The channel number to listen to (defaults to 0)
|
|
@@ -241,7 +240,7 @@ const emitAudioError = (channelNumber, errorInfo, audioChannels) => {
|
|
|
241
240
|
// Log to analytics if enabled
|
|
242
241
|
if (globalErrorRecovery.logErrorsToAnalytics) {
|
|
243
242
|
// eslint-disable-next-line no-console
|
|
244
|
-
console.
|
|
243
|
+
console.error('Audio Error Analytics:', errorInfo);
|
|
245
244
|
}
|
|
246
245
|
channel.audioErrorCallbacks.forEach((callback) => {
|
|
247
246
|
try {
|
|
@@ -306,37 +305,9 @@ const setupAudioErrorHandling = (audio, channelNumber, originalUrl, onError) =>
|
|
|
306
305
|
const channel = info_1.audioChannels[channelNumber];
|
|
307
306
|
if (!channel)
|
|
308
307
|
return;
|
|
309
|
-
// Set up loading timeout with test environment compatibility
|
|
310
|
-
let timeoutId;
|
|
311
|
-
if (typeof setTimeout !== 'undefined') {
|
|
312
|
-
timeoutId = setTimeout(() => {
|
|
313
|
-
if (audio.networkState === HTMLMediaElement.NETWORK_LOADING) {
|
|
314
|
-
const timeoutError = new Error(`Audio loading timeout after ${globalRetryConfig.timeoutMs}ms`);
|
|
315
|
-
(0, exports.handleAudioError)(audio, channelNumber, originalUrl, timeoutError);
|
|
316
|
-
}
|
|
317
|
-
}, globalRetryConfig.timeoutMs);
|
|
318
|
-
loadTimeouts.set(audio, timeoutId);
|
|
319
|
-
}
|
|
320
|
-
// Clear timeout when metadata loads successfully
|
|
321
|
-
const handleLoadSuccess = () => {
|
|
322
|
-
if (typeof setTimeout !== 'undefined') {
|
|
323
|
-
const timeoutId = loadTimeouts.get(audio);
|
|
324
|
-
if (timeoutId) {
|
|
325
|
-
clearTimeout(timeoutId);
|
|
326
|
-
loadTimeouts.delete(audio);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
308
|
// Handle various error events
|
|
331
309
|
const handleError = (_event) => {
|
|
332
310
|
var _a;
|
|
333
|
-
if (typeof setTimeout !== 'undefined') {
|
|
334
|
-
const timeoutId = loadTimeouts.get(audio);
|
|
335
|
-
if (timeoutId) {
|
|
336
|
-
clearTimeout(timeoutId);
|
|
337
|
-
loadTimeouts.delete(audio);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
311
|
const error = new Error(`Audio loading failed: ${((_a = audio.error) === null || _a === void 0 ? void 0 : _a.message) || 'Unknown error'}`);
|
|
341
312
|
(0, exports.handleAudioError)(audio, channelNumber, originalUrl, error);
|
|
342
313
|
};
|
|
@@ -352,8 +323,6 @@ const setupAudioErrorHandling = (audio, channelNumber, originalUrl, onError) =>
|
|
|
352
323
|
audio.addEventListener('error', handleError);
|
|
353
324
|
audio.addEventListener('abort', handleAbort);
|
|
354
325
|
audio.addEventListener('stalled', handleStall);
|
|
355
|
-
audio.addEventListener('loadedmetadata', handleLoadSuccess);
|
|
356
|
-
audio.addEventListener('canplay', handleLoadSuccess);
|
|
357
326
|
// Custom play error handling
|
|
358
327
|
if (onError) {
|
|
359
328
|
const originalPlay = audio.play.bind(audio);
|
|
@@ -451,19 +420,10 @@ exports.handleAudioError = handleAudioError;
|
|
|
451
420
|
const createProtectedAudioElement = (url, channelNumber) => __awaiter(void 0, void 0, void 0, function* () {
|
|
452
421
|
const audio = new Audio();
|
|
453
422
|
return new Promise((resolve, reject) => {
|
|
454
|
-
const cleanup = () => {
|
|
455
|
-
const timeoutId = loadTimeouts.get(audio);
|
|
456
|
-
if (timeoutId) {
|
|
457
|
-
clearTimeout(timeoutId);
|
|
458
|
-
loadTimeouts.delete(audio);
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
423
|
const handleSuccess = () => {
|
|
462
|
-
cleanup();
|
|
463
424
|
resolve(audio);
|
|
464
425
|
};
|
|
465
426
|
const handleError = (error) => {
|
|
466
|
-
cleanup();
|
|
467
427
|
reject(error);
|
|
468
428
|
};
|
|
469
429
|
// Set up error handling
|
package/dist/events.d.ts
CHANGED
package/dist/events.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Event handling and emission for the
|
|
3
|
+
* @fileoverview Event handling and emission for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.cleanupProgressTracking = exports.setupProgressTracking = exports.emitAudioResume = exports.emitAudioPause = exports.emitAudioComplete = exports.emitAudioStart = exports.emitQueueChange = void 0;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Main entry point for the
|
|
2
|
+
* @fileoverview Main entry point for the audioq package
|
|
3
3
|
* Exports all public functions and types for audio queue management, pause/resume controls,
|
|
4
4
|
* volume management with ducking, progress tracking, and comprehensive event system
|
|
5
5
|
*/
|
|
@@ -7,9 +7,10 @@ export { queueAudio, queueAudioPriority, stopCurrentAudioInChannel, stopAllAudio
|
|
|
7
7
|
export { clearQueueAfterCurrent, getQueueItemInfo, getQueueLength, removeQueuedItem, reorderQueue, swapQueueItems } from './queue-manipulation';
|
|
8
8
|
export { getErrorRecovery, getRetryConfig, offAudioError, onAudioError, retryFailedAudio, setErrorRecovery, setRetryConfig } from './errors';
|
|
9
9
|
export { getAllChannelsPauseState, isChannelPaused, pauseAllChannels, pauseAllWithFade, pauseChannel, pauseWithFade, resumeAllChannels, resumeAllWithFade, resumeChannel, resumeWithFade, togglePauseAllChannels, togglePauseAllWithFade, togglePauseChannel, togglePauseWithFade } from './pause';
|
|
10
|
-
export { cancelAllVolumeTransitions, cancelVolumeTransition, clearVolumeDucking, getAllChannelsVolume, getChannelVolume, getFadeConfig, setAllChannelsVolume, setChannelVolume, setVolumeDucking, transitionVolume } from './volume';
|
|
10
|
+
export { cancelAllVolumeTransitions, cancelVolumeTransition, clearVolumeDucking, getAllChannelsVolume, getChannelVolume, getFadeConfig, getGlobalVolume, setAllChannelsVolume, setChannelVolume, setGlobalVolume, setVolumeDucking, transitionVolume } from './volume';
|
|
11
|
+
export { cleanupWebAudioNodes, createWebAudioNodes, getAudioContext, getWebAudioConfig, getWebAudioSupport, getWebAudioVolume, isIOSDevice, isWebAudioSupported, resumeAudioContext, setWebAudioConfig, setWebAudioVolume, shouldUseWebAudio } from './web-audio';
|
|
11
12
|
export { getAllChannelsInfo, getCurrentAudioInfo, getQueueSnapshot, offAudioComplete, offAudioPause, offAudioProgress, offAudioResume, offAudioStart, offQueueChange, onAudioComplete, onAudioPause, onAudioProgress, onAudioResume, onAudioStart, onQueueChange } from './info';
|
|
12
13
|
export { audioChannels } from './info';
|
|
13
14
|
export { cleanWebpackFilename, createQueueSnapshot, extractFileName, getAudioInfoFromElement, sanitizeForDisplay, validateAudioUrl } from './utils';
|
|
14
|
-
export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ChannelFadeState, ErrorRecoveryOptions, ExtendedAudioQueueChannel, FadeConfig, ProgressCallback, QueueChangeCallback, QueueItem, QueueManipulationResult, QueueSnapshot, RetryConfig, VolumeConfig,
|
|
15
|
+
export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ChannelFadeState, ErrorRecoveryOptions, ExtendedAudioQueueChannel, FadeConfig, ProgressCallback, QueueChangeCallback, QueueConfig, QueueItem, QueueManipulationResult, QueueSnapshot, RetryConfig, VolumeConfig, WebAudioConfig, WebAudioNodeSet, WebAudioSupport } from './types';
|
|
15
16
|
export { AudioErrorType, EasingType, FadeType, MAX_CHANNELS, TimerType, GLOBAL_PROGRESS_KEY } from './types';
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Main entry point for the
|
|
3
|
+
* @fileoverview Main entry point for the audioq package
|
|
4
4
|
* Exports all public functions and types for audio queue management, pause/resume controls,
|
|
5
5
|
* volume management with ducking, progress tracking, and comprehensive event system
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
9
|
-
exports.GLOBAL_PROGRESS_KEY = exports.TimerType = exports.MAX_CHANNELS = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.validateAudioUrl = exports.sanitizeForDisplay = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioStart = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.offAudioComplete = exports.getQueueSnapshot = void 0;
|
|
8
|
+
exports.transitionVolume = exports.setVolumeDucking = exports.setGlobalVolume = exports.setChannelVolume = exports.setAllChannelsVolume = exports.getGlobalVolume = exports.getFadeConfig = exports.getChannelVolume = exports.getAllChannelsVolume = exports.clearVolumeDucking = exports.cancelVolumeTransition = exports.cancelAllVolumeTransitions = exports.togglePauseWithFade = exports.togglePauseChannel = exports.togglePauseAllWithFade = exports.togglePauseAllChannels = exports.resumeWithFade = exports.resumeChannel = exports.resumeAllWithFade = exports.resumeAllChannels = exports.pauseWithFade = exports.pauseChannel = exports.pauseAllWithFade = exports.pauseAllChannels = exports.isChannelPaused = exports.getAllChannelsPauseState = exports.setRetryConfig = exports.setErrorRecovery = exports.retryFailedAudio = exports.onAudioError = exports.offAudioError = exports.getRetryConfig = exports.getErrorRecovery = exports.swapQueueItems = exports.reorderQueue = exports.removeQueuedItem = exports.getQueueLength = exports.getQueueItemInfo = exports.clearQueueAfterCurrent = exports.setChannelQueueLimit = exports.getQueueConfig = exports.setQueueConfig = exports.destroyAllChannels = exports.destroyChannel = exports.playAudioQueue = exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.queueAudioPriority = exports.queueAudio = void 0;
|
|
9
|
+
exports.GLOBAL_PROGRESS_KEY = exports.TimerType = exports.MAX_CHANNELS = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.validateAudioUrl = exports.sanitizeForDisplay = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioStart = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.offAudioComplete = exports.getQueueSnapshot = exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.shouldUseWebAudio = exports.setWebAudioVolume = exports.setWebAudioConfig = exports.resumeAudioContext = exports.isWebAudioSupported = exports.isIOSDevice = exports.getWebAudioVolume = exports.getWebAudioSupport = exports.getWebAudioConfig = exports.getAudioContext = exports.createWebAudioNodes = exports.cleanupWebAudioNodes = void 0;
|
|
10
10
|
// Core queue management functions
|
|
11
11
|
var core_1 = require("./core");
|
|
12
12
|
Object.defineProperty(exports, "queueAudio", { enumerable: true, get: function () { return core_1.queueAudio; } });
|
|
@@ -61,10 +61,26 @@ Object.defineProperty(exports, "clearVolumeDucking", { enumerable: true, get: fu
|
|
|
61
61
|
Object.defineProperty(exports, "getAllChannelsVolume", { enumerable: true, get: function () { return volume_1.getAllChannelsVolume; } });
|
|
62
62
|
Object.defineProperty(exports, "getChannelVolume", { enumerable: true, get: function () { return volume_1.getChannelVolume; } });
|
|
63
63
|
Object.defineProperty(exports, "getFadeConfig", { enumerable: true, get: function () { return volume_1.getFadeConfig; } });
|
|
64
|
+
Object.defineProperty(exports, "getGlobalVolume", { enumerable: true, get: function () { return volume_1.getGlobalVolume; } });
|
|
64
65
|
Object.defineProperty(exports, "setAllChannelsVolume", { enumerable: true, get: function () { return volume_1.setAllChannelsVolume; } });
|
|
65
66
|
Object.defineProperty(exports, "setChannelVolume", { enumerable: true, get: function () { return volume_1.setChannelVolume; } });
|
|
67
|
+
Object.defineProperty(exports, "setGlobalVolume", { enumerable: true, get: function () { return volume_1.setGlobalVolume; } });
|
|
66
68
|
Object.defineProperty(exports, "setVolumeDucking", { enumerable: true, get: function () { return volume_1.setVolumeDucking; } });
|
|
67
69
|
Object.defineProperty(exports, "transitionVolume", { enumerable: true, get: function () { return volume_1.transitionVolume; } });
|
|
70
|
+
// Web Audio API support functions
|
|
71
|
+
var web_audio_1 = require("./web-audio");
|
|
72
|
+
Object.defineProperty(exports, "cleanupWebAudioNodes", { enumerable: true, get: function () { return web_audio_1.cleanupWebAudioNodes; } });
|
|
73
|
+
Object.defineProperty(exports, "createWebAudioNodes", { enumerable: true, get: function () { return web_audio_1.createWebAudioNodes; } });
|
|
74
|
+
Object.defineProperty(exports, "getAudioContext", { enumerable: true, get: function () { return web_audio_1.getAudioContext; } });
|
|
75
|
+
Object.defineProperty(exports, "getWebAudioConfig", { enumerable: true, get: function () { return web_audio_1.getWebAudioConfig; } });
|
|
76
|
+
Object.defineProperty(exports, "getWebAudioSupport", { enumerable: true, get: function () { return web_audio_1.getWebAudioSupport; } });
|
|
77
|
+
Object.defineProperty(exports, "getWebAudioVolume", { enumerable: true, get: function () { return web_audio_1.getWebAudioVolume; } });
|
|
78
|
+
Object.defineProperty(exports, "isIOSDevice", { enumerable: true, get: function () { return web_audio_1.isIOSDevice; } });
|
|
79
|
+
Object.defineProperty(exports, "isWebAudioSupported", { enumerable: true, get: function () { return web_audio_1.isWebAudioSupported; } });
|
|
80
|
+
Object.defineProperty(exports, "resumeAudioContext", { enumerable: true, get: function () { return web_audio_1.resumeAudioContext; } });
|
|
81
|
+
Object.defineProperty(exports, "setWebAudioConfig", { enumerable: true, get: function () { return web_audio_1.setWebAudioConfig; } });
|
|
82
|
+
Object.defineProperty(exports, "setWebAudioVolume", { enumerable: true, get: function () { return web_audio_1.setWebAudioVolume; } });
|
|
83
|
+
Object.defineProperty(exports, "shouldUseWebAudio", { enumerable: true, get: function () { return web_audio_1.shouldUseWebAudio; } });
|
|
68
84
|
// Audio information and progress tracking functions
|
|
69
85
|
var info_1 = require("./info");
|
|
70
86
|
Object.defineProperty(exports, "getAllChannelsInfo", { enumerable: true, get: function () { return info_1.getAllChannelsInfo; } });
|
package/dist/info.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Audio information and progress tracking functions for the
|
|
2
|
+
* @fileoverview Audio information and progress tracking functions for the audioq package
|
|
3
3
|
*/
|
|
4
4
|
import { AudioInfo, QueueSnapshot, ProgressCallback, QueueChangeCallback, AudioStartCallback, AudioCompleteCallback, AudioPauseCallback, AudioResumeCallback, ExtendedAudioQueueChannel } from './types';
|
|
5
5
|
/**
|
package/dist/info.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Audio information and progress tracking functions for the
|
|
3
|
+
* @fileoverview Audio information and progress tracking functions for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.offAudioComplete = exports.offAudioStart = exports.offAudioResume = exports.offAudioPause = exports.onAudioResume = exports.onAudioPause = exports.onAudioComplete = exports.onAudioStart = exports.offQueueChange = exports.onQueueChange = exports.onAudioProgress = exports.getQueueSnapshot = exports.getAllChannelsInfo = exports.getCurrentAudioInfo = exports.audioChannels = exports.getNonWhitelistedChannelProperties = exports.getWhitelistedChannelProperties = void 0;
|
|
@@ -36,7 +36,9 @@ const getWhitelistedChannelProperties = () => {
|
|
|
36
36
|
'isLocked',
|
|
37
37
|
'maxQueueSize',
|
|
38
38
|
'retryConfig',
|
|
39
|
-
'volumeConfig' // Legacy property that might still be used
|
|
39
|
+
'volumeConfig', // Legacy property that might still be used
|
|
40
|
+
'webAudioContext', // Web Audio API context
|
|
41
|
+
'webAudioNodes' // Web Audio API nodes map
|
|
40
42
|
];
|
|
41
43
|
return [...new Set(propertyNames)]; // Remove duplicates
|
|
42
44
|
};
|
package/dist/pause.d.ts
CHANGED
package/dist/pause.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Pause and resume management functions for the
|
|
3
|
+
* @fileoverview Pause and resume management functions for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
6
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -18,6 +18,7 @@ const info_1 = require("./info");
|
|
|
18
18
|
const utils_1 = require("./utils");
|
|
19
19
|
const events_1 = require("./events");
|
|
20
20
|
const volume_1 = require("./volume");
|
|
21
|
+
const web_audio_1 = require("./web-audio");
|
|
21
22
|
/**
|
|
22
23
|
* Gets the current volume for a channel, accounting for synchronous state
|
|
23
24
|
* @param channelNumber - The channel number
|
|
@@ -38,7 +39,15 @@ const setChannelVolumeSync = (channelNumber, volume) => {
|
|
|
38
39
|
if (channel) {
|
|
39
40
|
channel.volume = volume;
|
|
40
41
|
if (channel.queue.length > 0) {
|
|
41
|
-
channel.queue[0]
|
|
42
|
+
const audio = channel.queue[0];
|
|
43
|
+
if (channel.webAudioNodes) {
|
|
44
|
+
const nodes = channel.webAudioNodes.get(audio);
|
|
45
|
+
if (nodes) {
|
|
46
|
+
// Update the gain node when Web Audio is active
|
|
47
|
+
(0, web_audio_1.setWebAudioVolume)(nodes.gainNode, volume);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
audio.volume = volume;
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
};
|
|
@@ -58,12 +67,14 @@ const setChannelVolumeSync = (channelNumber, volume) => {
|
|
|
58
67
|
const pauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0, duration) {
|
|
59
68
|
var _a, _b, _c;
|
|
60
69
|
const channel = info_1.audioChannels[channelNumber];
|
|
61
|
-
if (!channel || channel.queue.length === 0)
|
|
70
|
+
if (!channel || channel.queue.length === 0) {
|
|
62
71
|
return;
|
|
72
|
+
}
|
|
63
73
|
const currentAudio = channel.queue[0];
|
|
64
74
|
// Don't pause if already paused or ended
|
|
65
|
-
if (currentAudio.paused || currentAudio.ended)
|
|
75
|
+
if (currentAudio.paused || currentAudio.ended) {
|
|
66
76
|
return;
|
|
77
|
+
}
|
|
67
78
|
const config = (0, volume_1.getFadeConfig)(fadeType);
|
|
68
79
|
const effectiveDuration = duration !== null && duration !== void 0 ? duration : config.duration;
|
|
69
80
|
// Race condition fix: Use existing fadeState originalVolume if already transitioning,
|
|
@@ -100,9 +111,11 @@ const pauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, func
|
|
|
100
111
|
}
|
|
101
112
|
// Fade to 0 with pause curve, then pause
|
|
102
113
|
yield (0, volume_1.transitionVolume)(channelNumber, 0, effectiveDuration, config.pauseCurve);
|
|
114
|
+
// Pause the audio
|
|
103
115
|
yield (0, exports.pauseChannel)(channelNumber);
|
|
104
|
-
//
|
|
105
|
-
|
|
116
|
+
// Restore channel.volume for resume, but DON'T restore gain node to prevent blip
|
|
117
|
+
// The gain node will be restored during the resume fade
|
|
118
|
+
channel.volume = originalVolume;
|
|
106
119
|
// Mark transition as complete
|
|
107
120
|
if (channel.fadeState) {
|
|
108
121
|
channel.fadeState.isTransitioning = false;
|
|
@@ -125,8 +138,10 @@ exports.pauseWithFade = pauseWithFade;
|
|
|
125
138
|
*/
|
|
126
139
|
const resumeWithFade = (fadeType_1, ...args_1) => __awaiter(void 0, [fadeType_1, ...args_1], void 0, function* (fadeType, channelNumber = 0, duration) {
|
|
127
140
|
const channel = info_1.audioChannels[channelNumber];
|
|
128
|
-
if (!channel || channel.queue.length === 0)
|
|
141
|
+
if (!channel || channel.queue.length === 0) {
|
|
129
142
|
return;
|
|
143
|
+
}
|
|
144
|
+
const audio = channel.queue[0];
|
|
130
145
|
const fadeState = channel.fadeState;
|
|
131
146
|
if (!(fadeState === null || fadeState === void 0 ? void 0 : fadeState.isPaused)) {
|
|
132
147
|
// Fall back to regular resume if no fade state
|
|
@@ -160,8 +175,19 @@ const resumeWithFade = (fadeType_1, ...args_1) => __awaiter(void 0, [fadeType_1,
|
|
|
160
175
|
const targetVolume = fadeState.originalVolume > 0 ? fadeState.originalVolume : 1.0;
|
|
161
176
|
// Mark as transitioning to prevent volume capture during rapid toggles
|
|
162
177
|
fadeState.isTransitioning = true;
|
|
163
|
-
//
|
|
164
|
-
|
|
178
|
+
// Ensure gain node is at 0 before resuming (should already be from pause)
|
|
179
|
+
// Don't touch audio.volume when Web Audio is active - iOS may reset it
|
|
180
|
+
// Don't touch channel.volume - it should stay at originalVolume
|
|
181
|
+
if (channel.webAudioNodes) {
|
|
182
|
+
const nodes = channel.webAudioNodes.get(audio);
|
|
183
|
+
if (nodes) {
|
|
184
|
+
(0, web_audio_1.setWebAudioVolume)(nodes.gainNode, 0);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Fallback for non-Web Audio: set audio.volume directly
|
|
189
|
+
audio.volume = 0;
|
|
190
|
+
}
|
|
165
191
|
yield (0, exports.resumeChannel)(channelNumber);
|
|
166
192
|
// Use the stored original volume, not current volume, to prevent race conditions
|
|
167
193
|
yield (0, volume_1.transitionVolume)(channelNumber, targetVolume, effectiveDuration, config.resumeCurve);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Queue manipulation functions for the
|
|
2
|
+
* @fileoverview Queue manipulation functions for the audioq package
|
|
3
3
|
* Provides advanced queue management including item removal, reordering, and clearing
|
|
4
4
|
*/
|
|
5
5
|
import { QueueManipulationResult, QueueItem } from './types';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Queue manipulation functions for the
|
|
3
|
+
* @fileoverview Queue manipulation functions for the audioq package
|
|
4
4
|
* Provides advanced queue management including item removal, reordering, and clearing
|
|
5
5
|
*/
|
|
6
6
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Type definitions for the
|
|
2
|
+
* @fileoverview Type definitions for the audioq package
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* Maximum number of audio channels allowed to prevent memory exhaustion
|
|
@@ -260,6 +260,39 @@ export interface ErrorRecoveryOptions {
|
|
|
260
260
|
* Callback function type for audio error events
|
|
261
261
|
*/
|
|
262
262
|
export type AudioErrorCallback = (errorInfo: AudioErrorInfo) => void;
|
|
263
|
+
/**
|
|
264
|
+
* Web Audio API configuration options
|
|
265
|
+
*/
|
|
266
|
+
export interface WebAudioConfig {
|
|
267
|
+
/** Whether to automatically use Web Audio API on iOS devices */
|
|
268
|
+
autoDetectIOS: boolean;
|
|
269
|
+
/** Whether Web Audio API support is enabled */
|
|
270
|
+
enabled: boolean;
|
|
271
|
+
/** Whether to force Web Audio API usage on all devices */
|
|
272
|
+
forceWebAudio: boolean;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Web Audio API support information
|
|
276
|
+
*/
|
|
277
|
+
export interface WebAudioSupport {
|
|
278
|
+
/** Whether Web Audio API is available in the current environment */
|
|
279
|
+
available: boolean;
|
|
280
|
+
/** Whether the current device is iOS */
|
|
281
|
+
isIOS: boolean;
|
|
282
|
+
/** Whether Web Audio API is currently being used */
|
|
283
|
+
usingWebAudio: boolean;
|
|
284
|
+
/** Reason for current Web Audio API usage state */
|
|
285
|
+
reason: string;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Web Audio API node set for audio element control
|
|
289
|
+
*/
|
|
290
|
+
export interface WebAudioNodeSet {
|
|
291
|
+
/** Gain node for volume control */
|
|
292
|
+
gainNode: GainNode;
|
|
293
|
+
/** Media element source node */
|
|
294
|
+
sourceNode: MediaElementAudioSourceNode;
|
|
295
|
+
}
|
|
263
296
|
/**
|
|
264
297
|
* Extended audio channel with comprehensive queue management, callback support, and state tracking
|
|
265
298
|
*/
|
|
@@ -292,6 +325,10 @@ export interface ExtendedAudioQueueChannel {
|
|
|
292
325
|
retryConfig?: RetryConfig;
|
|
293
326
|
/** Current volume level for the channel (0-1) */
|
|
294
327
|
volume: number;
|
|
328
|
+
/** Web Audio API context for this channel */
|
|
329
|
+
webAudioContext?: AudioContext;
|
|
330
|
+
/** Map of Web Audio API nodes for each audio element */
|
|
331
|
+
webAudioNodes?: Map<HTMLAudioElement, WebAudioNodeSet>;
|
|
295
332
|
}
|
|
296
333
|
/**
|
|
297
334
|
* Easing function types for smooth volume transitions and animations
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Type definitions for the
|
|
3
|
+
* @fileoverview Type definitions for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.TimerType = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.GLOBAL_PROGRESS_KEY = exports.MAX_CHANNELS = void 0;
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Utility functions for the
|
|
3
|
+
* @fileoverview Utility functions for the audioq package
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.cleanWebpackFilename = exports.createQueueSnapshot = exports.getAudioInfoFromElement = exports.extractFileName = exports.sanitizeForDisplay = exports.validateAudioUrl = void 0;
|