refactor(voice): tote Fenster-Settings ausgeräumt (Konv-Fenster/Passiv-Lauschen)
Nachdem die Stille-Toleranz jetzt überall der einzige Wert ist, sind die alten
Settings obsolet — raus damit:
- audio.ts: CONV_WINDOW_* Konstanten + loadConvWindowMs() entfernt.
- wakeword.ts: PASSIVE_LISTEN_* + load/savePassiveListenMs() entfernt; der Passiv-
Master-Timer nutzt jetzt einen festen internen Backstop (PASSIVE_BACKSTOP_MS,
15s) statt eines Nutzer-Werts — das echte Ende regelt die Stille-Toleranz.
- SettingsScreen: "Konversations-Fenster"- und "Weiterreden-Fenster"-Slider raus;
Letzterer durch eine kurze Erklärung ersetzt (verweist auf Stille-Toleranz).
- ChatScreen: tote Imports weg.
Kein Verhaltensänderung ggü. ebe0e80 — nur Aufräumen. tsc grün.
Deploy: neue APK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,7 @@ import MemoryBrowser from '../components/MemoryBrowser';
|
|||||||
import ErrorBoundary from '../components/ErrorBoundary';
|
import ErrorBoundary from '../components/ErrorBoundary';
|
||||||
import rvs, { RVSMessage, ConnectionState } from '../services/rvs';
|
import rvs, { RVSMessage, ConnectionState } from '../services/rvs';
|
||||||
import audioService from '../services/audio';
|
import audioService from '../services/audio';
|
||||||
import wakeWordService, { loadPassiveListenMs } from '../services/wakeword';
|
import wakeWordService from '../services/wakeword';
|
||||||
import ProjectsBrowser from '../components/ProjectsBrowser';
|
import ProjectsBrowser from '../components/ProjectsBrowser';
|
||||||
import brainApi, { Project as BrainProject } from '../services/brainApi';
|
import brainApi, { Project as BrainProject } from '../services/brainApi';
|
||||||
import projectFocus from '../services/projectFocus';
|
import projectFocus from '../services/projectFocus';
|
||||||
@@ -50,7 +50,7 @@ import VoiceButton from '../components/VoiceButton';
|
|||||||
import FileUpload, { FileData } from '../components/FileUpload';
|
import FileUpload, { FileData } from '../components/FileUpload';
|
||||||
import CameraUpload, { PhotoData } from '../components/CameraUpload';
|
import CameraUpload, { PhotoData } from '../components/CameraUpload';
|
||||||
import MessageText from '../components/MessageText';
|
import MessageText from '../components/MessageText';
|
||||||
import { loadConvWindowMs, loadTtsSpeed, TTS_SPEED_DEFAULT, loadSttEndpointMs, loadMaxRecordingMs, loadBargeInEnabled } from '../services/audio';
|
import { loadTtsSpeed, TTS_SPEED_DEFAULT, loadSttEndpointMs, loadMaxRecordingMs, loadBargeInEnabled } from '../services/audio';
|
||||||
import Geolocation from '@react-native-community/geolocation';
|
import Geolocation from '@react-native-community/geolocation';
|
||||||
|
|
||||||
// --- Typen ---
|
// --- Typen ---
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ import {
|
|||||||
VAD_SILENCE_MIN_SEC,
|
VAD_SILENCE_MIN_SEC,
|
||||||
VAD_SILENCE_MAX_SEC,
|
VAD_SILENCE_MAX_SEC,
|
||||||
VAD_SILENCE_STORAGE_KEY,
|
VAD_SILENCE_STORAGE_KEY,
|
||||||
CONV_WINDOW_DEFAULT_SEC,
|
|
||||||
CONV_WINDOW_MIN_SEC,
|
|
||||||
CONV_WINDOW_MAX_SEC,
|
|
||||||
CONV_WINDOW_STORAGE_KEY,
|
|
||||||
STT_ENDPOINT_DEFAULT_MS,
|
STT_ENDPOINT_DEFAULT_MS,
|
||||||
STT_ENDPOINT_MIN_MS,
|
STT_ENDPOINT_MIN_MS,
|
||||||
STT_ENDPOINT_MAX_MS,
|
STT_ENDPOINT_MAX_MS,
|
||||||
@@ -116,9 +112,6 @@ import wakeWordService, {
|
|||||||
WAKE_THRESHOLD_MAX,
|
WAKE_THRESHOLD_MAX,
|
||||||
loadWakeThreshold,
|
loadWakeThreshold,
|
||||||
saveWakeThreshold,
|
saveWakeThreshold,
|
||||||
PASSIVE_LISTEN_DEFAULT_MS,
|
|
||||||
loadPassiveListenMs,
|
|
||||||
savePassiveListenMs,
|
|
||||||
} from '../services/wakeword';
|
} from '../services/wakeword';
|
||||||
import ModeSelector from '../components/ModeSelector';
|
import ModeSelector from '../components/ModeSelector';
|
||||||
import QRScanner from '../components/QRScanner';
|
import QRScanner from '../components/QRScanner';
|
||||||
@@ -204,7 +197,6 @@ const SettingsScreen: React.FC = () => {
|
|||||||
// Aktive Streaming-Pausen-Toleranz (STT_ENDPOINT) — der "Stille-Toleranz"-Regler
|
// Aktive Streaming-Pausen-Toleranz (STT_ENDPOINT) — der "Stille-Toleranz"-Regler
|
||||||
// steuert jetzt DIESEN Wert (der alte vadSilenceSec war der tote Legacy-dB-Pfad).
|
// steuert jetzt DIESEN Wert (der alte vadSilenceSec war der tote Legacy-dB-Pfad).
|
||||||
const [sttEndpointSec, setSttEndpointSec] = useState<number>(STT_ENDPOINT_DEFAULT_MS / 1000);
|
const [sttEndpointSec, setSttEndpointSec] = useState<number>(STT_ENDPOINT_DEFAULT_MS / 1000);
|
||||||
const [convWindowSec, setConvWindowSec] = useState<number>(CONV_WINDOW_DEFAULT_SEC);
|
|
||||||
const [maxRecordingSec, setMaxRecordingSec] = useState<number>(MAX_RECORDING_DEFAULT_SEC);
|
const [maxRecordingSec, setMaxRecordingSec] = useState<number>(MAX_RECORDING_DEFAULT_SEC);
|
||||||
// Barge-in: ARIA waehrend ihrer Antwort unterbrechen duerfen. Default aus (Halb-Duplex).
|
// Barge-in: ARIA waehrend ihrer Antwort unterbrechen duerfen. Default aus (Halb-Duplex).
|
||||||
const [bargeIn, setBargeIn] = useState<boolean>(false);
|
const [bargeIn, setBargeIn] = useState<boolean>(false);
|
||||||
@@ -220,7 +212,6 @@ const SettingsScreen: React.FC = () => {
|
|||||||
const [wakeStatus, setWakeStatus] = useState<string>('');
|
const [wakeStatus, setWakeStatus] = useState<string>('');
|
||||||
const [wakeReadySound, setWakeReadySound] = useState<boolean>(true);
|
const [wakeReadySound, setWakeReadySound] = useState<boolean>(true);
|
||||||
const [wakeThreshold, setWakeThreshold] = useState<number>(WAKE_THRESHOLD_DEFAULT);
|
const [wakeThreshold, setWakeThreshold] = useState<number>(WAKE_THRESHOLD_DEFAULT);
|
||||||
const [passiveSec, setPassiveSec] = useState<number>(Math.round(PASSIVE_LISTEN_DEFAULT_MS / 1000));
|
|
||||||
const [editingPath, setEditingPath] = useState(false);
|
const [editingPath, setEditingPath] = useState(false);
|
||||||
const [xttsVoice, setXttsVoice] = useState('');
|
const [xttsVoice, setXttsVoice] = useState('');
|
||||||
const [loadingVoice, setLoadingVoice] = useState<string | null>(null);
|
const [loadingVoice, setLoadingVoice] = useState<string | null>(null);
|
||||||
@@ -309,14 +300,6 @@ const SettingsScreen: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
AsyncStorage.getItem(CONV_WINDOW_STORAGE_KEY).then(saved => {
|
|
||||||
if (saved != null) {
|
|
||||||
const n = parseFloat(saved);
|
|
||||||
if (isFinite(n) && n >= CONV_WINDOW_MIN_SEC && n <= CONV_WINDOW_MAX_SEC) {
|
|
||||||
setConvWindowSec(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
AsyncStorage.getItem(STT_ENDPOINT_STORAGE_KEY).then(saved => {
|
AsyncStorage.getItem(STT_ENDPOINT_STORAGE_KEY).then(saved => {
|
||||||
if (saved != null) {
|
if (saved != null) {
|
||||||
const n = parseInt(saved, 10);
|
const n = parseInt(saved, 10);
|
||||||
@@ -353,7 +336,6 @@ const SettingsScreen: React.FC = () => {
|
|||||||
});
|
});
|
||||||
isWakeReadySoundEnabled().then(setWakeReadySound);
|
isWakeReadySoundEnabled().then(setWakeReadySound);
|
||||||
loadWakeThreshold().then(setWakeThreshold).catch(() => {});
|
loadWakeThreshold().then(setWakeThreshold).catch(() => {});
|
||||||
loadPassiveListenMs().then(ms => setPassiveSec(Math.round(ms / 1000))).catch(() => {});
|
|
||||||
updateService.getApkCacheSize().then(setApkCacheInfo).catch(() => {});
|
updateService.getApkCacheSize().then(setApkCacheInfo).catch(() => {});
|
||||||
audioService.getTtsCacheSize().then(setTtsCacheInfo).catch(() => {});
|
audioService.getTtsCacheSize().then(setTtsCacheInfo).catch(() => {});
|
||||||
AsyncStorage.getItem('aria_xtts_voice').then(saved => {
|
AsyncStorage.getItem('aria_xtts_voice').then(saved => {
|
||||||
@@ -1721,39 +1703,6 @@ const SettingsScreen: React.FC = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={[styles.toggleLabel, {marginTop: 24}]}>Konversations-Fenster</Text>
|
|
||||||
<Text style={styles.toggleHint}>
|
|
||||||
Im Gespraechsmodus (Ohr-Button): nach ARIA's Antwort hast du so lange
|
|
||||||
Zeit, weiter zu sprechen, bevor die Konversation automatisch beendet wird.
|
|
||||||
Sprichst du nichts → Mikrofon zu.
|
|
||||||
Default: {CONV_WINDOW_DEFAULT_SEC.toFixed(1)}s.
|
|
||||||
</Text>
|
|
||||||
<View style={styles.prerollRow}>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.prerollButton}
|
|
||||||
onPress={() => {
|
|
||||||
const next = Math.max(CONV_WINDOW_MIN_SEC, Math.round((convWindowSec - 1) * 10) / 10);
|
|
||||||
setConvWindowSec(next);
|
|
||||||
AsyncStorage.setItem(CONV_WINDOW_STORAGE_KEY, String(next));
|
|
||||||
}}
|
|
||||||
disabled={convWindowSec <= CONV_WINDOW_MIN_SEC}
|
|
||||||
>
|
|
||||||
<Text style={styles.prerollButtonText}>−1</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<Text style={styles.prerollValue}>{convWindowSec.toFixed(0)} s</Text>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.prerollButton}
|
|
||||||
onPress={() => {
|
|
||||||
const next = Math.min(CONV_WINDOW_MAX_SEC, Math.round((convWindowSec + 1) * 10) / 10);
|
|
||||||
setConvWindowSec(next);
|
|
||||||
AsyncStorage.setItem(CONV_WINDOW_STORAGE_KEY, String(next));
|
|
||||||
}}
|
|
||||||
disabled={convWindowSec >= CONV_WINDOW_MAX_SEC}
|
|
||||||
>
|
|
||||||
<Text style={styles.prerollButtonText}>+1</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Text style={[styles.toggleLabel, {marginTop: 24}]}>Maximale Aufnahmedauer</Text>
|
<Text style={[styles.toggleLabel, {marginTop: 24}]}>Maximale Aufnahmedauer</Text>
|
||||||
<Text style={styles.toggleHint}>
|
<Text style={styles.toggleHint}>
|
||||||
Notbremse: nach so vielen Minuten wird die Aufnahme automatisch beendet,
|
Notbremse: nach so vielen Minuten wird die Aufnahme automatisch beendet,
|
||||||
@@ -1945,38 +1894,14 @@ const SettingsScreen: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={[styles.toggleLabel, {marginTop: 20}]}>Weiterreden-Fenster (Gespraech)</Text>
|
<Text style={[styles.toggleLabel, {marginTop: 20}]}>Weiterreden nach der Antwort</Text>
|
||||||
<Text style={styles.toggleHint}>
|
<Text style={styles.toggleHint}>
|
||||||
Nach einer gesprochenen ARIA-Antwort kannst du so lange einfach
|
Nach einer gesprochenen ARIA-Antwort geht das Mikro auf — du kannst ohne
|
||||||
weiterreden — ohne Wake-Word — bevor zurueck aufs Wake-Word geschaltet
|
Wake-Word weiterreden. Fängst du nicht innerhalb der „Stille-Toleranz"
|
||||||
wird. Reine Steuerbefehle (z.B. „nächster Titel") beenden sofort.
|
(Sektion Spracheingabe) an, geht's zurück aufs Wake-Word. Reine
|
||||||
Default: {Math.round(PASSIVE_LISTEN_DEFAULT_MS / 1000)}s.
|
Steuerbefehle beenden sofort. Ein separates Zeitfenster gibt es nicht
|
||||||
|
mehr — es zählt überall derselbe Stille-Wert.
|
||||||
</Text>
|
</Text>
|
||||||
<View style={styles.prerollRow}>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.prerollButton}
|
|
||||||
onPress={() => {
|
|
||||||
const next = Math.max(10, passiveSec - 5);
|
|
||||||
setPassiveSec(next);
|
|
||||||
savePassiveListenMs(next * 1000);
|
|
||||||
}}
|
|
||||||
disabled={passiveSec <= 10}
|
|
||||||
>
|
|
||||||
<Text style={styles.prerollButtonText}>−5</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<Text style={styles.prerollValue}>{passiveSec} s</Text>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.prerollButton}
|
|
||||||
onPress={() => {
|
|
||||||
const next = Math.min(60, passiveSec + 5);
|
|
||||||
setPassiveSec(next);
|
|
||||||
savePassiveListenMs(next * 1000);
|
|
||||||
}}
|
|
||||||
disabled={passiveSec >= 60}
|
|
||||||
>
|
|
||||||
<Text style={styles.prerollButtonText}>+5</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
</>)}
|
</>)}
|
||||||
|
|
||||||
|
|||||||
@@ -143,14 +143,6 @@ export const VAD_SILENCE_MIN_SEC = 1.0;
|
|||||||
export const VAD_SILENCE_MAX_SEC = 8.0;
|
export const VAD_SILENCE_MAX_SEC = 8.0;
|
||||||
export const VAD_SILENCE_STORAGE_KEY = 'aria_vad_silence_sec';
|
export const VAD_SILENCE_STORAGE_KEY = 'aria_vad_silence_sec';
|
||||||
|
|
||||||
// Konversations-Fenster (in Sekunden) — nach ARIA's Antwort hat der User so
|
|
||||||
// lange Zeit, im Gespraechsmodus weiter zu sprechen, ohne dass die Konversation
|
|
||||||
// beendet wird. Sprichst du im Fenster nichts → Konversation aus.
|
|
||||||
export const CONV_WINDOW_DEFAULT_SEC = 8.0;
|
|
||||||
export const CONV_WINDOW_MIN_SEC = 3.0;
|
|
||||||
export const CONV_WINDOW_MAX_SEC = 20.0;
|
|
||||||
export const CONV_WINDOW_STORAGE_KEY = 'aria_conv_window_sec';
|
|
||||||
|
|
||||||
// STT-Endpoint (ms Stille bis "fertig gesprochen"). Zu kurz = schneidet mitten
|
// STT-Endpoint (ms Stille bis "fertig gesprochen"). Zu kurz = schneidet mitten
|
||||||
// im Satz ab, besonders im Auto oder wenn man zum Nachdenken pausiert. 1500 war
|
// im Satz ab, besonders im Auto oder wenn man zum Nachdenken pausiert. 1500 war
|
||||||
// zu aggressiv; 2400 default, bis 8s hoch stellbar (Denkpausen). In den Settings
|
// zu aggressiv; 2400 default, bis 8s hoch stellbar (Denkpausen). In den Settings
|
||||||
@@ -208,18 +200,6 @@ export async function loadTtsSpeed(): Promise<number> {
|
|||||||
return TTS_SPEED_DEFAULT;
|
return TTS_SPEED_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadConvWindowMs(): Promise<number> {
|
|
||||||
try {
|
|
||||||
const raw = await AsyncStorage.getItem(CONV_WINDOW_STORAGE_KEY);
|
|
||||||
if (raw != null) {
|
|
||||||
const n = parseFloat(raw);
|
|
||||||
if (isFinite(n) && n >= CONV_WINDOW_MIN_SEC && n <= CONV_WINDOW_MAX_SEC) {
|
|
||||||
return Math.round(n * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
return Math.round(CONV_WINDOW_DEFAULT_SEC * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadVadSilenceMs(): Promise<number> {
|
async function loadVadSilenceMs(): Promise<number> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -30,26 +30,12 @@ type PassiveListenCallback = () => void;
|
|||||||
|
|
||||||
export type WakeWordState = 'off' | 'armed' | 'conversing' | 'listening';
|
export type WakeWordState = 'off' | 'armed' | 'conversing' | 'listening';
|
||||||
|
|
||||||
/** Default-Dauer fuer den Passive-Listen-Modus nach einer Konversation —
|
/** Backstop-Dauer fuer den Passive-Listen-Modus nach einer Antwort. Das echte
|
||||||
* in dem Fenster braucht's kein Wake-Word, Speaker-ID-Filter haelt
|
* Ende regelt die Stille-Toleranz (die passive Aufnahme endet nach dem einen
|
||||||
* fremde Stimmen raus (TV, Familie). 30s default; konfigurierbar. */
|
* No-Speech-Fenster → ChatScreen ruft exitPassiveListening). Dieser Timer ist
|
||||||
export const PASSIVE_LISTEN_DEFAULT_MS = 30_000;
|
* nur die Notbremse, falls die Aufnahme mal nicht sauber endpointet — daher
|
||||||
export const PASSIVE_LISTEN_STORAGE_KEY = 'aria_passive_listen_ms';
|
* fix und kurz, kein separater Nutzer-Wert mehr (das alte 30s-Fenster ist raus). */
|
||||||
|
const PASSIVE_BACKSTOP_MS = 15_000;
|
||||||
export async function loadPassiveListenMs(): Promise<number> {
|
|
||||||
try {
|
|
||||||
const raw = await AsyncStorage.getItem(PASSIVE_LISTEN_STORAGE_KEY);
|
|
||||||
if (raw) {
|
|
||||||
const n = parseInt(raw, 10);
|
|
||||||
if (isFinite(n) && n >= 0 && n <= 120_000) return n;
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
return PASSIVE_LISTEN_DEFAULT_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function savePassiveListenMs(ms: number): Promise<void> {
|
|
||||||
await AsyncStorage.setItem(PASSIVE_LISTEN_STORAGE_KEY, String(ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
export const WAKE_KEYWORD_STORAGE = 'aria_wake_keyword';
|
export const WAKE_KEYWORD_STORAGE = 'aria_wake_keyword';
|
||||||
|
|
||||||
@@ -152,8 +138,9 @@ class WakeWordService {
|
|||||||
* Ausnahme: bargeListening → Barge-In ist ein legitimer neuer Trigger
|
* Ausnahme: bargeListening → Barge-In ist ein legitimer neuer Trigger
|
||||||
* waehrend ARIA noch redet, NICHT vom Guard blockieren. */
|
* waehrend ARIA noch redet, NICHT vom Guard blockieren. */
|
||||||
private detectionInProgress: boolean = false;
|
private detectionInProgress: boolean = false;
|
||||||
/** Passive-Listen-Timer: feuert nach PASSIVE_LISTEN_MS ohne Stefan-Speech,
|
/** Passive-Listen-Backstop-Timer: Notbremse (PASSIVE_BACKSTOP_MS). Normal endet
|
||||||
* beendet den listening-State und geht zurueck zu armed. */
|
* das Fenster ueber die Stille-Toleranz der Aufnahme; feuert dieser Timer
|
||||||
|
* trotzdem, zurueck zu armed. */
|
||||||
private passiveListenTimer: ReturnType<typeof setTimeout> | null = null;
|
private passiveListenTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
/** Callbacks fuer den Eintritt in Passive-Listen — ChatScreen startet
|
/** Callbacks fuer den Eintritt in Passive-Listen — ChatScreen startet
|
||||||
* hier eine streaming-Aufnahme OHNE User-Bubble (passiv lauschen). */
|
* hier eine streaming-Aufnahme OHNE User-Bubble (passiv lauschen). */
|
||||||
@@ -489,13 +476,12 @@ class WakeWordService {
|
|||||||
import('./logger').then(m => m.reportAppDebug('wake.end',
|
import('./logger').then(m => m.reportAppDebug('wake.end',
|
||||||
`endConversation called, wasBarge=${wasBarge}, nativeReady=${this.nativeReady}`)).catch(()=>{});
|
`endConversation called, wasBarge=${wasBarge}, nativeReady=${this.nativeReady}`)).catch(()=>{});
|
||||||
|
|
||||||
// Passive-Listen aktiv? Dann nicht direkt zu armed — passive lauschen
|
// Kein skipPassive? Dann EIN Stille-Fenster zum Weiterreden (kein Wake-Word
|
||||||
// fuer N Sekunden, dann erst Wake-Word wieder aktivieren. Speaker-ID
|
// noetig). Das echte Ende regelt die Stille-Toleranz der passiven Aufnahme;
|
||||||
// (Phase 3) filtert fremde Stimmen weg, der User kann ohne erneute
|
// der Backstop-Timer ist nur die Notbremse. Der User kann ohne erneute
|
||||||
// Anrede weitersprechen.
|
// Anrede weitersprechen; sagt er nichts → zurueck aufs Wake-Word.
|
||||||
const passiveMs = await loadPassiveListenMs();
|
if (!skipPassive && this.nativeReady) {
|
||||||
if (!skipPassive && passiveMs > 0 && this.nativeReady) {
|
this.enterPassiveListening(PASSIVE_BACKSTOP_MS);
|
||||||
this.enterPassiveListening(passiveMs);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,10 +523,10 @@ class WakeWordService {
|
|||||||
this.cancelPassiveListenTimer();
|
this.cancelPassiveListenTimer();
|
||||||
this.setState('listening');
|
this.setState('listening');
|
||||||
const seconds = Math.round(durationMs / 1000);
|
const seconds = Math.round(durationMs / 1000);
|
||||||
console.log('[WakeWord] Passive-Listen aktiv (%ds) — Speaker-ID gefiltert', seconds);
|
console.log('[WakeWord] Passive-Listen aktiv (Backstop %ds) — Speaker-ID gefiltert', seconds);
|
||||||
import('./logger').then(m => m.reportAppDebug('wake.passive',
|
import('./logger').then(m => m.reportAppDebug('wake.passive',
|
||||||
`entered listening for ${seconds}s, cb-count=${this.passiveListenCallbacks.length}`)).catch(()=>{});
|
`entered listening (backstop ${seconds}s), cb-count=${this.passiveListenCallbacks.length}`)).catch(()=>{});
|
||||||
ToastAndroid.show(`🎧 ${seconds}s lauscht — sprich einfach weiter`, ToastAndroid.SHORT);
|
ToastAndroid.show('🎧 sprich einfach weiter', ToastAndroid.SHORT);
|
||||||
this.passiveListenTimer = setTimeout(() => {
|
this.passiveListenTimer = setTimeout(() => {
|
||||||
this.passiveListenTimer = null;
|
this.passiveListenTimer = null;
|
||||||
this.exitPassiveListening('timeout').catch(() => {});
|
this.exitPassiveListening('timeout').catch(() => {});
|
||||||
|
|||||||
Reference in New Issue
Block a user