Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c8881f9e4d | |||
| 028e3b2240 | |||
| c042f27106 |
@@ -79,8 +79,8 @@ android {
|
|||||||
applicationId "com.ariacockpit"
|
applicationId "com.ariacockpit"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 408
|
versionCode 409
|
||||||
versionName "0.0.4.8"
|
versionName "0.0.4.9"
|
||||||
// Fallback fuer Libraries mit Product Flavors
|
// Fallback fuer Libraries mit Product Flavors
|
||||||
missingDimensionStrategy 'react-native-camera', 'general'
|
missingDimensionStrategy 'react-native-camera', 'general'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aria-cockpit",
|
"name": "aria-cockpit",
|
||||||
"version": "0.0.4.8",
|
"version": "0.0.4.9",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"android": "react-native run-android",
|
"android": "react-native run-android",
|
||||||
|
|||||||
@@ -325,6 +325,15 @@ const ChatScreen: React.FC = () => {
|
|||||||
const tool = (message.payload.tool as string) || '';
|
const tool = (message.payload.tool as string) || '';
|
||||||
setAgentActivity({ activity, tool });
|
setAgentActivity({ activity, tool });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Voice-Config aus Diagnostic — setzt die lokale App-Stimme auf den
|
||||||
|
// gerade in Diagnostic gewaehlten Wert zurueck. User-Wahl in der App
|
||||||
|
// wird dadurch ueberschrieben.
|
||||||
|
if (message.type === ('config' as any)) {
|
||||||
|
const newVoice = ((message.payload as any).xttsVoice as string) ?? '';
|
||||||
|
localXttsVoiceRef.current = newVoice;
|
||||||
|
AsyncStorage.setItem('aria_xtts_voice', newVoice);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const unsubState = rvs.onStateChange((state) => {
|
const unsubState = rvs.onStateChange((state) => {
|
||||||
|
|||||||
@@ -265,6 +265,13 @@ const SettingsScreen: React.FC = () => {
|
|||||||
}
|
}
|
||||||
rvs.send('xtts_list_voices' as any, {});
|
rvs.send('xtts_list_voices' as any, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Diagnostic-Voice-Wechsel → lokale App-Stimme auf den neuen Default zuruecksetzen
|
||||||
|
if (message.type === ('config' as any)) {
|
||||||
|
const newVoice = ((message.payload as any).xttsVoice as string) ?? '';
|
||||||
|
setXttsVoice(newVoice);
|
||||||
|
AsyncStorage.setItem('aria_xtts_voice', newVoice);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -257,6 +257,12 @@ def clean_text_for_tts(text: str) -> str:
|
|||||||
for pat, repl in _UNIT_WORDS:
|
for pat, repl in _UNIT_WORDS:
|
||||||
t = _re_tts.sub(pat, repl, t)
|
t = _re_tts.sub(pat, repl, t)
|
||||||
|
|
||||||
|
# Generisches Buchstabieren: alle verbleibenden 2-5-Zeichen-Grossbuchstaben-Woerter
|
||||||
|
# (XTTS, USB, DNS, JSON, HTML, ...) → "X T T S". Laeuft NACH der expliziten Liste,
|
||||||
|
# damit TTS/GPU/... schon aufgeloest sind. "WLAN"-artige, die als Wort gesprochen
|
||||||
|
# werden, koennen bei Bedarf explizit in _UNIT_WORDS uebersteuert werden.
|
||||||
|
t = _re_tts.sub(r'\b([A-Z]{2,5})\b', lambda m: " ".join(m.group(1)), t)
|
||||||
|
|
||||||
# Anfuehrungszeichen
|
# Anfuehrungszeichen
|
||||||
t = _re_tts.sub(r'["""„`]', '', t)
|
t = _re_tts.sub(r'["""„`]', '', t)
|
||||||
|
|
||||||
|
|||||||
+14
-4
@@ -151,8 +151,18 @@ async function _runTTSRequest(payload) {
|
|||||||
log(`TTS-Request (streaming): "${cleanText.slice(0, 80)}..." (${cleanText.length} chars, voice: ${voice || "default"})`);
|
log(`TTS-Request (streaming): "${cleanText.slice(0, 80)}..." (${cleanText.length} chars, voice: ${voice || "default"})`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const voiceSample = voice ? path.join(VOICES_DIR, `${voice}.wav`) : null;
|
// Im local-Mode erwartet daswer123 XTTS speaker_wav als Basename (ohne .wav,
|
||||||
const hasCustomVoice = voiceSample && fs.existsSync(voiceSample);
|
// ohne Pfad) — der Server prefixt EXAMPLE_FOLDER selbst. Wir checken hier
|
||||||
|
// nur das physische File ab um Warnungen zu loggen; runter ans API geht
|
||||||
|
// nur der Name.
|
||||||
|
const voiceFilePath = voice ? path.join(VOICES_DIR, `${voice}.wav`) : null;
|
||||||
|
const hasCustomVoice = voiceFilePath && fs.existsSync(voiceFilePath);
|
||||||
|
const speakerName = hasCustomVoice ? voice : "";
|
||||||
|
if (voice && !hasCustomVoice) {
|
||||||
|
log(`WARNUNG: Voice "${voice}" angefordert, aber ${voiceFilePath} existiert nicht — nehme Default`);
|
||||||
|
} else if (hasCustomVoice) {
|
||||||
|
log(`Voice "${voice}" verwendet (speaker_wav="${speakerName}")`);
|
||||||
|
}
|
||||||
|
|
||||||
let chunkIndex = 0;
|
let chunkIndex = 0;
|
||||||
let pcmMeta = null;
|
let pcmMeta = null;
|
||||||
@@ -190,7 +200,7 @@ async function _runTTSRequest(payload) {
|
|||||||
await streamXTTSAsPCM(
|
await streamXTTSAsPCM(
|
||||||
cleanText,
|
cleanText,
|
||||||
language || "de",
|
language || "de",
|
||||||
hasCustomVoice ? voiceSample : null,
|
speakerName,
|
||||||
onChunk,
|
onChunk,
|
||||||
);
|
);
|
||||||
} catch (streamErr) {
|
} catch (streamErr) {
|
||||||
@@ -198,7 +208,7 @@ async function _runTTSRequest(payload) {
|
|||||||
await streamXTTSBatch(
|
await streamXTTSBatch(
|
||||||
cleanText,
|
cleanText,
|
||||||
language || "de",
|
language || "de",
|
||||||
hasCustomVoice ? voiceSample : null,
|
speakerName,
|
||||||
onChunk,
|
onChunk,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user