Skip to content

Commit 0251aae

Browse files
committed
Huge iOS playback fix
1 parent 99868f2 commit 0251aae

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/contexts/TTSContext.tsx

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
174174
const abortAudio = useCallback((clearPending = false) => {
175175
if (activeHowl) {
176176
activeHowl.stop();
177+
activeHowl.unload(); // Ensure Howl instance is fully cleaned up
177178
setActiveHowl(null);
178179
}
179180
if (clearPending) {
@@ -274,27 +275,34 @@ export function TTSProvider({ children }: { children: ReactNode }) {
274275
// Check for blank section first
275276
if (handleBlankSection(text)) return;
276277

277-
// Keep track of previous state
278+
// Keep track of previous state and pause playback
278279
const wasPlaying = isPlaying;
280+
setIsPlaying(false);
281+
abortAudio(true); // Clear pending requests since text is changing
282+
setIsProcessing(true); // Set processing state before text processing starts
279283

280284
console.log('Setting text:', text);
281285
processTextToSentences(text)
282286
.then(newSentences => {
283287
if (newSentences.length === 0) {
284288
console.warn('No sentences found in text');
289+
setIsProcessing(false);
285290
return;
286291
}
287292

293+
// Set all state updates in a predictable order
288294
setSentences(newSentences);
289295
setCurrentIndex(0);
296+
setIsProcessing(false);
290297

291-
// Only restore previous playback state if we shouldn't pause
292-
if (shouldPause) setIsPlaying(false);
293-
else if (wasPlaying) setIsPlaying(true);
294-
298+
// Restore playback state if needed
299+
if (!shouldPause && wasPlaying) {
300+
setIsPlaying(true);
301+
}
295302
})
296303
.catch(error => {
297304
console.warn('Error processing text:', error);
305+
setIsProcessing(false);
298306
toast.error('Failed to process text', {
299307
style: {
300308
background: 'var(--background)',
@@ -303,7 +311,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
303311
duration: 3000,
304312
});
305313
});
306-
}, [processTextToSentences, handleBlankSection, isPlaying]);
314+
}, [isPlaying, handleBlankSection, abortAudio, processTextToSentences]);
307315

308316
/**
309317
* Toggles the playback state between playing and paused
@@ -493,12 +501,17 @@ export function TTSProvider({ children }: { children: ReactNode }) {
493501
throw new Error('No audio URL generated');
494502
}
495503

504+
// Force unload any previous Howl instance to free up resources
505+
if (activeHowl) {
506+
activeHowl.unload();
507+
}
508+
496509
const howl = new Howl({
497510
src: [audioUrl],
498511
format: ['mp3'],
499512
html5: true,
500513
preload: true,
501-
pool: 1,
514+
pool: 5, // Reduced pool size for iOS compatibility
502515
onplay: () => {
503516
setIsProcessing(false);
504517
if ('mediaSession' in navigator) {
@@ -512,6 +525,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
512525
},
513526
onend: () => {
514527
URL.revokeObjectURL(audioUrl);
528+
howl.unload(); // Explicitly unload when done
515529
setActiveHowl(null);
516530
if (isPlaying) {
517531
advance();
@@ -522,12 +536,14 @@ export function TTSProvider({ children }: { children: ReactNode }) {
522536
setIsProcessing(false);
523537
setActiveHowl(null);
524538
URL.revokeObjectURL(audioUrl);
539+
howl.unload(); // Ensure cleanup on error
525540
// Don't auto-advance on load error
526541
setIsPlaying(false);
527542
},
528543
onstop: () => {
529544
setIsProcessing(false);
530545
URL.revokeObjectURL(audioUrl);
546+
howl.unload(); // Ensure cleanup on stop
531547
}
532548
});
533549

@@ -550,7 +566,7 @@ export function TTSProvider({ children }: { children: ReactNode }) {
550566

551567
advance(); // Skip problematic sentence
552568
}
553-
}, [isPlaying, processSentence, advance]);
569+
}, [isPlaying, processSentence, advance, activeHowl]);
554570

555571
/**
556572
* Preloads the next sentence's audio

0 commit comments

Comments
 (0)