voice: add global playback speed control for audio and voice
All checks were successful
CI / test (push) Successful in 25s
All checks were successful
CI / test (push) Successful in 25s
This commit is contained in:
@@ -10,6 +10,7 @@ interface AudioPlayerState {
|
||||
audioEl: HTMLAudioElement | null;
|
||||
isPlaying: boolean;
|
||||
volume: number;
|
||||
playbackRate: number;
|
||||
duration: number;
|
||||
position: number;
|
||||
playTrack: (track: ActiveTrack) => Promise<void>;
|
||||
@@ -17,11 +18,25 @@ interface AudioPlayerState {
|
||||
seekTo: (seconds: number) => void;
|
||||
seekBy: (secondsDelta: number) => void;
|
||||
setVolume: (volume: number) => void;
|
||||
setPlaybackRate: (rate: number) => void;
|
||||
cyclePlaybackRate: () => void;
|
||||
stop: () => void;
|
||||
}
|
||||
|
||||
let globalAudioEl: HTMLAudioElement | null = null;
|
||||
let isBound = false;
|
||||
const PLAYBACK_RATE_KEY = "bm_audio_playback_rate";
|
||||
|
||||
function getInitialPlaybackRate(): number {
|
||||
if (typeof window === "undefined") {
|
||||
return 1;
|
||||
}
|
||||
const raw = Number(window.localStorage.getItem(PLAYBACK_RATE_KEY) || "1");
|
||||
if (raw === 1 || raw === 1.5 || raw === 2) {
|
||||
return raw;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function ensureAudio(): HTMLAudioElement {
|
||||
if (globalAudioEl) {
|
||||
@@ -37,6 +52,7 @@ export const useAudioPlayerStore = create<AudioPlayerState>((set, get) => ({
|
||||
audioEl: ensureAudio(),
|
||||
isPlaying: false,
|
||||
volume: 1,
|
||||
playbackRate: getInitialPlaybackRate(),
|
||||
duration: 0,
|
||||
position: 0,
|
||||
playTrack: async (track) => {
|
||||
@@ -63,6 +79,7 @@ export const useAudioPlayerStore = create<AudioPlayerState>((set, get) => ({
|
||||
set({ track });
|
||||
}
|
||||
audio.volume = get().volume;
|
||||
audio.playbackRate = get().playbackRate;
|
||||
try {
|
||||
await audio.play();
|
||||
set({ isPlaying: true, audioEl: audio });
|
||||
@@ -111,6 +128,20 @@ export const useAudioPlayerStore = create<AudioPlayerState>((set, get) => ({
|
||||
audio.volume = normalized;
|
||||
set({ volume: normalized });
|
||||
},
|
||||
setPlaybackRate: (rate) => {
|
||||
const normalized = rate === 2 ? 2 : rate === 1.5 ? 1.5 : 1;
|
||||
const audio = ensureAudio();
|
||||
audio.playbackRate = normalized;
|
||||
if (typeof window !== "undefined") {
|
||||
window.localStorage.setItem(PLAYBACK_RATE_KEY, String(normalized));
|
||||
}
|
||||
set({ playbackRate: normalized });
|
||||
},
|
||||
cyclePlaybackRate: () => {
|
||||
const current = get().playbackRate;
|
||||
const next = current === 1 ? 1.5 : current === 1.5 ? 2 : 1;
|
||||
get().setPlaybackRate(next);
|
||||
},
|
||||
stop: () => {
|
||||
const audio = ensureAudio();
|
||||
if (audio) {
|
||||
|
||||
Reference in New Issue
Block a user