fix(voice): improve duration detection for new waveform playback
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-08 20:46:57 +03:00
parent 8092cb53c5
commit e59c60094f
3 changed files with 25 additions and 5 deletions

View File

@@ -64,10 +64,10 @@ function pickSupportedAudioMimeType(): string | undefined {
return undefined;
}
const candidates = [
"audio/ogg;codecs=opus",
"audio/mp4",
"audio/webm;codecs=opus",
"audio/webm",
"audio/mp4",
"audio/ogg;codecs=opus",
];
for (const mime of candidates) {
if (MediaRecorder.isTypeSupported(mime)) {

View File

@@ -47,6 +47,23 @@ function ensureAudio(): HTMLAudioElement {
return globalAudioEl;
}
function getPlayableDuration(audio: HTMLAudioElement): number {
if (Number.isFinite(audio.duration) && audio.duration > 0) {
return audio.duration;
}
try {
if (audio.seekable && audio.seekable.length > 0) {
const end = audio.seekable.end(audio.seekable.length - 1);
if (Number.isFinite(end) && end > 0) {
return end;
}
}
} catch {
return 0;
}
return 0;
}
export const useAudioPlayerStore = create<AudioPlayerState>((set, get) => ({
track: null,
audioEl: ensureAudio(),
@@ -59,10 +76,13 @@ export const useAudioPlayerStore = create<AudioPlayerState>((set, get) => ({
const audio = ensureAudio();
if (!isBound) {
audio.addEventListener("timeupdate", () => {
set({ position: audio.currentTime || 0 });
set({ position: audio.currentTime || 0, duration: getPlayableDuration(audio) });
});
audio.addEventListener("loadedmetadata", () => {
set({ duration: Number.isFinite(audio.duration) ? audio.duration : 0 });
set({ duration: getPlayableDuration(audio) });
});
audio.addEventListener("durationchange", () => {
set({ duration: getPlayableDuration(audio) });
});
audio.addEventListener("play", () => set({ isPlaying: true }));
audio.addEventListener("pause", () => set({ isPlaying: false }));