tts-voice-creator-clone-and.../static/sections/s-conversation.html
mARTin-B78 f4688ecc0c v1.2.0: VAD, live preview, hands-free mic, restore last section
Conversation playground:
- Live speech preview: MediaRecorder sends accumulated audio to
  /api/transcribe-bytes every 2.5 s; interim Whisper result shown in
  the text input field while recording. Web Speech API tried first as
  a faster path when available (HTTPS/localhost).
- VAD auto-stop: AudioContext AnalyserNode measures RMS every frame;
  auto-stops after 1.5 s silence with a visible countdown. Auto-stop
  toggle to revert to click-to-stop.
- Hands-free mode: mic auto-restarts after the agent finishes speaking
  via audio.ended event + generation-counter cancellation. Hands-free
  toggle (on by default) to disable.

Navigation:
- Persist active section and sub-page in localStorage; hard-reload
  returns to the same page instead of always jumping to My Voices.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:47:00 +02:00

120 lines
6.5 KiB
HTML

<div class="section-head">
<span class="section-icon"><span class="mdi mdi-forum-outline"></span></span>
<div class="section-title">
<h2>Conversation Playground</h2>
<p>Talk to an AI voice agent. Full STT &rarr; LLM &rarr; TTS pipeline with real-time streaming and latency stats.</p>
</div>
</div>
<!-- Config bar -->
<div class="conv-config-bar card">
<div class="conv-config-row">
<div class="conv-config-group">
<label class="conv-cfg-label"><span class="mdi mdi-microphone"></span> Speech to Text</label>
<select id="conv-stt-select"><option value="configured">Checking...</option></select>
</div>
<div class="conv-config-group">
<label class="conv-cfg-label"><span class="mdi mdi-brain"></span> Language Model</label>
<div style="display:flex;gap:6px">
<input id="conv-llm-url" class="conv-url-inp" type="text" placeholder="http://localhost:11434/v1" spellcheck="false">
<button class="btn-secondary" id="conv-llm-fetch-btn" title="Fetch models"><span class="mdi mdi-refresh"></span></button>
<select id="conv-llm-model-select"><option value="">— fetch models —</option></select>
</div>
</div>
<div class="conv-config-group">
<label class="conv-cfg-label"><span class="mdi mdi-text-to-speech"></span> Text to Speech</label>
<div style="display:flex;gap:6px">
<select id="conv-tts-backend-select"><option value="">Checking...</option></select>
<button class="btn-secondary" id="conv-tts-fetch-btn" title="Fetch voices"><span class="mdi mdi-refresh"></span></button>
<select id="conv-tts-voice-select"><option value="">— fetch voices —</option></select>
</div>
</div>
<div class="conv-config-group conv-config-group--actions">
<button class="btn-secondary" id="conv-clear-btn" title="Clear conversation"><span class="mdi mdi-delete-outline"></span> Clear</button>
</div>
</div>
<div class="conv-prompt-row">
<label class="conv-cfg-label"><span class="mdi mdi-text-box-outline"></span> System prompt</label>
<textarea id="conv-system-prompt" class="conv-system-textarea" rows="1" spellcheck="false">You are a helpful voice assistant. Keep replies short and conversational.</textarea>
</div>
</div>
<!-- Main area: chat + stats -->
<div class="conv-main">
<!-- Chat window -->
<div class="conv-chat-panel">
<div class="conv-chat-window" id="conv-chat-window">
<div class="conv-chat-welcome">
<span class="mdi mdi-forum-outline" style="font-size:32px;opacity:.25"></span>
<p>Type a message or press the microphone button below to start.</p>
</div>
</div>
<!-- Input bar: text field + send + mic -->
<div class="conv-input-bar">
<div class="conv-mic-status" id="conv-mic-status">Ready</div>
<div class="conv-level-wrap" id="conv-level-wrap"><div class="conv-level-fill" id="conv-level-fill"></div></div>
<div class="conv-text-row">
<input id="conv-text-input" class="conv-text-inp"
type="text" placeholder="Type a message and press Enter or →"
spellcheck="false" autocomplete="off">
<button class="conv-send-btn" id="conv-send-btn" title="Send text (Enter)">
<span class="mdi mdi-send"></span>
</button>
<div class="conv-divider" title="or use microphone"></div>
<button class="conv-mic-btn" id="conv-mic-btn" title="Click to record via microphone">
<span class="mdi mdi-microphone" id="conv-mic-icon"></span>
</button>
<div class="conv-mic-timer" id="conv-mic-timer"></div>
<label class="conv-vad-label" title="Auto-stop recording when silence is detected">
<input type="checkbox" id="conv-vad-toggle" checked>
<span>Auto-stop</span>
</label>
<label class="conv-vad-label" title="Automatically restart microphone after the agent finishes speaking">
<input type="checkbox" id="conv-handsfree-toggle" checked>
<span>Hands-free</span>
</label>
</div>
</div>
</div>
<!-- Stats panel -->
<div class="conv-stats-panel">
<div class="conv-stats-head">Latency</div>
<div class="conv-pipeline">
<div class="conv-pipe-step" id="cps-stt">
<div class="conv-pipe-label"><span class="mdi mdi-microphone-outline"></span> STT</div>
<div class="conv-pipe-bar"><div class="conv-pipe-fill" id="cpf-stt"></div></div>
<div class="conv-pipe-val" id="cpv-stt"></div>
</div>
<div class="conv-pipe-step" id="cps-ttft">
<div class="conv-pipe-label"><span class="mdi mdi-timer-outline"></span> LLM first token</div>
<div class="conv-pipe-bar"><div class="conv-pipe-fill" id="cpf-ttft"></div></div>
<div class="conv-pipe-val" id="cpv-ttft"></div>
</div>
<div class="conv-pipe-step" id="cps-llm">
<div class="conv-pipe-label"><span class="mdi mdi-brain"></span> LLM total</div>
<div class="conv-pipe-bar"><div class="conv-pipe-fill" id="cpf-llm"></div></div>
<div class="conv-pipe-val" id="cpv-llm"></div>
</div>
<div class="conv-pipe-step" id="cps-tts">
<div class="conv-pipe-label"><span class="mdi mdi-text-to-speech"></span> TTS</div>
<div class="conv-pipe-bar"><div class="conv-pipe-fill" id="cpf-tts"></div></div>
<div class="conv-pipe-val" id="cpv-tts"></div>
</div>
<div class="conv-pipe-step conv-pipe-total" id="cps-total">
<div class="conv-pipe-label"><span class="mdi mdi-timer-check-outline"></span> Total</div>
<div class="conv-pipe-bar"><div class="conv-pipe-fill" id="cpf-total" style="background:var(--accent)"></div></div>
<div class="conv-pipe-val" id="cpv-total"></div>
</div>
</div>
<div class="conv-stats-head" style="margin-top:14px">Turn history</div>
<div class="conv-turn-history" id="conv-turn-history">
<div class="conv-history-empty">No turns yet.</div>
</div>
</div>
</div>