audioq 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +486 -0
- package/dist/core.d.ts +129 -0
- package/dist/core.js +591 -0
- package/dist/errors.d.ts +138 -0
- package/dist/errors.js +441 -0
- package/dist/events.d.ts +81 -0
- package/dist/events.js +217 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +119 -0
- package/dist/info.d.ts +224 -0
- package/dist/info.js +529 -0
- package/dist/pause.d.ts +170 -0
- package/dist/pause.js +467 -0
- package/dist/queue-manipulation.d.ts +104 -0
- package/dist/queue-manipulation.js +319 -0
- package/dist/types.d.ts +382 -0
- package/dist/types.js +55 -0
- package/dist/utils.d.ts +83 -0
- package/dist/utils.js +215 -0
- package/dist/volume.d.ts +162 -0
- package/dist/volume.js +644 -0
- package/dist/web-audio.d.ts +156 -0
- package/dist/web-audio.js +327 -0
- package/package.json +63 -0
- package/src/core.ts +698 -0
- package/src/errors.ts +467 -0
- package/src/events.ts +252 -0
- package/src/index.ts +162 -0
- package/src/info.ts +590 -0
- package/src/pause.ts +523 -0
- package/src/queue-manipulation.ts +378 -0
- package/src/types.ts +415 -0
- package/src/utils.ts +235 -0
- package/src/volume.ts +735 -0
- package/src/web-audio.ts +331 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 TONY CARPENTER
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
# AudioQ
|
|
2
|
+
The purpose of this package is to help manage the playback of audio files.
|
|
3
|
+
|
|
4
|
+
🎵 [Demo](https://tonycarpenter21.github.io/audio-queue-demo/queue-management)
|
|
5
|
+
|
|
6
|
+
📚 [Docs](https://tonycarpenter21.github.io/audio-queue-docs/)
|
|
7
|
+
|
|
8
|
+
## Key Features
|
|
9
|
+
|
|
10
|
+
- **Multi-channel queue management** - Independent audio queues for concurrent playback
|
|
11
|
+
- **Pause/Resume functionality** - Full playback control for individual channels or all channels
|
|
12
|
+
- **Volume control with ducking** - Dynamic volume management, global volume control, and automatic background audio reduction
|
|
13
|
+
- **Loop support** - Seamless audio looping for background music and ambient sounds
|
|
14
|
+
- **Priority queueing** - Add urgent audio to the front of any queue
|
|
15
|
+
- **Real-time progress tracking** - Comprehensive playback monitoring and metadata
|
|
16
|
+
- **Event-driven architecture** - Extensive callback system for UI integration
|
|
17
|
+
- **TypeScript support** - Full type definitions and IntelliSense support
|
|
18
|
+
- **Zero dependencies** - Lightweight and self-contained
|
|
19
|
+
- **Backward compatible** - All existing APIs continue to work
|
|
20
|
+
|
|
21
|
+
This package offers TypeScript support, has zero dependencies, and is released under the MIT license.
|
|
22
|
+
|
|
23
|
+
To preview this package and see how it works with visualized code examples, check out the demo that can be found here: [AudioQ Demo](https://tonycarpenter21.github.io/audio-queue-demo/). (A link to the demo repo can be found here: [AudioQ Demo Repo](https://github.com/tonycarpenter21/audio-queue-demo).)
|
|
24
|
+
|
|
25
|
+
NPM package can be found [here](https://www.npmjs.com/package/audioq).
|
|
26
|
+
|
|
27
|
+
GitHub Repo can be found [here](https://github.com/tonycarpenter21/audioq).
|
|
28
|
+
|
|
29
|
+
Documentation can be found [here](https://tonycarpenter21.github.io/audio-queue-docs/)
|
|
30
|
+
|
|
31
|
+
## 🌐 Browser Compatibility
|
|
32
|
+
|
|
33
|
+
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
|
+
|
|
35
|
+
### **Supported Browsers:**
|
|
36
|
+
- **Chrome 51+** (June 2016)
|
|
37
|
+
- **Firefox 54+** (June 2017)
|
|
38
|
+
- **Safari 10+** (September 2016)
|
|
39
|
+
- **Edge 15+** (April 2017)
|
|
40
|
+
- **Mobile browsers** with HTML5 audio support
|
|
41
|
+
|
|
42
|
+
### **Development Requirements:**
|
|
43
|
+
- **Node.js 14+** (for building and testing only)
|
|
44
|
+
- **TypeScript 4.5+** (included in devDependencies)
|
|
45
|
+
|
|
46
|
+
### **Not Supported:**
|
|
47
|
+
- Node.js server environments (no HTMLAudioElement)
|
|
48
|
+
- Internet Explorer (lacks ES6 support)
|
|
49
|
+
- Web Workers (no DOM access)
|
|
50
|
+
|
|
51
|
+
## Architecture & Code Organization 🏗️
|
|
52
|
+
|
|
53
|
+
Modular architecture for maintainability and extensibility:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
src/
|
|
57
|
+
├── index.ts # Main entry point with organized exports
|
|
58
|
+
├── types.ts # TypeScript interfaces and type definitions
|
|
59
|
+
├── core.ts # Core queue management functions
|
|
60
|
+
├── pause.ts # Pause and resume functionality
|
|
61
|
+
├── volume.ts # Volume control and ducking management
|
|
62
|
+
├── info.ts # Audio information and progress tracking
|
|
63
|
+
├── events.ts # Event handling and emission logic
|
|
64
|
+
└── utils.ts # Helper functions and utilities
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## How To Install This Package:
|
|
68
|
+
Install this package by running either of these commands (typescript packages are included automatically):
|
|
69
|
+
- For npm run `npm install audioq`
|
|
70
|
+
- For yarn run `yarn add audioq`
|
|
71
|
+
|
|
72
|
+
## Basic Queue Management Functions:
|
|
73
|
+
|
|
74
|
+
### Queue Audio
|
|
75
|
+
```typescript
|
|
76
|
+
// Add an audio file to the queue and start playing it automatically.
|
|
77
|
+
queueAudio(audioUrl, channelNumber?, options?);
|
|
78
|
+
await queueAudio('hello.mp3'); // Add to default channel 0
|
|
79
|
+
await queueAudio('laser.mp3', 1, { loop: true, volume: 0.8 }); // Add to channel 1 with options
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
### Queue Audio with Priority
|
|
84
|
+
```typescript
|
|
85
|
+
// Add a file to the front of the queue (plays after current audio finishes).
|
|
86
|
+
queueAudioPriority(audioUrl, channelNumber?, options?);
|
|
87
|
+
await queueAudioPriority('urgent.mp3'); // Add to front of default channel 0
|
|
88
|
+
await queueAudioPriority('announcement.mp3', 1, { volume: 1.0 }); // Add to front of channel 1
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
### Stop Current Audio
|
|
93
|
+
```typescript
|
|
94
|
+
// Stop the current audio and automatically start playing the next one in queue.
|
|
95
|
+
stopCurrentAudioInChannel(channelNumber?);
|
|
96
|
+
await stopCurrentAudioInChannel(); // Stop current audio in default channel (0)
|
|
97
|
+
await stopCurrentAudioInChannel(2); // Stop current audio in channel 2
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
### Stop All Audio in Channel
|
|
102
|
+
```typescript
|
|
103
|
+
// Stop all audio in a channel and remove all enqueued files.
|
|
104
|
+
stopAllAudioInChannel(channelNumber?);
|
|
105
|
+
await stopAllAudioInChannel(); // Stop and clear all audio in default channel (0)
|
|
106
|
+
await stopAllAudioInChannel(1); // Stop and clear all audio in channel 1
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Stop All Audio
|
|
110
|
+
```typescript
|
|
111
|
+
// Stop all audio in all channels and remove all enqueued files.
|
|
112
|
+
await stopAllAudio();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 🔄 Advanced Queue Manipulation:
|
|
116
|
+
|
|
117
|
+
### Remove Queued Item
|
|
118
|
+
```typescript
|
|
119
|
+
// Remove a specific item from the queue by its position (cannot remove currently playing item at index 0).
|
|
120
|
+
removeQueuedItem(queuedSlotNumber, channelNumber?);
|
|
121
|
+
const result = await removeQueuedItem(2); // Remove item at index 2 from default channel (0)
|
|
122
|
+
const result = await removeQueuedItem(1, 1); // Remove item at index 1 from channel 1
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Reorder Queue Items
|
|
126
|
+
```typescript
|
|
127
|
+
// Move a queue item from one position to another (cannot move currently playing item at index 0).
|
|
128
|
+
reorderQueue(currentQueuedSlotNumber, newQueuedSlotNumber, channelNumber?);
|
|
129
|
+
const result = await reorderQueue(3, 1); // Move item from index 3 to index 1 in default channel (0)
|
|
130
|
+
const result = await reorderQueue(2, 4, 1); // Move item from index 2 to index 4 in channel 1
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Clear Queue After Current
|
|
134
|
+
```typescript
|
|
135
|
+
// Remove all items from the queue except the currently playing audio.
|
|
136
|
+
clearQueueAfterCurrent(channelNumber?);
|
|
137
|
+
const result = await clearQueueAfterCurrent(); // Clear queue after current in default channel (0)
|
|
138
|
+
const result = await clearQueueAfterCurrent(2); // Clear queue after current in channel 2
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Swap Queue Items
|
|
142
|
+
```typescript
|
|
143
|
+
// Swap the positions of two items in the queue (cannot involve currently playing item at index 0).
|
|
144
|
+
swapQueueItems(firstQueuedSlotNumber, secondQueuedSlotNumber, channelNumber?);
|
|
145
|
+
const result = await swapQueueItems(1, 3); // Swap items at index 1 and 3 in default channel (0)
|
|
146
|
+
const result = await swapQueueItems(2, 4, 1); // Swap items at index 2 and 4 in channel 1
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Get Queue Item Info
|
|
150
|
+
```typescript
|
|
151
|
+
// Get information about a specific item in the queue.
|
|
152
|
+
getQueueItemInfo(queuedSlotNumber, channelNumber?);
|
|
153
|
+
const itemInfo = getQueueItemInfo(1); // Get info for item at index 1 in default channel (0)
|
|
154
|
+
const info = getQueueItemInfo(2, 1); // Get info for item at index 2 in channel 1
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Get Queue Length
|
|
158
|
+
```typescript
|
|
159
|
+
// Get the total number of items in a channel's queue.
|
|
160
|
+
getQueueLength(channelNumber?);
|
|
161
|
+
const length = getQueueLength(); // Get queue length for default channel (0)
|
|
162
|
+
const count = getQueueLength(2); // Get queue length for channel 2
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// All queue manipulation functions return a QueueManipulationResult:
|
|
167
|
+
interface QueueManipulationResult {
|
|
168
|
+
success: boolean; // Whether the operation was successful
|
|
169
|
+
error?: string; // Error message if operation failed
|
|
170
|
+
updatedQueue?: QueueSnapshot; // The queue snapshot after the operation (if successful)
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## 🎛️ Volume Control Functions:
|
|
175
|
+
|
|
176
|
+
### Set Channel Volume
|
|
177
|
+
```typescript
|
|
178
|
+
// Set the volume for a specific channel (0-1 range).
|
|
179
|
+
setChannelVolume(channelNumber, volume);
|
|
180
|
+
await setChannelVolume(0, 0.5); // Set channel 0 to 50% volume
|
|
181
|
+
await setChannelVolume(1, 0.8); // Set channel 1 to 80% volume
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Get Channel Volume
|
|
185
|
+
```typescript
|
|
186
|
+
// Get the current volume level for a specific channel.
|
|
187
|
+
getChannelVolume(channelNumber?);
|
|
188
|
+
const volume = getChannelVolume(); // Get default channel (0) volume
|
|
189
|
+
console.log(`Channel volume: ${(getChannelVolume(2) * 100).toFixed(0)}%`); // Get channel 2 volume
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Set All Channels Volume
|
|
193
|
+
```typescript
|
|
194
|
+
// Set the same volume level for all channels.
|
|
195
|
+
setAllChannelsVolume(volume);
|
|
196
|
+
await setAllChannelsVolume(0.6); // Set all channels to 60% volume
|
|
197
|
+
await setAllChannelsVolume(0.0); // Mute all channels
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Global Volume Control
|
|
201
|
+
```typescript
|
|
202
|
+
// Set a global volume multiplier that affects all channels while preserving their relative levels.
|
|
203
|
+
setGlobalVolume(volume);
|
|
204
|
+
await setGlobalVolume(0.5); // Set global volume to 50%
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// Get the current global volume level.
|
|
209
|
+
getGlobalVolume();
|
|
210
|
+
const globalVol = getGlobalVolume(); // Returns current global volume (0-1)
|
|
211
|
+
console.log(`Global volume: ${(getGlobalVolume() * 100).toFixed(0)}%`);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**How Global Volume Works:**
|
|
215
|
+
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.
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Example: Setting up different audio types with a global volume control
|
|
219
|
+
await setChannelVolume(0, 0.3); // SFX channel at 30%
|
|
220
|
+
await setChannelVolume(1, 0.7); // Music channel at 70%
|
|
221
|
+
await setChannelVolume(2, 0.5); // Voice channel at 50%
|
|
222
|
+
|
|
223
|
+
// User adjusts global volume slider to 50%
|
|
224
|
+
await setGlobalVolume(0.5);
|
|
225
|
+
|
|
226
|
+
// Actual playback volumes become:
|
|
227
|
+
// - SFX: 30% × 50% = 15%
|
|
228
|
+
// - Music: 70% × 50% = 35%
|
|
229
|
+
// - Voice: 50% × 50% = 25%
|
|
230
|
+
|
|
231
|
+
// Channel volumes remain at their original settings (0.3, 0.7, 0.5)
|
|
232
|
+
// So when global volume is increased, ratios are preserved
|
|
233
|
+
await setGlobalVolume(1.0); // Back to full volume
|
|
234
|
+
// - SFX: 30% × 100% = 30%
|
|
235
|
+
// - Music: 70% × 100% = 70%
|
|
236
|
+
// - Voice: 50% × 100% = 50%
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Note:** `setAllChannelsVolume()` sets all channels to the **same** volume, while `setGlobalVolume()` **multiplies** all channels by the same amount, preserving their relative differences.
|
|
240
|
+
|
|
241
|
+
### Volume Ducking (Background Audio Reduction)
|
|
242
|
+
```typescript
|
|
243
|
+
// Automatically reduce other channels' volume when priority audio plays.
|
|
244
|
+
setVolumeDucking(config);
|
|
245
|
+
setVolumeDucking({ priorityChannel: 1, duckingVolume: 0.2 }); // Simple ducking
|
|
246
|
+
setVolumeDucking({
|
|
247
|
+
priorityChannel: 1,
|
|
248
|
+
priorityVolume: 1.0,
|
|
249
|
+
duckingVolume: 0.2,
|
|
250
|
+
transitionDuration: 500
|
|
251
|
+
}); // Full configuration
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Remove volume ducking configuration from all channels.
|
|
256
|
+
clearVolumeDucking();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## ⏯️ Pause/Resume Functions:
|
|
260
|
+
|
|
261
|
+
### Pause Channel
|
|
262
|
+
```typescript
|
|
263
|
+
// Pause audio playback in a specific channel.
|
|
264
|
+
pauseChannel(channelNumber?);
|
|
265
|
+
await pauseChannel(); // Pause audio in default channel (0)
|
|
266
|
+
await pauseChannel(1); // Pause audio in channel 1
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Resume Channel
|
|
270
|
+
```typescript
|
|
271
|
+
// Resume audio playback in a specific channel.
|
|
272
|
+
resumeChannel(channelNumber?);
|
|
273
|
+
await resumeChannel(); // Resume audio in default channel (0)
|
|
274
|
+
await resumeChannel(1); // Resume audio in channel 1
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Toggle Pause
|
|
278
|
+
```typescript
|
|
279
|
+
// Toggle between pause and resume states.
|
|
280
|
+
togglePauseChannel(channelNumber?);
|
|
281
|
+
await togglePauseChannel(); // Toggle default channel (0)
|
|
282
|
+
await togglePauseChannel(1); // Toggle channel 1
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Pause/Resume All Channels
|
|
286
|
+
```typescript
|
|
287
|
+
// Pause all channels simultaneously.
|
|
288
|
+
pauseAllChannels();
|
|
289
|
+
await pauseAllChannels();
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Resume all channels that were paused.
|
|
294
|
+
resumeAllChannels();
|
|
295
|
+
await resumeAllChannels();
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Global Toggle Pause/Resume
|
|
299
|
+
```typescript
|
|
300
|
+
// Smart toggle that pauses all channels if any are playing, or resumes all if all are paused.
|
|
301
|
+
togglePauseAllChannels();
|
|
302
|
+
await togglePauseAllChannels();
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Check Pause State
|
|
306
|
+
```typescript
|
|
307
|
+
// Check if a specific channel is paused.
|
|
308
|
+
isChannelPaused(channelNumber?);
|
|
309
|
+
const isPaused = isChannelPaused(); // Check if default channel (0) is paused
|
|
310
|
+
const channelPaused = isChannelPaused(2); // Check if channel 2 is paused
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
// Get pause state for all channels.
|
|
315
|
+
getAllChannelsPauseState();
|
|
316
|
+
const allPauseStates = getAllChannelsPauseState();
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Audio Information and Progress Tracking:
|
|
320
|
+
|
|
321
|
+
### AudioInfo Interface
|
|
322
|
+
The package provides detailed information about audio playback through the enhanced `AudioInfo` interface:
|
|
323
|
+
```typescript
|
|
324
|
+
interface AudioInfo {
|
|
325
|
+
currentTime: number; // Current position in milliseconds
|
|
326
|
+
duration: number; // Total duration in milliseconds
|
|
327
|
+
fileName: string; // Extracted filename from URL
|
|
328
|
+
isLooping: boolean; // Whether audio is set to loop
|
|
329
|
+
isPaused: boolean; // Whether audio is currently paused
|
|
330
|
+
isPlaying: boolean; // Whether audio is currently playing
|
|
331
|
+
progress: number; // Progress as percentage (0-1)
|
|
332
|
+
src: string; // Audio file source URL
|
|
333
|
+
volume: number; // Current volume level (0-1)
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Get Current Audio Info
|
|
338
|
+
```typescript
|
|
339
|
+
// Get information about the currently playing audio in a specific channel.
|
|
340
|
+
getCurrentAudioInfo(channelNumber?);
|
|
341
|
+
const audioInfo = getCurrentAudioInfo(); // Get current audio info for default channel (0)
|
|
342
|
+
const info = getCurrentAudioInfo(1); // Get info for channel 1 - returns AudioInfo | null
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Get All Channels Info
|
|
346
|
+
```typescript
|
|
347
|
+
// Get audio information for all channels.
|
|
348
|
+
getAllChannelsInfo();
|
|
349
|
+
const allChannelsInfo = getAllChannelsInfo();
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Queue State Management
|
|
353
|
+
```typescript
|
|
354
|
+
// Get a complete snapshot of the queue state for a specific channel.
|
|
355
|
+
getQueueSnapshot(channelNumber?);
|
|
356
|
+
const queueSnapshot = getQueueSnapshot(); // Get snapshot for default channel (0)
|
|
357
|
+
const snapshot = getQueueSnapshot(2); // Get snapshot for channel 2 - returns QueueSnapshot | null
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
interface QueueSnapshot {
|
|
362
|
+
channelNumber: number; // Channel this snapshot represents
|
|
363
|
+
currentIndex: number; // Index of currently playing item
|
|
364
|
+
isPaused: boolean; // Whether current audio is paused
|
|
365
|
+
items: Array<{ // Array of queue items with metadata
|
|
366
|
+
duration: number;
|
|
367
|
+
fileName: string;
|
|
368
|
+
isCurrentlyPlaying: boolean;
|
|
369
|
+
isLooping: boolean;
|
|
370
|
+
src: string;
|
|
371
|
+
volume: number;
|
|
372
|
+
}>;
|
|
373
|
+
totalItems: number; // Total items in queue
|
|
374
|
+
volume: number; // Current channel volume (0-1)
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Real-time Progress Tracking
|
|
379
|
+
```typescript
|
|
380
|
+
// Subscribe to real-time progress updates for a specific channel.
|
|
381
|
+
onAudioProgress(channelNumber, callback);
|
|
382
|
+
onAudioProgress(0, (info) => console.log(info.progress)); // Simple progress logging
|
|
383
|
+
onAudioProgress(1, (info) => updateProgressBar(info.currentTime, info.duration)); // Complex UI update
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
// Remove all progress listeners for a specific channel.
|
|
388
|
+
offAudioProgress(channelNumber?);
|
|
389
|
+
offAudioProgress(); // Remove all progress listeners in default channel (0)
|
|
390
|
+
offAudioProgress(1); // Remove all progress listeners in channel 1
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Enhanced Event System
|
|
394
|
+
```typescript
|
|
395
|
+
// Subscribe to queue change events for visual updates.
|
|
396
|
+
onQueueChange(channelNumber, callback);
|
|
397
|
+
onQueueChange(0, (snapshot) => updateQueueDisplay(snapshot)); // Update UI on queue changes
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// Unsubscribe from queue change events (removes ALL queue change callbacks for the channel)
|
|
402
|
+
offQueueChange(channelNumber?);
|
|
403
|
+
offQueueChange(); // Stop receiving all queue change notifications for default channel (0)
|
|
404
|
+
offQueueChange(1); // Stop receiving all queue change notifications for channel 1
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
// Subscribe to audio start events.
|
|
409
|
+
onAudioStart(channelNumber, callback);
|
|
410
|
+
onAudioStart(0, (info) => console.log(`Started: ${info.fileName}`)); // Log audio starts
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
// Unsubscribe from audio start events (removes ALL start callbacks for the channel)
|
|
415
|
+
offAudioStart(channelNumber?);
|
|
416
|
+
offAudioStart(); // Stop receiving all start notifications for default channel (0)
|
|
417
|
+
offAudioStart(1); // Stop receiving all start notifications for channel 1
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
// Subscribe to audio completion events.
|
|
422
|
+
onAudioComplete(channelNumber, callback);
|
|
423
|
+
onAudioComplete(0, (info) => logPlayHistory(info)); // Track completed audio
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// Unsubscribe from audio completion events (removes ALL complete callbacks for the channel)
|
|
428
|
+
offAudioComplete(channelNumber?);
|
|
429
|
+
offAudioComplete(); // Stop receiving all completion notifications for default channel (0)
|
|
430
|
+
offAudioComplete(1); // Stop receiving all completion notifications for channel 1
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
// Subscribe to audio pause events.
|
|
435
|
+
onAudioPause(channelNumber, callback);
|
|
436
|
+
onAudioPause(0, (info) => showPauseIcon(info)); // Show pause state in UI
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
// Unsubscribe from audio pause events (removes ALL pause callbacks for the channel)
|
|
441
|
+
offAudioPause(channelNumber?);
|
|
442
|
+
offAudioPause(); // Stop receiving all pause notifications for default channel (0)
|
|
443
|
+
offAudioPause(1); // Stop receiving all pause notifications for channel 1
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
// Subscribe to audio resume events.
|
|
448
|
+
onAudioResume(channelNumber, callback);
|
|
449
|
+
onAudioResume(0, (info) => showPlayIcon(info)); // Show play state in UI
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
// Unsubscribe from audio resume events (removes ALL resume callbacks for the channel)
|
|
454
|
+
offAudioResume(channelNumber?);
|
|
455
|
+
offAudioResume(); // Stop receiving all resume notifications for default channel (0)
|
|
456
|
+
offAudioResume(1); // Stop receiving all resume notifications for channel 1
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### TypeScript Support
|
|
460
|
+
If you cannot import audio files into your app, you may need a `custom.d.ts` file in the root directory. An example of one is shown here:
|
|
461
|
+
|
|
462
|
+
`custom.d.ts`
|
|
463
|
+
```typescript
|
|
464
|
+
declare module '*.mp3' {
|
|
465
|
+
const src: string;
|
|
466
|
+
export default src;
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Development & Contributing 🛠️
|
|
471
|
+
|
|
472
|
+
The package uses a modular TypeScript architecture that makes it easy to contribute and extend:
|
|
473
|
+
|
|
474
|
+
### Testing:
|
|
475
|
+
The package includes a comprehensive test suite with 74+ tests covering all functionality:
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# Run tests once
|
|
479
|
+
npm test
|
|
480
|
+
|
|
481
|
+
# Run tests in watch mode during development
|
|
482
|
+
npm run test:watch
|
|
483
|
+
|
|
484
|
+
# Run tests with coverage report
|
|
485
|
+
npm run test:coverage
|
|
486
|
+
```
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core queue management functions for the audioq package
|
|
3
|
+
*/
|
|
4
|
+
import { AudioQueueOptions, QueueConfig } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Sets the global queue configuration
|
|
7
|
+
* @param config - Queue configuration options
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* setQueueConfig({
|
|
11
|
+
* defaultMaxQueueSize: 50,
|
|
12
|
+
* dropOldestWhenFull: true,
|
|
13
|
+
* showQueueWarnings: true
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const setQueueConfig: (config: Partial<QueueConfig>) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Gets the current global queue configuration
|
|
20
|
+
* @returns Current queue configuration
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const config = getQueueConfig();
|
|
24
|
+
* console.log(`Default max queue size: ${config.defaultMaxQueueSize}`);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const getQueueConfig: () => QueueConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Sets the maximum queue size for a specific channel
|
|
30
|
+
* @param channelNumber - The channel number to configure
|
|
31
|
+
* @param maxSize - Maximum queue size (undefined for unlimited)
|
|
32
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* setChannelQueueLimit(0, 25); // Limit channel 0 to 25 items
|
|
36
|
+
* setChannelQueueLimit(1, undefined); // Remove limit for channel 1
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare const setChannelQueueLimit: (channelNumber: number, maxSize?: number) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Queues an audio file to a specific channel and starts playing if it's the first in queue
|
|
42
|
+
* @param audioUrl - The URL of the audio file to queue
|
|
43
|
+
* @param channelNumber - The channel number to queue the audio to (defaults to 0)
|
|
44
|
+
* @param options - Optional configuration for the audio file
|
|
45
|
+
* @returns Promise that resolves when the audio is queued and starts playing (if first in queue)
|
|
46
|
+
* @throws Error if the audio URL is invalid or potentially malicious
|
|
47
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
48
|
+
* @throws Error if the queue size limit would be exceeded
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* await queueAudio('https://example.com/song.mp3', 0);
|
|
52
|
+
* await queueAudio('./sounds/notification.wav'); // Uses default channel 0
|
|
53
|
+
* await queueAudio('./music/loop.mp3', 1, { loop: true }); // Loop the audio
|
|
54
|
+
* await queueAudio('./urgent.wav', 0, { addToFront: true }); // Add to front of queue
|
|
55
|
+
* await queueAudio('./limited.mp3', 0, { maxQueueSize: 10 }); // Limit this queue to 10 items
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare const queueAudio: (audioUrl: string, channelNumber?: number, options?: AudioQueueOptions) => Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Adds an audio file to the front of the queue in a specific channel
|
|
61
|
+
* This is a convenience function that places the audio right after the currently playing track
|
|
62
|
+
* @param audioUrl - The URL of the audio file to queue
|
|
63
|
+
* @param channelNumber - The channel number to queue the audio to (defaults to 0)
|
|
64
|
+
* @param options - Optional configuration for the audio file
|
|
65
|
+
* @returns Promise that resolves when the audio is queued
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* await queueAudioPriority('./urgent-announcement.wav', 0);
|
|
69
|
+
* await queueAudioPriority('./priority-sound.mp3', 1, { loop: true });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare const queueAudioPriority: (audioUrl: string, channelNumber?: number, options?: AudioQueueOptions) => Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Plays the audio queue for a specific channel
|
|
75
|
+
* @param channelNumber - The channel number to play
|
|
76
|
+
* @returns Promise that resolves when the audio starts playing (setup complete)
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* await playAudioQueue(0); // Start playing queue for channel 0
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare const playAudioQueue: (channelNumber: number) => Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Stops the currently playing audio in a specific channel and plays the next audio in queue
|
|
85
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* await stopCurrentAudioInChannel(); // Stop current audio in default channel (0)
|
|
89
|
+
* await stopCurrentAudioInChannel(1); // Stop current audio in channel 1
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export declare const stopCurrentAudioInChannel: (channelNumber?: number) => Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Stops all audio in a specific channel and clears the entire queue
|
|
95
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* await stopAllAudioInChannel(); // Clear all audio in default channel (0)
|
|
99
|
+
* await stopAllAudioInChannel(1); // Clear all audio in channel 1
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare const stopAllAudioInChannel: (channelNumber?: number) => Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Stops all audio across all channels and clears all queues
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* await stopAllAudio(); // Emergency stop - clears everything
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare const stopAllAudio: () => Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Completely destroys a channel and cleans up all associated resources
|
|
113
|
+
* This stops all audio, cancels transitions, clears callbacks, and removes the channel
|
|
114
|
+
* @param channelNumber - The channel number to destroy (defaults to 0)
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* await destroyChannel(1); // Completely removes channel 1 and cleans up resources
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare const destroyChannel: (channelNumber?: number) => Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Destroys all channels and cleans up all resources
|
|
123
|
+
* This is useful for complete cleanup when the audio system is no longer needed
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* await destroyAllChannels(); // Complete cleanup - removes all channels
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare const destroyAllChannels: () => Promise<void>;
|