Spaces:
Sleeping
Sleeping
File size: 2,696 Bytes
2498190 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | class AudioQueueManager {
private queue: string[] = [];
private isPlaying: boolean = false;
private currentAudio: HTMLAudioElement | null = null;
private _instance: AudioQueueManager | null = null;
constructor() {}
public static getInstance(): AudioQueueManager {
if (!(window as any).audioQueueInstance) {
(window as any).audioQueueInstance = new AudioQueueManager();
}
return (window as any).audioQueueInstance;
}
public play(path: string) {
// Avoid adding duplicates if the same sound is already at the end of the queue
// This helps with the "double trigger" issue if the UI sends it twice rapidly
if (this.queue.length > 0 && this.queue[this.queue.length - 1] === path) {
return;
}
// Also check if currently playing is the same sound and we are just starting (optional robustness)
console.log(`[AudioQueue] Added to queue: ${path}`);
this.queue.push(path);
this.processQueue();
}
private processQueue() {
if (this.isPlaying || this.queue.length === 0) {
return;
}
const nextPath = this.queue.shift();
if (!nextPath) return;
this.isPlaying = true;
// Prefix with /audio/ if not present and it's a relative filename
const fullPath = nextPath.startsWith('/') || nextPath.startsWith('http')
? nextPath
: `/audio/${nextPath}`;
this.currentAudio = new Audio(fullPath);
this.currentAudio.onended = () => {
console.log(`[AudioQueue] Finished: ${nextPath}`);
this.isPlaying = false;
this.currentAudio = null;
this.processQueue(); // Play next
};
this.currentAudio.onerror = (e) => {
console.error(`[AudioQueue] Error playing ${nextPath}`, e);
this.isPlaying = false;
this.currentAudio = null;
this.processQueue(); // Skip and play next
};
this.currentAudio.play().catch(e => {
console.error(`[AudioQueue] Autoplay failed for ${nextPath}`, e);
this.isPlaying = false;
this.processQueue();
});
}
public stopAll() {
if (this.currentAudio) {
this.currentAudio.pause();
this.currentAudio = null;
}
this.queue = [];
this.isPlaying = false;
}
}
export const AudioQueue = {
play: (path: string) => {
if (typeof window !== 'undefined') {
AudioQueueManager.getInstance().play(path);
}
},
stopAll: () => {
if (typeof window !== 'undefined') {
AudioQueueManager.getInstance().stopAll();
}
}
};
|