Preload audio clips on mount so first playthrough timing stays in sync.
This commit is contained in:
@@ -1,6 +1,46 @@
|
||||
import type { MediaConfig } from './mediaConfig';
|
||||
|
||||
const audioElements = new Map<string, HTMLAudioElement>();
|
||||
|
||||
function ensureAudio(src: string): HTMLAudioElement {
|
||||
let audio = audioElements.get(src);
|
||||
if (!audio) {
|
||||
audio = new Audio();
|
||||
audio.preload = 'auto';
|
||||
audio.src = src;
|
||||
audioElements.set(src, audio);
|
||||
}
|
||||
return audio;
|
||||
}
|
||||
|
||||
const AUDIO_URL_KEYS = [
|
||||
'incorrectUrl',
|
||||
'unlockConfirmUrl',
|
||||
'celebrationPopUrl',
|
||||
'celebrationHornUrl',
|
||||
] as const satisfies readonly (keyof MediaConfig)[];
|
||||
|
||||
/** Fetch and decode audio clips so first playback is not delayed. */
|
||||
export function preloadAudioAssets(config: MediaConfig): void {
|
||||
for (const key of AUDIO_URL_KEYS) {
|
||||
ensureAudio(config[key]).load();
|
||||
}
|
||||
}
|
||||
|
||||
export function playClip(src: string): HTMLAudioElement {
|
||||
const cached = audioElements.get(src);
|
||||
if (cached) {
|
||||
if (cached.paused || cached.ended) {
|
||||
cached.currentTime = 0;
|
||||
void cached.play();
|
||||
return cached;
|
||||
}
|
||||
|
||||
const fallback = new Audio(src);
|
||||
void fallback.play();
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const audio = new Audio(src);
|
||||
void audio.play();
|
||||
return audio;
|
||||
|
||||
Reference in New Issue
Block a user