shreyask commited on
Commit
9966ac0
Β·
verified Β·
1 Parent(s): 50e783f

Upload folder using huggingface_hub

Browse files
assets/{index-_bf5fS8E.js β†’ index-BuZjYFHI.js} RENAMED
The diff for this file is too large to render. See raw diff
 
index.html CHANGED
@@ -4,160 +4,257 @@
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Voxtral Realtime 4B β€” Live Speech-to-Text</title>
 
 
 
7
  <style>
8
  * { box-sizing: border-box; margin: 0; padding: 0; }
9
- :root {
10
- --mistral-orange: #FF7000;
11
- --mistral-amber: #FF8C00;
12
- --mistral-dark: #1A1008;
13
- --mistral-surface: #181210;
14
- --mistral-border: #2A2018;
15
- --mistral-muted: #887860;
16
- --mistral-text: #F0E8E0;
17
- --mistral-green: #4ADE80;
18
- }
19
  body {
20
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
21
- background: var(--mistral-dark); color: var(--mistral-text);
22
- min-height: 100vh; display: flex; flex-direction: column;
 
 
 
 
 
 
23
  align-items: center; padding: 2rem 1rem;
24
  }
25
- a { color: var(--mistral-orange); text-decoration: none; }
26
  a:hover { text-decoration: underline; }
27
- .container { max-width: 700px; width: 100%; }
28
 
29
- /* Header */
30
- .header { text-align: center; margin-bottom: 2rem; }
31
- h1 {
32
- font-size: 1.5rem; font-weight: 700;
33
- background: linear-gradient(135deg, var(--mistral-orange), var(--mistral-amber));
34
- -webkit-background-clip: text; -webkit-text-fill-color: transparent;
35
- background-clip: text;
36
- }
37
- .subtitle { color: var(--mistral-muted); font-size: 0.8rem; margin-top: 0.25rem; }
38
- .model-links {
39
- display: flex; align-items: center; justify-content: center; gap: 0.4rem;
40
- font-size: 0.75rem; margin-top: 0.5rem; color: var(--mistral-muted);
41
- flex-wrap: wrap;
42
- }
43
- .model-links .sep { color: var(--mistral-border); }
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- /* Load section */
46
- .load-section {
47
- background: var(--mistral-surface); border: 1px solid var(--mistral-border);
48
- border-radius: 12px; padding: 1.5rem; margin-bottom: 1.5rem;
 
 
49
  text-align: center;
 
 
50
  }
51
- .load-section.hidden { display: none; }
52
  .config-row {
53
- display: flex; gap: 0.5rem; justify-content: center; margin-bottom: 1rem;
 
54
  }
55
  .config-row select {
56
- background: var(--mistral-dark); border: 1px solid var(--mistral-border);
57
- border-radius: 8px; padding: 0.5rem 0.75rem; color: var(--mistral-text);
58
- font-size: 0.8rem; cursor: pointer;
59
  }
60
- .config-row select:focus { outline: 1px solid var(--mistral-orange); }
61
  .load-btn {
62
- background: linear-gradient(135deg, var(--mistral-orange), var(--mistral-amber));
63
- border: none; border-radius: 10px; padding: 0.7rem 2rem;
64
- color: #fff; font-size: 0.9rem; font-weight: 600;
65
- cursor: pointer; transition: all 0.2s; letter-spacing: 0.02em;
66
- }
67
- .load-btn:hover { filter: brightness(1.1); transform: translateY(-1px); }
68
- .load-btn:active { transform: translateY(0); }
69
- .load-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; filter: none; }
70
- .load-hint { font-size: 0.7rem; color: var(--mistral-muted); margin-top: 0.75rem; }
71
-
72
- /* Progress */
73
- .progress-bar {
74
- width: 100%; height: 4px; background: var(--mistral-dark); border-radius: 2px;
75
- overflow: hidden; margin-top: 0.75rem; opacity: 0; transition: opacity 0.3s;
76
- }
77
- .progress-bar.visible { opacity: 1; }
78
- .progress-bar .fill {
79
- height: 100%; border-radius: 2px;
80
- background: linear-gradient(90deg, var(--mistral-orange), var(--mistral-amber));
81
- transition: width 0.3s; width: 0%;
82
- }
83
- #loadStatus { font-size: 0.75rem; color: var(--mistral-muted); margin-top: 0.5rem; min-height: 1.2em; }
84
-
85
- /* Mic */
86
- .mic-wrap { display: flex; justify-content: center; margin: 1.25rem 0; }
87
- .mic-btn {
88
- width: 80px; height: 80px; border-radius: 50%;
89
- border: 2px solid var(--mistral-border); background: var(--mistral-surface);
90
- cursor: pointer; display: flex; align-items: center; justify-content: center;
91
- transition: all 0.2s;
92
  }
93
- .mic-btn:hover { border-color: var(--mistral-orange); }
94
- .mic-btn.listening {
95
- border-color: var(--mistral-green); background: rgba(74,222,128,0.05);
96
- box-shadow: 0 0 0 0 rgba(74,222,128,0.3);
97
- animation: ring 2s ease-out infinite;
98
  }
99
- .mic-btn.disabled { opacity: 0.25; cursor: not-allowed; pointer-events: none; }
100
- @keyframes ring {
101
- 0% { box-shadow: 0 0 0 0 rgba(74,222,128,0.3); }
102
- 100% { box-shadow: 0 0 0 18px rgba(74,222,128,0); }
103
  }
104
- .mic-btn svg { width: 32px; height: 32px; fill: var(--mistral-muted); transition: fill 0.2s; }
105
- .mic-btn.listening svg { fill: var(--mistral-green); }
106
-
107
- /* Waveform */
108
- .waveform { height: 44px; margin: 0.25rem 0; }
109
- .waveform canvas { width: 100%; height: 100%; display: block; border-radius: 6px; }
110
-
111
- /* Status */
112
- #status {
113
- text-align: center; font-size: 0.75rem; color: var(--mistral-muted);
114
- min-height: 1.2em; margin: 0.25rem 0;
 
 
115
  }
116
 
117
- /* Transcript */
118
  .transcript-card {
119
- background: var(--mistral-surface); border: 1px solid var(--mistral-border);
120
- border-radius: 12px; padding: 1.25rem; margin-top: 0.75rem; min-height: 140px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
- .transcript-label {
123
- font-size: 0.65rem; color: var(--mistral-muted);
124
- text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.75rem;
 
 
 
 
 
 
 
 
 
125
  }
126
  #transcript {
127
- font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
128
- font-size: 0.9rem; line-height: 1.7; color: var(--mistral-text);
129
  white-space: pre-wrap; word-break: break-word;
130
  }
131
- #transcript.placeholder { color: #554830; font-style: italic; font-family: inherit; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
- /* Timing */
134
- .timing {
135
- text-align: center; font-size: 0.65rem; color: var(--mistral-muted);
136
- margin-top: 0.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
138
 
139
- /* Footer */
140
  .footer {
141
- margin-top: 2rem; text-align: center; font-size: 0.65rem;
142
- color: var(--mistral-muted); line-height: 1.6;
 
143
  }
144
  </style>
145
- <script type="module" crossorigin src="/assets/index-_bf5fS8E.js"></script>
146
  </head>
147
  <body>
148
  <div class="container">
149
- <div class="header">
150
- <h1>Voxtral Realtime 4B</h1>
151
- <p class="subtitle">Speech-to-Text in the browser with transformers.js + WebGPU</p>
152
- <div class="model-links">
153
- <a href="https://huggingface.co/mistralai/Voxtral-Mini-4B-Realtime-2602" target="_blank" rel="noopener">mistralai/Voxtral-Mini-4B-Realtime-2602</a>
 
 
 
 
 
 
154
  <span class="sep">&middot;</span>
155
- <a href="https://huggingface.co/onnx-community/Voxtral-Mini-4B-Realtime-2602-ONNX" target="_blank" rel="noopener">ONNX weights</a>
 
 
156
  </div>
157
  </div>
158
 
159
  <!-- Load Model -->
160
- <div class="load-section" id="loadSection">
161
  <div class="config-row">
162
  <select id="dtype" title="Quantization">
163
  <option value="q4">q4 (~1.5 GB)</option>
@@ -170,32 +267,45 @@
170
  </select>
171
  </div>
172
  <button class="load-btn" id="loadBtn" onclick="window.__loadModel()">Load Model</button>
173
- <div class="load-hint">Requires a browser with WebGPU support (Chrome 113+, Edge 113+)</div>
174
- <div class="progress-bar" id="progressBar"><div class="fill" id="progressFill"></div></div>
175
- <div id="loadStatus"></div>
 
 
176
  </div>
177
 
178
- <!-- Active UI (hidden until model loads) -->
179
  <div id="activeUI" style="display:none">
180
- <div class="mic-wrap">
181
- <button class="mic-btn" id="micBtn" title="Click to start/stop listening">
182
  <svg viewBox="0 0 24 24"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1-9c0-.55.45-1 1-1s1 .45 1 1v6c0 .55-.45 1-1 1s-1-.45-1-1V5zm6 6c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/></svg>
183
  </button>
 
184
  </div>
185
-
186
- <div class="waveform"><canvas id="waveCanvas"></canvas></div>
187
- <div id="status">Click the mic to start listening</div>
188
  </div>
189
 
 
190
  <div class="transcript-card" id="transcriptCard" style="display:none">
191
- <div class="transcript-label">Transcript</div>
192
- <div id="transcript" class="placeholder">Speak into your microphone...</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  </div>
194
- <div class="timing" id="timing"></div>
195
 
196
  <div class="footer">
197
- Powered by <a href="https://huggingface.co/docs/transformers.js" target="_blank">transformers.js</a>
198
- &middot; Runs entirely in your browser
199
  </div>
200
  </div>
201
 
 
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Voxtral Realtime 4B β€” Live Speech-to-Text</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
10
  <style>
11
  * { box-sizing: border-box; margin: 0; padding: 0; }
12
+
 
 
 
 
 
 
 
 
 
13
  body {
14
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
15
+ background-color: #FFFAEB;
16
+ background-image:
17
+ linear-gradient(#E9E2CB 1px, transparent 1px),
18
+ linear-gradient(90deg, #E9E2CB 1px, transparent 1px);
19
+ background-size: 40px 40px;
20
+ color: #1E1E1E;
21
+ min-height: 100vh;
22
+ display: flex; flex-direction: column;
23
  align-items: center; padding: 2rem 1rem;
24
  }
25
+ a { color: #FF8205; text-decoration: none; }
26
  a:hover { text-decoration: underline; }
 
27
 
28
+ .container { max-width: 680px; width: 100%; }
29
+
30
+ /* ── Header card ── */
31
+ .header-card {
32
+ background: linear-gradient(135deg, #FFFAEB 0%, #FFF0C3 100%);
33
+ border: 2px solid #E9E2CB;
34
+ border-top: 4px solid #FF8205;
35
+ border-radius: 8px;
36
+ padding: 1.75rem 2rem;
37
+ margin-bottom: 1.25rem;
38
+ box-shadow: 0 4px 24px rgba(0,0,0,0.06);
39
+ }
40
+ .header-title {
41
+ font-size: 1.6rem; font-weight: 700; color: #1E1E1E;
42
+ letter-spacing: -0.02em;
43
+ display: flex; align-items: center; gap: 0.6rem;
44
+ }
45
+ .header-title .accent { color: #FF8205; }
46
+ .header-subtitle {
47
+ color: #555; font-size: 0.85rem; margin-top: 0.35rem;
48
+ }
49
+ .header-links {
50
+ display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
51
+ margin-top: 0.6rem; font-size: 0.72rem; color: #888;
52
+ font-family: 'JetBrains Mono', monospace;
53
+ }
54
+ .header-links .sep { color: #E9E2CB; }
55
 
56
+ /* ── Load section ── */
57
+ .load-card {
58
+ background: rgba(255,255,255,0.6);
59
+ border: 2px solid #E9E2CB;
60
+ border-radius: 8px;
61
+ padding: 2rem;
62
  text-align: center;
63
+ box-shadow: 0 4px 24px rgba(0,0,0,0.04);
64
+ margin-bottom: 1.25rem;
65
  }
66
+ .load-card.hidden { display: none; }
67
  .config-row {
68
+ display: flex; gap: 0.5rem; justify-content: center;
69
+ margin-bottom: 1.25rem;
70
  }
71
  .config-row select {
72
+ background: #FFFAEB; border: 1.5px solid #E9E2CB; border-radius: 4px;
73
+ padding: 0.5rem 0.75rem; color: #1E1E1E; font-size: 0.8rem;
74
+ font-family: 'JetBrains Mono', monospace; cursor: pointer;
75
  }
76
+ .config-row select:focus { outline: none; border-color: #FF8205; }
77
  .load-btn {
78
+ background: #FF8205; border: none; border-radius: 4px;
79
+ padding: 0.75rem 2.5rem; color: #fff;
80
+ font-family: 'JetBrains Mono', monospace;
81
+ font-size: 0.8rem; font-weight: 700;
82
+ text-transform: uppercase; letter-spacing: 0.08em;
83
+ cursor: pointer; transition: all 0.2s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
+ .load-btn:hover { background: #E67300; }
86
+ .load-btn:disabled { opacity: 0.5; cursor: not-allowed; }
87
+ .load-hint {
88
+ font-size: 0.7rem; color: #888; margin-top: 1rem;
89
+ font-family: 'JetBrains Mono', monospace;
90
  }
91
+ .progress-wrap {
92
+ margin-top: 1rem; opacity: 0; transition: opacity 0.3s;
 
 
93
  }
94
+ .progress-wrap.visible { opacity: 1; }
95
+ .progress-track {
96
+ width: 100%; height: 4px; background: #E9E2CB; border-radius: 2px;
97
+ overflow: hidden;
98
+ }
99
+ .progress-fill {
100
+ height: 100%; width: 0%; border-radius: 2px;
101
+ background: #FF8205; transition: width 0.3s;
102
+ }
103
+ .load-status {
104
+ font-family: 'JetBrains Mono', monospace;
105
+ font-size: 0.7rem; color: #888; margin-top: 0.4rem;
106
+ min-height: 1.2em;
107
  }
108
 
109
+ /* ── Transcription card ── */
110
  .transcript-card {
111
+ background: #FFFAEB;
112
+ border: 2px solid #E9E2CB;
113
+ border-radius: 8px;
114
+ box-shadow: 0 8px 32px rgba(0,0,0,0.06);
115
+ overflow: hidden;
116
+ margin-bottom: 0.75rem;
117
+ }
118
+ .card-header {
119
+ background: rgba(255,255,255,0.6);
120
+ border-bottom: 1px solid #E9E2CB;
121
+ padding: 0.6rem 1rem;
122
+ display: flex; align-items: center; justify-content: space-between;
123
+ }
124
+ .card-header-left {
125
+ display: flex; align-items: center; gap: 0.6rem;
126
+ }
127
+ .card-title {
128
+ font-family: 'JetBrains Mono', monospace;
129
+ font-size: 0.6rem; font-weight: 700; color: #1E1E1E;
130
+ text-transform: uppercase; letter-spacing: 0.1em;
131
+ }
132
+ .status-badge {
133
+ display: inline-flex; align-items: center; gap: 0.4rem;
134
+ padding: 0.2rem 0.6rem; border-radius: 2px;
135
+ font-family: 'JetBrains Mono', monospace;
136
+ font-size: 0.55rem; font-weight: 700;
137
+ text-transform: uppercase; letter-spacing: 0.08em;
138
+ }
139
+ .status-idle {
140
+ background: #f0f0f0; color: #888; border: 1px solid #E9E2CB;
141
+ }
142
+ .status-listening {
143
+ background: rgba(255,130,5,0.15); color: #CC6A04;
144
+ border: 1px solid #FF8205;
145
+ }
146
+ .status-transcribing {
147
+ background: rgba(255,130,5,0.25); color: #CC6A04;
148
+ border: 1px solid #FF8205;
149
+ }
150
+ .status-dot {
151
+ width: 6px; height: 6px; border-radius: 50%;
152
+ background: currentColor;
153
+ }
154
+ .status-dot.pulse {
155
+ animation: pulse 1.2s ease-in-out infinite;
156
  }
157
+ @keyframes pulse {
158
+ 0%, 100% { opacity: 1; transform: scale(1); }
159
+ 50% { opacity: 0.4; transform: scale(0.7); }
160
+ }
161
+
162
+ .card-content {
163
+ padding: 1.25rem 1.25rem 1.5rem;
164
+ min-height: 180px;
165
+ background-image:
166
+ linear-gradient(rgba(0,0,0,0.02) 1px, transparent 1px),
167
+ linear-gradient(90deg, rgba(0,0,0,0.02) 1px, transparent 1px);
168
+ background-size: 20px 20px;
169
  }
170
  #transcript {
171
+ font-family: 'JetBrains Mono', monospace;
172
+ font-size: 0.95rem; line-height: 1.8; color: #1E1E1E;
173
  white-space: pre-wrap; word-break: break-word;
174
  }
175
+ #transcript.placeholder {
176
+ color: #bbb; font-style: italic;
177
+ }
178
+ .transcript-cursor {
179
+ display: inline-block; width: 8px; height: 16px;
180
+ background: #FF8205; margin-left: 3px; vertical-align: middle;
181
+ animation: blink 1s step-end infinite;
182
+ }
183
+ @keyframes blink {
184
+ 0%, 100% { opacity: 1; }
185
+ 50% { opacity: 0; }
186
+ }
187
+ .card-footer {
188
+ background: rgba(255,255,255,0.4);
189
+ border-top: 1px solid #E9E2CB;
190
+ padding: 0.4rem 1rem;
191
+ font-family: 'JetBrains Mono', monospace;
192
+ font-size: 0.6rem; color: #888;
193
+ display: flex; justify-content: space-between;
194
+ }
195
 
196
+ /* ── Mic + waveform ── */
197
+ .controls {
198
+ display: flex; align-items: center; justify-content: center;
199
+ gap: 1rem; margin-bottom: 1rem;
200
+ }
201
+ .mic-btn {
202
+ width: 56px; height: 56px; border-radius: 50%;
203
+ border: 2px solid #E9E2CB; background: rgba(255,255,255,0.7);
204
+ cursor: pointer; display: flex; align-items: center; justify-content: center;
205
+ transition: all 0.2s;
206
+ }
207
+ .mic-btn:hover { border-color: #FF8205; background: rgba(255,130,5,0.05); }
208
+ .mic-btn.listening {
209
+ border-color: #FF8205; background: rgba(255,130,5,0.1);
210
+ box-shadow: 0 0 0 0 rgba(255,130,5,0.3);
211
+ animation: ring 2s ease-out infinite;
212
+ }
213
+ .mic-btn.disabled { opacity: 0.3; cursor: not-allowed; pointer-events: none; }
214
+ @keyframes ring {
215
+ 0% { box-shadow: 0 0 0 0 rgba(255,130,5,0.3); }
216
+ 100% { box-shadow: 0 0 0 16px rgba(255,130,5,0); }
217
+ }
218
+ .mic-btn svg { width: 24px; height: 24px; fill: #888; transition: fill 0.2s; }
219
+ .mic-btn.listening svg { fill: #FF8205; }
220
+
221
+ .waveform { flex: 1; height: 44px; max-width: 400px; }
222
+ .waveform canvas {
223
+ width: 100%; height: 100%; display: block; border-radius: 4px;
224
+ border: 1px solid #E9E2CB; background: rgba(255,255,255,0.4);
225
  }
226
 
227
+ /* ── Footer ── */
228
  .footer {
229
+ text-align: center; font-size: 0.65rem; color: #aaa;
230
+ font-family: 'JetBrains Mono', monospace;
231
+ margin-top: 0.5rem;
232
  }
233
  </style>
234
+ <script type="module" crossorigin src="/assets/index-BuZjYFHI.js"></script>
235
  </head>
236
  <body>
237
  <div class="container">
238
+
239
+ <!-- Header -->
240
+ <div class="header-card">
241
+ <div class="header-title">
242
+ <span class="accent">Voxtral</span> Realtime 4B
243
+ </div>
244
+ <p class="header-subtitle">
245
+ Real-time speech transcription running entirely in your browser via WebGPU
246
+ </p>
247
+ <div class="header-links">
248
+ <a href="https://huggingface.co/mistralai/Voxtral-Mini-4B-Realtime-2602" target="_blank">mistralai/Voxtral-Mini-4B-Realtime-2602</a>
249
  <span class="sep">&middot;</span>
250
+ <a href="https://huggingface.co/onnx-community/Voxtral-Mini-4B-Realtime-2602-ONNX" target="_blank">ONNX weights</a>
251
+ <span class="sep">&middot;</span>
252
+ <a href="https://huggingface.co/docs/transformers.js" target="_blank">transformers.js</a>
253
  </div>
254
  </div>
255
 
256
  <!-- Load Model -->
257
+ <div class="load-card" id="loadSection">
258
  <div class="config-row">
259
  <select id="dtype" title="Quantization">
260
  <option value="q4">q4 (~1.5 GB)</option>
 
267
  </select>
268
  </div>
269
  <button class="load-btn" id="loadBtn" onclick="window.__loadModel()">Load Model</button>
270
+ <div class="load-hint">Requires WebGPU (Chrome 113+, Edge 113+). Models are cached after first download.</div>
271
+ <div class="progress-wrap" id="progressWrap">
272
+ <div class="progress-track"><div class="progress-fill" id="progressFill"></div></div>
273
+ <div class="load-status" id="loadStatus"></div>
274
+ </div>
275
  </div>
276
 
277
+ <!-- Active UI -->
278
  <div id="activeUI" style="display:none">
279
+ <div class="controls">
280
+ <button class="mic-btn" id="micBtn" title="Start / stop listening">
281
  <svg viewBox="0 0 24 24"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1-9c0-.55.45-1 1-1s1 .45 1 1v6c0 .55-.45 1-1 1s-1-.45-1-1V5zm6 6c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/></svg>
282
  </button>
283
+ <div class="waveform"><canvas id="waveCanvas"></canvas></div>
284
  </div>
 
 
 
285
  </div>
286
 
287
+ <!-- Transcript -->
288
  <div class="transcript-card" id="transcriptCard" style="display:none">
289
+ <div class="card-header">
290
+ <div class="card-header-left">
291
+ <span class="card-title">Transcript</span>
292
+ </div>
293
+ <span class="status-badge status-idle" id="statusBadge">
294
+ <span class="status-dot" id="statusDot"></span>
295
+ <span id="statusText">Idle</span>
296
+ </span>
297
+ </div>
298
+ <div class="card-content">
299
+ <div id="transcript" class="placeholder">Press the mic button and start speaking...</div>
300
+ </div>
301
+ <div class="card-footer">
302
+ <span id="timing"></span>
303
+ <span>voxtral-realtime-4b &middot; in-browser</span>
304
+ </div>
305
  </div>
 
306
 
307
  <div class="footer">
308
+ No data leaves your device &middot; Powered by <a href="https://huggingface.co/docs/transformers.js" target="_blank">transformers.js</a> + WebGPU
 
309
  </div>
310
  </div>
311