audio-channel-queue 1.4.0 → 1.6.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/README.md +483 -20
- package/dist/core.d.ts +71 -0
- package/dist/core.js +273 -0
- package/dist/events.d.ts +81 -0
- package/dist/events.js +210 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +77 -0
- package/dist/info.d.ts +166 -0
- package/dist/info.js +352 -0
- package/dist/pause.d.ts +87 -0
- package/dist/pause.js +186 -0
- package/dist/types.d.ts +183 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +58 -0
- package/dist/utils.js +126 -0
- package/dist/volume.d.ts +98 -0
- package/dist/volume.js +302 -0
- package/package.json +10 -4
- package/src/core.ts +306 -0
- package/src/events.ts +243 -0
- package/src/index.ts +104 -0
- package/src/info.ts +380 -0
- package/src/pause.ts +190 -0
- package/src/types.ts +199 -0
- package/src/utils.ts +134 -0
- package/src/volume.ts +328 -0
- package/dist/audio.d.ts +0 -10
- package/dist/audio.js +0 -66
package/README.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Audio Channel Queue
|
|
2
|
-
The purpose of this package is to help
|
|
2
|
+
The purpose of this package is to help manage the playback of audio files.
|
|
3
|
+
|
|
4
|
+
## 🌟 Key Features
|
|
5
|
+
|
|
6
|
+
- ✅ **Multi-channel queue management** - Independent audio queues for concurrent playback
|
|
7
|
+
- ✅ **Pause/Resume functionality** - Full playback control for individual channels or all channels
|
|
8
|
+
- ✅ **Volume control with ducking** - Dynamic volume management and automatic background audio reduction
|
|
9
|
+
- ✅ **Loop support** - Seamless audio looping for background music and ambient sounds
|
|
10
|
+
- ✅ **Priority queueing** - Add urgent audio to the front of any queue
|
|
11
|
+
- ✅ **Real-time progress tracking** - Comprehensive playback monitoring and metadata
|
|
12
|
+
- ✅ **Event-driven architecture** - Extensive callback system for UI integration
|
|
13
|
+
- ✅ **TypeScript support** - Full type definitions and IntelliSense support
|
|
14
|
+
- ✅ **Zero dependencies** - Lightweight and self-contained
|
|
15
|
+
- ✅ **Backward compatible** - All existing APIs continue to work
|
|
3
16
|
|
|
4
17
|
This package offers TypeScript support 📘, boasts zero dependencies 🚫, and is released under the MIT license 📜. As an added bonus, it's NON-GMO 🌱 and 100% Free Range Organic 🐓.
|
|
5
18
|
|
|
@@ -9,55 +22,505 @@ NPM package can be found [here](https://www.npmjs.com/package/audio-channel-queu
|
|
|
9
22
|
|
|
10
23
|
GitHub Repo can be found [here](https://github.com/tonycarpenter21/audio-channel-queue).
|
|
11
24
|
|
|
25
|
+
## 🌐 Browser Compatibility
|
|
26
|
+
|
|
27
|
+
This package is designed for **browser environments** and uses the Web Audio API (`HTMLAudioElement`). It is **not** intended for Node.js server-side use.
|
|
28
|
+
|
|
29
|
+
### ✅ **Supported Browsers:**
|
|
30
|
+
- **Chrome 51+** (June 2016)
|
|
31
|
+
- **Firefox 54+** (June 2017)
|
|
32
|
+
- **Safari 10+** (September 2016)
|
|
33
|
+
- **Edge 15+** (April 2017)
|
|
34
|
+
- **Mobile browsers** with HTML5 audio support
|
|
35
|
+
|
|
36
|
+
### 🛠️ **Development Requirements:**
|
|
37
|
+
- **Node.js 14+** (for building and testing only)
|
|
38
|
+
- **TypeScript 4.5+** (included in devDependencies)
|
|
39
|
+
|
|
40
|
+
### ⚠️ **Not Supported:**
|
|
41
|
+
- Node.js server environments (no HTMLAudioElement)
|
|
42
|
+
- Internet Explorer (lacks ES6 support)
|
|
43
|
+
- Web Workers (no DOM access)
|
|
44
|
+
|
|
45
|
+
## Architecture & Code Organization 🏗️
|
|
46
|
+
|
|
47
|
+
Modular architecture for maintainability and extensibility:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
src/
|
|
51
|
+
├── index.ts # Main entry point with organized exports
|
|
52
|
+
├── types.ts # TypeScript interfaces and type definitions
|
|
53
|
+
├── core.ts # Core queue management functions
|
|
54
|
+
├── pause.ts # Pause and resume functionality
|
|
55
|
+
├── volume.ts # Volume control and ducking management
|
|
56
|
+
├── info.ts # Audio information and progress tracking
|
|
57
|
+
├── events.ts # Event handling and emission logic
|
|
58
|
+
└── utils.ts # Helper functions and utilities
|
|
59
|
+
```
|
|
60
|
+
|
|
12
61
|
## How To Install This Package:
|
|
13
62
|
Install this package by running either of these commands (typescript packages are included automatically):
|
|
14
63
|
- For npm run `npm install audio-channel-queue`
|
|
15
64
|
- For yarn run `yarn add audio-channel-queue`
|
|
16
65
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
66
|
+
## Basic Queue Management Functions:
|
|
67
|
+
|
|
68
|
+
### Queue Audio
|
|
69
|
+
```queueAudio(audioFileGoesHere, channelNumber, options);```
|
|
70
|
+
Use the `queueAudio()` function to add a file to the queue and start playing it automatically. It takes three arguments:
|
|
20
71
|
- The first argument is an imported sound file.
|
|
21
|
-
- The second argument is optional and it allows you to choose a different queue channel.
|
|
72
|
+
- The second argument is optional and it allows you to choose a different queue channel.
|
|
73
|
+
- The third argument is optional configuration for loop, volume, and priority.
|
|
74
|
+
|
|
75
|
+
### Queue Audio with Priority
|
|
76
|
+
```queueAudioPriority(audioFileGoesHere, channelNumber, options);```
|
|
77
|
+
Use the `queueAudioPriority()` function to add a file to the front of the queue (plays after current audio finishes). Perfect for urgent announcements!
|
|
22
78
|
|
|
79
|
+
### Stop Current Audio
|
|
23
80
|
```stopCurrentAudioInChannel(queueChannelNumberGoesHere);```
|
|
24
|
-
Use the `stopCurrentAudioInChannel()` function to stop the current playback of a file in a queue and start playing the next one automatically.
|
|
25
|
-
- The first argument is optional and it allows you to choose a different queue channel. If you are only using the default channel, just use `stopCurrentAudioInChannel()`.
|
|
81
|
+
Use the `stopCurrentAudioInChannel()` function to stop the current playback of a file in a queue and start playing the next one automatically.
|
|
26
82
|
|
|
83
|
+
### Stop All Audio in Channel
|
|
27
84
|
```stopAllAudioInChannel(queueChannelNumberGoesHere);```
|
|
28
|
-
Use the `stopAllAudioInChannel()` function to stop the current playback of all files in a queue and removes all enqueued files.
|
|
29
|
-
- The first argument is optional and it allows you to choose a different queue channel. If you are only using the default channel, just use `stopAllAudioInChannel()`.
|
|
85
|
+
Use the `stopAllAudioInChannel()` function to stop the current playback of all files in a queue and removes all enqueued files.
|
|
30
86
|
|
|
31
|
-
|
|
87
|
+
### Stop All Audio
|
|
88
|
+
```stopAllAudio();```
|
|
32
89
|
Use the `stopAllAudio()` function to stop the current playback of all files in all queues. It takes no arguments.
|
|
33
90
|
|
|
34
|
-
|
|
91
|
+
## 🎛️ Volume Control Functions:
|
|
35
92
|
|
|
36
|
-
###
|
|
93
|
+
### Set Channel Volume
|
|
94
|
+
```setChannelVolume(channelNumber, volume);```
|
|
95
|
+
Set the volume for a specific channel (0-1 range).
|
|
96
|
+
```typescript
|
|
97
|
+
setChannelVolume(0, 0.5); // Set channel 0 to 50% volume
|
|
98
|
+
setChannelVolume(1, 0.8); // Set channel 1 to 80% volume
|
|
99
|
+
```
|
|
37
100
|
|
|
38
|
-
|
|
101
|
+
### Get Channel Volume
|
|
102
|
+
```getChannelVolume(channelNumber);```
|
|
103
|
+
Get the current volume level for a specific channel.
|
|
104
|
+
```typescript
|
|
105
|
+
const volume = getChannelVolume(0);
|
|
106
|
+
console.log(`Channel 0 volume: ${volume * 100}%`);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Set All Channels Volume
|
|
110
|
+
```setAllChannelsVolume(volume);```
|
|
111
|
+
Set the same volume level for all channels.
|
|
112
|
+
```typescript
|
|
113
|
+
setAllChannelsVolume(0.6); // Set all channels to 60% volume
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Volume Ducking (Background Audio Reduction)
|
|
117
|
+
```setVolumeDucking(config);```
|
|
118
|
+
Automatically reduce other channels' volume when priority audio plays - perfect for voice announcements over background music!
|
|
119
|
+
```typescript
|
|
120
|
+
// When channel 1 plays, reduce all other channels to 20% volume
|
|
121
|
+
setVolumeDucking({
|
|
122
|
+
priorityChannel: 1,
|
|
123
|
+
priorityVolume: 1.0,
|
|
124
|
+
duckingVolume: 0.2
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```clearVolumeDucking();```
|
|
129
|
+
Remove volume ducking configuration from all channels.
|
|
130
|
+
|
|
131
|
+
## ⏯️ Pause/Resume Functions:
|
|
132
|
+
|
|
133
|
+
### Pause Channel
|
|
134
|
+
```pauseChannel(channelNumber);```
|
|
135
|
+
Pause audio playback in a specific channel.
|
|
136
|
+
```typescript
|
|
137
|
+
await pauseChannel(0); // Pause audio in channel 0
|
|
138
|
+
await pauseChannel(); // Pause audio in default channel
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Resume Channel
|
|
142
|
+
```resumeChannel(channelNumber);```
|
|
143
|
+
Resume audio playback in a specific channel.
|
|
144
|
+
```typescript
|
|
145
|
+
await resumeChannel(0); // Resume audio in channel 0
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Toggle Pause
|
|
149
|
+
```togglePauseChannel(channelNumber);```
|
|
150
|
+
Toggle between pause and resume states.
|
|
151
|
+
```typescript
|
|
152
|
+
await togglePauseChannel(0); // Pause if playing, resume if paused
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Pause/Resume All Channels
|
|
156
|
+
```pauseAllChannels();``` and ```resumeAllChannels();```
|
|
157
|
+
Control all channels simultaneously.
|
|
158
|
+
```typescript
|
|
159
|
+
await pauseAllChannels(); // Emergency pause - everything stops
|
|
160
|
+
await resumeAllChannels(); // Resume everything that was paused
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Global Toggle Pause/Resume
|
|
164
|
+
```togglePauseAllChannels();```
|
|
165
|
+
Smart toggle that pauses all channels if any are playing, or resumes all if all are paused.
|
|
166
|
+
```typescript
|
|
167
|
+
await togglePauseAllChannels(); // Pause all if any playing, resume all if all paused
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Check Pause State
|
|
171
|
+
```isChannelPaused(channelNumber);``` and ```getAllChannelsPauseState();```
|
|
172
|
+
```typescript
|
|
173
|
+
const isPaused = isChannelPaused(0);
|
|
174
|
+
const allPauseStates = getAllChannelsPauseState();
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Audio Information and Progress Tracking:
|
|
178
|
+
|
|
179
|
+
### AudioInfo Interface
|
|
180
|
+
The package provides detailed information about audio playback through the enhanced `AudioInfo` interface:
|
|
181
|
+
```typescript
|
|
182
|
+
interface AudioInfo {
|
|
183
|
+
currentTime: number; // Current position in milliseconds
|
|
184
|
+
duration: number; // Total duration in milliseconds
|
|
185
|
+
fileName: string; // Extracted filename from URL
|
|
186
|
+
isLooping: boolean; // Whether audio is set to loop
|
|
187
|
+
isPaused: boolean; // Whether audio is currently paused
|
|
188
|
+
isPlaying: boolean; // Whether audio is currently playing
|
|
189
|
+
progress: number; // Progress as percentage (0-1)
|
|
190
|
+
src: string; // Audio file source URL
|
|
191
|
+
volume: number; // Current volume level (0-1)
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Get Current Audio Info
|
|
196
|
+
```getCurrentAudioInfo(channelNumber);```
|
|
197
|
+
Get information about the currently playing audio in a specific channel. Returns `AudioInfo | null`.
|
|
198
|
+
|
|
199
|
+
### Get All Channels Info
|
|
200
|
+
```getAllChannelsInfo();```
|
|
201
|
+
Get audio information for all channels. Returns an array of `AudioInfo | null` objects.
|
|
202
|
+
|
|
203
|
+
### Queue State Management
|
|
204
|
+
```getQueueSnapshot(channelNumber);```
|
|
205
|
+
Get a complete snapshot of the queue state for a specific channel. Returns `QueueSnapshot | null`.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
interface QueueSnapshot {
|
|
209
|
+
channelNumber: number; // Channel this snapshot represents
|
|
210
|
+
currentIndex: number; // Index of currently playing item
|
|
211
|
+
isPaused: boolean; // Whether current audio is paused
|
|
212
|
+
items: Array<{ // Array of queue items with metadata
|
|
213
|
+
duration: number;
|
|
214
|
+
fileName: string;
|
|
215
|
+
isCurrentlyPlaying: boolean;
|
|
216
|
+
isLooping: boolean;
|
|
217
|
+
src: string;
|
|
218
|
+
volume: number;
|
|
219
|
+
}>;
|
|
220
|
+
totalItems: number; // Total items in queue
|
|
221
|
+
volume: number; // Current channel volume (0-1)
|
|
222
|
+
}
|
|
39
223
|
```
|
|
40
|
-
|
|
41
|
-
|
|
224
|
+
|
|
225
|
+
### Real-time Progress Tracking
|
|
226
|
+
```onAudioProgress(channelNumber, callback);```
|
|
227
|
+
Subscribe to real-time progress updates for a specific channel.
|
|
228
|
+
|
|
229
|
+
```offAudioProgress(channelNumber);```
|
|
230
|
+
Remove all progress listeners for a specific channel.
|
|
231
|
+
|
|
232
|
+
### Enhanced Event System
|
|
233
|
+
```onQueueChange(channelNumber, callback);```
|
|
234
|
+
Subscribe to queue change events for visual updates.
|
|
235
|
+
|
|
236
|
+
```onAudioStart(channelNumber, callback);```
|
|
237
|
+
Subscribe to audio start events.
|
|
238
|
+
|
|
239
|
+
```onAudioComplete(channelNumber, callback);```
|
|
240
|
+
Subscribe to audio completion events.
|
|
241
|
+
|
|
242
|
+
```onAudioPause(channelNumber, callback);```
|
|
243
|
+
Subscribe to audio pause events.
|
|
244
|
+
|
|
245
|
+
```onAudioResume(channelNumber, callback);```
|
|
246
|
+
Subscribe to audio resume events.
|
|
247
|
+
|
|
248
|
+
### Example Usage with All New Features:
|
|
249
|
+
|
|
250
|
+
`App.tsx`
|
|
251
|
+
```typescript
|
|
252
|
+
import backgroundMusic from './audio/background.mp3';
|
|
253
|
+
import announcement from './audio/announcement.wav';
|
|
254
|
+
import {
|
|
255
|
+
queueAudio,
|
|
256
|
+
queueAudioPriority,
|
|
257
|
+
getCurrentAudioInfo,
|
|
258
|
+
pauseChannel,
|
|
259
|
+
resumeChannel,
|
|
260
|
+
togglePauseAllChannels,
|
|
261
|
+
setChannelVolume,
|
|
262
|
+
setVolumeDucking,
|
|
263
|
+
onAudioProgress,
|
|
264
|
+
onAudioPause,
|
|
265
|
+
onAudioResume,
|
|
266
|
+
onQueueChange,
|
|
267
|
+
AudioInfo,
|
|
268
|
+
QueueSnapshot
|
|
269
|
+
} from 'audio-channel-queue';
|
|
270
|
+
import { useState, useEffect } from 'react';
|
|
42
271
|
|
|
43
272
|
function App(): JSX.Element {
|
|
273
|
+
const [currentInfo, setCurrentInfo] = useState<AudioInfo | null>(null);
|
|
274
|
+
const [queueSnapshot, setQueueSnapshot] = useState<QueueSnapshot | null>(null);
|
|
275
|
+
const [isPaused, setIsPaused] = useState(false);
|
|
276
|
+
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
// Set up background music with looping
|
|
279
|
+
const setupBackgroundMusic = async () => {
|
|
280
|
+
await queueAudio(backgroundMusic, 0, {
|
|
281
|
+
loop: true,
|
|
282
|
+
volume: 0.3
|
|
283
|
+
});
|
|
284
|
+
setChannelVolume(0, 0.3); // 30% volume for background
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
// Configure volume ducking for announcements
|
|
288
|
+
setVolumeDucking({
|
|
289
|
+
priorityChannel: 1, // Announcements on channel 1
|
|
290
|
+
priorityVolume: 1.0, // Full volume for announcements
|
|
291
|
+
duckingVolume: 0.1 // Reduce background to 10% during announcements
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Set up event listeners
|
|
295
|
+
onAudioProgress(0, (info: AudioInfo) => {
|
|
296
|
+
setCurrentInfo(info);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
onQueueChange(0, (snapshot: QueueSnapshot) => {
|
|
300
|
+
setQueueSnapshot(snapshot);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
onAudioPause(0, (channelNumber, info) => {
|
|
304
|
+
setIsPaused(true);
|
|
305
|
+
console.log(`Channel ${channelNumber} paused: ${info.fileName}`);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
onAudioResume(0, (channelNumber, info) => {
|
|
309
|
+
setIsPaused(false);
|
|
310
|
+
console.log(`Channel ${channelNumber} resumed: ${info.fileName}`);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
setupBackgroundMusic();
|
|
314
|
+
}, []);
|
|
315
|
+
|
|
316
|
+
const playAnnouncement = async () => {
|
|
317
|
+
// Priority queue - plays next, automatically ducks background music
|
|
318
|
+
await queueAudioPriority(announcement, 1);
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const toggleBackgroundMusic = async () => {
|
|
322
|
+
if (isPaused) {
|
|
323
|
+
await resumeChannel(0);
|
|
324
|
+
} else {
|
|
325
|
+
await pauseChannel(0);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const adjustBackgroundVolume = (volume: number) => {
|
|
330
|
+
setChannelVolume(0, volume);
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const emergencyToggleAll = async () => {
|
|
334
|
+
await togglePauseAllChannels(); // Smart toggle - pause all if any playing, resume all if all paused
|
|
335
|
+
};
|
|
44
336
|
|
|
45
337
|
return (
|
|
46
338
|
<div className="App">
|
|
47
|
-
<
|
|
339
|
+
<h2>Audio Control Center</h2>
|
|
340
|
+
|
|
341
|
+
{/* Background Music Controls */}
|
|
342
|
+
<div className="background-controls">
|
|
343
|
+
<h3>Background Music</h3>
|
|
344
|
+
<button onClick={toggleBackgroundMusic}>
|
|
345
|
+
{isPaused ? '▶️ Resume' : '⏸️ Pause'}
|
|
346
|
+
</button>
|
|
347
|
+
<label>
|
|
348
|
+
Volume:
|
|
349
|
+
<input
|
|
350
|
+
type="range"
|
|
351
|
+
min="0"
|
|
352
|
+
max="1"
|
|
353
|
+
step="0.1"
|
|
354
|
+
onChange={(e) => adjustBackgroundVolume(Number(e.target.value))}
|
|
355
|
+
/>
|
|
356
|
+
</label>
|
|
357
|
+
</div>
|
|
358
|
+
|
|
359
|
+
{/* Announcement Controls */}
|
|
360
|
+
<div className="announcement-controls">
|
|
361
|
+
<h3>Announcements</h3>
|
|
362
|
+
<button onClick={playAnnouncement}>
|
|
363
|
+
📢 Play Announcement (Auto-ducks background)
|
|
364
|
+
</button>
|
|
365
|
+
</div>
|
|
366
|
+
|
|
367
|
+
{/* Emergency Controls */}
|
|
368
|
+
<div className="emergency-controls">
|
|
369
|
+
<h3>Emergency Controls</h3>
|
|
370
|
+
<button onClick={emergencyToggleAll}>
|
|
371
|
+
🚨 Toggle All Audio (Smart Pause/Resume)
|
|
372
|
+
</button>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
{/* Current Audio Info */}
|
|
376
|
+
{currentInfo && (
|
|
377
|
+
<div className="current-info">
|
|
378
|
+
<h3>Now Playing:</h3>
|
|
379
|
+
<p>🎵 {currentInfo.fileName}</p>
|
|
380
|
+
<p>⏱️ {(currentInfo.currentTime / 1000).toFixed(1)}s / {(currentInfo.duration / 1000).toFixed(1)}s</p>
|
|
381
|
+
<p>📊 Progress: {(currentInfo.progress * 100).toFixed(1)}%</p>
|
|
382
|
+
<p>🔊 Volume: {(currentInfo.volume * 100).toFixed(0)}%</p>
|
|
383
|
+
<p>🔄 Looping: {currentInfo.isLooping ? 'Yes' : 'No'}</p>
|
|
384
|
+
<p>⏸️ Paused: {currentInfo.isPaused ? 'Yes' : 'No'}</p>
|
|
385
|
+
|
|
386
|
+
{/* Progress Bar */}
|
|
387
|
+
<div className="progress-bar">
|
|
388
|
+
<div
|
|
389
|
+
className="progress-fill"
|
|
390
|
+
style={{ width: `${currentInfo.progress * 100}%` }}
|
|
391
|
+
/>
|
|
392
|
+
</div>
|
|
393
|
+
</div>
|
|
394
|
+
)}
|
|
395
|
+
|
|
396
|
+
{/* Queue Status */}
|
|
397
|
+
{queueSnapshot && (
|
|
398
|
+
<div className="queue-status">
|
|
399
|
+
<h3>Queue Status (Channel {queueSnapshot.channelNumber}):</h3>
|
|
400
|
+
<p>📋 Total Items: {queueSnapshot.totalItems}</p>
|
|
401
|
+
<p>🔊 Channel Volume: {(queueSnapshot.volume * 100).toFixed(0)}%</p>
|
|
402
|
+
<p>⏸️ Channel Paused: {queueSnapshot.isPaused ? 'Yes' : 'No'}</p>
|
|
403
|
+
|
|
404
|
+
<h4>Queue Items:</h4>
|
|
405
|
+
<ul>
|
|
406
|
+
{queueSnapshot.items.map((item, index) => (
|
|
407
|
+
<li key={index} style={{
|
|
408
|
+
fontWeight: item.isCurrentlyPlaying ? 'bold' : 'normal',
|
|
409
|
+
color: item.isCurrentlyPlaying ? '#007bff' : 'inherit'
|
|
410
|
+
}}>
|
|
411
|
+
{item.fileName} ({(item.duration / 1000).toFixed(1)}s)
|
|
412
|
+
{item.isCurrentlyPlaying && ' ▶️ PLAYING'}
|
|
413
|
+
{item.isLooping && ' 🔄 LOOP'}
|
|
414
|
+
</li>
|
|
415
|
+
))}
|
|
416
|
+
</ul>
|
|
417
|
+
</div>
|
|
418
|
+
)}
|
|
48
419
|
</div>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
420
|
+
);
|
|
421
|
+
}
|
|
51
422
|
|
|
52
423
|
export default App;
|
|
53
424
|
```
|
|
54
425
|
|
|
426
|
+
### Advanced Usage Examples:
|
|
427
|
+
|
|
428
|
+
#### Gaming Audio System
|
|
429
|
+
```typescript
|
|
430
|
+
// Background music (channel 0)
|
|
431
|
+
await queueAudio('./music/background.mp3', 0, { loop: true, volume: 0.4 });
|
|
432
|
+
|
|
433
|
+
// Sound effects (channel 1)
|
|
434
|
+
await queueAudio('./sfx/explosion.wav', 1);
|
|
435
|
+
|
|
436
|
+
// Voice chat (channel 2) - ducks other audio
|
|
437
|
+
setVolumeDucking({
|
|
438
|
+
priorityChannel: 2,
|
|
439
|
+
priorityVolume: 1.0,
|
|
440
|
+
duckingVolume: 0.2
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// Critical game announcements (priority)
|
|
444
|
+
await queueAudioPriority('./voice/game-over.wav', 2);
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### Podcast/Radio App
|
|
448
|
+
```typescript
|
|
449
|
+
// Main content (channel 0)
|
|
450
|
+
await queueAudio('./podcast/episode1.mp3', 0);
|
|
451
|
+
|
|
452
|
+
// Jingles and ads (channel 1) - interrupt at natural breaks
|
|
453
|
+
await queueAudioPriority('./ads/sponsor.mp3', 0);
|
|
454
|
+
|
|
455
|
+
// Background ambient (channel 2)
|
|
456
|
+
await queueAudio('./ambient/coffee-shop.mp3', 2, {
|
|
457
|
+
loop: true,
|
|
458
|
+
volume: 0.1
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// Pause everything for phone calls
|
|
462
|
+
onPhoneCall(() => pauseAllChannels());
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Legacy Access
|
|
466
|
+
If you need to expose the queue array for logging or other purposes, it is available to you as well: `audioChannels`.
|
|
467
|
+
|
|
468
|
+
### TypeScript Support
|
|
55
469
|
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:
|
|
56
470
|
|
|
57
471
|
`custom.d.ts`
|
|
58
|
-
```
|
|
472
|
+
```typescript
|
|
59
473
|
declare module '*.mp3' {
|
|
60
474
|
const src: string;
|
|
61
475
|
export default src;
|
|
62
476
|
}
|
|
63
|
-
```
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Features:
|
|
480
|
+
- ✅ Queue management across multiple channels
|
|
481
|
+
- ✅ Pause and resume functionality for individual channels and all channels
|
|
482
|
+
- ✅ Volume control with per-channel precision (0-1 range)
|
|
483
|
+
- ✅ Volume ducking for priority audio (automatic background reduction)
|
|
484
|
+
- ✅ Audio looping capabilities for background music and ambient sounds
|
|
485
|
+
- ✅ Priority queueing system for urgent audio playback
|
|
486
|
+
- ✅ Real-time audio progress tracking with enhanced metadata
|
|
487
|
+
- ✅ Comprehensive event system (start, complete, pause, resume, queue changes)
|
|
488
|
+
- ✅ Audio duration and metadata extraction with loop and volume info
|
|
489
|
+
- ✅ Automatic filename extraction from URLs
|
|
490
|
+
- ✅ Queue state snapshots with pause and volume information
|
|
491
|
+
- ✅ TypeScript support with full type definitions
|
|
492
|
+
- ✅ Modular architecture with clean separation of concerns
|
|
493
|
+
- ✅ Comprehensive JSDoc documentation with examples
|
|
494
|
+
- ✅ Zero dependencies
|
|
495
|
+
- ✅ Backward compatible with existing implementations
|
|
496
|
+
- ✅ Comprehensive error handling with graceful degradation
|
|
497
|
+
|
|
498
|
+
## Development & Contributing 🛠️
|
|
499
|
+
|
|
500
|
+
The package uses a modular TypeScript architecture that makes it easy to contribute and extend:
|
|
501
|
+
|
|
502
|
+
### File Structure:
|
|
503
|
+
- **`src/types.ts`** - Interface definitions and type exports
|
|
504
|
+
- **`src/core.ts`** - Main queue management logic and priority queueing
|
|
505
|
+
- **`src/pause.ts`** - Pause and resume functionality
|
|
506
|
+
- **`src/volume.ts`** - Volume control and ducking management
|
|
507
|
+
- **`src/info.ts`** - Audio information and progress tracking
|
|
508
|
+
- **`src/events.ts`** - Event system and callback management
|
|
509
|
+
- **`src/utils.ts`** - Helper functions and utilities
|
|
510
|
+
- **`src/index.ts`** - Public API exports
|
|
511
|
+
|
|
512
|
+
### Testing:
|
|
513
|
+
The package includes a comprehensive test suite with 74+ tests covering all functionality:
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
# Run tests once
|
|
517
|
+
npm test
|
|
518
|
+
|
|
519
|
+
# Run tests in watch mode during development
|
|
520
|
+
npm run test:watch
|
|
521
|
+
|
|
522
|
+
# Run tests with coverage report
|
|
523
|
+
npm run test:coverage
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**Test Coverage**: 85%+ code coverage across all modules with realistic HTMLAudioElement mocking using jsdom.
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core queue management functions for the audio-channel-queue package
|
|
3
|
+
*/
|
|
4
|
+
import { AudioQueueOptions } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Queues an audio file to a specific channel and starts playing if it's the first in queue
|
|
7
|
+
* @param audioUrl - The URL of the audio file to queue
|
|
8
|
+
* @param channelNumber - The channel number to queue the audio to (defaults to 0)
|
|
9
|
+
* @param options - Optional configuration for the audio file
|
|
10
|
+
* @returns Promise that resolves when the audio is queued and starts playing (if first in queue)
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* await queueAudio('https://example.com/song.mp3', 0);
|
|
14
|
+
* await queueAudio('./sounds/notification.wav'); // Uses default channel 0
|
|
15
|
+
* await queueAudio('./music/loop.mp3', 1, { loop: true }); // Loop the audio
|
|
16
|
+
* await queueAudio('./urgent.wav', 0, { addToFront: true }); // Add to front of queue
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare const queueAudio: (audioUrl: string, channelNumber?: number, options?: AudioQueueOptions) => Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Adds an audio file to the front of the queue in a specific channel
|
|
22
|
+
* This is a convenience function that places the audio right after the currently playing track
|
|
23
|
+
* @param audioUrl - The URL of the audio file to queue
|
|
24
|
+
* @param channelNumber - The channel number to queue the audio to (defaults to 0)
|
|
25
|
+
* @param options - Optional configuration for the audio file
|
|
26
|
+
* @returns Promise that resolves when the audio is queued
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* await queueAudioPriority('./urgent-announcement.wav', 0);
|
|
30
|
+
* await queueAudioPriority('./priority-sound.mp3', 1, { loop: true });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const queueAudioPriority: (audioUrl: string, channelNumber?: number, options?: AudioQueueOptions) => Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Plays the audio queue for a specific channel
|
|
36
|
+
* @param channelNumber - The channel number to play
|
|
37
|
+
* @returns Promise that resolves when the current audio finishes playing
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* await playAudioQueue(0); // Play queue for channel 0
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const playAudioQueue: (channelNumber: number) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Stops the currently playing audio in a specific channel and plays the next audio in queue
|
|
46
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* await stopCurrentAudioInChannel(); // Stop current audio in default channel (0)
|
|
50
|
+
* await stopCurrentAudioInChannel(1); // Stop current audio in channel 1
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare const stopCurrentAudioInChannel: (channelNumber?: number) => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Stops all audio in a specific channel and clears the entire queue
|
|
56
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* await stopAllAudioInChannel(); // Clear all audio in default channel (0)
|
|
60
|
+
* await stopAllAudioInChannel(1); // Clear all audio in channel 1
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const stopAllAudioInChannel: (channelNumber?: number) => Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Stops all audio across all channels and clears all queues
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* await stopAllAudio(); // Emergency stop - clears everything
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare const stopAllAudio: () => Promise<void>;
|