Speak dialogue with persistent character voices
Build and publish frontend / publish (push) Successful in 50s
Build and publish frontend / publish (push) Successful in 50s
This commit is contained in:
+13
-5
@@ -84,6 +84,7 @@
|
||||
let submitBusy = false;
|
||||
let pendingDialogue = null;
|
||||
let latestAssistantText = '';
|
||||
let latestAssistantVoice = {role: 'narrator', voiceIdentity: 'neutral'};
|
||||
const voiceSettingsKey = 'ai-spel.voice-settings.v1';
|
||||
let voiceSettings = window.GameVoice.loadSettings(localStorage, voiceSettingsKey);
|
||||
let voiceController;
|
||||
@@ -106,9 +107,10 @@
|
||||
line.scrollIntoView({block: 'end'});
|
||||
if (role === 'assistant') {
|
||||
latestAssistantText = content;
|
||||
latestAssistantVoice = options.voice || {role: 'narrator', voiceIdentity: 'neutral'};
|
||||
if (options.speak !== false && !content.trim().endsWith('…') && !content.trim().endsWith('...')
|
||||
&& voiceSettings.mode === 'game-voice' && voiceSettings.autoSpeak && !play.hidden) {
|
||||
voiceController?.speak(content, options.voice || {});
|
||||
voiceController?.speak(content, latestAssistantVoice);
|
||||
}
|
||||
}
|
||||
return line;
|
||||
@@ -199,7 +201,7 @@
|
||||
signalLabel.append(signals, document.createTextNode(' Ljudsignal vid röstinmatning')); fieldset.append(signalLabel);
|
||||
item.append(fieldset);
|
||||
const speakLatest = () => {
|
||||
if (!voiceController.speak(latestAssistantText)) setVoiceStatus('Talsyntes stöds inte här eller är avstängd. Dialogen finns kvar som text.');
|
||||
if (!voiceController.speak(latestAssistantText, latestAssistantVoice)) setVoiceStatus('Talsyntes stöds inte här eller är avstängd. Dialogen finns kvar som text.');
|
||||
};
|
||||
addVoiceButton(item, 'Läs senaste repliken', speakLatest);
|
||||
addVoiceButton(item, 'Upprepa', speakLatest);
|
||||
@@ -231,7 +233,7 @@
|
||||
if (!parsed) return false;
|
||||
if (parsed.command === 'settings') appendVoiceSettings();
|
||||
else if (parsed.command === 'repeat') {
|
||||
if (!voiceController.speak(latestAssistantText)) setVoiceStatus('Talsyntes stöds inte här eller är avstängd. Dialogen finns kvar som text.');
|
||||
if (!voiceController.speak(latestAssistantText, latestAssistantVoice)) setVoiceStatus('Talsyntes stöds inte här eller är avstängd. Dialogen finns kvar som text.');
|
||||
} else if (parsed.command === 'stop') {
|
||||
voiceController.cancelSpeech(); voiceController.stopListening(); setVoiceStatus('Röstinteraktionen är avbruten.');
|
||||
} else if (parsed.command === 'help') {
|
||||
@@ -532,10 +534,16 @@
|
||||
gameState.world.version = result.world_version;
|
||||
gameState.world.world_time = result.world_time;
|
||||
pendingDialogue = null;
|
||||
if (result.intent === 'move') {
|
||||
try {
|
||||
const refreshed = await request('/api/world');
|
||||
if (refreshed.world) gameState = refreshed;
|
||||
} catch (_) { /* The committed dialogue stays successful if this optional view refresh fails. */ }
|
||||
}
|
||||
const speakingNpc = result.intent === 'speak' ? gameState.world.npc : null;
|
||||
appendLine('assistant', result.reply, speakingNpc
|
||||
? {speaker: speakingNpc.name, voice: {characterId: speakingNpc.id}}
|
||||
: {speaker: 'Berättelsen'});
|
||||
? {speaker: speakingNpc.name, voice: {characterId: speakingNpc.id, voiceIdentity: speakingNpc.voice_identity}}
|
||||
: {speaker: 'Berättelsen', voice: {role: 'narrator', voiceIdentity: 'neutral'}});
|
||||
} catch (error) {
|
||||
messageField.value = message;
|
||||
appendLine('assistant', `Meddelandet kunde inte behandlas: ${error.message}. Texten ligger kvar i inmatningen; skicka igen för att försöka på nytt.`);
|
||||
|
||||
Reference in New Issue
Block a user