Files
ai-podcast/frontend/call-in.html
tcpsyn d4e25ceb88 Stream TTS audio to caller in real-time chunks
TTS audio was sent as a single huge WebSocket frame that overflowed the
browser's 3s ring buffer. Now streams in 60ms chunks at real-time rate.
Also increased browser ring buffer from 3s to 10s as safety net.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 16:56:22 -07:00

156 lines
4.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Call In - Luke at the Roost</title>
<style>
:root {
--bg: #1a1a2e;
--bg-light: #252547;
--accent: #e94560;
--text: #fff;
--text-muted: #888;
--radius: 8px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
max-width: 400px;
width: 100%;
padding: 30px;
text-align: center;
}
h1 {
font-size: 1.5em;
margin-bottom: 8px;
}
.subtitle {
color: var(--text-muted);
margin-bottom: 30px;
font-size: 0.9em;
}
.form-group {
margin-bottom: 20px;
}
.form-group input {
width: 100%;
padding: 12px 16px;
border: 1px solid #444;
border-radius: var(--radius);
background: var(--bg-light);
color: var(--text);
font-size: 1em;
outline: none;
}
.form-group input:focus {
border-color: var(--accent);
}
.call-btn {
width: 100%;
padding: 14px;
border: none;
border-radius: var(--radius);
background: var(--accent);
color: #fff;
font-size: 1.1em;
font-weight: 600;
cursor: pointer;
transition: opacity 0.2s;
}
.call-btn:hover { opacity: 0.9; }
.call-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.hangup-btn {
width: 100%;
padding: 14px;
border: none;
border-radius: var(--radius);
background: #c0392b;
color: #fff;
font-size: 1.1em;
font-weight: 600;
cursor: pointer;
margin-top: 12px;
display: none;
}
.hangup-btn:hover { opacity: 0.9; }
.status {
margin-top: 20px;
padding: 16px;
background: var(--bg-light);
border-radius: var(--radius);
display: none;
}
.status.visible { display: block; }
.status-label {
font-size: 0.85em;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 6px;
}
.status-text {
font-size: 1.1em;
font-weight: 500;
}
.on-air .status-text {
color: var(--accent);
font-weight: 700;
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
.mic-meter {
margin-top: 16px;
height: 6px;
background: #333;
border-radius: 3px;
overflow: hidden;
display: none;
}
.mic-meter.visible { display: block; }
.mic-meter-fill {
height: 100%;
background: #2ecc71;
width: 0%;
transition: width 0.1s;
border-radius: 3px;
}
</style>
</head>
<body>
<div class="container">
<h1>Luke at the Roost</h1>
<p class="subtitle">Call in to the show</p>
<div class="form-group">
<input type="text" id="caller-name" placeholder="Your name" maxlength="30" autocomplete="off">
</div>
<button id="call-btn" class="call-btn">Call In</button>
<button id="hangup-btn" class="hangup-btn">Hang Up</button>
<div id="status" class="status">
<div class="status-label">Status</div>
<div id="status-text" class="status-text">Connecting...</div>
</div>
<div id="mic-meter" class="mic-meter">
<div id="mic-meter-fill" class="mic-meter-fill"></div>
</div>
</div>
<script src="/js/call-in.js?v=5"></script>
</body>
</html>