- Switch whisper transcription from faster-whisper (CPU) to lightning-whisper-mlx (GPU) - Fix word_timestamps hanging, use ffprobe for accurate duration - Add Cloudflare Pages Worker for SignalWire voicemail fallback when server offline - Add voicemail sync on startup, delete tracking, save feature - Add /feed RSS proxy to _worker.js (was broken by worker taking over routing) - Redesign website hero section: ghost buttons, compact phone, plain text links - Rewrite caller prompts for faster point-getting and host-following - Expand TOPIC_CALLIN from ~250 to 547 entries across 34 categories - Add new categories: biology, psychology, engineering, math, geology, animals, work, money, books, movies, relationships, health, language, true crime, drunk/high/unhinged callers - Remove bad Inworld voices (Pixie, Dominus), reduce repeat caller frequency - Add audio monitor device routing, uvicorn --reload-dir fix - Publish episode 13 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
238 lines
11 KiB
HTML
238 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Luke at The Roost</title>
|
|
<link rel="stylesheet" href="/css/style.css">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<header>
|
|
<h1>Luke at The Roost</h1>
|
|
<div class="header-buttons">
|
|
<button id="on-air-btn" class="on-air-btn off">OFF AIR</button>
|
|
<button id="rec-btn" class="rec-btn" title="Record stems for post-production">REC</button>
|
|
<button id="new-session-btn" class="new-session-btn">New Session</button>
|
|
<button id="export-session-btn">Export</button>
|
|
<button id="settings-btn">Settings</button>
|
|
</div>
|
|
</header>
|
|
|
|
<main>
|
|
<!-- Callers -->
|
|
<section class="callers-section">
|
|
<h2>Callers <span id="session-id" class="session-id"></span></h2>
|
|
<div id="callers" class="caller-grid"></div>
|
|
<!-- Active Call Indicator -->
|
|
<div id="active-call" class="active-call hidden">
|
|
<div id="real-caller-info" class="caller-info hidden">
|
|
<span class="caller-type real">LIVE</span>
|
|
<span id="real-caller-name"></span>
|
|
<span id="real-caller-channel" class="channel-badge"></span>
|
|
<span id="real-caller-duration" class="call-duration"></span>
|
|
<button id="hangup-real-btn" class="hangup-btn small">Hang Up</button>
|
|
</div>
|
|
<div id="ai-caller-info" class="caller-info hidden">
|
|
<span class="caller-type ai">AI</span>
|
|
<span id="ai-caller-name"></span>
|
|
<div class="ai-controls">
|
|
<div class="mode-toggle">
|
|
<button id="mode-manual" class="mode-btn active">Manual</button>
|
|
<button id="mode-auto" class="mode-btn">Auto</button>
|
|
</div>
|
|
<button id="ai-respond-btn" class="respond-btn">Let them respond</button>
|
|
</div>
|
|
<button id="hangup-ai-btn" class="hangup-btn small">Hang Up</button>
|
|
</div>
|
|
<label class="auto-followup-label">
|
|
<input type="checkbox" id="auto-followup"> Auto Follow-Up
|
|
</label>
|
|
</div>
|
|
<div id="call-status" class="call-status">No active call</div>
|
|
<details id="caller-background-details" class="caller-background hidden">
|
|
<summary>Caller Background</summary>
|
|
<div id="caller-background"></div>
|
|
</details>
|
|
<button id="hangup-btn" class="hangup-btn" disabled>Hang Up</button>
|
|
</section>
|
|
|
|
<!-- Call Queue -->
|
|
<section class="queue-section">
|
|
<h2>Incoming Calls <span style="font-size:0.6em;font-weight:normal;color:var(--text-muted);">(208) 439-5853</span></h2>
|
|
<div id="call-queue" class="call-queue">
|
|
<div class="queue-empty">No callers waiting</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Voicemail -->
|
|
<section class="voicemail-section">
|
|
<h2>Voicemail <span id="voicemail-badge" class="voicemail-badge hidden">0</span></h2>
|
|
<div id="voicemail-list" class="voicemail-list">
|
|
<div class="queue-empty">No voicemails</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Chat -->
|
|
<section class="chat-section">
|
|
<div id="chat" class="chat-log"></div>
|
|
<div class="talk-controls">
|
|
<button id="talk-btn" class="talk-btn">Hold to Talk</button>
|
|
<button id="type-btn" class="type-btn">Type</button>
|
|
</div>
|
|
<div id="status" class="status hidden"></div>
|
|
</section>
|
|
|
|
<!-- Music -->
|
|
<section class="music-section">
|
|
<h2>Music</h2>
|
|
<select id="track-select"></select>
|
|
<div class="music-controls">
|
|
<button id="play-btn">Play</button>
|
|
<button id="stop-btn">Stop</button>
|
|
<input type="range" id="volume" min="0" max="100" value="30">
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Ads -->
|
|
<section class="music-section">
|
|
<h2>Ads</h2>
|
|
<select id="ad-select"></select>
|
|
<div class="music-controls">
|
|
<button id="ad-play-btn">Play Ad</button>
|
|
<button id="ad-stop-btn">Stop</button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Sound Effects -->
|
|
<section class="sounds-section">
|
|
<h2>Sounds</h2>
|
|
<div id="soundboard" class="soundboard"></div>
|
|
</section>
|
|
|
|
<!-- Server Log -->
|
|
<section class="log-section">
|
|
<div class="log-header">
|
|
<h2>Server Log</h2>
|
|
<div class="server-controls">
|
|
<button id="restart-server-btn" class="server-btn restart">Restart</button>
|
|
<button id="stop-server-btn" class="server-btn stop">Stop</button>
|
|
<label class="auto-scroll-label">
|
|
<input type="checkbox" id="auto-scroll" checked> Auto-scroll
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div id="server-log" class="server-log"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<!-- Settings Modal -->
|
|
<div id="settings-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<h2>Settings</h2>
|
|
|
|
<!-- Audio Devices -->
|
|
<div class="settings-group">
|
|
<h3>Audio Routing</h3>
|
|
<div class="device-row">
|
|
<label>
|
|
Input Device
|
|
<select id="input-device"></select>
|
|
</label>
|
|
<label>
|
|
Ch
|
|
<input type="number" id="input-channel" value="1" min="1" max="16" class="channel-input">
|
|
</label>
|
|
</div>
|
|
<div class="device-row">
|
|
<label>
|
|
Output Device
|
|
<select id="output-device"></select>
|
|
</label>
|
|
</div>
|
|
<div class="channel-row">
|
|
<label>Caller Ch <input type="number" id="caller-channel" value="3" min="1" max="16" class="channel-input"></label>
|
|
<label>Live Ch <input type="number" id="live-caller-channel" value="9" min="1" max="16" class="channel-input"></label>
|
|
<label>Music Ch <input type="number" id="music-channel" value="5" min="1" max="16" class="channel-input"></label>
|
|
<label>SFX Ch <input type="number" id="sfx-channel" value="7" min="1" max="16" class="channel-input"></label>
|
|
<label>Ad Ch <input type="number" id="ad-channel" value="11" min="1" max="16" class="channel-input"></label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- LLM Settings -->
|
|
<div class="settings-group">
|
|
<h3>LLM Provider</h3>
|
|
<label>
|
|
Provider
|
|
<select id="provider">
|
|
<option value="openrouter">OpenRouter</option>
|
|
<option value="ollama">Ollama</option>
|
|
</select>
|
|
</label>
|
|
|
|
<div id="openrouter-settings">
|
|
<label>
|
|
Model
|
|
<select id="openrouter-model"></select>
|
|
</label>
|
|
</div>
|
|
|
|
<div id="ollama-settings" class="hidden">
|
|
<label>
|
|
Model
|
|
<select id="ollama-model"></select>
|
|
</label>
|
|
<label>
|
|
Host
|
|
<input type="text" id="ollama-host" value="http://localhost:11434">
|
|
</label>
|
|
<button type="button" id="refresh-ollama" class="refresh-btn">Refresh Models</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- TTS Settings -->
|
|
<div class="settings-group">
|
|
<h3>TTS Provider</h3>
|
|
<label>
|
|
Provider
|
|
<select id="tts-provider">
|
|
<option value="inworld">Inworld (High quality, natural)</option>
|
|
<option value="f5tts">F5-TTS (Most natural local)</option>
|
|
<option value="elevenlabs">ElevenLabs (Best quality, paid)</option>
|
|
<option value="kokoro">Kokoro MLX (Fast, Apple Silicon)</option>
|
|
<option value="chattts">ChatTTS (Conversational)</option>
|
|
<option value="styletts2">StyleTTS2 (Voice cloning)</option>
|
|
<option value="vits">VITS (Fast local)</option>
|
|
<option value="bark">Bark (Expressive, supports [laughs])</option>
|
|
</select>
|
|
</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="phone-filter">
|
|
Phone filter on voices
|
|
</label>
|
|
</div>
|
|
|
|
<div class="modal-buttons">
|
|
<button id="save-settings">Save</button>
|
|
<button id="close-settings">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Type Modal -->
|
|
<div id="type-modal" class="modal hidden">
|
|
<div class="modal-content">
|
|
<h2>Type Message</h2>
|
|
<textarea id="type-input" rows="3" placeholder="Type what you want to say..."></textarea>
|
|
<div class="modal-buttons">
|
|
<button id="send-type">Send</button>
|
|
<button id="close-type">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/js/app.js?v=17"></script>
|
|
</body>
|
|
</html>
|