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;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { DEFAULT_MEDIA_CONFIG, mergeMediaConfig, type MediaConfig } from './mediaConfig';
|
||||
import { preloadAudioAssets } from './mediaSounds';
|
||||
|
||||
export function useMediaConfig(): MediaConfig {
|
||||
const [config, setConfig] = useState<MediaConfig>(DEFAULT_MEDIA_CONFIG);
|
||||
@@ -22,5 +23,9 @@ export function useMediaConfig(): MediaConfig {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
preloadAudioAssets(config);
|
||||
}, [config]);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user