refactor(tts): ensure timeout cleanup and validate remote voice payloads
Make voice-fetching more robust by always clearing the request timeout and stricter type-checking of remote data. - move clearTimeout into finally blocks for Deepinfra and custom OpenAI voice fetches to guarantee the timeout is cleared on success, failure, or abort - validate that custom endpoint returns an array of strings before accepting voices; otherwise fall back to defaults This reduces potential timer leaks and avoids accepting malformed voice lists from custom endpoints.
This commit is contained in:
parent
09944ec4e4
commit
bf139d9a67
1 changed files with 7 additions and 7 deletions
|
|
@ -181,8 +181,6 @@ async function fetchDeepinfraVoices(apiKey: string): Promise<string[]> {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Failed to fetch Deepinfra voices');
|
throw new Error('Failed to fetch Deepinfra voices');
|
||||||
}
|
}
|
||||||
|
|
@ -195,12 +193,13 @@ async function fetchDeepinfraVoices(apiKey: string): Promise<string[]> {
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
clearTimeout(timeoutId);
|
|
||||||
if (error instanceof DOMException && error.name === 'AbortError') {
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
console.error('Error fetching Deepinfra voices:', error);
|
console.error('Error fetching Deepinfra voices:', error);
|
||||||
return [];
|
return [];
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,18 +219,19 @@ async function fetchCustomOpenAiVoices(baseUrl: string, apiKey: string): Promise
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return Array.isArray(data.voices) ? data.voices : null;
|
return Array.isArray(data.voices) && data.voices.every((voice: unknown) => typeof voice === 'string')
|
||||||
|
? data.voices
|
||||||
|
: null;
|
||||||
} catch {
|
} catch {
|
||||||
clearTimeout(timeoutId);
|
|
||||||
console.log('Custom endpoint does not support voices, using defaults');
|
console.log('Custom endpoint does not support voices, using defaults');
|
||||||
return null;
|
return null;
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue