mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
female tts
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
|||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Roomba Rover" />
|
<meta name="apple-mobile-web-app-title" content="Roomba Rover" />
|
||||||
<title>Roomba Rover</title>
|
<title>Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-BwAhhUs8.js"></script>
|
<script type="module" crossorigin src="/assets/index-BhQJmAe_.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-Djpv3bOo.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-Djpv3bOo.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -5,6 +5,26 @@ import { useEffect, useRef } from 'react';
|
|||||||
|
|
||||||
const SPEECH_START_TIMEOUT_MS = 1500;
|
const SPEECH_START_TIMEOUT_MS = 1500;
|
||||||
const SPEECH_RETRY_DELAY_MS = 700;
|
const SPEECH_RETRY_DELAY_MS = 700;
|
||||||
|
const PREFERRED_VOICE_PATTERN = /female|samantha|victoria|zira|karen|moira|serena|ava|susan|hazel|google uk english female/i;
|
||||||
|
|
||||||
|
function pickScannerVoice(synth) {
|
||||||
|
const voices = typeof synth?.getVoices === 'function' ? synth.getVoices() : [];
|
||||||
|
if (!voices.length) return null;
|
||||||
|
|
||||||
|
const englishVoices = voices.filter((voice) => String(voice?.lang || '').toLowerCase().startsWith('en'));
|
||||||
|
// Browser voice lists vary by operating system and installed speech packs, so
|
||||||
|
// this is intentionally a preference rather than a requirement. A recognized
|
||||||
|
// female-sounding English voice is best for the scanner speaker, but any
|
||||||
|
// English voice is better than failing to speak, and the browser default is
|
||||||
|
// the final fallback.
|
||||||
|
return (
|
||||||
|
englishVoices.find((voice) => PREFERRED_VOICE_PATTERN.test(String(voice?.name || ''))) ||
|
||||||
|
voices.find((voice) => PREFERRED_VOICE_PATTERN.test(String(voice?.name || ''))) ||
|
||||||
|
englishVoices[0] ||
|
||||||
|
voices[0] ||
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function useScannerSpeech(scan) {
|
export default function useScannerSpeech(scan) {
|
||||||
const retryTimerRef = useRef(null);
|
const retryTimerRef = useRef(null);
|
||||||
@@ -52,6 +72,11 @@ export default function useScannerSpeech(scan) {
|
|||||||
// browser reports an error or never fires the expected start callback.
|
// browser reports an error or never fires the expected start callback.
|
||||||
synth.cancel();
|
synth.cancel();
|
||||||
const utterance = new window.SpeechSynthesisUtterance(speechText);
|
const utterance = new window.SpeechSynthesisUtterance(speechText);
|
||||||
|
const preferredVoice = pickScannerVoice(synth);
|
||||||
|
if (preferredVoice) {
|
||||||
|
utterance.voice = preferredVoice;
|
||||||
|
utterance.lang = preferredVoice.lang;
|
||||||
|
}
|
||||||
utterance.rate = 0.92;
|
utterance.rate = 0.92;
|
||||||
utterance.pitch = 1;
|
utterance.pitch = 1;
|
||||||
utterance.volume = 1;
|
utterance.volume = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user