update frontend for new variables
Browse files- src/web/live_transcription.html +100 -40
src/web/live_transcription.html
CHANGED
@@ -15,17 +15,22 @@
|
|
15 |
#recordButton {
|
16 |
width: 80px;
|
17 |
height: 80px;
|
18 |
-
font-size: 36px;
|
19 |
border: none;
|
20 |
border-radius: 50%;
|
21 |
background-color: white;
|
22 |
cursor: pointer;
|
23 |
-
box-shadow: 0 0px 10px rgba(0, 0, 0, 0.2);
|
24 |
transition: background-color 0.3s ease, transform 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
|
27 |
#recordButton.recording {
|
28 |
-
background-color:
|
|
|
|
|
29 |
color: white;
|
30 |
}
|
31 |
|
@@ -33,6 +38,29 @@
|
|
33 |
transform: scale(0.95);
|
34 |
}
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
#status {
|
37 |
margin-top: 20px;
|
38 |
font-size: 16px;
|
@@ -60,7 +88,8 @@
|
|
60 |
padding: 5px;
|
61 |
border-radius: 5px;
|
62 |
border: 1px solid #ddd;
|
63 |
-
background-color: #
|
|
|
64 |
}
|
65 |
|
66 |
#websocketInput {
|
@@ -94,12 +123,33 @@
|
|
94 |
}
|
95 |
|
96 |
#speaker {
|
97 |
-
background-color:
|
98 |
border-radius: 8px 8px 8px 0px;
|
99 |
padding: 2px 10px;
|
100 |
font-size: 14px;
|
101 |
margin-bottom: 0px;
|
102 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
#timeInfo {
|
105 |
color: #666;
|
@@ -110,28 +160,35 @@
|
|
110 |
font-size: 16px;
|
111 |
/* margin-left: 10px; */
|
112 |
padding-left: 10px;
|
113 |
-
border-left:
|
114 |
margin-bottom: 10px;
|
115 |
margin-top: 1px;
|
116 |
padding-top: 5px;
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
}
|
118 |
|
119 |
-
.
|
120 |
-
color:
|
121 |
-
font-style: italic;
|
122 |
margin-left: 4px;
|
123 |
}
|
124 |
|
|
|
125 |
.spinner {
|
126 |
display: inline-block;
|
127 |
width: 8px;
|
128 |
height: 8px;
|
129 |
-
border: 2px solid
|
130 |
-
border-top: 2px solid #
|
131 |
border-radius: 50%;
|
132 |
animation: spin 0.6s linear infinite;
|
133 |
vertical-align: middle;
|
134 |
margin-bottom: 2px;
|
|
|
135 |
}
|
136 |
|
137 |
@keyframes spin {
|
@@ -155,6 +212,7 @@
|
|
155 |
padding: 2px 10px;
|
156 |
font-size: 14px;
|
157 |
margin-bottom: 0px;
|
|
|
158 |
}
|
159 |
</style>
|
160 |
</head>
|
@@ -162,7 +220,11 @@
|
|
162 |
<body>
|
163 |
|
164 |
<div class="settings-container">
|
165 |
-
<button id="recordButton"
|
|
|
|
|
|
|
|
|
166 |
<div class="settings">
|
167 |
<div>
|
168 |
<label for="chunkSelector">Chunk size (ms):</label>
|
@@ -248,34 +310,27 @@
|
|
248 |
// Handle messages from server
|
249 |
websocket.onmessage = (event) => {
|
250 |
const data = JSON.parse(event.data);
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
"
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
|
|
|
|
265 |
};
|
266 |
});
|
267 |
}
|
268 |
|
269 |
-
function renderLinesWithBuffer(lines,
|
270 |
-
if (!Array.isArray(lines) || lines.length === 0) {
|
271 |
-
if (buffer) {
|
272 |
-
linesTranscriptDiv.innerHTML = `<span class="buffer">${buffer}</span>`;
|
273 |
-
} else {
|
274 |
-
linesTranscriptDiv.innerHTML = "";
|
275 |
-
}
|
276 |
-
return;
|
277 |
-
}
|
278 |
-
|
279 |
const linesHtml = lines.map((item, idx) => {
|
280 |
let timeInfo = "";
|
281 |
if (item.beg !== undefined && item.end !== undefined) {
|
@@ -286,7 +341,7 @@
|
|
286 |
if (item.speaker === -2) {
|
287 |
speakerLabel = `<span class="silence">Silence<span id='timeInfo'>${timeInfo}</span></span>`;
|
288 |
} else if (item.speaker == 0) {
|
289 |
-
speakerLabel = `<span class='loading'><span class="spinner"></span><span id='timeInfo'>${
|
290 |
} else if (item.speaker == -1) {
|
291 |
speakerLabel = `<span id="speaker"><span id='timeInfo'>${timeInfo}</span>`;
|
292 |
} else if (item.speaker !== -1) {
|
@@ -294,8 +349,13 @@
|
|
294 |
}
|
295 |
|
296 |
let textContent = item.text;
|
297 |
-
if (idx === lines.length - 1 &&
|
298 |
-
|
|
|
|
|
|
|
|
|
|
|
299 |
}
|
300 |
|
301 |
return textContent
|
@@ -336,7 +396,7 @@
|
|
336 |
websocket = null;
|
337 |
}
|
338 |
|
339 |
-
updateUI();
|
340 |
}
|
341 |
|
342 |
async function toggleRecording() {
|
|
|
15 |
#recordButton {
|
16 |
width: 80px;
|
17 |
height: 80px;
|
|
|
18 |
border: none;
|
19 |
border-radius: 50%;
|
20 |
background-color: white;
|
21 |
cursor: pointer;
|
|
|
22 |
transition: background-color 0.3s ease, transform 0.2s ease;
|
23 |
+
border: 1px solid rgb(252, 230, 229);
|
24 |
+
border-bottom: 5px solid rgb(252, 230, 229);
|
25 |
+
display: flex;
|
26 |
+
align-items: center;
|
27 |
+
justify-content: center;
|
28 |
}
|
29 |
|
30 |
#recordButton.recording {
|
31 |
+
background-color: rgba(255, 130, 123, 0.032);
|
32 |
+
border: 1px solid rgb(240, 198, 195);
|
33 |
+
border-bottom: 5px solid rgb(240, 198, 195);
|
34 |
color: white;
|
35 |
}
|
36 |
|
|
|
38 |
transform: scale(0.95);
|
39 |
}
|
40 |
|
41 |
+
.shape-container {
|
42 |
+
width: 40px;
|
43 |
+
height: 40px;
|
44 |
+
display: flex;
|
45 |
+
align-items: center;
|
46 |
+
justify-content: center;
|
47 |
+
}
|
48 |
+
|
49 |
+
.shape {
|
50 |
+
width: 40px;
|
51 |
+
height: 40px;
|
52 |
+
background-color: rgb(209, 61, 53);
|
53 |
+
border-radius: 50%;
|
54 |
+
transition: border-radius 0.3s ease, background-color 0.3s ease;
|
55 |
+
}
|
56 |
+
|
57 |
+
#recordButton.recording .shape {
|
58 |
+
border-radius: 10px;
|
59 |
+
width: 30px;
|
60 |
+
height: 30px;
|
61 |
+
|
62 |
+
}
|
63 |
+
|
64 |
#status {
|
65 |
margin-top: 20px;
|
66 |
font-size: 16px;
|
|
|
88 |
padding: 5px;
|
89 |
border-radius: 5px;
|
90 |
border: 1px solid #ddd;
|
91 |
+
background-color: #ffffff;
|
92 |
+
max-height: 30px;
|
93 |
}
|
94 |
|
95 |
#websocketInput {
|
|
|
123 |
}
|
124 |
|
125 |
#speaker {
|
126 |
+
background-color: rgb(252, 230, 229);
|
127 |
border-radius: 8px 8px 8px 0px;
|
128 |
padding: 2px 10px;
|
129 |
font-size: 14px;
|
130 |
margin-bottom: 0px;
|
131 |
}
|
132 |
+
.label_diarization {
|
133 |
+
background-color: #ffffff66;
|
134 |
+
border-radius: 8px 8px 8px 8px;
|
135 |
+
padding: 2px 10px;
|
136 |
+
margin-left: 10px;
|
137 |
+
font-size: 14px;
|
138 |
+
margin-bottom: 0px;
|
139 |
+
border-bottom: 3px solid rgb(155, 84, 84);
|
140 |
+
color: rgb(155, 84, 84)
|
141 |
+
}
|
142 |
+
|
143 |
+
.label_transcription {
|
144 |
+
background-color: #ffffff66;
|
145 |
+
border-radius: 8px 8px 8px 8px;
|
146 |
+
padding: 2px 10px;
|
147 |
+
margin-left: 10px;
|
148 |
+
font-size: 14px;
|
149 |
+
margin-bottom: 0px;
|
150 |
+
border-bottom: 3px solid #8825255c;
|
151 |
+
color: #8825255c
|
152 |
+
}
|
153 |
|
154 |
#timeInfo {
|
155 |
color: #666;
|
|
|
160 |
font-size: 16px;
|
161 |
/* margin-left: 10px; */
|
162 |
padding-left: 10px;
|
163 |
+
border-left: 3px solid rgb(252, 230, 229);
|
164 |
margin-bottom: 10px;
|
165 |
margin-top: 1px;
|
166 |
padding-top: 5px;
|
167 |
+
border-radius: 0px 0px 0px 10px;
|
168 |
+
}
|
169 |
+
|
170 |
+
.buffer_diarization {
|
171 |
+
color: rgb(155, 84, 84);
|
172 |
+
margin-left: 4px;
|
173 |
}
|
174 |
|
175 |
+
.buffer_transcription {
|
176 |
+
color: #8825255c;
|
|
|
177 |
margin-left: 4px;
|
178 |
}
|
179 |
|
180 |
+
|
181 |
.spinner {
|
182 |
display: inline-block;
|
183 |
width: 8px;
|
184 |
height: 8px;
|
185 |
+
border: 2px solid #8825255c;
|
186 |
+
border-top: 2px solid #882525e5;
|
187 |
border-radius: 50%;
|
188 |
animation: spin 0.6s linear infinite;
|
189 |
vertical-align: middle;
|
190 |
margin-bottom: 2px;
|
191 |
+
margin-right: 5px;
|
192 |
}
|
193 |
|
194 |
@keyframes spin {
|
|
|
212 |
padding: 2px 10px;
|
213 |
font-size: 14px;
|
214 |
margin-bottom: 0px;
|
215 |
+
|
216 |
}
|
217 |
</style>
|
218 |
</head>
|
|
|
220 |
<body>
|
221 |
|
222 |
<div class="settings-container">
|
223 |
+
<button id="recordButton">
|
224 |
+
<div class="shape-container">
|
225 |
+
<div class="shape"></div>
|
226 |
+
</div>
|
227 |
+
</button>
|
228 |
<div class="settings">
|
229 |
<div>
|
230 |
<label for="chunkSelector">Chunk size (ms):</label>
|
|
|
310 |
// Handle messages from server
|
311 |
websocket.onmessage = (event) => {
|
312 |
const data = JSON.parse(event.data);
|
313 |
+
|
314 |
+
const {
|
315 |
+
lines = [],
|
316 |
+
buffer_transcription = "",
|
317 |
+
buffer_diarization = "",
|
318 |
+
remaining_time_transcription = 0,
|
319 |
+
remaining_time_diarization = 0
|
320 |
+
} = data;
|
321 |
+
|
322 |
+
renderLinesWithBuffer(
|
323 |
+
lines,
|
324 |
+
buffer_diarization,
|
325 |
+
buffer_transcription,
|
326 |
+
remaining_time_diarization,
|
327 |
+
remaining_time_transcription
|
328 |
+
);
|
329 |
};
|
330 |
});
|
331 |
}
|
332 |
|
333 |
+
function renderLinesWithBuffer(lines, buffer_diarization, buffer_transcription, remaining_time_diarization, remaining_time_transcription) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
const linesHtml = lines.map((item, idx) => {
|
335 |
let timeInfo = "";
|
336 |
if (item.beg !== undefined && item.end !== undefined) {
|
|
|
341 |
if (item.speaker === -2) {
|
342 |
speakerLabel = `<span class="silence">Silence<span id='timeInfo'>${timeInfo}</span></span>`;
|
343 |
} else if (item.speaker == 0) {
|
344 |
+
speakerLabel = `<span class='loading'><span class="spinner"></span><span id='timeInfo'>${remaining_time_diarization} second(s) of audio are undergoing diarization</span></span>`;
|
345 |
} else if (item.speaker == -1) {
|
346 |
speakerLabel = `<span id="speaker"><span id='timeInfo'>${timeInfo}</span>`;
|
347 |
} else if (item.speaker !== -1) {
|
|
|
349 |
}
|
350 |
|
351 |
let textContent = item.text;
|
352 |
+
if (idx === lines.length - 1 && buffer_diarization) {
|
353 |
+
speakerLabel += `<span class="label_diarization"><span class="spinner"></span>Diarization lag<span id='timeInfo'>${remaining_time_diarization}s</span></span>`
|
354 |
+
textContent += `<span class="buffer_diarization">${buffer_diarization}</span>`;
|
355 |
+
}
|
356 |
+
if (idx === lines.length - 1 && buffer_transcription) {
|
357 |
+
speakerLabel += `<span class="label_transcription"><span class="spinner"></span>Transcription lag <span id='timeInfo'>${remaining_time_transcription}s</span></span>`
|
358 |
+
textContent += `<span class="buffer_transcription">${buffer_transcription}</span>`;
|
359 |
}
|
360 |
|
361 |
return textContent
|
|
|
396 |
websocket = null;
|
397 |
}
|
398 |
|
399 |
+
updateUI();
|
400 |
}
|
401 |
|
402 |
async function toggleRecording() {
|